1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-10-06 22:19:30 +03:00

Merge branch 'master' into 2018-05-11-fork-libdm

This commit is contained in:
Joe Thornber 2018-05-16 13:43:02 +01:00
commit 89fdc0b588
60 changed files with 645 additions and 336 deletions

View File

@ -1,6 +1,6 @@
#
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
# Copyright (C) 2004-2015 Red Hat, Inc. All rights reserved.
# Copyright (C) 2004-2018 Red Hat, Inc. All rights reserved.
#
# This file is part of LVM2.
#
@ -61,6 +61,7 @@ po: tools daemons
man: tools
all_man: tools
scripts: liblvm libdm
test: tools daemons
lib.device-mapper: include.device-mapper
libdm.device-mapper: include.device-mapper
@ -96,7 +97,7 @@ endif
DISTCLEAN_TARGETS += cscope.out
CLEAN_DIRS += autom4te.cache
check check_system check_cluster check_local check_lvmetad check_lvmpolld check_lvmlockd_test check_lvmlockd_dlm check_lvmlockd_sanlock: all
check check_system check_cluster check_local check_lvmetad check_lvmpolld check_lvmlockd_test check_lvmlockd_dlm check_lvmlockd_sanlock: test
$(MAKE) -C test $(@)
conf.generate man.generate: tools
@ -145,7 +146,7 @@ install_system_dirs:
$(INSTALL_ROOT_DIR) $(DESTDIR)$(DEFAULT_RUN_DIR)
$(INSTALL_ROOT_DATA) /dev/null $(DESTDIR)$(DEFAULT_CACHE_DIR)/.cache
install_initscripts:
install_initscripts:
$(MAKE) -C scripts install_initscripts
install_systemd_generators:
@ -168,6 +169,7 @@ install_tmpfiles_configuration:
LCOV_TRACES = libdm.info lib.info liblvm.info tools.info \
libdaemon/client.info libdaemon/server.info \
test/unit.info \
daemons/clvmd.info \
daemons/dmeventd.info \
daemons/lvmetad.info \

View File

@ -1,5 +1,9 @@
Version 2.02.178 -
=====================================
Remove lvm1 and pool format handling and add filter to ignore them.
Move some filter checks to after disks are read.
Rework disk scanning and when it is used.
Add new io layer and shift code to using it.
lvconvert: don't return success on degraded -m raid1 conversion
--enable-testing switch for ./configure has been removed.
--with-snapshots switch for ./configure has been removed.

View File

@ -702,29 +702,17 @@ global {
activation = 1
# Configuration option global/fallback_to_lvm1.
# Try running LVM1 tools if LVM cannot communicate with DM.
# This option only applies to 2.4 kernels and is provided to help
# switch between device-mapper kernels and LVM1 kernels. The LVM1
# tools need to be installed with .lvm1 suffices, e.g. vgscan.lvm1.
# They will stop working once the lvm2 on-disk metadata format is used.
# This setting is no longer used.
# This configuration option has an automatic default value.
# fallback_to_lvm1 = @DEFAULT_FALLBACK_TO_LVM1@
# fallback_to_lvm1 = 0
# Configuration option global/format.
# The default metadata format that commands should use.
# The -M 1|2 option overrides this setting.
#
# Accepted values:
# lvm1
# lvm2
#
# This setting is no longer used.
# This configuration option has an automatic default value.
# format = "lvm2"
# Configuration option global/format_libraries.
# Shared libraries that process different metadata formats.
# If support for LVM1 metadata was compiled as a shared library use
# format_libraries = "liblvm2format1.so"
# This setting is no longer used.
# This configuration option does not have a default value defined.
# Configuration option global/segment_libraries.
@ -821,13 +809,6 @@ global {
# encountered the internal error. Please only enable for debugging.
abort_on_internal_errors = 0
# Configuration option global/detect_internal_vg_cache_corruption.
# Internal verification of VG structures.
# Check if CRC matches when a parsed VG is used multiple times. This
# is useful to catch unexpected changes to cached VG structures.
# Please only enable for debugging.
detect_internal_vg_cache_corruption = 0
# Configuration option global/metadata_read_only.
# No operations that change on-disk metadata are permitted.
# Additionally, read-only commands that encounter metadata in need of

5
configure vendored
View File

@ -6141,7 +6141,7 @@ fi
for ac_header in assert.h ctype.h dirent.h errno.h fcntl.h float.h \
getopt.h inttypes.h langinfo.h libgen.h limits.h locale.h paths.h \
getopt.h inttypes.h langinfo.h libaio.h libgen.h limits.h locale.h paths.h \
signal.h stdarg.h stddef.h stdio.h stdlib.h string.h sys/file.h \
sys/ioctl.h syslog.h sys/mman.h sys/param.h sys/resource.h sys/stat.h \
sys/time.h sys/types.h sys/utsname.h sys/wait.h time.h \
@ -15559,7 +15559,7 @@ _ACEOF
################################################################################
ac_config_files="$ac_config_files Makefile make.tmpl libdm/make.tmpl daemons/Makefile daemons/clvmd/Makefile daemons/cmirrord/Makefile daemons/dmeventd/Makefile daemons/dmeventd/libdevmapper-event.pc daemons/dmeventd/plugins/Makefile daemons/dmeventd/plugins/lvm2/Makefile daemons/dmeventd/plugins/raid/Makefile daemons/dmeventd/plugins/mirror/Makefile daemons/dmeventd/plugins/snapshot/Makefile daemons/dmeventd/plugins/thin/Makefile daemons/dmfilemapd/Makefile daemons/lvmdbusd/Makefile daemons/lvmdbusd/lvmdbusd daemons/lvmdbusd/lvmdb.py daemons/lvmdbusd/lvm_shell_proxy.py daemons/lvmdbusd/path.py daemons/lvmetad/Makefile daemons/lvmpolld/Makefile daemons/lvmlockd/Makefile conf/Makefile conf/example.conf conf/lvmlocal.conf conf/command_profile_template.profile conf/metadata_profile_template.profile include/Makefile lib/Makefile lib/locking/Makefile include/lvm-version.h libdaemon/Makefile libdaemon/client/Makefile libdaemon/server/Makefile libdm/Makefile libdm/libdevmapper.pc liblvm/Makefile liblvm/liblvm2app.pc man/Makefile po/Makefile python/Makefile python/setup.py scripts/blkdeactivate.sh scripts/blk_availability_init_red_hat scripts/blk_availability_systemd_red_hat.service scripts/clvmd_init_red_hat scripts/cmirrord_init_red_hat scripts/com.redhat.lvmdbus1.service scripts/dm_event_systemd_red_hat.service scripts/dm_event_systemd_red_hat.socket scripts/lvm2_cluster_activation_red_hat.sh scripts/lvm2_cluster_activation_systemd_red_hat.service scripts/lvm2_clvmd_systemd_red_hat.service scripts/lvm2_cmirrord_systemd_red_hat.service scripts/lvm2_lvmdbusd_systemd_red_hat.service scripts/lvm2_lvmetad_init_red_hat scripts/lvm2_lvmetad_systemd_red_hat.service scripts/lvm2_lvmetad_systemd_red_hat.socket scripts/lvm2_lvmpolld_init_red_hat scripts/lvm2_lvmpolld_systemd_red_hat.service scripts/lvm2_lvmpolld_systemd_red_hat.socket scripts/lvm2_lvmlockd_systemd_red_hat.service scripts/lvm2_lvmlocking_systemd_red_hat.service scripts/lvm2_monitoring_init_red_hat scripts/lvm2_monitoring_systemd_red_hat.service scripts/lvm2_pvscan_systemd_red_hat@.service scripts/lvm2_tmpfiles_red_hat.conf scripts/lvmdump.sh scripts/Makefile test/Makefile test/api/Makefile test/unit/Makefile tools/Makefile udev/Makefile"
ac_config_files="$ac_config_files Makefile make.tmpl libdm/make.tmpl daemons/Makefile daemons/clvmd/Makefile daemons/cmirrord/Makefile daemons/dmeventd/Makefile daemons/dmeventd/libdevmapper-event.pc daemons/dmeventd/plugins/Makefile daemons/dmeventd/plugins/lvm2/Makefile daemons/dmeventd/plugins/raid/Makefile daemons/dmeventd/plugins/mirror/Makefile daemons/dmeventd/plugins/snapshot/Makefile daemons/dmeventd/plugins/thin/Makefile daemons/dmfilemapd/Makefile daemons/lvmdbusd/Makefile daemons/lvmdbusd/lvmdbusd daemons/lvmdbusd/lvmdb.py daemons/lvmdbusd/lvm_shell_proxy.py daemons/lvmdbusd/path.py daemons/lvmetad/Makefile daemons/lvmpolld/Makefile daemons/lvmlockd/Makefile conf/Makefile conf/example.conf conf/lvmlocal.conf conf/command_profile_template.profile conf/metadata_profile_template.profile include/Makefile lib/Makefile lib/locking/Makefile include/lvm-version.h libdaemon/Makefile libdaemon/client/Makefile libdaemon/server/Makefile libdm/Makefile libdm/libdevmapper.pc liblvm/Makefile liblvm/liblvm2app.pc man/Makefile po/Makefile python/Makefile python/setup.py scripts/blkdeactivate.sh scripts/blk_availability_init_red_hat scripts/blk_availability_systemd_red_hat.service scripts/clvmd_init_red_hat scripts/cmirrord_init_red_hat scripts/com.redhat.lvmdbus1.service scripts/dm_event_systemd_red_hat.service scripts/dm_event_systemd_red_hat.socket scripts/lvm2_cluster_activation_red_hat.sh scripts/lvm2_cluster_activation_systemd_red_hat.service scripts/lvm2_clvmd_systemd_red_hat.service scripts/lvm2_cmirrord_systemd_red_hat.service scripts/lvm2_lvmdbusd_systemd_red_hat.service scripts/lvm2_lvmetad_init_red_hat scripts/lvm2_lvmetad_systemd_red_hat.service scripts/lvm2_lvmetad_systemd_red_hat.socket scripts/lvm2_lvmpolld_init_red_hat scripts/lvm2_lvmpolld_systemd_red_hat.service scripts/lvm2_lvmpolld_systemd_red_hat.socket scripts/lvm2_lvmlockd_systemd_red_hat.service scripts/lvm2_lvmlocking_systemd_red_hat.service scripts/lvm2_monitoring_init_red_hat scripts/lvm2_monitoring_systemd_red_hat.service scripts/lvm2_pvscan_systemd_red_hat@.service scripts/lvm2_tmpfiles_red_hat.conf scripts/lvmdump.sh scripts/Makefile test/Makefile test/api/Makefile test/api/python_lvm_unit.py test/unit/Makefile tools/Makefile udev/Makefile"
cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
@ -16326,6 +16326,7 @@ do
"scripts/Makefile") CONFIG_FILES="$CONFIG_FILES scripts/Makefile" ;;
"test/Makefile") CONFIG_FILES="$CONFIG_FILES test/Makefile" ;;
"test/api/Makefile") CONFIG_FILES="$CONFIG_FILES test/api/Makefile" ;;
"test/api/python_lvm_unit.py") CONFIG_FILES="$CONFIG_FILES test/api/python_lvm_unit.py" ;;
"test/unit/Makefile") CONFIG_FILES="$CONFIG_FILES test/unit/Makefile" ;;
"tools/Makefile") CONFIG_FILES="$CONFIG_FILES tools/Makefile" ;;
"udev/Makefile") CONFIG_FILES="$CONFIG_FILES udev/Makefile" ;;

View File

@ -103,7 +103,7 @@ AC_HEADER_SYS_WAIT
AC_HEADER_TIME
AC_CHECK_HEADERS([assert.h ctype.h dirent.h errno.h fcntl.h float.h \
getopt.h inttypes.h langinfo.h libgen.h limits.h locale.h paths.h \
getopt.h inttypes.h langinfo.h libaio.h libgen.h limits.h locale.h paths.h \
signal.h stdarg.h stddef.h stdio.h stdlib.h string.h sys/file.h \
sys/ioctl.h syslog.h sys/mman.h sys/param.h sys/resource.h sys/stat.h \
sys/time.h sys/types.h sys/utsname.h sys/wait.h time.h \
@ -2158,6 +2158,7 @@ scripts/lvmdump.sh
scripts/Makefile
test/Makefile
test/api/Makefile
test/api/python_lvm_unit.py
test/unit/Makefile
tools/Makefile
udev/Makefile

View File

@ -27,6 +27,8 @@ ifeq ("@BUILD_LOCKDDLM@", "yes")
LOCK_LIBS += -ldlm_lt
endif
SOURCES2 = lvmlockctl.c
TARGETS = lvmlockd lvmlockctl
.PHONY: install_lvmlockd

View File

@ -229,3 +229,110 @@ It may be worthwhile to change the filters to use the udev info as a hint,
or only use udev info for filtering in reporting commands where
inaccuracies are not a big problem.)
I/O Performance
---------------
. 400 loop devices used as PVs
. 40 VGs each with 10 PVs
. each VG has one active LV
. each of the 10 PVs in vg0 has an artificial 100 ms read delay
. read/write/io_submit are system call counts using strace
. old is lvm 2.2.175
. new is lvm 2.2.178 (shortly before)
Command: pvs
------------
old: 0m17.422s
new: 0m0.331s
old: read 7773 write 497
new: read 2807 write 495 io_submit 448
Command: vgs
------------
old: 0m20.383s
new: 0m0.325s
old: read 10684 write 129
new: read 2807 write 129 io_submit 448
Command: vgck vg0
-----------------
old: 0m16.212s
new: 0m1.290s
old: read 6372 write 4
new: read 2807 write 4 io_submit 458
Command: lvcreate -n test -l1 -an vg0
-------------------------------------
old: 0m29.271s
new: 0m1.351s
old: read 6503 write 39
new: read 2808 write 9 io_submit 488
Command: lvremove vg0/test
--------------------------
old: 0m29.262s
new: 0m1.348s
old: read 6502 write 36
new: read 2807 write 6 io_submit 488
io_submit sources
-----------------
vgs:
reads:
- 400 for each PV
- 40 for each LV
- 8 for other devs on the system
vgck vg0:
reads:
- 400 for each PV
- 40 for each LV
- 10 for each PV in vg0 (rescan)
- 8 for other devs on the system
lvcreate -n test -l1 -an vg0
reads:
- 400 for each PV
- 40 for each LV
- 10 for each PV in vg0 (rescan)
- 8 for other devs on the system
writes:
- 10 for metadata on each PV in vg0
- 10 for precommit on each PV in vg0
- 10 for commit on each PV in vg0
With lvmetad
------------
Command: pvs
------------
old: 0m5.405s
new: 0m1.404s
Command: vgs
------------
old: 0m0.222s
new: 0m0.223s
Command: lvcreate -n test -l1 -an vg0
-------------------------------------
old: 0m10.128s
new: 0m1.137s

View File

@ -245,6 +245,9 @@
/* Define to 1 if you have the <langinfo.h> header file. */
#undef HAVE_LANGINFO_H
/* Define to 1 if you have the <libaio.h> header file. */
#undef HAVE_LIBAIO_H
/* Define to 1 if you have the <libcman.h> header file. */
#undef HAVE_LIBCMAN_H

68
lib/cache/lvmcache.c vendored
View File

@ -643,7 +643,6 @@ void lvmcache_unlock_vgname(const char *vgname)
/* FIXME Do this per-VG */
if (strcmp(vgname, VG_GLOBAL) && !--_vgs_locked) {
dev_close_all();
dev_size_seqno_inc(); /* invalidate all cached dev sizes */
}
}
@ -811,7 +810,7 @@ const struct format_type *lvmcache_fmt_from_vgname(struct cmd_context *cmd,
dm_list_iterate_safe(devh, tmp, &devs) {
devl = dm_list_item(devh, struct device_list);
label_read(devl->dev, NULL, UINT64_C(0));
label_read(devl->dev);
dm_list_del(&devl->list);
dm_free(devl);
}
@ -977,6 +976,36 @@ int lvmcache_dev_is_unchosen_duplicate(struct device *dev)
return _dev_in_device_list(dev, &_unused_duplicate_devs);
}
/*
* Treat some duplicate devs as if they were filtered out by filters.
* The actual filters are evaluated too early, before a complete
* picture of all PVs is available, to eliminate these duplicates.
*
* By removing the filtered duplicates from unused_duplicate_devs, we remove
* the restrictions that are placed on using duplicate devs or VGs with
* duplicate devs.
*
* There may other kinds of duplicates that we want to ignore.
*/
static void _filter_duplicate_devs(struct cmd_context *cmd)
{
struct dev_types *dt = cmd->dev_types;
struct lvmcache_info *info;
struct device_list *devl, *devl2;
dm_list_iterate_items_safe(devl, devl2, &_unused_duplicate_devs) {
info = lvmcache_info_from_pvid(devl->dev->pvid, NULL, 0);
if (MAJOR(info->dev->dev) == dt->md_major) {
log_debug_devs("Ignoring md component duplicate %s", dev_name(devl->dev));
dm_list_del(&devl->list);
dm_free(devl);
}
}
}
/*
* Compare _found_duplicate_devs entries with the corresponding duplicate dev
* in lvmcache. There may be multiple duplicates in _found_duplicate_devs for
@ -1279,9 +1308,9 @@ next:
int lvmcache_label_rescan_vg(struct cmd_context *cmd, const char *vgname, const char *vgid)
{
struct dm_list devs;
struct device_list *devl;
struct device_list *devl, *devl2;
struct lvmcache_vginfo *vginfo;
struct lvmcache_info *info, *info2;
struct lvmcache_info *info;
if (lvmetad_used())
return 1;
@ -1310,8 +1339,9 @@ int lvmcache_label_rescan_vg(struct cmd_context *cmd, const char *vgname, const
dm_list_add(&devs, &devl->list);
}
dm_list_iterate_items_safe(info, info2, &vginfo->infos)
lvmcache_del(info);
/* Delete info for each dev, deleting the last info will delete vginfo. */
dm_list_iterate_items(devl, &devs)
lvmcache_del_dev(devl->dev);
/* Dropping the last info struct is supposed to drop vginfo. */
if ((vginfo = lvmcache_vginfo_from_vgname(vgname, vgid)))
@ -1322,6 +1352,11 @@ int lvmcache_label_rescan_vg(struct cmd_context *cmd, const char *vgname, const
label_scan_devs(cmd, cmd->filter, &devs);
dm_list_iterate_items_safe(devl, devl2, &devs) {
dm_list_del(&devl->list);
dm_free(devl);
}
if (!(vginfo = lvmcache_vginfo_from_vgname(vgname, vgid))) {
log_warn("VG info not found after rescan of %s", vgname);
return 0;
@ -1439,10 +1474,17 @@ int lvmcache_label_scan(struct cmd_context *cmd)
dm_list_iterate_items(devl, &add_cache_devs) {
log_debug_cache("Rescan preferred device %s for lvmcache", dev_name(devl->dev));
label_read(devl->dev, NULL, UINT64_C(0));
label_read(devl->dev);
}
dm_list_splice(&_unused_duplicate_devs, &del_cache_devs);
/*
* We might want to move the duplicate device warnings until
* after this filtering so that we can skip warning about
* duplicates that we are filtering out.
*/
_filter_duplicate_devs(cmd);
}
/* Perform any format-specific scanning e.g. text files */
@ -1630,7 +1672,7 @@ const char *lvmcache_pvid_from_devname(struct cmd_context *cmd,
return NULL;
}
if (!(label_read(dev, NULL, UINT64_C(0))))
if (!label_read(dev))
return NULL;
return dev->pvid;
@ -1714,6 +1756,7 @@ void lvmcache_del(struct lvmcache_info *info)
info->label->labeller->ops->destroy_label(info->label->labeller,
info->label);
label_destroy(info->label);
dm_free(info);
}
@ -2457,15 +2500,6 @@ void lvmcache_destroy(struct cmd_context *cmd, int retain_orphans, int reset)
}
}
int lvmcache_pvid_is_locked(const char *pvid) {
struct lvmcache_info *info;
info = lvmcache_info_from_pvid(pvid, NULL, 0);
if (!info || !info->vginfo)
return 0;
return lvmcache_vgname_is_locked(info->vginfo->vgname);
}
int lvmcache_fid_add_mdas(struct lvmcache_info *info, struct format_instance *fid,
const char *id, int id_len)
{

View File

@ -132,7 +132,6 @@ struct dm_list *lvmcache_get_pvids(struct cmd_context *cmd, const char *vgname,
void lvmcache_drop_metadata(const char *vgname, int drop_precommitted);
void lvmcache_commit_metadata(const char *vgname);
int lvmcache_pvid_is_locked(const char *pvid);
int lvmcache_fid_add_mdas(struct lvmcache_info *info, struct format_instance *fid,
const char *id, int id_len);
int lvmcache_fid_add_mdas_pv(struct lvmcache_info *info, struct format_instance *fid);

View File

@ -768,7 +768,7 @@ cfg(global_activation_CFG, "activation", global_CFG_SECTION, 0, CFG_TYPE_BOOL, D
"the error messages.\n")
cfg(global_fallback_to_lvm1_CFG, "fallback_to_lvm1", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, 0, vsn(1, 0, 18), NULL, 0, NULL,
"This setting setting no longer used.\n")
"This setting is no longer used.\n")
cfg(global_format_CFG, "format", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_FORMAT, vsn(1, 0, 0), NULL, 0, NULL,
"This setting is no longer used.\n")

View File

@ -15,7 +15,7 @@
#define _GNU_SOURCE
#include "lib/device/bcache.h"
#include "device_mapper/misc/dm-logging.h"
#include "lib/log/lvm-logging.h"
#include "lib/log/log.h"
#include <errno.h>
@ -667,6 +667,7 @@ static void _issue_low_level(struct block *b, enum dir d)
b->io_dir = d;
_set_flags(b, BF_IO_PENDING);
cache->nr_io_pending++;
dm_list_move(&cache->io_pending, &b->list);

View File

@ -73,7 +73,6 @@ static void _dev_init(struct device *dev, int max_error_count)
dev->ext.src = DEV_EXT_NONE;
dm_list_init(&dev->aliases);
dm_list_init(&dev->open_list);
}
void dev_destroy_file(struct device *dev)

View File

@ -16,7 +16,6 @@
#include "lib/misc/lib.h"
#include "lib/device/device.h"
#include "lib/metadata/metadata.h"
#include "lib/cache/lvmcache.h"
#include "lib/mm/memlock.h"
#include "lib/locking/locking.h"
@ -53,7 +52,6 @@
# endif
#endif
static DM_LIST_INIT(_open_devices);
static unsigned _dev_size_seqno = 1;
static const char *_reasons[] = {
@ -199,7 +197,7 @@ int dev_get_block_size(struct device *dev, unsigned int *physical_block_size, un
*physical_block_size = (unsigned int) dev->phys_block_size;
*block_size = (unsigned int) dev->block_size;
out:
if (needs_open && !dev_close(dev))
if (needs_open && !dev_close_immediate(dev))
stack;
return r;
@ -349,7 +347,7 @@ static int _dev_get_size_dev(struct device *dev, uint64_t *size)
if (ioctl(fd, BLKGETSIZE64, size) < 0) {
log_sys_error("ioctl BLKGETSIZE64", name);
if (do_close && !dev_close(dev))
if (do_close && !dev_close_immediate(dev))
log_sys_error("close", name);
return 0;
}
@ -360,7 +358,7 @@ static int _dev_get_size_dev(struct device *dev, uint64_t *size)
log_very_verbose("%s: size is %" PRIu64 " sectors", name, *size);
if (do_close && !dev_close(dev))
if (do_close && !dev_close_immediate(dev))
log_sys_error("close", name);
return 1;
@ -380,7 +378,7 @@ static int _dev_read_ahead_dev(struct device *dev, uint32_t *read_ahead)
if (ioctl(dev->fd, BLKRAGET, &read_ahead_long) < 0) {
log_sys_error("ioctl BLKRAGET", dev_name(dev));
if (!dev_close(dev))
if (!dev_close_immediate(dev))
stack;
return 0;
}
@ -391,7 +389,7 @@ static int _dev_read_ahead_dev(struct device *dev, uint32_t *read_ahead)
log_very_verbose("%s: read_ahead is %u sectors",
dev_name(dev), *read_ahead);
if (!dev_close(dev))
if (!dev_close_immediate(dev))
stack;
return 1;
@ -412,13 +410,13 @@ static int _dev_discard_blocks(struct device *dev, uint64_t offset_bytes, uint64
if (ioctl(dev->fd, BLKDISCARD, &discard_range) < 0) {
log_error("%s: BLKDISCARD ioctl at offset %" PRIu64 " size %" PRIu64 " failed: %s.",
dev_name(dev), offset_bytes, size_bytes, strerror(errno));
if (!dev_close(dev))
if (!dev_close_immediate(dev))
stack;
/* It doesn't matter if discard failed, so return success. */
return 1;
}
if (!dev_close(dev))
if (!dev_close_immediate(dev))
stack;
return 1;
@ -597,8 +595,6 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet)
if ((flags & O_CREAT) && !(flags & O_TRUNC))
dev->end = lseek(dev->fd, (off_t) 0, SEEK_END);
dm_list_add(&_open_devices, &dev->open_list);
log_debug_devs("Opened %s %s%s%s", dev_name(dev),
dev->flags & DEV_OPENED_RW ? "RW" : "RO",
dev->flags & DEV_OPENED_EXCL ? " O_EXCL" : "",
@ -650,7 +646,6 @@ static void _close(struct device *dev)
dev->fd = -1;
dev->phys_block_size = -1;
dev->block_size = -1;
dm_list_del(&dev->open_list);
log_debug_devs("Closed %s", dev_name(dev));
@ -678,9 +673,7 @@ static int _dev_close(struct device *dev, int immediate)
log_debug_devs("%s: Immediate close attempt while still referenced",
dev_name(dev));
/* Close unless device is known to belong to a locked VG */
if (immediate ||
(dev->open_count < 1 && !lvmcache_pvid_is_locked(dev->pvid)))
if (immediate || (dev->open_count < 1))
_close(dev);
return 1;
@ -696,18 +689,6 @@ int dev_close_immediate(struct device *dev)
return _dev_close(dev, 1);
}
void dev_close_all(void)
{
struct dm_list *doh, *doht;
struct device *dev;
dm_list_iterate_safe(doh, doht, &_open_devices) {
dev = dm_list_struct_base(doh, struct device, open_list);
if (dev->open_count < 1)
_close(dev);
}
}
static inline int _dev_is_valid(struct device *dev)
{
return (dev->max_error_count == NO_DEV_ERROR_COUNT_LIMIT ||

View File

@ -134,8 +134,7 @@ static int _native_dev_is_md(struct device *dev, uint64_t *offset_found, int ful
* Those checks can't be satisfied with the initial bcache data, and
* would require an extra read i/o at the end of every device. Issuing
* an extra read to every device in every command, just to check for
* the old md format is a bad tradeoff. It's also not a big issue if
* one happens to exist and we don't filter it out.
* the old md format is a bad tradeoff.
*
* When "full" is set, we check a the start and end of the device for
* md magic numbers. When "full" is not set, we only check at the
@ -143,6 +142,13 @@ static int _native_dev_is_md(struct device *dev, uint64_t *offset_found, int ful
* command if it should do a full check (cmd->use_full_md_check),
* and set it for commands that could possibly write to an md dev
* (pvcreate/vgcreate/vgextend).
*
* For old md versions with magic numbers at the end of devices,
* the md dev components won't be filtered out here when full is 0,
* so they will be scanned, and appear as duplicate PVs in lvmcache.
* The md device itself will be chosen as the primary duplicate,
* and the components are dropped from the list of duplicates in,
* i.e. a kind of post-scan filtering.
*/
if (!full) {
sb_offset = 0;

View File

@ -215,6 +215,9 @@ int dev_subsystem_part_major(struct dev_types *dt, struct device *dev)
if (MAJOR(dev->dev) == dt->device_mapper_major)
return 1;
if (MAJOR(dev->dev) == dt->md_major)
return 1;
if (MAJOR(dev->dev) == dt->drbd_major)
return 1;

View File

@ -74,7 +74,6 @@ struct device {
unsigned size_seqno;
uint64_t size;
uint64_t end;
struct dm_list open_list;
struct dev_ext ext;
const char *vgid; /* if device is an LV */
@ -144,7 +143,6 @@ int dev_open_readonly_buffered(struct device *dev);
int dev_open_readonly_quiet(struct device *dev);
int dev_close(struct device *dev);
int dev_close_immediate(struct device *dev);
void dev_close_all(void);
int dev_test_excl(struct device *dev);
int dev_fd(struct device *dev);

View File

@ -251,9 +251,11 @@ static bool _in_bcache(struct device *dev)
static struct labeller *_find_lvm_header(struct device *dev,
char *scan_buf,
uint32_t scan_buf_sectors,
char *label_buf,
uint64_t *label_sector,
uint64_t scan_sector)
uint64_t block_sector,
uint64_t start_sector)
{
struct labeller_i *li;
struct labeller *labeller_ret = NULL;
@ -266,25 +268,34 @@ static struct labeller *_find_lvm_header(struct device *dev,
* and copy it into label_buf.
*/
for (sector = 0; sector < LABEL_SCAN_SECTORS;
for (sector = start_sector; sector < start_sector + LABEL_SCAN_SECTORS;
sector += LABEL_SIZE >> SECTOR_SHIFT) {
/*
* The scan_buf passed in is a bcache block, which is
* BCACHE_BLOCK_SIZE_IN_SECTORS large. So if start_sector is
* one of the last couple sectors in that buffer, we need to
* break early.
*/
if (sector >= scan_buf_sectors)
break;
lh = (struct label_header *) (scan_buf + (sector << SECTOR_SHIFT));
if (!strncmp((char *)lh->id, LABEL_ID, sizeof(lh->id))) {
if (found) {
log_error("Ignoring additional label on %s at sector %llu",
dev_name(dev), (unsigned long long)(sector + scan_sector));
dev_name(dev), (unsigned long long)(block_sector + sector));
}
if (xlate64(lh->sector_xl) != sector + scan_sector) {
log_very_verbose("%s: Label for sector %llu found at sector %llu - ignoring.",
dev_name(dev),
(unsigned long long)xlate64(lh->sector_xl),
(unsigned long long)(sector + scan_sector));
if (xlate64(lh->sector_xl) != sector) {
log_warn("%s: Label for sector %llu found at sector %llu - ignoring.",
dev_name(dev),
(unsigned long long)xlate64(lh->sector_xl),
(unsigned long long)(block_sector + sector));
continue;
}
if (calc_crc(INITIAL_CRC, (uint8_t *)&lh->offset_xl, LABEL_SIZE -
((uint8_t *) &lh->offset_xl - (uint8_t *) lh)) !=
xlate32(lh->crc_xl)) {
if (calc_crc(INITIAL_CRC, (uint8_t *)&lh->offset_xl,
LABEL_SIZE - ((uint8_t *) &lh->offset_xl - (uint8_t *) lh)) != xlate32(lh->crc_xl)) {
log_very_verbose("Label checksum incorrect on %s - ignoring", dev_name(dev));
continue;
}
@ -293,14 +304,14 @@ static struct labeller *_find_lvm_header(struct device *dev,
}
dm_list_iterate_items(li, &_labellers) {
if (li->l->ops->can_handle(li->l, (char *) lh, sector + scan_sector)) {
if (li->l->ops->can_handle(li->l, (char *) lh, block_sector + sector)) {
log_very_verbose("%s: %s label detected at sector %llu",
dev_name(dev), li->name,
(unsigned long long)(sector + scan_sector));
(unsigned long long)(block_sector + sector));
if (found) {
log_error("Ignoring additional label on %s at sector %llu",
dev_name(dev),
(unsigned long long)(sector + scan_sector));
(unsigned long long)(block_sector + sector));
continue;
}
@ -309,7 +320,7 @@ static struct labeller *_find_lvm_header(struct device *dev,
memcpy(label_buf, lh, LABEL_SIZE);
if (label_sector)
*label_sector = sector + scan_sector;
*label_sector = block_sector + sector;
break;
}
}
@ -329,7 +340,9 @@ static struct labeller *_find_lvm_header(struct device *dev,
* are performed in the processing functions to get that data.
*/
static int _process_block(struct cmd_context *cmd, struct dev_filter *f,
struct device *dev, struct block *bb, int *is_lvm_device)
struct device *dev, struct block *bb,
uint64_t block_sector, uint64_t start_sector,
int *is_lvm_device)
{
char label_buf[LABEL_SIZE] __attribute__((aligned(8)));
struct label *label = NULL;
@ -345,7 +358,7 @@ static int _process_block(struct cmd_context *cmd, struct dev_filter *f,
* data had been read (here). They set this flag to indicate that the
* filters should be retested now that data from the device is ready.
*/
if (cmd && (dev->flags & DEV_FILTER_AFTER_SCAN)) {
if (f && (dev->flags & DEV_FILTER_AFTER_SCAN)) {
dev->flags &= ~DEV_FILTER_AFTER_SCAN;
log_debug_devs("Scan filtering %s", dev_name(dev));
@ -374,7 +387,7 @@ static int _process_block(struct cmd_context *cmd, struct dev_filter *f,
* FIXME: we don't need to copy one sector from bb->data into label_buf,
* we can just point label_buf at one sector in ld->buf.
*/
if (!(labeller = _find_lvm_header(dev, bb->data, label_buf, &sector, 0))) {
if (!(labeller = _find_lvm_header(dev, bb->data, BCACHE_BLOCK_SIZE_IN_SECTORS, label_buf, &sector, block_sector, start_sector))) {
/*
* Non-PVs exit here
@ -567,7 +580,7 @@ static int _scan_list(struct cmd_context *cmd, struct dev_filter *f,
} else {
log_debug_devs("Processing data from device %s fd %d block %p", dev_name(devl->dev), devl->dev->bcache_fd, bb);
ret = _process_block(cmd, f, devl->dev, bb, &is_lvm_device);
ret = _process_block(cmd, f, devl->dev, bb, 0, 0, &is_lvm_device);
if (!ret && is_lvm_device) {
log_debug_devs("Scan failed to process %s", dev_name(devl->dev));
@ -610,32 +623,46 @@ static int _scan_list(struct cmd_context *cmd, struct dev_filter *f,
return 1;
}
/*
* How many blocks to set up in bcache? Is 1024 a good max?
*
* Currently, we tell bcache to set up N blocks where N
* is the number of devices that are going to be scanned.
* Reasons why this number may not be be a good choice:
*
* - there may be a lot of non-lvm devices, which
* would make this number larger than necessary
*
* - each lvm device may use more than one cache
* block if the metadata is large enough or it
* uses more than one metadata area, which
* would make this number smaller than it
* should be for the best performance.
*
* This is even more tricky to estimate when lvmetad
* is used, because it's hard to predict how many
* devs might need to be scanned when using lvmetad.
* This currently just sets up bcache with MIN blocks.
*/
#define MIN_BCACHE_BLOCKS 32
#define MAX_BCACHE_BLOCKS 1024
static int _setup_bcache(int cache_blocks)
{
struct io_engine *ioe;
/* No devices can happen, just create bcache with any small number. */
if (cache_blocks < MIN_BCACHE_BLOCKS)
cache_blocks = MIN_BCACHE_BLOCKS;
/*
* 100 is arbitrary, it's the max number of concurrent aio's
* possible, i.e, the number of devices that can be read at
* once. Should this be configurable?
*/
if (cache_blocks > MAX_BCACHE_BLOCKS)
cache_blocks = MAX_BCACHE_BLOCKS;
if (!(ioe = create_async_io_engine())) {
log_error("Failed to create bcache io engine.");
return 0;
}
/*
* Configure one cache block for each device on the system.
* We won't generally need to cache that many because some
* of the devs will not be lvm devices, and we don't need
* an entry for those. We might want to change this.
*/
if (!(scan_bcache = bcache_create(BCACHE_BLOCK_SIZE_IN_SECTORS, cache_blocks, ioe))) {
log_error("Failed to create bcache with %d cache blocks.", cache_blocks);
return 0;
@ -653,7 +680,7 @@ int label_scan(struct cmd_context *cmd)
{
struct dm_list all_devs;
struct dev_iter *iter;
struct device_list *devl;
struct device_list *devl, *devl2;
struct device *dev;
log_debug_devs("Finding devices to scan");
@ -695,16 +722,17 @@ int label_scan(struct cmd_context *cmd)
log_debug_devs("Found %d devices to scan", dm_list_size(&all_devs));
if (!scan_bcache) {
/*
* FIXME: there should probably be some max number of
* cache blocks we use when setting up bcache.
*/
if (!_setup_bcache(dm_list_size(&all_devs)))
return 0;
}
_scan_list(cmd, cmd->full_filter, &all_devs, NULL);
dm_list_iterate_items_safe(devl, devl2, &all_devs) {
dm_list_del(&devl->list);
dm_free(devl);
}
return 1;
}
@ -834,9 +862,7 @@ void label_scan_destroy(struct cmd_context *cmd)
* device, this is not a commonly used function.
*/
/* FIXME: remove unused_sector arg */
int label_read(struct device *dev, struct label **labelp, uint64_t unused_sector)
int label_read(struct device *dev)
{
struct dm_list one_dev;
struct device_list *devl;
@ -856,17 +882,7 @@ int label_read(struct device *dev, struct label **labelp, uint64_t unused_sector
_scan_list(NULL, NULL, &one_dev, &failed);
/*
* FIXME: this ugliness of returning a pointer to the label is
* temporary until the callers can be updated to not use this.
*/
if (labelp) {
struct lvmcache_info *info;
info = lvmcache_info_from_pvid(dev->pvid, dev, 1);
if (info)
*labelp = lvmcache_get_label(info);
}
dm_free(devl);
if (failed)
return 0;
@ -875,25 +891,66 @@ int label_read(struct device *dev, struct label **labelp, uint64_t unused_sector
/*
* Read a label from a specfic, non-zero sector. This is used in only
* one place: pvck -> pv_analyze.
* one place: pvck/pv_analyze.
*/
int label_read_sector(struct device *dev, struct label **labelp, uint64_t scan_sector)
int label_read_sector(struct device *dev, uint64_t read_sector)
{
if (scan_sector) {
/* TODO: not yet implemented */
/* When is this done? When does it make sense? Is it actually possible? */
return 0;
struct block *bb = NULL;
uint64_t block_num;
uint64_t block_sector;
uint64_t start_sector;
int is_lvm_device = 0;
int result;
int ret;
block_num = read_sector / BCACHE_BLOCK_SIZE_IN_SECTORS;
block_sector = block_num * BCACHE_BLOCK_SIZE_IN_SECTORS;
start_sector = read_sector % BCACHE_BLOCK_SIZE_IN_SECTORS;
label_scan_open(dev);
bcache_prefetch(scan_bcache, dev->bcache_fd, block_num);
if (!bcache_get(scan_bcache, dev->bcache_fd, block_num, 0, &bb)) {
log_error("Scan failed to read %s at %llu",
dev_name(dev), (unsigned long long)block_num);
ret = 0;
goto out;
}
return label_read(dev, labelp, 0);
/*
* TODO: check if scan_sector is larger than the bcache block size.
* If it is, we need to fetch a later block from bcache.
*/
result = _process_block(NULL, NULL, dev, bb, block_sector, start_sector, &is_lvm_device);
if (!result && is_lvm_device) {
log_error("Scan failed to process %s", dev_name(dev));
ret = 0;
goto out;
}
if (!result || !is_lvm_device) {
log_error("Could not find LVM label on %s", dev_name(dev));
ret = 0;
goto out;
}
ret = 1;
out:
if (bb)
bcache_put(bb);
return ret;
}
/*
* This is only needed when commands are using lvmetad, in which case they
* don't do an initial label_scan, but may later need to rescan certain devs
* from disk and call this function. FIXME: is there some better number to
* choose here?
* choose here? How should we predict the number of devices that might need
* scanning when using lvmetad?
*/
int label_scan_setup_bcache(void)
@ -922,18 +979,10 @@ int label_scan_open(struct device *dev)
bool dev_read_bytes(struct device *dev, uint64_t start, size_t len, void *data)
{
int ret;
if (!scan_bcache) {
if (!dev_open_readonly(dev))
return false;
ret = dev_read(dev, start, len, 0, data);
if (!dev_close(dev))
stack;
return ret ? true : false;
/* Should not happen */
log_error("dev_read bcache not set up %s", dev_name(dev));
return false;
}
if (dev->bcache_fd <= 0) {
@ -956,21 +1005,13 @@ bool dev_read_bytes(struct device *dev, uint64_t start, size_t len, void *data)
bool dev_write_bytes(struct device *dev, uint64_t start, size_t len, void *data)
{
int ret;
if (test_mode())
return true;
if (!scan_bcache) {
if (!dev_open(dev))
return false;
ret = dev_write(dev, start, len, 0, data);
if (!dev_close(dev))
stack;
return ret ? true : false;
/* Should not happen */
log_error("dev_write bcache not set up %s", dev_name(dev));
return false;
}
if (dev->bcache_fd <= 0) {
@ -1003,7 +1044,7 @@ bool dev_write_zeros(struct device *dev, uint64_t start, size_t len)
return true;
if (!scan_bcache) {
log_error("dev_write_zeros %s bcache not set up", dev_name(dev));
log_error("dev_write_zeros bcache not set up %s", dev_name(dev));
return false;
}
@ -1037,7 +1078,7 @@ bool dev_set_bytes(struct device *dev, uint64_t start, size_t len, uint8_t val)
return true;
if (!scan_bcache) {
log_error("dev_set_bytes %s bcache not set up", dev_name(dev));
log_error("dev_set_bytes bcache not set up %s", dev_name(dev));
return false;
}

View File

@ -109,8 +109,8 @@ void label_scan_invalidate(struct device *dev);
void label_scan_invalidate_lv(struct cmd_context *cmd, struct logical_volume *lv);
void label_scan_drop(struct cmd_context *cmd);
void label_scan_destroy(struct cmd_context *cmd);
int label_read(struct device *dev, struct label **labelp, uint64_t unused_sector);
int label_read_sector(struct device *dev, struct label **labelp, uint64_t scan_sector);
int label_read(struct device *dev);
int label_read_sector(struct device *dev, uint64_t scan_sector);
void label_scan_confirm(struct device *dev);
int label_scan_setup_bcache(void);
int label_scan_open(struct device *dev);

View File

@ -483,7 +483,6 @@ static int _pvremove_check(struct cmd_context *cmd, const char *name,
{
static const char really_wipe_msg[] = "Really WIPE LABELS from physical volume";
struct device *dev;
struct label *label;
struct pv_list *pvl;
struct physical_volume *pv = NULL;
int used;
@ -498,7 +497,7 @@ static int _pvremove_check(struct cmd_context *cmd, const char *name,
/* Is there a pv here already? */
/* If not, this is an error unless you used -f. */
if (!label_read(dev, &label, 0)) {
if (!label_read(dev)) {
if (force_count)
return 1;
log_error("No PV label found on %s.", name);

View File

@ -4058,7 +4058,7 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
release_vg(correct_vg);
correct_vg = NULL;
lvmcache_del(info);
label_read(pvl->pv->dev, NULL, 0);
label_read(pvl->pv->dev);
goto restart_scan;
}
#endif
@ -5192,8 +5192,6 @@ static struct volume_group *_recover_vg(struct cmd_context *cmd,
unlock_vg(cmd, NULL, vg_name);
dev_close_all();
if (!lock_vol(cmd, vg_name, LCK_VG_WRITE, NULL))
return_NULL;

View File

@ -78,7 +78,6 @@ int exec_cmd(struct cmd_context *cmd, const char *const argv[],
if (!pid) {
/* Child */
reset_locking();
dev_close_all();
/* FIXME Fix effect of reset_locking on cache then include this */
/* destroy_toolcontext(cmd); */
/* FIXME Use execve directly */

View File

@ -186,6 +186,8 @@ int lvm_vg_close(vg_t vg)
struct saved_env e = store_user_env(vg->cmd);
if (vg_read_error(vg) == FAILED_LOCKING)
release_vg(vg);
else if (!lvmcache_vgname_is_locked(vg->name))
release_vg(vg);
else
unlock_and_release_vg(vg->cmd, vg, vg->name);
restore_user_env(&e);

View File

@ -503,7 +503,7 @@ Merge LV images that were split from a raid1 LV.
Convert LV to a thin LV, using the original LV as an external origin.
.br
.P
\fBlvconvert\fP \fB--type\fP \fBthin\fP \fB--thinpool\fP \fILV\fP \fILV\fP\fI_linear_striped_cache_raid\fP
\fBlvconvert\fP \fB--type\fP \fBthin\fP \fB--thinpool\fP \fILV\fP \fILV\fP\fI_linear_striped_thin_cache_raid\fP
.br
.RS 4
.ad l
@ -1530,7 +1530,7 @@ Convert LV to a thin LV, using the original LV as an external origin
(infers --type thin).
.br
.P
\fBlvconvert\fP \fB-T\fP|\fB--thin\fP \fB--thinpool\fP \fILV\fP \fILV\fP\fI_linear_striped_cache_raid\fP
\fBlvconvert\fP \fB-T\fP|\fB--thin\fP \fB--thinpool\fP \fILV\fP \fILV\fP\fI_linear_striped_thin_cache_raid\fP
.br
.RS 4
.ad l
@ -1714,7 +1714,9 @@ origin LV (first arg) to reverse a splitsnapshot command.
.br
-
Poll LV to continue conversion (also see --startpoll).
Poll LV to continue conversion (also see --startpoll)
.br
or waits till conversion/mirror syncing is finished
.br
.P
\fBlvconvert\fP \fILV\fP\fI_mirror_raid\fP

View File

@ -38,7 +38,7 @@ normally prevent it, e.g. if the PV is already in a VG.
.ad b
.br
.ad l
[ \fB-M\fP|\fB--metadatatype\fP \fBlvm2\fP|\fBlvm1\fP ]
[ \fB-M\fP|\fB--metadatatype\fP \fBlvm2\fP ]
.ad b
.br
.ad l
@ -266,12 +266,11 @@ The size may be rounded.
.ad b
.HP
.ad l
\fB-M\fP|\fB--metadatatype\fP \fBlvm2\fP|\fBlvm1\fP
\fB-M\fP|\fB--metadatatype\fP \fBlvm2\fP
.br
Specifies the type of on-disk metadata to use.
\fBlvm2\fP (or just \fB2\fP) is the current, standard format.
\fBlvm1\fP (or just \fB1\fP) is a historical format that
can be used for accessing old data.
\fBlvm1\fP (or just \fB1\fP) is no longer used.
.ad b
.HP
.ad l

View File

@ -51,7 +51,7 @@ vgcfgrestore - Restore volume group configuration
.ad b
.br
.ad l
\fB-M\fP|\fB--metadatatype\fP \fBlvm2\fP|\fBlvm1\fP
\fB-M\fP|\fB--metadatatype\fP \fBlvm2\fP
.ad b
.br
.ad l
@ -141,7 +141,7 @@ Common options for command:
.
.RS 4
.ad l
[ \fB-M\fP|\fB--metadatatype\fP \fBlvm2\fP|\fBlvm1\fP ]
[ \fB-M\fP|\fB--metadatatype\fP \fBlvm2\fP ]
.ad b
.br
.ad l
@ -280,12 +280,11 @@ Display long help text.
.ad b
.HP
.ad l
\fB-M\fP|\fB--metadatatype\fP \fBlvm2\fP|\fBlvm1\fP
\fB-M\fP|\fB--metadatatype\fP \fBlvm2\fP
.br
Specifies the type of on-disk metadata to use.
\fBlvm2\fP (or just \fB2\fP) is the current, standard format.
\fBlvm1\fP (or just \fB1\fP) is a historical format that
can be used for accessing old data.
\fBlvm1\fP (or just \fB1\fP) is no longer used.
.ad b
.HP
.ad l

View File

@ -8,12 +8,9 @@ vgconvert - Change volume group metadata format
[ \fIoption_args\fP ]
.br
.SH DESCRIPTION
vgconvert converts VG metadata from one format to another. The new
metadata format must be able to fit into the space provided by the old
vgconvert converts VG metadata from one format to another. This command
is no longer used because this version of lvm no longer supports the LVM1
format.
Because the LVM1 format should no longer be used, this command is no