1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-12-31 12:32:49 +03:00

Compare commits

..

1298 Commits

Author SHA1 Message Date
David Teigland
07338325e5 devices: fix name handling
- Fix cases where incorrect device paths were left
  on the dev->aliases list.  Leaving incorrect paths
  on dev->aliases could result in using the wrong device.

- Fix a widespread incorrect assumption that dev_name()
  always returns a valid path (or NULL).  dev_name()
  returns "[unknown]" when there are no paths to a
  device, and is mainly meant to be used in messages.

- Check for valid dev paths in cases that want to use
  the from dev_name() for things other than a message.
2022-02-24 15:37:53 -06:00
David Teigland
ac1f4bbbfd writecache: display block size from lvs
lvs was missing the ability to display writecache block size.
now possible with lvs -o writecache_block_size
2022-02-21 16:11:13 -06:00
David Teigland
6144dac897 man lvmcache: mention writecache memory usage 2022-02-21 11:35:58 -06:00
David Teigland
96c99d647e man: update cachesettings option description
to be more consistent with man page description
2022-02-16 15:37:54 -06:00
David Teigland
ec2119bedd man lvmcache: add more writecache cachesettings info 2022-02-16 15:21:09 -06:00
Zdenek Kabelac
d4a0816a58 dev_manager: use list info for preset devs
In some cases we can also use cached info obtained from DM_DEVICE_LIST
also to avoid extra ioctl check for present devices.
2022-02-16 01:00:36 +01:00
Zdenek Kabelac
fa7b67eeeb dev_manager: do not query for open_count
Oepn count is not used along this code path.
2022-02-16 01:00:36 +01:00
Zdenek Kabelac
4fd76de4b6 clang: possible better compilation with musl c
Try to help resolving reported compilation problem with
clang & musl C.
https://github.com/lvmteam/lvm2/issues/61
2022-02-16 01:00:36 +01:00
Zdenek Kabelac
d2e7a05573 clang: add extra check
Make clang happier.
2022-02-16 01:00:36 +01:00
Zdenek Kabelac
c2679f76e5 dev_manager: failing status is not internal error
Different target type for LV it's not an internal error.
i.e.  when target type is replaced with 'error' type - it should be
reported as regular warning and not cause interruption of command with
internall error.
2022-02-16 01:00:36 +01:00
Zdenek Kabelac
6ffb150f30 dev_manager: fix dm_task_get_device_list
With very old version of DM target driver we have to avoid
trying to use newuuid setting - otherwise we get error
during ioctl preparation phase.

Patch is fixing regression from commit:
988ea0e94c
2022-02-16 01:00:36 +01:00
David Teigland
6626adb467 tests: skip vgchange-pvs-online.sh on rhel5
the /dev/mapper/ paths to test devices don't seem to work there
2022-02-15 15:56:46 -06:00
David Teigland
d59382c772 devices file: do not clear PVID of unread devices
In a certain disconnected state, a block device is present on
the system, can be opened, reports a valid size, reports the
correct device id (wwid), and matches a devices file entry.
But, reading the device can still fail.  In this case,
device_ids_validate() was misinterpreting the read error as
the device having no data/label on it (and no PVID).
The validate function would then clear the PVID from the
devices file entry for the device, thinking that it was
fixing the devices file (making it consistent with the on disk
state.)  Fix this by not attempting to check and correct a
devices file entry that cannot be read.  Also make this case
explicit in the hints validation code (which was doing the
right thing but indirectly.)
2022-02-10 14:16:04 -06:00
David Teigland
61f23fe15e tests: udev-pvscan-vgchange fix service wait
As a result of removing -r from systemd-run in
commit fbd8b0cf43
this test needs to change how it handles the
transient services.
2022-02-07 16:44:57 -06:00
Zdenek Kabelac
13122bcc33 make: generate 2022-02-07 20:02:11 +01:00
Zdenek Kabelac
f83b3962c1 asan: fix some reports from libasan
When compiled and used with:

CFLAGS="-fsanitize=address -g -O0"
ASAN_OPTIONS=strict_string_checks=1:detect_stack_use_after_return=1:check_initialization_order=1:strict_init_order=1

we have few reported issue - they where not normally spotted, since
we were still accessing our own memory - but ouf of buffer-range.

TODO: there is still something to enhance with handling of #orphan vgids
2022-02-07 20:02:11 +01:00
Marian Csontos
8dccc2314e post-release 2022-02-07 18:02:07 +01:00
Marian Csontos
6987f318ec pre-release 2022-02-07 18:00:54 +01:00
David Teigland
563105bba9 tests: devicesfile-edit
test lvmdevices add/del
2022-02-03 16:58:12 -06:00
David Teigland
3fce6a81f8 lvmdevices: make deldev work for missing device 2022-02-03 16:56:03 -06:00
David Teigland
f0cd54a873 writecache: look for settings in lvm.conf
Restore the lvm.conf cache_settings for writecache
added by c6639056e0.
Shorter method reduces and isolates the complexity
of config trees.
2022-01-31 16:59:37 -06:00
David Teigland
ffa07c8e39 Revert "writecache: handle options from lvm.conf"
This reverts commit c6639056e0.

Next commit restores this feature.
2022-01-31 16:54:40 -06:00
Zdenek Kabelac
208af8db2a tests: skip test part when missed in kernel 2022-01-31 15:11:47 +01:00
Zdenek Kabelac
b36fce26a2 activation: use lv_is_active
Use existing lv_is_active
2022-01-31 14:56:11 +01:00
Zdenek Kabelac
f8d12913e7 tools: missing sync after deactivation
Caching of DM states optimisation revealed some missing
synchronisation points.
2022-01-31 14:55:42 +01:00
Martin Wilck
e10f67e917 udev: create symlinks and watch even in suspended state
If a dm device is suspended, we can't run blkid on it. But earlier
rules (e.g. 11-dm-parts.rules) might have imported previously scanned
properties from the udev db, in particular if the device had been correctly
set up beforehand (DM_UDEV_PRIMARY_SOURCE_FLAG==1). Symlinks for existing
ID_FS_xyz properties must be preserved in this case. Otherwise lower-priority
devices (such as multipath components) might take over the symlink
temporarily.

Likewise, we should't stop watching a temporarily suspended, but previously
correctly configured dm device.

Signed-off-by: Martin Wilck <mwilck@suse.com>
2022-01-31 14:55:20 +01:00
David Teigland
ee8fb0310c remove static autoactivation
event based autoactivation is now the only method that lvm
provides for autoactivation.

Setting lvm.conf event_activation=0 can still be used to disable
event based autoactivation commands, but doing so will no longer
enable static autoactivation.
2022-01-27 16:43:11 -06:00
Zdenek Kabelac
a425729da9 test: remove leaked exit 2022-01-26 15:32:30 +01:00
Zdenek Kabelac
62f11b0b0b gcc: increate buffer sizes
Make all possible string buffers to fit so they are not shortened in the
middle.
2022-01-26 15:09:58 +01:00
Zdenek Kabelac
cf68bf7b6c gcc: snprintf may need here upto 18 bytes
Although hypothetical case....
2022-01-26 15:09:58 +01:00
Zdenek Kabelac
7f1f7ad694 lvcreate: code move 2022-01-26 15:09:58 +01:00
Zdenek Kabelac
89cec5b65a test: check writecache profile support
FIXME
2022-01-26 15:09:58 +01:00
Zdenek Kabelac
b95506815f man: doc writecache profile support 2022-01-26 15:09:58 +01:00
Zdenek Kabelac
d8dbabb28e lvcreate: cachesettings works also with writecache 2022-01-26 15:09:58 +01:00
Zdenek Kabelac
a06ccdf44b lvcreate: fix crash for unspecified LV name for writecache
Fix aplication crash when creating writecached LV with 'automatic' name.
2022-01-26 15:09:58 +01:00
Zdenek Kabelac
c6639056e0 writecache: handle options from lvm.conf
User can place default settings into lvm.conf i.e.:

allocation {
	cache_settings {
		writecache {
			block_size = 4096
		}
	}
}
2022-01-26 15:09:58 +01:00
David Teigland
8f50c5e79b lvmdevices: fix checks when adding entries
Removes some incorrect and unnecessary checks for other entries
when adding a new devices.  The removed checks and corrections were
mostly redundant with what is already done by device id matching.
Other checking is reworked so the warnings are a bit different.
2022-01-25 15:18:29 -06:00
David Teigland
9e9f02acf0 device_id: fix search for renamed device when the wwid is ignored
When a device has a wwid (from sysfs), but lvm ignores the wwid,
e.g. because it contains an unreliable "QEMU" value, then lvm
falls back to using IDTYPE=devname (the device name) as the
device id.  If the device name changes after reboot, then lvm
automatically searches for the PV on other devices to find the
new device name and correct system.devices.  When searching for
the PV, lvm skips looking at devices that would use other id types,
e.g. if a device would use a wwid and not a devname, then it
skips checking it.  However, it failed to account for the fact
that a device may have wwid that was ignored, in which case it
should be checked.
2022-01-25 10:47:50 -06:00
David Teigland
de7892f0af Revert "pvcreate: overwrite partition header with -f"
This reverts commit d5a950ca67.

This commit did not properly recognize GPT cases.
2022-01-18 12:15:03 -06:00
David Teigland
a972d63c54 lvmdevices check: error exit if update is needed
. error exit means that lvmdevices --update would make a change.

. remove check of PART field from --check because it isn't used.

. unlink searched_devnames file to ensure check|update will search
2022-01-14 14:59:28 -06:00
David Teigland
d5a950ca67 pvcreate: overwrite partition header with -f
$ pvcreate /dev/sdc
  Cannot use /dev/sdc: device is partitioned
$ pvcreate -f /dev/sdc
  Physical volume "/dev/sdc" successfully created.
2022-01-14 13:57:20 -06:00
David Teigland
0c80ea8847 remove unused variable
resulting from commit cb798ee1c1
  "lvmcache: remove lvmcache_update_vg_from_write"
2022-01-13 11:41:39 -06:00
David Teigland
18f451e09e handle duplicate vgids
The approach to duplicate VGIDs has been that it is not possible
or not allowed, so the behavior has been undefined.  The actual
result was unpredictable and/or broken, and generally unhelpful.

Improve this by recognizing the problem, displaying the VGs,
and printing a warning to fix the problem.  Beyond this,
using VGs with duplicate VGIDs remains undefined, but should
work well enough to correct the problem with vgchange -u.

It's possible to create this condition without too much difficulty
by cloning PVs, followed by an incomplete attempt at making the two
VGs unique (vgrename and pvchange -u, but missing vgchange -u.)
2022-01-13 10:01:24 -06:00
David Teigland
cb798ee1c1 lvmcache: remove lvmcache_update_vg_from_write
After a vg_write, this function was used to attempt to
make lvmcache data match the new state written to disk.
It was not updated correctly in a many or most cases,
and the resulting lvmcache is not actually used after
vg_write, making the update unnecessary.
2022-01-13 10:01:16 -06:00
David Teigland
5e428d22d9 vgsplit: don't reread vg_to
The destination vg is first written with the EXPORTED flag,
then the source vg is written, then the destination vg is
written again without the EXPORTED flag.  Remove an unnecessary
vg_read of the destination vg just before the second write.
2022-01-12 16:42:01 -06:00
David Teigland
7502f78678 Revert "handle duplicate vgids"
This reverts commit bd2baeaaa6.

This commit broke vgrename because vgrename relies on old bugs
in lvmcache_update_vg_from_write and lvmcache_update_vgname
which need to be fixed first.
2022-01-11 16:04:51 -06:00
David Teigland
bd2baeaaa6 handle duplicate vgids
The approach to duplicate VGIDs has been that it is not possible
or not allowed, so the behavior has been undefined.  The actual
result was unpredictable and/or broken, and generally unhelpful.

Improve this by recognizing the problem, displaying the VGs,
and printing a warning to fix the problem.  Beyond this,
using VGs with duplicate VGIDs remains undefined, but should
work well enough to correct the problem with vgchange -u.

It's possible to create this condition without too much difficulty
by cloning PVs, followed by an incomplete attempt at making the two
VGs unique (vgrename and pvchange -u, but missing vgchange -u.)
2022-01-06 10:15:16 -06:00
David Teigland
42a16aa6f3 lvmlockd: cleanup after sanlock_rem_lockspace error
When storage is lost under a sanlock VG, and kill_vg/drop_vg
are used, sanlock_rem_lockspace() may return an error, but
the cleanup steps should still be performed.  Without the
cleanup, gl_lsname_sanlock was not cleared.  This caused
future lock requests to fail with ENOLS, but the NO_GL_LS
flag was not set due to gl_lsname_sanlock being set.
This caused lockd_global(sh) in lvm commands to fail when
they could succeed.

Fix from guozhonghua216
2022-01-04 14:53:47 -06:00
Zdenek Kabelac
04fbffb116 label: cache dm device list
Since we check for present DM devices - cache result for
futher use of checking presence of such device.

lvm2 uses cache result for label scan, but also when
it tries to activate or deactivate LV - however only simple
target 'striped' is reasonably supported.

Use disable_dm_devs to be able to control when lv_info()
get cache or uncached results.

TODO: support more type, however this is getting very complicated.
2021-12-20 16:13:28 +01:00
Zdenek Kabelac
0d67bc96fd activate: add get_device_list
Add funtion get_device_list() to get list of active DM devices.
Handled through new dm_task_get_device_list().
2021-12-20 16:13:28 +01:00
Zdenek Kabelac
988ea0e94c devicemapper: add dm_task_get_device_list
New API extension (internal ATM) for getting a list
of active DM device with extra features like i.e. uuid.

To easily lookout for existing UUID in device list,
there is: dm_device_list_find_by_uuid()

Once the returned structure is no longer usable call:
dm_device_list_destroy()

Struct dm_active_device {} holds all the info,
but is always allocated and destroyed within library.

TODO: once it's stable, copy to libdm
2021-12-20 16:13:28 +01:00
Zdenek Kabelac
90da953fd2 libdm: unmangling UUID for DM_DEVICE_LIST
Properly unmangle UUID if they are provided as result
of DM_DEVICE_LIST ioctl on newer linux kernels.
2021-12-20 16:13:28 +01:00
Zdenek Kabelac
65236ee722 activate: device_is_usable
Move checking of usable uuid into separate function
and pass in also cmd context.
2021-12-20 16:13:28 +01:00
Zdenek Kabelac
5a78979b68 lvmcmdline: comment reset of configuration settings
We used to reset 'settings' to their defaults after command is finished.
This however has a drawback we lose all the logging after this point.

So this patch disables this 'reset' to observe for side-effects.

lvm shell should be getting reset when next command is run -
so this might or might not have some 'hidden' effects.

ATM it looks like nothing really bad should happen - we just should be
able to get more logs - at least from normal commands.
2021-12-20 16:13:28 +01:00
Zdenek Kabelac
39a121ddbc libdm: correct version check
If there ever would be API version 5,
these check would give incorrect results.
2021-12-20 16:13:28 +01:00
Zdenek Kabelac
47ac2659d5 activate: cache driver_version result 2021-12-20 16:13:28 +01:00
Zdenek Kabelac
26e6580dfb toolcontext: reuse destroy_config_context
Call existing destroy_config_context() to destroy
some parts of cmd_context.
2021-12-20 16:13:28 +01:00
Zdenek Kabelac
09a4b56895 hash: raise hash table size
With slightly bigger hash tables, there is considerable
less hash collisions.
2021-12-20 16:13:28 +01:00
Zdenek Kabelac
ed1651d11f toollib: avoid repeated remove of online vg
Call just once unlink after every deactivation of LV from VG.
2021-12-20 16:13:28 +01:00
Andrew Walsh
522561e64b vdo: ensure VDO config is removed
Make sure to remove the VDO config after conversion
of LVM-backed VDO.

Addresses point 3 in rhbz#1987024#c5
2021-12-20 16:13:28 +01:00
David Teigland
0f71183f94 man lvmautoactivation: replace systemctl with journalctl 2021-12-14 12:02:08 -06:00
David Teigland
fbd8b0cf43 udev: remove -r from systemd-run
If the transient service remains after it's done, then
it prevents the same transient service from being run
again later if the PVs are detached and reattached
(although the behavior of a second autoactivation is not
well defined and may only work in limited cases.)
2021-12-14 11:57:13 -06:00
наб
6a431eb242 devices: recognise rbd (ceph rados block device)
Description stolen from linux d/b/rbd.c L3:
  rbd.c -- Export ceph rados objects as a Linux block device

16 partitions seem to make sense according to L90:
  #define RBD_SINGLE_MAJOR_PART_SHIFT 4

Running *scan -vvvvvvdddddd yields
  #filters/filter-type.c:28            /dev/rbd1p5: Skipping: Unrecognised LVM device type 252
  #filters/filter-persistent.c:131           filter caching bad /dev/rbd1p5
right now, and adding
  types = ["rbd", 252]
to /e/l/lvm.conf (with the matching "252 rbd" in /p/devices) works as a
per-machine fix:
  rbd1               252:16   0      1T  1 disk
  |-rbd1p1           252:17   0    243M  1 part
  |-rbd1p2           252:18   0      1K  1 part
  `-rbd1p5           252:21   0 1023.8G  1 part
    `-dev01--vg-root 253:0    0 1023.8G  0 lvm
but rbd is supported by upstream so it'd be nice to have it work OOB
2021-12-13 13:32:06 -06:00
David Teigland
c28541eccd lvcreate: include recent options
The permitted option list in lvcreate has not kept
up with command-lines.in.
2021-12-13 08:59:31 -06:00
David Teigland
d803d9202c man: add section about static autoactivation 2021-12-06 13:20:32 -06:00
David Teigland
ae54e75176 device_id: handle wwid with spaces or control characters
non-standard wwid can be reported from sysfs with spaces/etc.
replace with "_"
2021-12-02 13:33:18 -06:00
David Teigland
455c29b10d print warning about unrecognized journal option value 2021-12-02 12:40:52 -06:00
David Teigland
c42a05c3ec pvscan: fix error message for invalid devname
uninitialized name buffer used in message.
fixes "pvs_online: include devname in pvid files"
2021-12-01 14:38:17 -06:00
David Teigland
05d9a01351 pvscan: fix filter symlink checks
Fixes commit "pvscan: match device arg to filter symlink"
which failed to account for the fact that filter entries
are not just path names but include "a" or "r", etc.
2021-12-01 13:42:32 -06:00
David Teigland
d5402e55f6 devices file: don't write in test mode 2021-12-01 10:08:08 -06:00
David Teigland
71e7ebb3e4 tests devicesfile-devname.sh drop mdadm chunk 2021-12-01 08:56:05 -06:00
Marian Csontos
36095ac374 spec: Add lvmautoactivation man page 2021-12-01 15:36:34 +01:00
David Teigland
470b967bc5 pvscan: limit md device_hint for slow autoactivation
The device_hint name in the metadata was meant to prevent
autoactivation from md components, but the name checks were
more general and would catch unnecessary cases.
2021-11-30 09:06:08 -06:00
David Teigland
d12baba1a9 pvscan: match device arg to filter symlink
This fixes an issue related to the optimization in
  "pvscan: only add device args to dev cache"

If the devices file is not used, and the lvm.conf filter
accepts devices via symlink names, then those devices won't
be accepted by pvscan for autoactivation.  To resolve this,
recognize when the filter contains symlinks and disable the
optimization.  When the optimization is disabled, a full
dev_cache_scan is performed, and symlinks are associated
with the device names passed to pvscan.  filter-regex
will accept a device if symlinks to that device are accepted.
2021-11-29 17:13:44 -06:00
David Teigland
009007484b man: lvmautoactivation
new topical man page describing autoactivation
2021-11-29 11:10:02 -06:00
David Teigland
01bf8e1747 devices: exclude md components when duplicate pvs are seen
Improve handling of md components that get through the
filter, like the previous improvement for multipath.
If md components get through the filter and trigger
duplicate PV code, then eliminate any devs entirely
that are not an md device.
2021-11-22 15:10:43 -06:00
David Teigland
114e1cfee5 fix spelling of pruning 2021-11-19 12:02:35 -06:00
David Teigland
212b1fc529 devices: exclude multipath components based on matching wwid
If multipath component devices get through the filter and
cause lvm to see duplicate PVs, then check the wwid of the
devs and drop the component devices as if they had been
filtered.  If a dm mpath device was found among the duplicates
then use that as the PV, otherwise do not use any of the
components as the PV.

"duplicate PVs" associated with multipath configs will no
longer stop commands from working.
2021-11-18 17:41:00 -06:00
David Teigland
b8f4ec846d display: ignore --reportformat
Using the option would do nothing useful but would
print extraneous braces.
2021-11-17 10:40:27 -06:00
David Teigland
e4b8726b6d Revert "tests devicesfile-devname: remove searched_devnames"
This reverts commit 8e61c0ad6e.

The changes from "device_id: searched_devnames improvements"
allow this to work without the external removal.
2021-11-16 14:30:09 -06:00
David Teigland
5c71aa7510 tests pv-ext-flags: work with devices file 2021-11-16 14:29:22 -06:00
David Teigland
5c4ce4669e device_id: searched_devnames improvements
Remove the searched_devnames file in a couple more places:
. When hints need refreshing it's possible that a missing
  devices file entry could be found by searching devices
  again.
. When a devices file entry devname is first found to be
  incorrect, a new search for missing entries may be
  useful.
2021-11-16 14:29:17 -06:00
David Teigland
fee3937002 device_id: fix search on filtered device
When devnames are used as device ids and devnames change,
then new devices need to be located for the PVs.  If the old
devname is now used by a filtered device, this was preventing
the code from searching for the new device, so the PV was
reported as missing.
2021-11-16 09:29:24 -06:00
David Teigland
8e61c0ad6e tests devicesfile-devname: remove searched_devnames
remove /run/lvm/searched_devnames when preparing each test
in case it has appeared on the system
2021-11-15 18:04:10 -06:00
David Teigland
89c54db16c vgchange autoactivation: error path cleanup
If the optimized label scan fails (using online files),
then clear the device state prior to falling back to the
standard label_scan.  This avoids printing output about
unexpected state.
2021-11-15 11:07:11 -06:00
David Teigland
c5f998aec4 device_id: match different dm device names
If a devices file entry for a dm device is using the devname
for the device id, then recognize different dm names as matching.
2021-11-12 16:42:51 -06:00
David Teigland
4926061d32 tests: udev-pvscan-vgchange clear services 2021-11-12 12:10:26 -06:00
David Teigland
66f0fe57c3 online files: fix vgname check
The pvs_online file for a PV will not contain a vgname
if the PV has no metadata, so don't require matching
vgname with the pvs_lookup file.
2021-11-12 11:52:36 -06:00
David Teigland
5dbf316cee pvscan: consistent creation of pvs_lookup file
Consistently create the pvs_lookup file for VGs with
more than one PV.  Previously the file create would be
skipped if all the PVs happened to already be online.
That led to unpredicatable results in an uncommon case
(when the last PV to come online is the only PV with
metadata.)
2021-11-12 11:40:06 -06:00
David Teigland
b945ea1c93 tests vgchange-pvs-online: clean up with devices file
changing the dev names resulted in stale devices file
entries that created noise in the output.
2021-11-11 16:38:10 -06:00
David Teigland
20c550ab10 tests: udev-pvscan-vgchange fix wait
the service now remains after completion
2021-11-11 16:04:24 -06:00
David Teigland
0e0faf30e0 vgchange autoactivation: lock vg early to avoid second label scan
Copy another optimization from pvscan -aay to vgchange -aay.
When using the optimized label scan for only one VG, acquire the
VG lock prior to the scan.  This allows vg_read to then skip the
repeated label scan that normally happens after locking the vg.
2021-11-10 16:50:50 -06:00
David Teigland
92e741eda0 vgchange: move autoactivation setup code
into its own function, no functional change.
2021-11-10 14:44:11 -06:00
David Teigland
d608837b2a filter-sysfs: support old kernels without sys/dev/block
rhel5 for example doesn't have /sys/dev/block
2021-11-09 11:54:48 -06:00
David Teigland
73b4602f21 pvs_online: include devname in pvid files
Include the device name in the /run/lvm/pvs_online/pvid files.
Commands using the pvid file can use the devname to more quickly
find the correct device, vs finding the device using the
major:minor number.  If the devname in the pvid file is missing
or incorrect, fall back to using the devno.
2021-11-09 11:26:26 -06:00
David Teigland
024ce50f06 vgchange -aay: improve unexpected command variations
For completeness and consistency, adjust the behavior
for some variations of:

  vgchange -aay --autoactivation event [vgname]

The current standard use is with a VG name arg, and the
command is only called when all pvs_online files exist.
This is the optimal case, in which only pvs_online devs
are read.  This remains the same.

Clean up behaviors for some other unexpected uses of the
command:

. With no VG name arg, the command activates any VGs
  that are complete according to pvs_online.  If no
  pvs_online files exist, it does nothing.

. If a VG name is used but no PVs online files exist for
  the VG, or the PVs online files are incomplete, then
  consider there could be a problem with the pvs_online
  files, and fall back to a full label scan prior to
  attempting the activation.
2021-11-08 15:19:25 -06:00
David Teigland
14b68ea313 vgchange -aay: fall back to dev_cache_scan if optimization fails
Part of the optimization to avoid a full dev_cache_scan requires
translating major:minor numbers to a device name.  If this devno
translation fails, then fall back to doing a full dev_cache_scan
which is slower but certain to provide the info.  This preserves
the most important part of the label scanning optimization in the
vgchange aay (avoiding dev_cache_scan is a relatively small part
of the optimized activation compared to label scanning.)
2021-11-05 17:07:13 -05:00
David Teigland
b4067e84c7 fix device name from devno for partitions
sysfs files for partitions are different from
whole devices and will require more work to translate
to device names.
2021-11-05 16:21:23 -05:00
David Teigland
62533ae3fa vgchange -aay: optimize device list using pvs_online files
Port another optimization from pvscan -aay to vgchange -aay:
  "pvscan: only add device args to dev cache"

This optimization avoids doing a full dev_cache_scan, and
instead populates dev-cache with only the devices in the
VG being activated.

This involves shifting the use of pvs_online files from
the hints interface up to the higher level label_scan
interface.  This specialized label_scan is structured
around creating a list of devices from the pvs_online
files.  Previously, a list of all devices was created
first, and then reduced based on the pvs_online files.
The initial step of listing all devices was slow when
thousands of devices are present on the system.

This optimization extends the previous optimization that
used pvs_online files to limit the devices that were
actually scanned (i.e. reading to identify the device):
  "vgchange -aay: optimize device scan using pvs_online files"
2021-11-05 12:19:35 -05:00
David Teigland
5f7cb97743 lvm2-pvscan: include --autoactivation event
in the pvscan --cache -aay command so that the use
of the command for event activation is explicit.
2021-11-04 14:14:37 -05:00
David Teigland
f40fd88374 move code from pvscan.c to online.c
related to managing files in /run/lvm/pvs_online
and /run/lvm/vgs_online
2021-11-04 11:09:29 -05:00
David Teigland
d558b3ad7e vgchange -aay: optimize device scan using pvs_online files
Port the old pvscan -aay scanning optimization to vgchange -aay.
The optimization uses pvs_online files created by pvscan --cache
to derive a list of devices to use when activating a VG.  This
allows autoactivation of a VG to avoid scanning all devices, and
only scan the devices used by the VG itself.  The optimization is
applied internally using the device hints interface.

The new option "--autoactivation event" is given to pvscan and
vgchange commands that are called by event activation.  This
informs the command that it is being used for event activation,
so that it can apply checks and optimizations that are specific
to event activation.  Those include:

- skipping the command if lvm.conf event_activation=0
- checking that a VG is complete before activating it
- using pvs_online files to limit device scanning
2021-11-04 11:08:38 -05:00
David Teigland
594f6ca970 rename pvscan_cache_single to expect_missing_vg_device in cmd 2021-11-04 11:08:38 -05:00
David Teigland
726dd25969 add hints interface to the pvs_online file information
The information in /run/lvm/pvs_online/<pvid> files can
be used to build a list of devices for a given VG.

The pvscan -aay command has long used this information to
activate a VG while scanning only devices in that VG, which
is an important optimization for autoactivation.

This patch implements the same thing through the existing
device hints interface, so that the optimization can be
applied elsewhere.  A future patch will take advantage of
this optimization in vgchange -aay, which is now used in
place of pvscan -aay for event activation.
2021-11-04 10:58:16 -05:00
David Teigland
6ea8d975b2 lvmdevices: increase open file limit 2021-11-03 08:50:57 -05:00
David Teigland
b5b0369e4d filter-sysfs: skip when device id is set
When a device id is set for a device, using an idtype other
than devname, it means that sysfs has been used with the device
to match the device id.  So, checking for a sysfs entry for the
device in filter-sysfs is redundant.  For any other cases not
covered by this (e.g. devname ids), have filter-sysfs simply
stat /sys/dev/block/major:minor to test if the device exists
in sysfs.

The extensive processing done by filter-sysfs init is removed.
It was taking an immense amount of time with many devices, e.g.
. 1024 PVs in 520 VGs
. 520 concurrent vgchange -ay <vgname> commands
. vgchange scans only PVs in the named VG (based on pvs_online
  files from a pending patch)

A large number of the vgchange commands were taking over 1 min,
and nearly half of that time was used by filter-sysfs init.
With this patch, the vgchange commands take about half the time.
2021-11-02 16:54:53 -05:00
David Teigland
5d0964d127 hints: remove the cmd hints list
which is no longer used after commit
"toollib: remove all devices list from process_each_pv"
2021-11-01 16:01:45 -05:00
David Teigland
b65a2c3f3a vgimportdevices: skip lvmlockd locking
Help bootstrapping existing shared vgs into the devices file.
Reading the vg in vgimportdevices would require locking to be
started, but vgchange lockstart won't see the vg if it's not
in the devices file.  The lvmlockd locks are not protecting
vg modifications so skipping them here won't be a problem.
2021-10-25 12:11:17 -05:00
Christian Hesse
221e75316f The path is known anyway and should be the bullet proof option.
Signed-off-by: Christian Hesse <mail@eworm.de>
2021-10-21 16:33:23 -05:00
David Teigland
ae355ffc3f pvscan: fix messages from coverity changes 2021-10-20 16:12:55 -05:00
Marian Csontos
819a35cc91 post-release 2021-10-20 11:13:28 +02:00
Marian Csontos
ef4521831d pre-release 2021-10-20 11:12:39 +02:00
Marian Csontos
36be4d68f6 WHATS_NEW: update 2021-10-20 11:10:37 +02:00
David Teigland
33e47182f7 pvscan: only add device args to dev cache
Optimize the common pvscan --cache command by only adding
the necessary devs to dev-cache.
2021-10-19 17:13:57 -05:00
Zdenek Kabelac
60dc44b707 dev-cache: enhance dir scan also for non-udev build 2021-10-18 21:50:56 +02:00
Zdenek Kabelac
88e0d68909 dev-cache: better detection of filesystem
It appear on some systems the first found dev might not be actually for
the filesytem - so use a better way through _cache.st_dev.
2021-10-18 21:16:53 +02:00
Zdenek Kabelac
c60bac4661 configure: update 2021-10-18 19:17:27 +02:00
Zdenek Kabelac
1b104ddb55 configure.ac: remove unused part
As we are not using 'enable-compat' for anything, remove this section.
Also remove duplicated check for blkid.
Move setting of some AC_ARG_ENABLE defaults into the macro so it's always
defined.
2021-10-18 19:17:27 +02:00
Zdenek Kabelac
a172a02a9a cleanup: use const char buffer 2021-10-18 19:17:27 +02:00
Zdenek Kabelac
9cf4eac250 dev-cache: skip different filesystems on dir scan
When scanning configured  /dev dir, avoid entring
directories with different filesystem.

This minimizes risk we will block on i.e. entring
directory with mount point.
2021-10-18 19:17:26 +02:00
Zdenek Kabelac
bae1083472 cov: check device_ids_write return code
At least 'stack' failure code path as the
function device_id_update_vg_uuid() is void.
2021-10-15 23:40:56 +02:00
Zdenek Kabelac
c2be6c38d5 cov: ensure id is always initialize
Always resed sd_id128_t id and report warning in case
sd_id128_get_machine_app_specific() does not exit with 0.
2021-10-15 23:40:56 +02:00
Zdenek Kabelac
882141eb8c cov: check pointer before dereferencing
Check pv2 is non-null before trying to deref its tags.
2021-10-15 23:40:56 +02:00
Zdenek Kabelac
65ba4964df cov: do not drop already known error state
Do not try to 'discover' another error state, when ENOMEM
is already detected.
2021-10-15 23:40:56 +02:00
Zdenek Kabelac
e7b5f490c5 cov: ignore close result 2021-10-15 23:40:29 +02:00
Zdenek Kabelac
6668d6409a cov: validate subcommand existance
Before dereference of subcommand pointer, check it's not NULL
as  coverity believes there exists theoretical path for this...
2021-10-15 23:39:25 +02:00
Zdenek Kabelac
2779830a06 cov: avoid using NULL info
Check lvmcache info exists before calling lvmcache_del_save_bad_mda().
2021-10-15 23:36:22 +02:00
Zdenek Kabelac
8aefd97252 configure: fix use of withval
Newly added option --with-default-use-devices-file needs to use withval.
2021-10-15 23:35:05 +02:00
Zdenek Kabelac
bf87b8354d configure: update 2021-10-15 10:11:34 +02:00
Zdenek Kabelac
9d87549f80 configure.ac: enhance systemd testing
Enhance logic for checking supported systemd version,
while doing only a single check for systemd package.
For version checking use  PKG_CHECK_EXISTS() macro.

Also use one pkg check for blkid.

Avoid checking version for thin/cache_check when tools are not present
on system.
2021-10-15 10:09:21 +02:00
Zdenek Kabelac
2e2d673780 makefile: enhance run-unit-test target
Use TMPDIR for executing test and also ensure
all libraries linked to the test are from builddir.
2021-10-15 09:55:54 +02:00
Zdenek Kabelac
037165300e unit-test: better check for O_DIRECT
Instead of guessing tmpfs usage, just directly try if we could
reopen file with O_DIRECT on the used filesystem.
2021-10-15 09:55:54 +02:00
Zdenek Kabelac
52a52d5567 configure: bash var typo 2021-10-15 00:32:36 +02:00
Zdenek Kabelac
04725763a1 gcc: always initialize vg_complete 2021-10-15 00:09:07 +02:00
Zdenek Kabelac
14cf579263 gcc: archive reoder struct vars
Easier for automatic struct initialization = { 0 } without warns
from older gcc.
2021-10-15 00:09:07 +02:00
Zdenek Kabelac
438408de7d configure: missed braces
Missed [] around AS_IF internals,
Also missed to call pkg_config_init prior PKG_CHECK_MODULES().
2021-10-15 00:08:29 +02:00
Zdenek Kabelac
8784211958 debug: reduce some debugging noise
Resolve event_activation configure option just once.

Do not print debug_devs about 'bad' filtering, when
actually filter already printed reason for skipping

Do not trace more then once about backup being disabled.

No debug when unlinked file does not exists in pvscan.
2021-10-14 23:34:11 +02:00
Zdenek Kabelac
ae92888a7b make: generate 2021-10-14 23:34:11 +02:00
Zdenek Kabelac
0bd5388b16 log: also build without systemd_journal_support 2021-10-14 23:34:11 +02:00
Zdenek Kabelac
b73e1cd4b3 configure: updates 2021-10-14 23:34:11 +02:00
Zdenek Kabelac
6635ff77e3 configure.ac: improvement
Handle automatically new setttings

--disable-systemd-journal
--disable-appmachineid

Both setting will check presence of apropriate header files.
In case they are present, build will try to automatically build with
them (adding systemd dependency)

User can anytime disabled them and drop systemd dependency.

Also add --with-default-use-devices-file  configure option to
select automatically default value for this option.
For this moment keep default upstream as 0
2021-10-14 23:34:11 +02:00
Zdenek Kabelac
32cb1c4cdd makefiles: use proper install prefix for python dbus
For non-standard prefix dir use correct installation path
(so the python files are not installed into user's system).
2021-10-14 23:34:11 +02:00
Zdenek Kabelac
af0ce203e9 debug: better error message
Add more details about size difference.
2021-10-14 23:34:11 +02:00
Zdenek Kabelac
7e346ee2a5 archiving: update refactoring
Commit 5ea426e656 handled case with
file path without '/' incorrectly - there is valid use-case so
switch 'log_error()' to valid code branch.
2021-10-14 23:33:26 +02:00
David Teigland
c38473548e fix segfault handling duplicate PVs
cmd arg was missing when switching to use an alternative
duplicate dev.
2021-10-14 14:02:59 -05:00
David Teigland
e88163ceac fix lvmcache_add log_debug pvid
from previous cleanup
2021-10-13 17:30:21 -05:00
David Teigland
6fb497ef42 toollib: remove all devices list from process_each_pv
Reporting non-PVs / "all devices" is only done by
pvs -a or pvdisplay -a, so avoid the work managing
a list of all devices in process_each_pv.
In the case when it's needed, use the results of
label_scan which already determines which devs
are not PVs.
2021-10-13 17:29:32 -05:00
David Teigland
272d1ccac8 devices file: unmatching system id should just be warning
there are likely more cases than not where the systemid
does not match and the command should still run.
2021-10-13 13:42:04 -05:00
David Teigland
062ea3c418 fix syslog setting
Just setting lvm.conf level=N should not send messages to
syslog (now the journal by default.)

Sending messages to syslog should require setting lvm.conf
log { syslog=1 level=N }.
2021-10-11 17:11:01 -05:00
Marian Csontos
ca38251b10 make: generate 2021-10-07 12:42:44 -05:00
Vojtech Trefny
61bd5e5023 lvmdbusd: Use ID_FS_TYPE UDev property in udevwatch
'.ID_FS_TYPE_NEW' is a custom property added by an LVM UDev rule
which is now being removed and 'ID_FS_TYPE' has the same value.

Signed-off-by: Vojtech Trefny <vtrefny@redhat.com>
2021-10-07 12:42:44 -05:00
Marian Csontos
5ac4b662df configure: update 2021-10-07 12:42:43 -05:00
David Teigland
67722b3123 new udev autoactivation
new udev rule 69-dm-lvm.rules replaces
69-dm-lvm-meta.rules and lvm2-pvscan.service

udev rule calls pvscan directly on the added device

pvscan output indicates if a complete VG can be activated

udev env var LVM_VG_NAME_COMPLETE is used to pass complete
VG name from pvscan to the udev rule

udev rule uses systemd-run to run vgchange -aay <vgname>
2021-10-07 12:42:31 -05:00
David Teigland
bbf8e7db74 logging: to the systemd journal
Configure via lvm.conf log/journal or command line --journal.

Possible values:
"command" records command information.
"output" records default command output.
"debug" records full command debugging.

Multiple values can be set in lvm.conf as an array.
One value can be set in --journal which is added to
values set in lvm.conf
2021-10-07 12:06:49 -05:00
David Teigland
0b6782fa01 pvscan: add options listlvs listvg checkcomplete
pvscan --cache <dev>
    . read only dev
    . create online file for dev

pvscan --listvg <dev>
    . read only dev
    . list VG using dev

pvscan --listlvs <dev>
    . read only dev
    . list VG using dev
    . list LVs using dev

pvscan --cache --listvg [--checkcomplete] <dev>
    . read only dev
    . create online file for dev
    . list VG using dev
    . [check online files and report if VG is complete]

pvscan --cache --listlvs [--checkcomplete] <dev>
    . read only dev
    . create online file for dev
    . list VG using dev
    . list LVs using dev
    . [check online files and report if VG is complete]
    . [check online files and report if LVs are complete]

[--vgonline]
can be used with --checkcomplete, to enable use of a vg online
file.  This results in only the first pvscan command to see
the complete VG to report 'VG complete', and others will report
'VG finished'.  This allows the caller to easily run a single
activation of the VG.

[--udevoutput]
can be used with --cache --listvg --checkcomplete, to enable
an output mode that prints LVM_VG_NAME_COMPLETE='vgname' that
a udev rule can import, and prevents other output from the
command (other output causes udev to ignore the command.)

The list of complete LVs is meant to be passed to lvchange -aay,
or the complete VG used with vgchange -aay.

When --checkcomplete is used, lvm assumes that that the output
will be used to trigger event-based autoactivation, so the pvscan
does nothing if event_activation=0 and --checkcomplete is used.

Example of listlvs
------------------

$ lvs -a vg -olvname,devices
  LV     Devices
  lv_a   /dev/loop0(0)
  lv_ab  /dev/loop0(1),/dev/loop1(1)
  lv_abc /dev/loop0(3),/dev/loop1(3),/dev/loop2(1)
  lv_b   /dev/loop1(0)
  lv_c   /dev/loop2(0)

$ pvscan --cache --listlvs --checkcomplete /dev/loop0
  pvscan[35680] PV /dev/loop0 online, VG vg incomplete (need 2).
  VG vg incomplete
  LV vg/lv_a complete
  LV vg/lv_ab incomplete
  LV vg/lv_abc incomplete

$ pvscan --cache --listlvs --checkcomplete /dev/loop1
  pvscan[35681] PV /dev/loop1 online, VG vg incomplete (need 1).
  VG vg incomplete
  LV vg/lv_b complete
  LV vg/lv_ab complete
  LV vg/lv_abc incomplete

$ pvscan --cache --listlvs --checkcomplete /dev/loop2
  pvscan[35682] PV /dev/loop2 online, VG vg is complete.
  VG vg complete
  LV vg/lv_c complete
  LV vg/lv_abc complete

Example of listvg
-----------------

$ pvscan --cache --listvg --checkcomplete /dev/loop0
  pvscan[35684] PV /dev/loop0 online, VG vg incomplete (need 2).
  VG vg incomplete

$ pvscan --cache --listvg --checkcomplete /dev/loop1
  pvscan[35685] PV /dev/loop1 online, VG vg incomplete (need 1).
  VG vg incomplete

$ pvscan --cache --listvg --checkcomplete /dev/loop2
  pvscan[35686] PV /dev/loop2 online, VG vg is complete.
  VG vg complete
2021-10-07 12:06:49 -05:00
David Teigland
3e1316bb09 system_id: new appmachineid option
The new system_id_source="appmachineid" will cause
lvm to use an lvm-specific derivation of the machine-id,
instead of the machine-id directly.  This is now
recommended in place of using machineid.
2021-10-07 12:06:49 -05:00
David Teigland
6c22392a3f config: change default use_devicesfile to 1 2021-10-07 12:06:49 -05:00
David Teigland
02626cbd33 config: comment all default settings 2021-10-07 12:06:49 -05:00
Zdenek Kabelac
3cf97a737b cleanup: use dm_list_empty
Instant check for 'dm_list_size() == 0' without any size calc.
2021-10-06 15:43:31 +02:00
Zdenek Kabelac
197f6aaad7 cleanup: skip zeroing buffer overwritten by memcpy
Since the buffer is going to be overwritten by memcpy, reset only last
char to 0.

Also more use of DM_LIST_INIT list.h macro.
2021-10-06 15:43:31 +02:00
Zdenek Kabelac
79e65a3596 cleanup: all lvmcache_add users pass char with 0
No local copy needed, both users submit zero-end string as pv/vgid.
2021-10-06 15:43:31 +02:00
Zdenek Kabelac
5ccb373d86 cleanup: always initialize historical ptr
Set ptr for all paths.
2021-10-06 15:43:31 +02:00
Zdenek Kabelac
a841babaf7 cleanup: remove unused code 2021-10-06 15:43:31 +02:00
Zdenek Kabelac
5ea426e656 archiving: refactor code to allocate less memory
Do not store full path with each archived name reduces memory usage if
the directory has thousands of entries and just add 'dir' path when
needed.

Also emit info print message to a user if the total size of archived
files for a VG is more then 128MiB or 8192 files.

TODO: Consider wheather adding a new 'lvm.conf  archive{option}' to support
trimming these wild archive sizes can make situation better.
We already support retain_min && retain_days  - but if user is
generating too many and too large archives with minutes - maybe archiving
should be disabled by a user - as it's not producing anything largely usable
and just slows-down command ??
If we add 'retain_max & retain_max_size' the condition will go against
each other and we need to chose priorities.

mm
2021-10-06 15:42:53 +02:00
Zdenek Kabelac
98c57f7ce4 metadata: enhance internal error
Consider missing config tree from vg read to be an internal error
since we do not want to 'regenerate' this one in expesive parsing way.

Also if there is any failure on recreating committed VG, make it also
a 'vg_write' error.
2021-10-06 15:39:58 +02:00
Zdenek Kabelac
b7e9ec0cbf debug: fix stack tracing
Emit stack trace only on log_error path, and avoid on 'expected'
not-found path.
2021-10-06 15:39:58 +02:00
Zdenek Kabelac
e30f3c8410 metadata: simplify code 2021-10-06 15:39:58 +02:00
David Teigland
8e62cbb18e device_id: update stacked PVs for vgchange uuid
If a VG uuid is changed, update the device_id of any
PVs stacked on LVs in the changed VG.
2021-10-04 16:54:44 -05:00
David Teigland
939b4bc587 handle bad metadata text in vg_read path
Corrupt metadata text (with good mda header) was being handled
in the label_scan phase, but not in the vg_read phase.  This
was sufficient because metadata areas would always be read and
checksummed during label_scan (metadata parsing was skipped
previously as an optimization.)

This changed with the optimization in
commit 61a6f9905e
"metadata: optimize reading metadata copies in scan"

Now, some metadata areas will not be read and checksummed
at all during the label_scan phase, only during the vg_read
phase.  This means that bad metadata text may first be detected
in the vg_read phase.  So, add equivalent bad metadata handling
to the vg_read path to match the label_scan path.
2021-09-28 15:17:43 -05:00
Zdenek Kabelac
e3b4c365a4 debug: shorter code 2021-09-27 18:56:14 +02:00
Zdenek Kabelac
f74d30d411 cleanup: use already known lv size 2021-09-27 18:56:14 +02:00
Zdenek Kabelac
a8a958cc04 cleanup: reuse existing code for free path 2021-09-27 18:56:14 +02:00
Zdenek Kabelac
9668427fe8 cleanup: use first parameter uint
Easier with struct zeroing and matching assing of type uint.
2021-09-27 18:56:14 +02:00
Zdenek Kabelac
614d150a8c cov; matching enum type 2021-09-27 18:56:14 +02:00
Zdenek Kabelac
bf0d558067 cov: ignoring 2021-09-27 18:56:14 +02:00
Zdenek Kabelac
dab4acb8f8 make: build without versionsort
Reported-by: adamboardman of gemian
2021-09-27 18:56:14 +02:00
Zdenek Kabelac
df70dca995 make: opened can be needed for either defines case
Reported-by: adamboardman of gemian
2021-09-27 18:56:14 +02:00
Zdenek Kabelac
9971459d19 make: replace legacy use rindex with strrchr
Seems already dropped by some systems.

Reported-by: adamboardman of gemian
2021-09-27 18:56:14 +02:00
Zdenek Kabelac
e585c10fad make: fix compilation for undefined RAID_INTERNAL
Reported-by: adamboardman of gemian
2021-09-27 18:56:14 +02:00
Zdenek Kabelac
6c85ea50de make: fix compilation for some compiler
Reported-by: adamboardman of gemian
2021-09-27 18:56:14 +02:00
Zdenek Kabelac
ef21ed78ae utils: define macro for ffs
Provide ffs() macro using __builtin_ffs(), when there is missing
ffs() implementation in header file.

Reported-by: adamboardman of gemian
2021-09-27 18:56:14 +02:00
Zdenek Kabelac
6a186dd1e8 configure: replace AC_HELP_STRING with AS_
Upgrade to newer autoconf setup is approaching...
Will cause large set of configure changes.
2021-09-27 18:56:13 +02:00
Zdenek Kabelac
ff788ef19c configure: check ffs __builtin_ffs versionsort
Check for presence of ffs(), __builtin_ffs() and versionsort().
2021-09-27 18:56:13 +02:00
Zdenek Kabelac
27eef1b964 cov: make more obvious buffer is zero ended 2021-09-27 18:56:13 +02:00
Zdenek Kabelac
3a3aabb832 metadata: avoid excessive check of /etc/localtime
With larger metadata, decoding 'localtime()' for hinting time creation
of every LV may cause excessive check of /etc/localtime file.
Set TZ to ":/etc/localtime" so glibc reads this file just once
instead of check everytime if there has anything changed.
2021-09-27 18:56:13 +02:00
Zdenek Kabelac
61a6f9905e metadata: optimize reading metadata copies in scan
While being in lockless scanning phase, we can avoid reading and checking
matching metadata copies if we already know them from other PV
and just rely on matching metadata header information.

These copies will be examined later during locked metadata read/write
access.

This patch may postpone discovering some read failures to locked phase.
2021-09-27 18:56:13 +02:00
Zdenek Kabelac
24e90f9594 metadata: remember parsing size of VG metadata
When creating lvm2 metadata for VG, lvm2 allocate some buffer,
and if buffer is not big enough, the buffer is 'reallocated' bigger,
and whole metadata creation is repeated until metadata fits.
We can try to use 'previous' metadata size as hint to reduce looping
here.
2021-09-27 18:49:41 +02:00
Zdenek Kabelac
a42ea349f6 metadata: remember crc32 when writing vg metadata
Preserve computed crc32 check from first written PV, just like we
preserve generated metadata.

Also there is no need to call crc32 twice on wrapping buffer with 2 calcs,
result must be always the same as with single crc32 checking.
2021-09-27 18:49:41 +02:00
Zdenek Kabelac
a3352f08f6 dmsetup: fix measure handling
Previous patch f853a1bc7a enabled
ima measurement unconditionally for every status call,
but it needs to be set only for 'dmsetup measure' command.
2021-09-27 18:45:25 +02:00
David Teigland
e62a71f3dd lvmlockd: update error message
refer specifically to the "use_lvmlockd" setting in lvm.conf
2021-09-24 15:40:20 -05:00
Zdenek Kabelac
a1cb33b633 devicemapper: in sync with libdm 2021-09-23 16:49:58 +02:00
Alasdair G Kergon
f853a1bc7a libdm: dmsetup measure support for IMA
Add support for DM_IMA_MEASUREMENT_FLAG with
DM_TABLE_STATUS_CMD.

This feature requires DM version 4.45  (5.15+ kernels)
2021-09-23 16:49:28 +02:00
Zdenek Kabelac
707e7d762e devicemapper: add DM_NAME_LIST_FLAG
Match libdm part
2021-09-23 16:49:16 +02:00
Zdenek Kabelac
566c2f1828 libdm: support DM_NAME_LIST_FLAG
Kernel patch 8b638081bd4520f63db1defc660666ec5f65bc15
introduced support to return UUID in DM_LIST_DEVICES_CMD.

Useful when asking for UUID of each device where the list
could be now returned directly with NAME && UUID for each device.

Returning UUID is done in backward-compatible way. There's one unused
32-bit word value after the event number. This patch sets the bit
DM_NAME_LIST_FLAG_HAS_UUID if UUID is present and
DM_NAME_LIST_FLAG_DOESNT_HAVE_UUID if it isn't (if none of these bits is
set, then we have an old kernel that doesn't support returning UUIDs). The
UUID is stored after this word. The 'next' value is updated to point after
the UUID, so that old version of libdevmapper will skip the UUID without
attempting to interpret it.
2021-09-23 16:49:14 +02:00
Zdenek Kabelac
ee15065a0f gcc: match types 2021-09-22 17:18:50 +02:00
Zdenek Kabelac
9eafd44734 gcc: use more zero length arrays
Define last array struct member with zero size.
2021-09-22 17:18:50 +02:00
Zdenek Kabelac
4515acf734 make: generate 2021-09-22 14:48:58 +02:00
Zdenek Kabelac
4cfa80f02f tests: raise required version for conversion
Real conversion needs this version driver.
TODO: handle properly older versions.
2021-09-21 21:43:02 +02:00
Zdenek Kabelac
b0d40109a6 cov: ignore leak of fd descriptor
There is no 'fd' leak.
2021-09-21 21:03:47 +02:00
Zdenek Kabelac
e6d3587482 cov: check dev_get_size result
Check we have obtained some device size out of dev_get_size().
2021-09-21 21:03:47 +02:00
Zdenek Kabelac
30e27d2f8b cov: sanitize function environment
Coverity can see that function is either used with 'dev' or 'def'.
2021-09-21 21:03:47 +02:00
Zdenek Kabelac
a13dfcbc77 cov: check for function result 2021-09-21 21:03:47 +02:00
Zdenek Kabelac
7bd55f8c15 cov: check strchr for NULL
Although unlikely, ensuring coverity we not use NULL.
2021-09-21 21:03:47 +02:00
Zdenek Kabelac
377e326156 cov: ensuring buffer is zeroed 2021-09-21 21:03:47 +02:00
Zdenek Kabelac
8c44597820 gcc-fanalyzer: zallocate memory for clean buffer 2021-09-21 21:03:47 +02:00
Zdenek Kabelac
4ef8f7cde6 gcc-fanalyzer: remove unneded zeroing
Since we zallocate array here, we don't need to set to NULL
and clean gcc warning about strdup leakage.
2021-09-21 21:03:47 +02:00
Zdenek Kabelac
178df1c8f4 gcc-fanalyzer: helping understand answer is not null
gcc can't easily see pointer 'answer' is only being checked once 'ret > 0'.
2021-09-21 21:03:47 +02:00
Zdenek Kabelac
462ac47003 clang: check for buffer existance
Make obvious to analyzer we can't get NULL here.
2021-09-21 21:03:47 +02:00
Zdenek Kabelac
bb6fd1a15f shellcheck: warning enhancements 2021-09-21 21:03:47 +02:00
Zdenek Kabelac
5bd99d55b0 shellcheck: tests fixes
Correcting some shell problems.
2021-09-21 21:03:47 +02:00
David Teigland
130993bab1 lvmcache: follow pv_id/pvid naming convention
name the variable pv_id_arg to follow the convention:
. "pvid" variable is null-terminated string
. "pv_id" variable is non-null-terminated struct
2021-09-20 09:35:47 -05:00
Zdenek Kabelac
b1f33a4000 tests: len always initialized 2021-09-20 16:24:08 +02:00
Zdenek Kabelac
133686ebc7 gcc: avoid name colision with function pv_id() from metadata.h 2021-09-20 16:12:10 +02:00
Zdenek Kabelac
2e990d1fec gcc: avoid warns on missing braces with older version 2021-09-20 16:11:49 +02:00
Zdenek Kabelac
1a8a33ae9b tests: a bit more fancy way to initialized struct
Older g++ is not smart enough to figure this out, so add a bit more push.
2021-09-20 16:01:22 +02:00
Zdenek Kabelac
4c0354fe0f cleanup: better wording
Follow-up advice of native speaker.
2021-09-20 15:41:14 +02:00
Zdenek Kabelac
1b52451996 cov: mask some warning about leakage
Mask false-positive leak report.
2021-09-20 14:26:09 +02:00
Zdenek Kabelac
548c69f581 cov: hide reports from optarg being NULL
It's basically irrelavant which value we assing to optarg,
since it's set by getopt() function, but Coverity tool
is incorrectly reporting possibly dereference of NULL.
2021-09-20 14:26:09 +02:00
Zdenek Kabelac
efaab93491 cov: ignore syscall 2021-09-20 14:26:09 +02:00
Zdenek Kabelac
055406bb39 cov: validate syscall result 2021-09-20 14:26:09 +02:00
Zdenek Kabelac
9721f3e0ff cov: test for fixture being NULL pointer
Explicit check for teoretical NULL pointer passed as fixture.
2021-09-20 14:26:09 +02:00
Zdenek Kabelac
3f946bfce7 cov: capture runtime exception 2021-09-20 14:26:09 +02:00
Zdenek Kabelac
d5c82b0e73 cov: better defined constructors
Ensure C++ initializes all struct members.
Also some deterministic buffer initialization.
2021-09-20 14:26:09 +02:00
Zdenek Kabelac
ebd150366f cov: add explicit NULL pointer check
Make obvious to coverity strcmp() is not getting NULL pointer.
2021-09-20 14:26:09 +02:00
Zdenek Kabelac
752a9ec4b4 cov: make read buffer obviously zero ended
Coverity doesn't get the idea from memset() here.
2021-09-20 14:26:09 +02:00
Zdenek Kabelac
6c87e98ee3 cov: check for possible NULL segtype
Although likely impossible to ever miss ERROR segtype,
make analyzer hapier.
2021-09-20 14:26:09 +02:00
Zdenek Kabelac
bfc6fe2bac cov: ensure data is not derefenced
Ensure all hypothetical paths cannot dereference NULL *(u->data).
2021-09-20 14:26:09 +02:00
Zdenek Kabelac
3e7e9cc5e6 cov: handle better leak reports
Rewrite code so the leaks are eliminated from Coverity.
2021-09-20 14:26:09 +02:00
Zdenek Kabelac
825e49a244 cov: use different variable name
Better for Coverity to see no change for possibly opened handle.
2021-09-20 14:26:09 +02:00
Zdenek Kabelac
376e707232 cov: better handle reallocation of adapt_file
If the option would be given more then once.
2021-09-20 14:26:09 +02:00
Zdenek Kabelac
ce907bcd26 cov: handle teoretical sysconf failure
sysconf() may also return -1 although rather theoretically.
Default to 4K when such case would happen.
Also in function call it just once and keep as static variable.
2021-09-20 14:26:09 +02:00
Zdenek Kabelac
f410035181 cov: check fid instance is created 2021-09-20 14:26:09 +02:00
Zdenek Kabelac
e1840dd9e0 cov: add error path for daemon_request_extend
Check for errors in daemon_request_extend().
2021-09-20 14:26:09 +02:00
Zdenek Kabelac
6427803252 cov: pvck validates setup_device return value 2021-09-20 14:18:13 +02:00
Zdenek Kabelac
b6e9892bc6 tests: use single funtion to get random value 2021-09-20 14:18:13 +02:00
Zdenek Kabelac
a428856a21 tests: fix test of read buffer
Patch 7aba7fe68b incorrectly
converted  SECTOR_SIZE * BLOCK_SIZE_SECTORS to sizeof(f->data).
2021-09-20 14:18:13 +02:00
Zdenek Kabelac
becffe4567 gcc-fanalyzer: drop zeroing of pointers
This explicit pointer zeroing is not needed since
we use 'zalloced' buffers.
2021-09-20 14:18:13 +02:00
Zdenek Kabelac
909401226c gcc-fanalyzer: rewrite _fetch_string
Slightly more optimal code, that is less confusing analyzers.
2021-09-20 14:18:13 +02:00
Zdenek Kabelac
30b188857c gcc-fanalyzer: some explicit NULL checks for tests
Testing code being happier with these extra checks...
2021-09-20 14:17:46 +02:00
Zdenek Kabelac
9512638656 gcc-fanalyzer: better losetup error path
Fix leaking memory on error path on _process_losetup_switches().
However real impact is close to zero as dm-loop target isn't really used.
2021-09-20 13:58:57 +02:00
Zdenek Kabelac
3e21c8524e gcc-fanalyzer: add extra check for origin_from_cow
Make analyzer work easier with explicit check for internal error.
2021-09-20 13:58:57 +02:00
Zdenek Kabelac
93d565eda9 gcc-fanalyzer: use zeroed memory
Analyzer here was rather confused about possiblity of loosing previously
assigned device pointers - fixed by passing zero initialize memory
before first assign.
2021-09-20 13:58:57 +02:00
Zdenek Kabelac
5126ac7c3a gcc-fanalyzer: explicit test null not pass
Make analyzer explicitelly aware we can't get NULL here.
2021-09-20 10:51:30 +02:00
Zdenek Kabelac
e15d1e53c1 gcc-fanalyzer: notices 'du' could be NULL
Ensure only nonNULL 'du' pointer is dereference altough the comment
to the last assign 'du' pointer already suggest 'NULL' case should not happen.
So just being explicit.

mer du
2021-09-20 10:51:30 +02:00
Zdenek Kabelac
834f17bb33 clang: ensure new_len is at least 1 2021-09-20 10:51:30 +02:00
Zdenek Kabelac
0d9f3dbd95 clang: add explicit test for VG
Clang can't figure out connection to 'skip' variable.
2021-09-20 10:51:30 +02:00
Zdenek Kabelac
48163e32f1 lvmlockd: better error path
Set ->num to correct num of pointers.
and fixes regression from previous clang fix
9c5d2874a7.
2021-09-20 10:49:56 +02:00
Zdenek Kabelac
a0bbdfba7f cleanup: typo fix 2021-09-17 22:42:41 +02:00
Zdenek Kabelac
3817392d87 lvm_import_vdo: --dry-run automatically verbose
Dry-run is way more usable when it's verbose.
2021-09-17 16:49:17 +02:00
Zdenek Kabelac
944e560e96 debug: change message level
These message do not cause command error - switch to debug.
2021-09-15 15:24:56 +02:00
Zdenek Kabelac
ed59b50512 cleanup: free already does NULL check
Drop extra check for NULL before calling free().
Also drop zeroing data that will be free().
2021-09-15 15:24:56 +02:00
Zdenek Kabelac
73087c2c0f clang: free on arg parsing
If the parameter would be given twice, the 1st. alloc memleaks.
2021-09-15 15:24:56 +02:00
Zdenek Kabelac
dd5f8b3f8c clang: keep metaname initialized
Never access uninitialized metaname buffer.
2021-09-15 15:24:56 +02:00
Zdenek Kabelac
1a5c79d1d1 clang: keep final_opts_list initialized for all paths
Likely impossible path, but just keep always initilized.
2021-09-15 15:24:56 +02:00
Zdenek Kabelac
9c5d2874a7 clang: avoid double free on error path
Error path in _lockd_retrive_vg_pv_list() has not zeroed released path
caussing possible double-free later in the code.

Fix it by using one single function freeing lock_pvs structure.
2021-09-15 15:24:56 +02:00
David Teigland
8935dfee56 lvmdevices: allow deviceidtype with addpvid
in addition to using with adddev
2021-09-13 14:11:07 -05:00
David Teigland
9857b5a3dc add --nohints option
The command will not use the hints file to locate devices for PVs.
It will still do standard hint file invalidation where appropriate.
2021-09-13 10:55:07 -05:00
Wu Guanghao
b36ab8a063 cmdlib_lvm2_init: release cmd on failure path
The cmd memory space is allocated by zalloc, and the registration
fails and is not released.

Although this code would be ever triggered just in the case
of some internal (likely compilation) bug.

Signed-off-by: Wu Guanghao <wuguanghao3@huawei.com>
2021-09-13 12:34:41 +02:00
Adrian Ratiu
cd897e536f man-generator: initialize struct stat to avoid MSAN error
When building lvm2 in Gentoo/ChromeOS with the ASAN memory
sanitizer enabled, man-generator fails with the following
error. Initializing makes the error go away.

* SUMMARY: MemorySanitizer: use-of-uninitialized-value /build/amd64-generic/tmp/portage/sys-fs/lvm2-2.02.187-r3/work/LVM2.2.02.187/tools/man-generator.c:3316:6 in _include_description_file
* Exiting
* ASAN error detected:
* ==2548047==WARNING: MemorySanitizer: use-of-uninitialized-value
*     #0 0x558b00ab4730 in _include_description_file /build/amd64-generic/tmp/portage/sys-fs/lvm2-2.02.187-r3/work/LVM2.2.02.187/tools/man-generator.c:3316:6
*     #1 0x558b00ab4730 in _print_man /build/amd64-generic/tmp/portage/sys-fs/lvm2-2.02.187-r3/work/LVM2.2.02.187/tools/man-generator.c:3426:21
*     #2 0x558b00ab4730 in main /build/amd64-generic/tmp/portage/sys-fs/lvm2-2.02.187-r3/work/LVM2.2.02.187/tools/man-generator.c:3570:7
*     #0 0x7fa9b2cbb807 in find_derivation /var/tmp/portage/cross-x86_64-cros-linux-gnu/glibc-2.33-r8/work/glibc-2.33/iconv/gconv_db.c:583:15
*     #1 0x558b00a29559 in ?? ??:0
*
*   Uninitialized value was created by an allocation of 'statbuf.i.i' in the stack frame of function 'main'
*     #0 0x558b00ab1d4d in main /build/amd64-generic/tmp/portage/sys-fs/lvm2-2.02.187-r3/work/LVM2.2.02.187/tools/man-generator.c:3505
2021-09-13 12:34:41 +02:00
Zdenek Kabelac
064979dc32 gcc: remove unused vg setting 2021-09-13 12:34:41 +02:00
Zdenek Kabelac
00ec716b4d gcc: remove invalid attribute
In this function parameter 'attribute' is used.
2021-09-13 12:34:41 +02:00
Zdenek Kabelac
9ba76450f4 cov: remove unused variable setting
Since there is no use for &end after strtol, remove it.
2021-09-13 12:34:41 +02:00
Zdenek Kabelac
3b2a4e3e6f cov: make it aware we need these headers for muslC 2021-09-13 12:34:41 +02:00
Zdenek Kabelac
a14371e495 cov: hide false positive warning
Here we have valid use case of strncpy() which just need
to fill precise buffer size - so no explicit \0 on buffer
end is needed.
2021-09-13 12:34:41 +02:00
Zdenek Kabelac
63930f576a cov: add some initializers 2021-09-13 12:34:41 +02:00
Zdenek Kabelac
f5f1cdfa70 cov: initilized more struct members
For some hypothetical path, make these vars defined.
2021-09-13 12:34:41 +02:00
Zdenek Kabelac
a8ee13900d cov: initialize attr 2021-09-13 12:34:41 +02:00
Zdenek Kabelac
be1c2a1ae2 cov: keep time calculation ready for 2038
Be prepared ;) and keep arithmetic 64bit ready.
2021-09-13 12:34:41 +02:00
Zdenek Kabelac
3ce8db8b88 cov: keep 64bit arithmetic
Highly unlikely this case will ever need 64bit math, but just in case,
keep the expression as 64bit.
2021-09-13 12:34:41 +02:00
Zdenek Kabelac
a7258ae394 cov: do not try to change passed in argv
It's not a good idea to change passed 'argv[]' and replace it with
pointers to local stack - although in this case we are not using
this argv[] after return from this function.
2021-09-13 12:34:41 +02:00
Zdenek Kabelac
aa522d5862 cov: fix copy from tmp_name buffer
Mask for strncpy() Coverity report warning would
actually need to copy buffer from 'tmp_name' instead of 'str'.

But replace it directly with single 'strncpy()' again for better readbility,
just mask out the warning reported for this strncpy instance
(so we do not need to put comment fro every call of strcpy_name_len).
2021-09-13 12:34:41 +02:00
Zdenek Kabelac
7af0a1b9d8 tests: increase size of thin-pool for newer mkfs
Looks like newer version of mkfs.ext4 consumes more 'real' disk space,
when formating virtual volumes - so double the size of thin-pool to
have enough backend chunks for provisioning.
2021-09-13 12:34:41 +02:00
Zdenek Kabelac
fc5f9924c7 tests: add test for handling unknown cache settings 2021-09-13 12:34:41 +02:00
Zdenek Kabelac
a8ee82ed51 libdm: enhance tracking of activated LVs
Existing mechanism was not able to trace root volume issue.
Simplify the functionality by using simply using activated flag
and trace the dtree in reverse order.
2021-09-13 12:34:41 +02:00
Zdenek Kabelac
d489445e5a cache: implement better revert path
When cache creation fails on table reload path, implemen more
advanced revert solution, that tries to restore state of LVM
metadata into is look before actual caching started.
2021-09-13 12:34:41 +02:00
Zdenek Kabelac
4c3d7a01d4 cache: filter out unsupported policy settings
Loading invalid MQ/SMQ policy settings table line cause immediate
rejection - to prevent such failure, automatically filter valid
settins before it is being uploaded by lvm2.

For invalid setting issue a warnning informing user how to remove
them.

This solution is used to keep running cached LVs that might had
been created in the past with invalid settings that have been actually
unused due to another code bug.
2021-09-13 12:34:41 +02:00
Zdenek Kabelac
6c4cd7b2f2 cache: fix parentheses for migration_threshold
When generating table line for cache target line,
the estimation of added arguments was incorrectly
calculated as the evaluation order of "?" is
made after "+".

However the result was 'masked' by the

Reported-by: Jian Cai jcai19
2021-09-13 12:34:41 +02:00
Zdenek Kabelac
30050769b1 filters: fix memleak on mpath filter destroy
Missing free() leaks filter structure.
2021-09-13 12:34:41 +02:00
Zdenek Kabelac
3b24c0fe4e vdo: prompt with no return failure
Exit 1  (failure) when prompt for conversion is answered as 'No'.
2021-09-13 12:34:41 +02:00
Zdenek Kabelac
812653d598 vdo: man page updates 2021-09-13 12:34:41 +02:00
Zdenek Kabelac
9db4ddabc1 vdo: lvm_import_vdo script needs to continue when vgname does not exist
When the script cannot find vgname - it needs to continue to run.
2021-09-13 12:34:41 +02:00
Zdenek Kabelac
bd2dae4643 tests: check lvm2 parses vdo statistics 2021-09-09 15:24:21 +02:00
Zdenek Kabelac
e6f735d411 vdo: read new sysfs path
New versions of kvdo module exposes statistics at new location:
/sys/block/dm-XXX/vdo/statistics/...

Enhance lvm2 to access this location first.
Also if the statistic info is missing - make it 'debug' level info,
so it is not failing 'lvs' command.
2021-09-09 15:24:15 +02:00
Zdenek Kabelac
89595a3665 vdo: more lvm_import_vdo fixes
Do not call 'dmsetup info' for non-dm devices.

Better handling for VGNAME and LVNAME - so when convering LV as
backend device automatically recognize it and reuse LV name for VDOLV.

Add prompt for final confirmation before actual conversion is started
(once confirmed, lvm2 commands no longer prompts to avoid leaving
conversion in the middle of its process.)
2021-09-06 15:19:51 +02:00
Zdenek Kabelac
3287d37f44 vdo: better message for missing device
Show readable message when passed device cannot be accessed.
And use STAT shell var wrapper to call 'stat' command.
2021-09-06 15:19:51 +02:00
Zdenek Kabelac
8d5b7de54f vdo: lvm_import_vdo fix max_discard size
Use correct 4K units in lvm2 for max_discard VDO option.
2021-09-06 15:19:51 +02:00
Zdenek Kabelac
79427151dc vdo: add support for auto-unsafe writePolicy
This vdoWritePolicy policy missed matching support in lvm2.
2021-09-06 15:19:51 +02:00
Zdenek Kabelac
337053c56a tests: remove all debug logs when using die
Since die is called from a shell script, there is no need
to report any recent lvm2 command debug traces.
2021-09-06 15:01:11 +02:00
Zdenek Kabelac
52b5620476 makefiles: sanitize environment
Compilation needs to generate 'C' locale sorted command file
definitions. To always enforce 'C' sorting rules user LC_ALL
instead of LANG, as  LANG settings can be overuled by
other LC settings like LC_COLLATE and may result into miscompiled
lvm2 binary if locales ordering differs from 'C'.

Reported-by: jmp-lvm2@ookaze.fr
2021-09-06 14:00:20 +02:00
Zdenek Kabelac
1ae157a0f6 vdo: fixes
Better identify VDO device with major:minor.
Handle different LV name from originally converted origin LV.
Improve --dry-run handling.
2021-08-31 22:05:47 +02:00
Zdenek Kabelac
419c93c873 vdo: support lvcreate with skipped activation
Support creation of VDO LV for 'lvcreate -ky...'.
2021-08-31 22:05:47 +02:00
Zdenek Kabelac
4afe872fd6 vdo: fix conversion of large virtual sizes
Properly accept virtual sizes above 2TiB.
2021-08-31 22:05:47 +02:00
Zdenek Kabelac
88360b0c51 vdo: skip zeroing for VDO LV
Since VDO is always returns 'zero' on unprovisioned read
and every provisioned block is always 'zeroed' on partial writes,
we can avoid 'zeroing' of such LVs.
2021-08-31 22:05:47 +02:00
David Teigland
62c599f781 cov: lvmlockd read_adopt_file free structs on error path 2021-08-30 13:48:42 -05:00
David Teigland
350f8845bd pvremove: apply devices file
pvremove was wrongly allowed to operate on a device
not listed in the devices file.
2021-08-27 14:48:33 -05:00
Zdenek Kabelac
12ba43ccd0 vdo: rename vdoimport to lvm_import_vdo
Missed bits in previous rename commits.
2021-08-26 19:10:28 +02:00
Marian Csontos
49822624e8 spec: Rename vdoimport to lvm_import_vdo. 2021-08-26 17:14:08 +02:00
Marian Csontos
bbbd4fed69 vdo: Rename vdoimport to lvm_import_vdo. 2021-08-26 17:13:59 +02:00
David Teigland
0969e90d45 devices: restrict device id types to specific major numbers
Some device id types can only be used with specific device major
numbers, so use this restriction to avoid some comparisions.
This is more efficient, and can avoid some incorrect matches.
2021-08-23 15:54:41 -05:00
Alex Xu (Hello71)
a6a8443a07 add missing sys/file.h include
required for LOCK_EX etc on musl
2021-08-23 09:24:45 -05:00
David Teigland
72af1cb085 vgimportclone: fix when duplicates are both in the devices file
Fix case where duplicate PVs are created (e.g. with dd) from
devices that are both already in the devices file.
2021-08-20 15:06:33 -05:00
David Teigland
8b72313936 devices file: recognize old locking_type 0
if the old locking_type is 0, set cmd->nolocking so that
it will be applied to the devices file lock.
2021-08-20 14:51:13 -05:00
David Teigland
9e79a022ea logging: messages for found metadata 2021-08-20 14:51:09 -05:00
David Teigland
6cd4470e6d devices: apply ignorelockingfailure to devices file lock 2021-08-20 14:07:00 -05:00
David Teigland
4df6931c4c tests: adjust for check_devicesfile 2021-08-20 14:06:55 -05:00
David Teigland
b0bda7c25b lvmdevices: check yes option for adding duplicate 2021-08-19 13:00:43 -05:00
David Teigland
96b777167c cov: clean up pvid and vgid usage
pvid and vgid are sometimes a null-terminated string, and
other times a 'struct id', and the two types were often
cast between each other.  When a struct id was cast to a char
pointer, the resulting string would not necessarily be null
terminated.  Casting a null-terminated string id to a
struct id is fine, but is still avoided when possible.

A struct id is:  int8_t uuid[ID_LEN]
A string id is:  char pvid[ID_LEN + 1]

A convention is introduced to help distinguish them:

- variables and struct fields named "pvid" or "vgid"
  should be null-terminated strings.

- variables and struct fields named "pv_id" or "vg_id"
  should be struct id's.

- examples:
  char pvid[ID_LEN + 1];
  char vgid[ID_LEN + 1];
  struct id pv_id;
  struct id vg_id;

Function names also attempt to follow this convention.

Avoid casting between the two types as much as possible,
with limited exceptions when known to be safe and clearly
commented.

Avoid using variations of strcpy and strcmp, and instead
use memcpy/memcmp with ID_LEN (with similar limited
exceptions possible.)
2021-08-16 11:31:15 -05:00
David Teigland
0d572d14ad cov: lvmlockd: rewrite string copies to avoid warnings
- Use a new function for all instances of copying
  a null-terminated string into a fixed size struct
  field that is not null-terminated.

- use memcpy when copying between struct fields of
  the same size
2021-08-16 11:31:09 -05:00
Yi Wang
47bcb446b8 lvchange: fix lvchange refresh failed for dm suspend or resume failed
When multiple lvchange refresh processes executed at the same time,
suspend/resume ioctl on the same dm, some of these commands will be failed
for dm aready change status, and ioctl will return EINVAL in _do_dm_ioctl function.
to avoid this problem, add READ_FOR_ACTIVATE flags in lvchange refresh process,
it will hold LCK_WRITE lock and avoid suspend/resume dm at the same time.

Signed-off-by: Long YunJian <long.yunjian@zte.com.cn>
Signed-off-by: Yi Wang <wang.yi59@zte.com.cn>
2021-08-16 09:45:40 -05:00
David Teigland
e5c0562654 toolcontext.h: use bit field in struct
Two recent additions should have used a bit instead
of an entire int.
2021-08-12 15:51:43 -05:00
Marian Csontos
59209ef049 post-release 2021-08-11 17:15:51 +02:00
Marian Csontos
67a853f337 pre-release 2021-08-11 17:14:26 +02:00
Marian Csontos
7dfaf5dc13 WHATS_NEW: update 2021-08-10 14:19:24 +02:00
root
b328cfee52 make: generate 2021-08-05 21:38:43 +02:00
David Teigland
d0ab5bf7f9 pvscan: only match devices file for command args
Avoid matching all devices with the devices file to
avoid delays during startup.
2021-08-05 13:20:26 -05:00
David Teigland
87714a1384 devices file: avoid updating entry dev names in some cases
Avoid thrashing changes to devices file device names by
some commands that are run during startup when devnames
are still being set up.
2021-08-05 13:20:26 -05:00
David Teigland
d3d6a0e820 devices file: limit warnings about devices file entries not found
All commands were printing a warning if a devices file
entry was not found.  Limit this to commands that report/display
lvm state.
2021-08-05 13:20:26 -05:00
David Teigland
bf6dfc248a cov: lvmlockd path copy 2021-08-02 15:49:39 -05:00
Zdenek Kabelac
d2a2dc2e41 debug: stack tracing on error path 2021-07-28 00:49:28 +02:00
Zdenek Kabelac
3e2827f3b7 cov: add initilizer 2021-07-28 00:49:28 +02:00
Zdenek Kabelac
a4eb378fe4 cov: add explicit check for vg existence
Since we check !vg - add check before accessing ->status.
2021-07-28 00:49:28 +02:00
Zdenek Kabelac
f4b49dae1e cov: raid: no more checks with missing areas
Since ->areas is directly dereferenced we need to stop
validation right here.
2021-07-28 00:49:28 +02:00
Zdenek Kabelac
b2db01b530 cov: dev-mpath: check config_wwids_file
Since config_wwids_file is checked for NULL,
test is also before calling _read_wwid_file()
that is directly dereferencing it.
2021-07-28 00:49:28 +02:00
Zdenek Kabelac
b7edda8a98 cov: guard index
Analyzer wants explicit protect to not underflow index.
2021-07-28 00:49:28 +02:00
Zdenek Kabelac
d499491501 cov: ensure bufffe size is at least 5
Analyzer can now see, the buffer size will have at least 5 chars
on succefull path.
2021-07-28 00:49:28 +02:00
Zdenek Kabelac
046d85af3d cov: add internal error for missing arg
Analyzer is happier.
2021-07-28 00:49:28 +02:00
Zdenek Kabelac
69379df8f3 cov: remove unneeded includes 2021-07-28 00:49:28 +02:00
Zdenek Kabelac
ec9dd728aa cov: memleak dir descriptor
opendir() missed closedir().
2021-07-28 00:49:22 +02:00
Zdenek Kabelac
308c6f31c3 pvck: ensure buffer is 0 terminated
Since readed metadata buffer is passed to printf(),
ensure the buffer is '\0' terminated.
2021-07-28 00:49:22 +02:00
Zdenek Kabelac
01081b2100 cov: pvck fix memleak
Fix memory leaks on error paths for allocated
path and backup_file name by converting allocation to
dm_pool_alloc  and also change devicefile structure to contain
embeded  path as last struct member - so we could allocate
only needed string size  instead of PATH_MAX from pool.

TODO: still to be fixed 'mf' struct.
2021-07-28 00:49:22 +02:00
Zdenek Kabelac
8ebcbe9ace tests: extend vgmerge testing 2021-07-23 16:36:31 +02:00
Zdenek Kabelac
4b856476e9 vgmerge: support option --poolmetadataspare 2021-07-23 16:36:31 +02:00
Zdenek Kabelac
9cbc9e8296 vgmerge: remove one of merge pmspare LVs
When merging 2 VG, where both of them have pmspare volume,
select the bigger one and remove the other.
2021-07-23 16:35:47 +02:00
David Teigland
06602942a3 writecache: use block size 512 for thin pool data
Recent commit 84bd394cf9
  "writecache: use block size 4096 when no fs is found"

failed to account for the case where writecache is attached
to thin pool data.  Checking fs block size on the thin pool
data LV is wrong, and checking the fs block on each thin LV
would be impractical, so default to 512 which cannot break
any existing file systems, and require the user to specify
4k when appropriate.
2021-07-21 14:24:27 -05:00
David Teigland
d91c018732 writecache: fix missing sync_dev_names when attaching cache
When activating an LV to check the fs block size, wait for
the LV dev to be accessible before running blkid on it.
2021-07-21 13:16:21 -05:00
Marian Csontos
640fe5cf42 spec: Add vdoimport man page 2021-07-21 16:40:27 +02:00
Zdenek Kabelac
b70c341c9e test 2021-07-21 15:56:33 +02:00
Zdenek Kabelac
2132fdc11f vgsplit: add support for option --poolmetadataspare
When splitting VG with thin/cache pool volume, handle pmspare during
such split and allocate new pmspare in new VG or extend existing pmspare
there and eventually drop  pmspare in original VG if is no longer needed
there.
2021-07-21 15:56:33 +02:00
Zdenek Kabelac
5042463c50 vgremove: remove forgotten pmspare
As pmspare is an invisible LV it's not getting automatically removed
since vgremove removes only visible LVs and it depending LVs.
If there was no other thin/cache pool volume, such pmspare stayed
undeleted and caused command failure.

So handle explicitelly such forgotten pmspare and remove it.
2021-07-21 13:19:51 +02:00
Zdenek Kabelac
d38fdb25e4 thin: fix component detection of external origin
When check active componet of thinLV with external origin,
we need to check if the external origin isn't already active.
For this however we need to use layered check for -real device.
2021-07-14 12:56:08 +02:00
David Teigland
e33c2e032c pvscan: narrow the previous commit slightly
to avoid change to pvscan-autoactivate.sh
2021-07-13 16:38:04 -05:00
David Teigland
25f0f5daac pvscan: do nothing for device removal and event_activation=0
The lvm2-pvscan service runs pvscan --cache -aay <dev> for
device addition, and pvscan --cache <dev> on device removal.
For event_activation=0, the addition does nothing.  Fix
device removal to also do nothing for event_activation=0.
Device removal was previously doing some work to process
the removal which slowed down stopping lvm2-pvscan services.
2021-07-13 16:09:54 -05:00
David Teigland
f8b52f2763 fix multipath component detection for multiple holders
sysfs-based multipath component detection quit if a
device had multiple holders, and in this case would
fail to detect a device was an mpath component.
2021-07-13 11:11:23 -05:00
David Teigland
deaf43d6f0 filter-usable: remove udev dev size check
For the pv_min_size check, always use dev_get_size()
which is commonly used elsewhere, and don't bother
asking libudev for the device size when
external_device_info_source=udev.
2021-07-13 11:11:23 -05:00
David Teigland
9048565093 devices: rework libudev usage
related to config settings:
  obtain_device_info_from_udev (controls if lvm gets
    a list of devices from readdir /dev or from libudev)
  external_device_info_source (controls if lvm asks
    libudev for device information)

. Make the obtain_device_list_from_udev setting
  affect only the choice of readdir /dev vs libudev.
  The setting no longer controls if udev is used for
  device type checks.

. Change obtain_device_list_from_udev default to 0.
  This helps avoid boot timeouts due to slow libudev
  queries, avoids reported failures from
  udev_enumerate_scan_devices, and avoids delays from
  "device not initialized in udev database" errors.
  Even without errors, for a system booting with 1024 PVs,
  lvm2-pvscan times improve from about 100 sec to 15 sec,
  and the pvscan command from about 64 sec to about 4 sec.

. For external_device_info_source="none", remove all
  libudev device info queries, and use only lvm
  native device info.

. For external_device_info_source="udev", first check
  lvm native device info, then check libudev info.

. Remove sleep/retry loop when attempting libudev
  queries for device info.  udev info will simply
  be skipped if it's not immediately available.

. Only set up a libdev connection if it will be used by
  obtain_device_list_from_udev/external_device_info_source.

. For native multipath component detection, use
  /etc/multipath/wwids.  If a device has a wwid
  matching an entry in the wwids file, then it's
  considered a multipath component.  This is
  necessary to natively detect multipath
  components when the mpath device is not set up.
2021-07-13 11:11:23 -05:00
Heming Zhao
db22a389cf toolcontext: fix double free (core dumped) issue
How to trigger:

```
~ # export LVM_SYSTEM_DIR=_
~ # pvscan
  No matching physical volumes found
double free or corruption (!prev)
Aborted (core dumped)
```

when LVM_SYSTEM_DIR is empty, _load_config_file() won't be called.

when LVM_SYSTEM_DIR is not empty, cfl->cft links into cmd->config_files
by _load_config_file()@lib/commands/toolcontext.c

core dumped code: _destroy_config()@lib/commands/toolcontext.c

```
    /* CONFIG_FILE/CONFIG_MERGED_FILES */
    if ((cft = remove_config_tree_by_source(cmd, CONFIG_MERGED_FILES)))
        config_destroy(cft);
    else if ((cft = remove_config_tree_by_source(cmd, CONFIG_FILE)))
        config_destroy(cft); <=== first free the cft

    dm_list_iterate_items(cfl, &cmd->config_files)
        config_destroy(cfl->cft); <=== double free the cft
```

Fixes: c43f2f8ae0

Signed-off-by: Heming Zhao <heming.zhao@suse.com>
2021-07-12 14:10:21 -05:00
David Teigland
66daedc6d2 skip indexing devices used by LVs in more commands
expands commit d5a06f9a7d
  "pvscan: skip indexing devices used by LVs"

The dev cache index is expensive and slow, so limit it
to commands that are used to observe the state of lvm.
The index is only used to print warnings about incorrect
device use by active LVs, e.g. if an LV is using a
multipath component device instead of the multipath
device.  Commands that continue to use the index and
print the warnings:

  fullreport, lvmdiskscan, vgs, lvs, pvs,
  vgdisplay, lvdisplay, pvdisplay,
  vgscan, lvscan, pvscan (excluding --cache)

A couple other commands were borrowing the DEV_USED_FOR_LV
flag to just check if a device was actively in use by LVs.
These are converted to the new dev_is_used_by_active_lv().
2021-07-09 13:59:31 -05:00
Zdenek Kabelac
70c32d1e74 man: vdoimport page 2021-07-09 20:50:40 +02:00
Zdenek Kabelac
ed48cb26a3 vdo: add vdoimport support
Add tool 'vdoimport' to support easy conversion of an existing VDO manager managed
VDO volumes into lvm2 managed VDO LV.

When physical converted volume is already a logical volume, conversion
happens with the VG itself, just with validation for extent_size, so
the virtually sized logical VDO volume size can be expressed in extents.

Example of basic simple usage:

vdoimport --name vg/vdolv  /dev/mapper/vdophysicalvolume
2021-07-09 14:57:59 +02:00
Zdenek Kabelac
3a92d633a5 configure: updates 2021-07-09 14:57:59 +02:00
David Teigland
d5a06f9a7d pvscan: skip indexing devices used by LVs
dev_cache_index_devs() is taking a large amount of time
when there are many PVs.  The index keeps track of
devices that are currently in use by active LVs.  This
info is used to print warnings for users in some limited
cases.

The checks/warnings that are enabled by the index are not
needed by pvscan --cache, so disable it in this case.

This may be expanded to other cases in future commits.
dev_cache_index_devs should also be improved in another
commit to avoid the extreme delays with many devices.
2021-07-06 10:18:07 -05:00
David Teigland
b876dbfc24 scan: move metadata vgname check
There have been two separate checks for metadata
validity: first that the metadata text begins with
a valid VG name, and second the checksum of the
metadata text.  These happen in different places,
which means there have been two separate error paths
for invalid metadata.  This also causes large metadata
to be read in multiple parts, the first part is read
just to check the vgname, and then remaining parts are
read later when the full metadata is needed.

This patch moves the vg name verification so it's
done just before the checksum verification, which
results in a single error path for invalid metadata,
and causes the entire metadata to be read together
rather that in parts from different parts of the code.
2021-07-06 10:10:23 -05:00
David Teigland
e035e32350 scan: retry reading metadata on error
If label_scan encounters bad vg metadata, invalidate
bcache data for the device and reread the mda_header
and metadata text back to back.  With concurrent commands
modifying large metadata, it's possible that the entire
metadata area can be rewritten in the time between a
command reading the mda_header and reading the metadata
text that the header points to.  Since the label_scan
is just assembling an initial overview of devices, it
doesn't use locking to serialize with other commands
that may be modifying the vg metadata at the same time.
2021-07-06 10:10:23 -05:00
David Teigland
d89942d157 scan: don't hold bcache block during scan
This allows data from the bcache block to be
invalidated and reread if needed.
2021-07-06 10:10:23 -05:00
David Teigland
a47e20a092 tests: skip tests that require blkid BLOCK_SIZE
Recent commit 84bd394cf9
  "writecache: use block size 4096 when no fs is found"

changed the default writecache block size from 512 to 4096
when no file system is detected.  The fs block size detection
requires the libblkid BLOCK_SIZE feature, so skip tests on
systems without this.  Otherwise, 4096 writecache added to
512 xfs leads fs io or mount failures.
2021-06-30 11:56:42 -05:00
Zdenek Kabelac
39f497b9d8 WHATS_NEW: update 2021-06-28 20:41:07 +02:00
Zdenek Kabelac
580e64e93b make: generate 2021-06-28 20:41:07 +02:00
Zdenek Kabelac
2c6a2b6e86 vdo: support vdo_pool_header_size
Add profilable configurable setting for vdo pool header size, that is
used as 'extra' empty space at the front and end of vdo-pool device
to avoid having a disk in the system the may have same data is real
vdo LV.

For some conversion cases however we may need to allow using '0' header size.

TODO: in this case we may eventually avoid adding 'linear' mapping layer
in future - but this requires further modification over lvm code base.
2021-06-28 20:41:07 +02:00
Zdenek Kabelac
5fcbc3bd7d vdo: rename variable vdo_pool_zero
Match rest of code.
2021-06-28 20:41:07 +02:00
Zdenek Kabelac
6e773bb196 lvconvert: fix vdo virtual size when specified
Correctly use virtual size specified by:
lvconvert --type vdo-pool --virtualsize
2021-06-28 20:41:07 +02:00
Zdenek Kabelac
d9cb1d3983 config_settings: typo fix 2021-06-28 18:11:14 +02:00
David Teigland
73a05c8f02 device_id: handle qemu wwid
Ignore made-up wwid values reported for qemu devices
that contain the string "QEMU HARDDISK".  The devname
will be used as the device id.
2021-06-24 11:30:46 -05:00
David Teigland
84bd394cf9 writecache: use block size 4096 when no fs is found
When there is no block size constraint from a file system
or from a user setting, use 4096 rather than 512 because of
better performance.
2021-06-23 12:38:57 -05:00
David Teigland
1139a05939 device_id: handle scsi_debug wwid
Ignore the wwid value reported by scsi_debug devices
that begin "t10.Linux   scsi_debug".  The devname
will be used as the device id.
2021-06-22 13:36:10 -05:00
David Teigland
c35f7722d5 lvconvert: allow writecache with other thinpool command syntax
"lvconvert --thinpool LV" should allow LV to have a writecache,
but there was an extra type check preventing it.
2021-06-17 16:15:18 -05:00
Tony Asleson
f773040625 lvmdbusd: Wrap json.load in try/except
In testing where we inject large amounts of additional output in stderr
we can occassionally get truncated stdout from lvm.  Catching and dumping
the json for debug before we re-raise the exception.  As this doesn't
happen without the error injecting wrapper around lvm, the error seems to
be with the wrapper.

Signed-off-by: Tony Asleson <tasleson@redhat.com>
2021-06-17 09:14:29 -05:00
Tony Asleson
c474f174cc lvmdbusd: Handle arbitrary amounts stdout & stderr
When exec'ing lvm, it's possible to get large amounts of both stdout
and stderr depending on the state of lvm and the size of the lvm
configuration.  If we allow any of the buffers to fill we can end
up deadlocking the process.  Ensure we are handling stdout & stderr
during lvm execution.

Ref. https://bugzilla.redhat.com/show_bug.cgi?id=1966636

Signed-off-by: Tony Asleson <tasleson@redhat.com>
2021-06-17 09:14:29 -05:00
David Teigland
71cb54d92f coverity cleanups 2021-06-16 13:42:51 -05:00
Tony Asleson
f70d97b916 lvmdbusd: Defer dbus object removal
When we are walking the new lvm state comparing it to the old state we can
run into an issue where we remove a VG that is no longer present from the
object manager, but is still needed by LVs that are left to be processed.
When we try to process existing LVs to see if their state needs to be
updated, or if they need to be removed, we need to be able to reference the
VG that was associated with it.  However, if it's been removed from the
object manager we fail to find it which results in:

Traceback (most recent call last):
File "/usr/lib/python3.6/site-packages/lvmdbusd/utils.py", line 666, in _run
  self.rc = self.f(*self.args)
File "/usr/lib/python3.6/site-packages/lvmdbusd/fetch.py", line 36, in _main_thread_load
  cache_refresh=False)[1]
File "/usr/lib/python3.6/site-packages/lvmdbusd/lv.py", line 146, in load_lvs
  lv_name, object_path, refresh, emit_signal, cache_refresh)
File "/usr/lib/python3.6/site-packages/lvmdbusd/loader.py", line 68, in common
  num_changes += dbus_object.refresh(object_state=o)
File "/usr/lib/python3.6/site-packages/lvmdbusd/automatedproperties.py", line 160, in refresh
  search = self.lvm_id
File "/usr/lib/python3.6/site-packages/lvmdbusd/lv.py", line 483, in lvm_id
  return self.state.lvm_id
File "/usr/lib/python3.6/site-packages/lvmdbusd/lv.py", line 173, in lvm_id
  return "%s/%s" % (self.vg_name_lookup(), self.Name)
File "/usr/lib/python3.6/site-packages/lvmdbusd/lv.py", line 169, in vg_name_lookup
  return cfg.om.get_object_by_path(self.Vg).Name

Instead of removing objects from the object manager immediately, we will
keep them in a list and remove them once we have processed all of the state.

Ref:
https://bugzilla.redhat.com/show_bug.cgi?id=1968752
2021-06-16 12:19:02 -05:00
Tony Asleson
e8f3a63000 lvmdbusd: Don't setup search key unless needed
self.lvm_id is a property which actually executes some code which doesn't
need to be executed everytime.
2021-06-16 12:19:02 -05:00
Leo Yan
27abb03a0d tests: Fix building for IDM program
When execute IDM testing, the command reports error:

  /usr/bin/install: cannot stat ‘lib/idm_inject_failure’: No such file
  or directory

Since there have a stale program in my local environment, thus Makefile
always uses the stale program and doesn't report any issue.  In the
brand new repository, it doesn't contain an idm_inject_failure program,
and Makefile doesn't build it without specifying the dependency, thus
the test command complaints the file 'idm_inject_failure' is not found.

This patch adds the dependency 'lib/idm_inject_failure' for IDM testing,
so it can firstly build the injection program and dismiss the error.

Signed-off-by: Leo Yan <leo.yan@linaro.org>
2021-06-16 10:35:12 -05:00
Leo Yan
f25df0386e tests: stress: Change to use $SHARED for vgcreate
Use the variable $SHARED to replace "--shared" for vgcreate commands.

Signed-off-by: Leo Yan <leo.yan@linaro.org>
2021-06-16 10:35:12 -05:00
David Teigland
e5740e9646 tests: fix skip in stress_single_thread.sh 2021-06-16 09:37:04 -05:00
David Teigland
f8742b6df2 tests: add some LVM_TEST_LOCK_TYPE_IDM 2021-06-15 14:02:45 -05:00
David Teigland
440d6ae79f lvmdevices: add deviceidtype option
When adding a device to the devices file with --adddev, lvm
by default chooses the best device ID type for the new device.
The new --deviceidtype option allows the user to override the
built in preference.  This is useful if there's a problem with
the default type, or if a secondary type is preferrable.

If the specified deviceidtype does not produce a device ID,
then lvm falls back to the preference it would otherwise use.
2021-06-11 13:27:18 -05:00
Wu Guanghao
8331321070 pvck: add lock_global() before clean_hint_file()
Signed-off-by: Wu Guanghao <wuguanghao3@huawei.com>
2021-06-11 10:21:07 -05:00
Zdenek Kabelac
17b2746486 archive: avoid abuse of internal flag
Since archive is now postponned we use internal variable 'changed'
to mark we need to commit new metadata.
2021-06-09 16:18:20 +02:00
Zdenek Kabelac
bb45e33518 backup: automatically store data on vg_unlock
Previously there have been necessary explicit call of backup (often
either forgotten or over-used). With this patch the necessity to
store backup is remember at vg_commit and once the VG is unlocked,
the committed metadata are automatically store in backup file.

This may possibly alter some printed messages from command when the
backup is now taken later.
2021-06-09 14:56:13 +02:00
Zdenek Kabelac
ba3707d953 archiving: take archive automatically
Instead of calling explicit archive with command processing logic,
move this step towards 1st. vg_write() call, which will automatically
store archive of committed metadata.

This slightly changes some error path where the error in archiving
was detected earlier in the command, while now some on going command
'actions' might have been, but will be simply scratched in case
of error (since even new metadata would not have been even written).

So general effect should be only some command message ordering.
2021-06-09 14:56:13 +02:00
David Teigland
df27392c8c man/help: fix common option listing 2021-06-08 14:07:39 -05:00
David Teigland
ca930bd936 devices: don't use deleted loop backing file for device id
check for "(deleted)" in the backing_file string and
fall back to devname for id.

$ cat /sys/block/loop0/loop/backing_file
/root/looptmp (deleted)
2021-06-08 12:16:06 -05:00
Leo Yan
5e17203ff5 lvmlockd: Fix the compilation warning
As SUSE build tool reports the warning:

lvmlockd-core.c: In function 'client_thread_main':
lvmlockd-core.c:4959:37: warning: '%d' directive output may be truncated writing between 1 and 10 bytes into a region of size 6 [-Wformat-truncation=]
    snprintf(buf, sizeof(buf), "path[%d]", i);
                                     ^~
lvmlockd-core.c:4959:31: note: directive argument in the range [0, 2147483647]
    snprintf(buf, sizeof(buf), "path[%d]", i);
                               ^~~~~~~~~~

To dismiss the compilation warning, enlarge the array "buf" to 17
bytes to support the max signed integer: string format 6 bytes + signed
integer 10 bytes + terminal char "\0".

Reported-by: Heming Zhao <heming.zhao@suse.com>
Signed-off-by: Leo Yan <leo.yan@linaro.org>
2021-06-08 09:33:26 -05:00
David Teigland
9759f915e7 tests: add writecache-cache-blocksize-2
inconsistent physical block size of devs used
for main LV and cache
2021-06-07 15:40:40 -05:00
David Teigland
ff677aa69f tests: rename test 2021-06-07 12:12:33 -05:00
David Teigland
a7f334a532 tests: writecache-blocksize add dm-cache tests
Add the same tests for dm-cache as exist for dm-writecache,
dm-cache uses a different blocksize in a couple cases.
2021-06-07 12:11:12 -05:00
David Teigland
c43f2f8ae0 fix empty mem pool leak
of "config" when LVM_SYSTEM_DIR=""
2021-06-03 14:46:33 -05:00
Leo Yan
fe05828e7e tests: multi-hosts: Test lease timeout with LV shareable mode
This patch is to test timeout handling after activate LV with shareable
mode.  It has the same logic with the testing for LV exclusive mode,
except it verifies the locking with shareable mode.

  On the host A:
    make check_lvmlockd_idm \
      LVM_TEST_BACKING_DEVICE=/dev/sdj3,/dev/sdk3,/dev/sdl3 \
      LVM_TEST_MULTI_HOST=1 T=multi_hosts_lv_sh_timeout_hosta.sh

  On the host B:
    make check_lvmlockd_idm \
      LVM_TEST_BACKING_DEVICE=/dev/sdj3,/dev/sdk3,/dev/sdl3 \
      LVM_TEST_MULTI_HOST=1 T=multi_hosts_lv_sh_timeout_hostb.sh

Signed-off-by: Leo Yan <leo.yan@linaro.org>
2021-06-03 09:39:32 -05:00
Leo Yan
0a4d6d9d1d tests: multi-hosts: Test lease timeout with LV exclusive mode
This patch is to test timeout handling after activate LV with exclusive
mode.  It contains two scripts for host A and host B separately.

The script on host A firstly creates VGs and LVs based on the passed
back devices, every back device is for a dedicated VG and a LV is
created as well in the VG.  Afterwards, all LVs are activated by host A,
so host A acquires the lease for these LVs.  Then the test is designed
to fail on host A.

After the host A fails, host B starts to run the paired testing script,
it firstly fails to activate the LVs since the locks are leased by
host A; after lease expiration (after 70s), host B can achieve the lease
for LVs and it can operate LVs and VGs.

  On the host A:
    make check_lvmlockd_idm \
      LVM_TEST_BACKING_DEVICE=/dev/sdj3,/dev/sdk3,/dev/sdl3 \
      LVM_TEST_MULTI_HOST=1 T=multi_hosts_lv_ex_timeout_hosta.sh

  On the host B:
    make check_lvmlockd_idm \
      LVM_TEST_BACKING_DEVICE=/dev/sdj3,/dev/sdk3,/dev/sdl3 \
      LVM_TEST_MULTI_HOST=1 T=multi_hosts_lv_ex_timeout_hostb.sh

Signed-off-by: Leo Yan <leo.yan@linaro.org>
2021-06-03 09:39:32 -05:00
Leo Yan
e9950efff1 tests: multi-hosts: Add LV testing
This patch is to add LV testing on multi hosts.  There have two scripts,
the script multi_hosts_lv_hosta.sh is used to create LVs on one host,
and the second script multi_hosts_lv_hostb.sh will acquire
global lock and VG lock, and remove VGs.  The testing flow verifies the
locking operations between two hosts with lvmlockd and the backend
locking manager.

  On the host A:
    make check_lvmlockd_idm \
      LVM_TEST_BACKING_DEVICE=/dev/sdj3,/dev/sdk3,/dev/sdl3 \
      LVM_TEST_MULTI_HOST=1 T=multi_hosts_lv_hosta.sh

  On the host B:
    make check_lvmlockd_idm \
      LVM_TEST_BACKING_DEVICE=/dev/sdj3,/dev/sdk3,/dev/sdl3 \
      LVM_TEST_MULTI_HOST=1 T=multi_hosts_lv_hostb.sh

Signed-off-by: Leo Yan <leo.yan@linaro.org>
2021-06-03 09:39:32 -05:00
Leo Yan
e75bd71aae tests: multi-hosts: Add VG testing
This patch is to add VG testing on multi hosts.  There have two scripts,
the script multi_hosts_vg_hosta.sh is used to create VGs on one host,
and the second script multi_hosts_vg_hostb.sh afterwards will acquire
global lock and VG lock, and remove VGs.  The testing flow verifies the
locking operations between two hosts with lvmlockd and the backend
locking manager.

  On the host A:
    make check_lvmlockd_idm \
      LVM_TEST_BACKING_DEVICE=/dev/sdj3,/dev/sdk3,/dev/sdl3 \
      LVM_TEST_MULTI_HOST=1 T=multi_hosts_vg_hosta.sh

  On the host B:
    make check_lvmlockd_idm \
      LVM_TEST_BACKING_DEVICE=/dev/sdj3,/dev/sdk3,/dev/sdl3 \
      LVM_TEST_MULTI_HOST=1 T=multi_hosts_vg_hostb.sh

Signed-off-by: Leo Yan <leo.yan@linaro.org>
2021-06-03 09:39:32 -05:00
Leo Yan
92b47d8eb8 tests: idm: Add testing for IDM lock manager failure
If the IDM lock manager fails to access drives, might partially fail to
access drives (e.g. it fails to access one of three drives), or totally
fail to access drives, the lock manager should handle properly for these
cases.  When the drives are partially failure, if the lock manager still
can renew the lease for the locking, then it doesn't need to take any
action for the drive failure; otherwise, if it detects it cannot renew
the locking majority, it needs ti immediately kill the VG from the
lvmlockd.

This patch adds the test for verification the IDM lock manager failure;
the command can be used as below:

  # make check_lvmlockd_idm \
    LVM_TEST_BACKING_DEVICE=/dev/sdp3,/dev/sdl3,/dev/sdq3 \
    LVM_TEST_FAILURE=1 T=idm_ilm_failure.sh

Signed-off-by: Leo Yan <leo.yan@linaro.org>
2021-06-03 09:39:32 -05:00
Leo Yan
38abd6bb2c tests: idm: Add testing for the fabric's half brain failure
If the fabric is broken instantly and the partial drives connected on
the fabric disappear from the system.  For this case, according to the
locking algorithm in idm, the lease will not lose since the half drives
are still alive so can renew the lease for the half drives.  On the
other hand, since the VG lock requires to acquire the majority of drive
number, but half drives failure cannot achieve the majority, so it
cannot acquire the lock for VG and thus cannot change metadata for VG.

This patch is to add half brain failure for idm; the test command is as
below:

  # make check_lvmlockd_idm \
	LVM_TEST_BACKING_DEVICE=/dev/sdp3,/dev/sdo3 LVM_TEST_FAILURE=1 \
	T=idm_fabric_failure_half_brain.sh

Signed-off-by: Leo Yan <leo.yan@linaro.org>
2021-06-03 09:39:32 -05:00
Leo Yan
91d3b56875 tests: idm: Add testing for the fabric failure and timeout
If the fabric is broken instantly, the drives connected on the fabric
will disappear from the system.  For worst case, the lease is timeout
and the drives cannot recovery back.  So a new test is added to emulate
this scenario, it uses a drive for LVM operations and this drive is also
used for locking scheme; if the drive and all its associated paths (if
the drive supports multiple paths) are disconnected, the lock manager
should stop the lockspace for the VG/LVs.

And afterwards, if the drive recovers back, the VG/LV resident in the
drive should be operated properly.  The test command is as below:

  # make check_lvmlockd_idm \
	LVM_TEST_BACKING_DEVICE=/dev/sdp3 LVM_TEST_FAILURE=1 \
	T=idm_fabric_failure_timeout.sh

Signed-off-by: Leo Yan <leo.yan@linaro.org>
2021-06-03 09:39:32 -05:00
Leo Yan
fc0495ea04 tests: idm: Add testing for the fabric failure
When the fabric failure occurs, it will lose the connection with hosts
instantly, and after a while it can recovery back so that the hosts can
continue to access the drives.

For this case, the locking manager should be reliable for this case and
can dynamically handle this case and allows user to continue to use the
VG/LV with associated locking scheme.

This patch adds a testing to emulate the fabric faliure, verify LVM
commands for this case.  The testing usage is:

  # make check_lvmlockd_idm \
	LVM_TEST_BACKING_DEVICE=/dev/sdo3,/dev/sdp3,/dev/sdp4 \
	LVM_TEST_FAILURE=1 T=idm_fabric_failure.sh

Signed-off-by: Leo Yan <leo.yan@linaro.org>
2021-06-03 09:39:32 -05:00
Leo Yan
874001ee6e tests: Add testing for lvmlockd failure
After the lvmlockd abnormally exits and relaunch the daemon, if LVM
commands continue to run, lvmlockd and the backend lock manager (e.g.
sanlock lock manager or IDM lock manager) should can continue to serve
the requests from LVM commands.

This patch adds a test to emulate lvmlockd failure, and verify the LVM
commands after lvmlockd recovers back.  Below is an example for testing
the case:

  # make check_lvmlockd_idm \
	LVM_TEST_BACKING_DEVICE=/dev/sdo3,/dev/sdp3,/dev/sdp4 \
	LVM_TEST_FAILURE=1 T=lvmlockd_failure.sh

Signed-off-by: Leo Yan <leo.yan@linaro.org>
2021-06-03 09:39:32 -05:00
Leo Yan
8c7b2df41f tests: Support idm failure injection
When the drive failure occurs, the IDM lock manager and lvmlockd should
handle this case properly.  E.g. when the IDM lock manager detects the
lease renewal failure caused by I/O errors, it should invoke the kill
path which is predefined by lvmlockd, so that the kill path program
(like lvmlockctl) can send requests to lvmlockd to stop and drop lock
for the relevant VG/LVs.

To verify the failure handling flow, this patch introduces an idm
failure injection program, it can input the "percentage" for drive
failures so that can emulate different failure cases.

Signed-off-by: Leo Yan <leo.yan@linaro.org>
2021-06-03 09:39:32 -05:00
Leo Yan
f83e11ff43 tests: stress: Add multi-threads stress testing for PV/VG/LV
This patch is to add the stress testing, which launches three threads,
one thread is for creating/removing PV, one thread is for
creating/removing VG, and the last one thread is for LV operations.

Signed-off-by: Leo Yan <leo.yan@linaro.org>
2021-06-03 09:39:32 -05:00
Leo Yan
692fe7bb31 tests: stress: Add multi-threads stress testing for VG/LV
This patch is to add the stress testing, which launches two threads,
each thread creates LV, activate and deactivate LV in the loop; so this
can test for multi-threading in lvmlockd and its backend lock manager.

Signed-off-by: Leo Yan <leo.yan@linaro.org>
2021-06-03 09:39:32 -05:00
Leo Yan
fe660467fa tests: stress: Add single thread stress testing
This patch is to add the stress testing, which loops to create LV,
activate and deactivate LV in the single thread.

Signed-off-by: Leo Yan <leo.yan@linaro.org>
2021-06-03 09:39:32 -05:00
Leo Yan
5b361b197e tests: Add checking for lvmlockd log
Add checking for lvmlockd log, this can be used for the test cases which
are interested in the interaction with lvmlockd.

Signed-off-by: Leo Yan <leo.yan@linaro.org>
2021-06-03 09:39:32 -05:00
Leo Yan
2097c27c05 tests: Cleanup idm context when prepare devices
For testing idm locking scheme, it's good to cleanup the idm context
before run the test cases.  This can give a clean environment for the
testing.

Signed-off-by: Leo Yan <leo.yan@linaro.org>
2021-06-03 09:39:32 -05:00
Leo Yan
759b0392d5 tests: Support multiple backing devices
In current implementation, the option "LVM_TEST_BACKING_DEVICE" only
supports to specify one backing device; this patch is to extend the
option to support multiple backing devices by using comma as separator,
e.g. below command specifies two backing devices:

  make check_lvmlockd_idm LVM_TEST_BACKING_DEVICE=/dev/sdj3,/dev/sdk3

This can allow the testing works on multiple drives and verify the
locking scheme if can work as expected for multiple drives case.  For
example, for Seagate IDM locking scheme, if a VG uses two PVs, every PV
is resident on a drive, thus the locking operations will be sent to two
drives respectively; so the extension for "LVM_TEST_BACKING_DEVICE" can
help to verify different drive configurations for locking.

Signed-off-by: Leo Yan <leo.yan@linaro.org>
2021-06-03 09:39:32 -05:00
Leo Yan
c64dbc7ee8 tests: Enable the testing for IDM locking scheme
This patch is to introduce testing option LVM_TEST_LOCK_TYPE_IDM, with
specifying this option, the Seagate IDM lock manager will be launched as
backend for testing.  Also add the prepare and remove shell scripts for
IDM.

Signed-off-by: Leo Yan <leo.yan@linaro.org>
2021-06-03 09:39:32 -05:00
David Teigland
2bce6faed0 pvchange: fix file locking deadlock
Calling clear_hint_file() to invalidate hints would acquire
the hints flock before the global flock which could cause deadlock.
The lock order requires the global lock to be taken first.

pvchange was always invalidating hints, which was unnecessary;
only invalidate hints when changing a PV uuid.  Because of the
lock ordering, take the global lock before clear_hint_file which
locks the hints file.
2021-06-02 16:29:54 -05:00
David Teigland
e7f107c246 writecache: don't pvmove device used by writecache
The existing check didn't cover the unusual case where the
cachevol exists on the same device as the origin LV.
2021-06-02 11:12:20 -05:00
David Teigland
247f69f9aa writecache: fix lv_on_pmem
dev_is_pmem on pv->dev requires a pv segment or it could segfault.
2021-06-02 10:51:12 -05:00
Zdenek Kabelac
b725b5ea6e vdo: fix preload of kvdo
Commit 5bf1dba9eb broke load of kvdo
kernel module - correct it by loading kvdo instead of trying dm-vdo.
2021-05-26 16:12:20 +02:00
David Teigland
4a746f7ffc lvremove: fix removing thin pool with writecache on data 2021-05-24 16:09:35 -05:00
David Teigland
a65f8e0a62 enable command syntax for thin and writecache
converting an LV with a writecache to thin pool data in
addition to previous attaching writecache to thin pool data
2021-05-24 16:09:35 -05:00
Leo Yan
102294f978 configure: Add macro LOCKDIDM_SUPPORT
The macro LOCKDIDM_SUPPORT is missed in configure.h.in file, thus when
execute "configure" command, it has no chance to add this macro in the
automatic generated header include/configure.h.

This patch adds macro LOCKDIDM_SUPPORT into configure.h.in.

Signed-off-by: Leo Yan <leo.yan@linaro.org>
2021-05-21 09:27:30 -05:00
Leo Yan
8b904dc711 tools: Add support for "idm" lock type
This patch is to update the comment and code to support "idm" lock type
which is used for LVM toolkit.

Signed-off-by: Leo Yan <leo.yan@linaro.org>
2021-05-20 16:01:05 -05:00
Leo Yan
affe1af148 lib: locking: Parse PV list for IDM locking
For shared VG or LV locking, IDM locking scheme needs to use the PV
list assocated with VG or LV for sending SCSI commands, thus it requires
to use some places to generate PV list.

In reviewing the flow for LVM commands, the best place to generate PV
list is in the locking lib.  So this is why this patch parses PV list as
shown.  It iterates over all the PV nodes one by one, and compare with
the VG name or LV prefix string.  If any PV matches, then the PV is
added into the PV list.  Finally the PV list is sent to lvmlockd daemon.

Here as mentioned, it compares LV prefix string with the format
"lv_name_", the reason is it needs to find out all relevant PVs, e.g.
for the thin pool, it has LVs for metadata, pool, error, and raw LV, so
we can use the prefix string to find out all PVs belonging to the thin
pool.

For the global lock, it's not covered in this patch.  To avoid the egg
and chicken issue, we need to prepare the global lock ahead before any
locking can be used.  So the global lock's PV list is established in
lvmlockd daemon by iterating all drives with partition labeled with
"propeller".

Signed-off-by: Leo Yan <leo.yan@linaro.org>
2021-05-20 16:01:05 -05:00
Leo Yan
ef1c57e68f lib: locking: Add new type "idm"
We can consider the drive firmware a server to handle the locking
request from nodes, this essentially is a client-server model.
DLM uses the kernel as a central place to manage locks, so it also
complies with client-server model for locking operations.  This is
why IDM and DLM are similar with each other for their wrappers.

This patch largely works by generalizing the DLM code paths and then
providing degeneralized functions as wrappers for both IDM and DLM.

Signed-off-by: Leo Yan <leo.yan@linaro.org>
2021-05-20 16:01:05 -05:00
Leo Yan
d02f5392a0 lvmlockd: idm: Hook Seagate IDM wrapper APIs
To allow the IDM locking scheme be used by users, this patch hooks the
IDM wrapper; it also introducs a new locking type "idm" and we can use
it for global lock with option '-g idm'.

To support IDM locking type, the main change in the data structure is to
add pvs path arrary.  The pvs list is transferred from the lvm commands,
when lvmlockd core layer receives message, it extracts the message with
the keyword "path[idx]".  Finally, the pv list will pass to IDM lock
manager as the target drives for sending IDM SCSI commands.

Signed-off-by: Leo Yan <leo.yan@linaro.org>
2021-05-20 16:01:04 -05:00
Leo Yan
7a8b7b4add lvmlockd: idm: Introduce new locking scheme
Alongside the existed locking schemes of DLM and sanlock, this patch is
to introduce new locking scheme: In-Drive-Mutex (IDM).

With the IDM support in the drive, the locks are resident in the drive,
thus, the locking lease is maintained in a central place: the drive
firmware.  We can consider this is a typical client-server model,
every host (or node) in the server cluster launches the request for
leasing mutex to a drive firmware, the drive firmware works as an
arbitrator to grant the mutex to a requester and it can reject other
applicants if the mutex has been acquired.  To satisfy the LVM
activation for different modes, IDM supports two locking modes:
exclusive and shareable.

Every IDM is identified with two IDs, one is the host ID and another is
the resource ID.  The resource ID is a unique identifier for what the
resource it's protected, in the integration with lvmlockd, the resource
ID is combined with VG's UUID and LV's UUID; for the global locking,
the bytes in resource ID are all zeros, and for the VG locking, the
LV's UUID is set as zero.   Every host can generate a random UUID and
use it as the host ID for the SCSI command, this ID is used to clarify
the ownership for mutex.

For easily invoking the IDM commands to drive, like other locking
scheme (e.g. sanlock), a daemon program named IDM lock manager is
created, so the detailed IDM SCSI commands are encapsulated in the
daemon, and lvmlockd uses the wrapper APIs to communicate with the
daemon program.

This patch introduces the IDM locking wrapper layer, it forwards the
locking requests from lvmlockd to the IDM lock manager, and returns the
result from drives' responding.

One thing should be mentioned is the IDM's LVB.  IDM supports LVB to max
7 bytes when stores into the drive, the most significant byte of 8 bytes
is reserved for control bits.  For this reason, the patch maps the
timestamp in macrosecond unit with its cached LVB, essentially, if any
timestamp was updated by other nodes, that means the local LVB is
invalidate.  When the timestamp is stored into drive's LVB, it's
possbile to cause time-going-backwards issue, which is introduced by the
time precision or missing synchronization acrossing over multiple nodes.
So the IDM wrapper fixes up the timestamp by increment 1 to the latest
value and write back into drive.

Currently LVB is used to track VG changes and its purpose is to notify
lvmetad cache invalidation when detects any metadata has been altered;
but lvmetad is not used anymore for caching metadata, LVB doesn't
really work.  It's possible that the LVB functionality could be useful
again in the future, so let's enable it for IDM in the first place.

Signed-off-by: Leo Yan <leo.yan@linaro.org>
2021-05-20 16:00:59 -05:00
Marian Csontos
3e2f09d78b post-release 2021-05-07 23:09:15 +02:00
Marian Csontos
01b05cf51d pre-release 2021-05-07 23:09:09 +02:00
Marian Csontos
64719861ec make: generate 2021-05-07 17:44:43 +02:00
David Teigland
00f603de2c tests: add lvextend-caches-on-thindata
to test lvextend of thin pool data while it has
cache|writecache attached
2021-05-06 16:23:26 -05:00
David Teigland
6b00c8c910 writecache: allow attaching to thin pool data 2021-05-06 16:23:03 -05:00
David Teigland
92fcfc59b2 tests: new lvextend-caches
to test lvextend of LVs with attached cache|writecache
2021-05-06 14:43:10 -05:00
David Teigland
318bb3a06b blkid: simplify fs block size check
Only the LV path name is needed for blkid query,
the step of getting a dev struct is not needed.
2021-05-05 16:15:10 -05:00
David Teigland
71933d3496 devices file: recommend removing filter
When the devices file is enabled and the filter is set,
recommand that the user remove the filter from lvm.conf
since it's ignored.
2021-05-05 13:59:42 -05:00
David Teigland
2419345b9d pvremove: use consistent error message
When the device is not a PV print
  "No PV found on device ..."

instead of
  "Failed to read lvm info for ... PVID ."

an earlier check had been added with a different
message for the same condition.
2021-05-04 13:08:02 -05:00
David Teigland
4dc5d4ac7e label_read_pvid: separate error and no-pvid
error reading dev and no pvid on dev were both
returning 0.  make it easier for callers to
know which, if they care.

return 1 if the device could be read, regardless
of whether a pvid was found or not.
set has_pvid=1 if a pvid is found and 0 if no
pvid is found.
2021-04-23 17:37:08 -05:00
David Teigland
fcbed26393 Revert "cov: check label_read_pvid return value"
This reverts commit bf461b99c6.

label_read_pvid returns 0 for non-PVs and these callers want
to handle non-PVs.
2021-04-23 17:12:24 -05:00
Zdenek Kabelac
9cdd4dcca7 make: generate 2021-04-23 23:02:58 +02:00
Zdenek Kabelac
64a8505b96 tests: use should for expected state
While we heavily try to spot arrays that are not yet in-sync,
some kernels tends to block our lvm2 command in kernel,
while we resume these smaller raid arrays even for 5 seconds.

But since the result is not really wrong - report these
check failures only as TEST WARNING.
2021-04-23 23:00:55 +02:00
Zdenek Kabelac
05eb90db68 cleanup: indent 2021-04-23 23:00:55 +02:00
Zdenek Kabelac
fccd6e0346 makefiles: add target for man-generator
Add supporting target for recreating man-generator when dependencies needs it.
2021-04-23 23:00:55 +02:00
Zdenek Kabelac
348c46c8fc man: add some resizing examples
Add some examples with -l% usage.
2021-04-23 23:00:55 +02:00
Zdenek Kabelac
a21028dea7 man: add missing _iorig suffix 2021-04-23 23:00:55 +02:00
Zdenek Kabelac
579c941321 man: document fsadm -l option
Missed -l option in man page, although users should prefer
lvresize -r when the also want to do a volume management,
as there they can specify i.e. extents for allocation.
Also mention dm-crypt support in command description.
2021-04-23 23:00:55 +02:00
Zdenek Kabelac
6f61de3009 args.h: bold command refference 2021-04-23 23:00:55 +02:00
Zdenek Kabelac
f678052385 shellcheck: updates
Ehance some shellcheck reported issues.
2021-04-23 23:00:55 +02:00
Zdenek Kabelac
6a099707c4 clang: remove unused assignment 2021-04-23 23:00:55 +02:00
Zdenek Kabelac
49caa9f3b1 clang: ensure vg is defined 2021-04-23 23:00:55 +02:00
Zdenek Kabelac
51fd232b8e clang: avoid possible use-after-free
If the 'act' has been already processed by add_client_result()
it could have been possibly release - so avoid accessin 'act->'
afterward and go for next item directly.
2021-04-23 23:00:55 +02:00
Zdenek Kabelac
21bdd0a359 clang: always initialized values 2021-04-23 23:00:55 +02:00
Zdenek Kabelac
8f85834a33 cov: convert to code that analyzer may better understand
Switch to code that is problematic to analyzer
2021-04-23 23:00:55 +02:00
Zdenek Kabelac
25b672417e cov: use correct enum type
Correct function declaration.
2021-04-23 23:00:55 +02:00
Zdenek Kabelac
395ce6c2bb cov: explicitely ignore return value 2021-04-23 23:00:55 +02:00
Zdenek Kabelac
2b3dcd754f cov: check return value
Log problems on fail path.
2021-04-23 23:00:55 +02:00
Zdenek Kabelac
86a3a0c765 cov: fix typo and reduce stack usage
Buffer on stack was for single LV name plus some  short text around.
Use of 50* was a typo so use correly 50+.
2021-04-23 23:00:55 +02:00
Zdenek Kabelac
e1287c3b71 cov: ensure fid is not null 2021-04-23 23:00:55 +02:00
Zdenek Kabelac
04fd55a0c9 cov: ensure segtype is not null 2021-04-23 23:00:55 +02:00
Zdenek Kabelac
cdcd8011d0 cov: add explicit check for external not being null
Although the code should never evaluate for null external
add explict check for analyzer.
2021-04-23 23:00:55 +02:00
Zdenek Kabelac
d388b36da2 cov: daemonize avoid leak of FD on error path
Use our common patter for reopening FDs to /dev/null
that avoids leaking FD on error path.
2021-04-23 23:00:55 +02:00
Zdenek Kabelac
d95b26fae0 cov: check setup_devices return code 2021-04-23 23:00:55 +02:00
Zdenek Kabelac
ece80cd0fb cov: avoid passed invalid dummy structure
Altough this dummy structure should not be using pe_size anywhere,
make analyzer happier and avoid PV structures with zero pe_size.
2021-04-23 23:00:55 +02:00
Zdenek Kabelac
bf461b99c6 cov: check label_read_pvid return value
Command can early exit when function returns 0.
2021-04-23 23:00:55 +02:00
Zdenek Kabelac
7e13586837 cov: check _insert_dev return value
Although we try later to validate device was inserted,
we can validate return value and early-exit.
2021-04-23 23:00:55 +02:00
Zdenek Kabelac
d7237ca63a cov: add checks to prevent NULL dereference 2021-04-23 23:00:55 +02:00
Zdenek Kabelac
3d96203e21 cov: avoid leak when repeating options
Do not leak previous buffer, when option is set more then once.
2021-04-23 22:59:25 +02:00
Zdenek Kabelac
7e77e250a9 cov: set error_vg only when pointer is non null 2021-04-23 22:58:45 +02:00
Zdenek Kabelac
d1f9845c96 cov: ensure there is space for 0 at eol
Reserve 1 char for \0.
2021-04-23 22:58:45 +02:00
Zdenek Kabelac
cfe26470e3 dev-cache: change message level to debug
This case happens when i.e. we convert LV to another type,
when we change existing LV into a different type - so change
to debug level and avoid confusing users with message about
Device path  not match.

We may eventually enhnace caching code to drop cached info
after taking lock and reading VG.
2021-04-23 22:58:45 +02:00
Zdenek Kabelac
2b90466f78 devicesfile: use pool memory
Switch to use command mempool instead of zalloc() as relase
part would be required otherwise.
2021-04-23 22:58:45 +02:00
Zdenek Kabelac
80ef913872 device_id: fix memleak and free idname
Remove extra code path used only for 'free()'
and free(idname) on all paths that do not add it to list
and avoid memleak in few cases.
2021-04-23 22:57:08 +02:00
Zdenek Kabelac
65c4f81dc2 pvscan: fix memleak
Commit 25b58310e3 add zalloc()
without correspoding free(), switch to use cmd mempool.
2021-04-23 22:55:39 +02:00
Zdenek Kabelac
5e8307f4bf lvmcache: fix memory leak
With commit 0b18c25d93 there
was introduced  'zalloc()' for allocation of outdates pvs,
but no matching  'free()' is present.
Switch to use cmd mempool instead of adding free() code into
several places.
2021-04-23 22:54:41 +02:00
David Teigland
66dd481f46 man/help: move implied annotation
from
[ --type foo (implied) ]

to
[ --type foo] (implied)
2021-04-21 12:05:10 -05:00
David Teigland
d651b340e6 commands: use AUTOTYPE in definitions
If a cmd def implies an LV type without --type
in the required options, then include the implied
type in the cmd def as AUTOTYPE: <type>
instead of including the redundant --type foo
in the OO list of options.

Including an implied --type in the OO list would
often cause multiple cmd defs to potentially be
identical when options were used, and a user
command could match more than one cmd def.

The AUTOTYPE values are listed in man page and
help output as
 [ --type foo (implied) ]

If a user command includes --type, it will usually
match a cmd def with --type in the required options.
But, if the user command matches a cmd def with
AUTOTYPE, then the specifed --type and AUTOTYPE must
match.

The man-generator program has a new --check
option that compares cmd defs to find any cmd defs
that are equivalent with the use of options,
and should have their options adjusted.
2021-04-21 08:41:37 -05:00
David Teigland
7b77226df2 man-generator: add option to check for repeated command definitions
Compares cmd defs based on two principles for avoiding repeated
commands (where a given command could match more than one cmd def):

. a cmd def should be a unique combination of required
  option args and position args

. avoid adding optional options to a cmd def that if
  used would make the command match a different cmd def

FIXME: record when repeated cmd defs are found so we can
avoid reporting them twice, e.g. once for A vs B and
second time for B vs A.
2021-04-20 10:31:00 -05:00
David Teigland
a616abba03 config: improve description for event_activation 2021-04-19 13:29:17 -05:00
Zdenek Kabelac
5eac292925 make: generate 2021-04-19 14:54:37 +02:00
Zdenek Kabelac
d1f8978ac5 man: replace empty lines 2021-04-19 14:54:37 +02:00
Zdenek Kabelac
5f75f5e2bc man: typography for raid and report
Some enhancements for better man page rendering.
2021-04-19 14:54:37 +02:00
Zdenek Kabelac
9164a393de man: typography fixes
Correcting some usage of Bold and Italics (files).
Adding some missing SEE ALSO.
Fixing missed replaceable paths that are configurable.
Be careful about .P in .TP sections - need to use .sp for space line.
Use .UR/.UE for URL references.
2021-04-19 14:54:37 +02:00
Zdenek Kabelac
0f87b015b5 args: documentation enhancements
Use #DEFAULT_SYS_DIR# replaceable string for devicesfile
so the man pages installation respects configured settings.

Update some missing lvm.conf(5) references.
2021-04-19 14:40:14 +02:00
Zdenek Kabelac
b1ad32acd6 commands: update definitions for thin creation
Add missing VG into description of thin pool creation command.

Remove one duplicated thin-pool creation command.
Remove options --discards and --errorwhenfull from the list when the command describes
only creation of a thin volume - as these options do apply for thin-pool.
Also use here more correct name OO_LVCONVERT_THINPOOL instead of OO_LVCONVERT_THIN.

Reorder extra options for cache & thin-pool before common pool options.
Order consistenly --stripes and --stripesize after --extents option
so the options related to pools are better together.

Remove invalid snapshot creation description - since this case is
handled through our configurable spare volume creation.

Add some missing optional --type parameters for few command instancies.
2021-04-19 14:40:14 +02:00
Zdenek Kabelac
82e3b2e0ad tools: correct units description
Option --units takes also [Number] to express size in configurable
units.
2021-04-19 14:40:14 +02:00
Zdenek Kabelac
7bde16f5e1 man-generator: markup updates
Emit .ad l / .ad b less frequently around larger blocks
we want to keep left aligned.

Avoid emittting empty lines.

Reduce .HP usage and replace it with .TP.
However keep .HP for all option listings, as i.e. html rendering
can't handle well combintion of .TP an .HP together and .TP alone
is not indenting 2nd. line of long option line.
(For .TP line we don't need to emit .br)

Surround .SH with dots for better look.

For some .TP use plain more readable .I for a line.

Support rendering of optional [Number] (for --units).

Use better markup for units and instead of long markup string,
show individual units with markup.
2021-04-19 14:40:07 +02:00
Zdenek Kabelac
d94e5ba5af man-generator: use \(em
Use \(em in command title description and command multidefs.
2021-04-19 14:37:08 +02:00
Zdenek Kabelac
efd0939583 man-generator: decorate optional option prefixes
Enhance man typography decoration of optional option
prefixes like --[raid]writebeind and use regular font to render []
as these are not part of the option name itself.
2021-04-19 14:37:08 +02:00
Zdenek Kabelac
679116a9b8 man: with internal build install cache, thin, vdo
Do not install .7 man pages when building --without internal segtype
support for types: cache, thin, vdo.
2021-04-19 14:37:08 +02:00
Zdenek Kabelac
dc934b13b9 man: use editline reference
When compiled with editline, refer this in man page as well
instead of readline.
2021-04-19 14:37:07 +02:00
Zdenek Kabelac
54f98c94b4 makefiles: generate only needed text
Avoid storing see_also & _end parts in  generated doc,
since these we can easily 'cat' while making man pages.
2021-04-19 14:37:07 +02:00
Zdenek Kabelac
adfdfd9c58 makefiles: improved hyphenation replacement
Sed replacements script missed to properly replace several '-' to '\-'.
Replace it with simpler set of regexes.

Also add new target 'make checksed' for testing with examples,
where the replacement should or should not occure for easier testing.
2021-04-19 14:37:07 +02:00
David Teigland
b94f2a8b55 remove unused flag DEV_UDEV_INFO_MISSING 2021-04-16 16:01:19 -05:00
David Teigland
8daf5cd45f man/help: change LV type listing
Previously, accepted LV types were presented as a series of suffixes
after the "LV" on the command line.  The addition of many new types
resulted in this becoming too long, e.g

  lvconvert --type cache --cachepool LV LV_linear_striped_thinpool_vdo_vdopool_vdopooldata_raid

For man pages, move these types from the command line to a new line
dedicated to listing accepted LV types:

  lvconvert --type cache --cachepool LV LV1
  ...

  LV1 types: linear striped thinpool vdo vdopool vdopooldata raid

The special "LV1" is used as a reference to avoid confusion
with other LVs that may appear on the command line.  There
are currently no commands with more than one typed LV, but
if there are cases with more, then "LV2" could also be used.

For command line usage/-h output, drop the LV types from the
command line specification.  The more detailed is not needed
in the help output and can be found in the man page.
2021-04-14 17:25:10 -05:00
Zdenek Kabelac
353718785f man: typography
With to use .TP where it's easy and doesn't change layout
(since .HP is marked as deprecated) - but .TP is not always perfetc match.

Avoid submitting empty lines to troff and replace them mostly with .P
and use '.' at line start to preserve 'visual' presence of empty line
while editing man page manually when there is no extra space needed.

Fix some markup.

Add some missing SEE ALSO section.

Drop some white-space at end-of-lines.

Improve hyphenation logic so we do not split options.

Use '.IP numbers' only with first one the row (others in row
automatically derive this value)

Use automatic enumeration for .SH titles.

Guidelines in-use:
https://man7.org/linux/man-pages/man7/groff.7.html
https://www.gnu.org/software/groff/manual/html_node/Man-usage.html
https://www.gnu.org/software/groff/manual/html_node/Lists-in-ms.html
2021-04-14 11:04:04 +02:00
Zdenek Kabelac
0004ffa73a makefiles: fix replacing path for LVM_PATH
Man pages were generated with incorrect LVM_PATH.
2021-04-14 10:53:34 +02:00
Zdenek Kabelac
b75e26874e WHATS_NEW: update 2021-04-14 10:53:34 +02:00
Zdenek Kabelac
87a3ea7f8f Revert "thinpool: support lvconvert without zeroing"
This reverts commit 8e7690b798.

Actully this was bad idea - to make it on pair.
-Zn for thin-pools is already used - so here user must have
create new pool and swap existing thin-pool metadata into.

So reverting this commit to avoid any possible regression.
2021-04-14 10:53:34 +02:00
Zdenek Kabelac
94c264b975 Revert "tests: add check for lvconvert without zeroing"
This reverts commit accf324ccb.
2021-04-14 10:53:34 +02:00
Zdenek Kabelac
9a33388c1a tests: race on md raid still being hit on 5.12-rc6
Still hits the race in initialization:

kernel BUG at drivers/md/raid5.c:7549!
invalid opcode: 0000 [#1] SMP PTI
CPU: 0 PID: 525149 Comm: dmsetup Tainted: G           OEi
    --------- ---  5.12.0-0.rc6.184.fc35.x86_64 #1
Hardware name: Red Hat KVM, BIOS 0.5.1 01/01/2007
RIP: 0010:raid5_run+0x40b/0x4b0 [raid456]
Code: 00 8b 83 3c 01 00 00 39 83 bc 00 00 00 0f 85 ac 00 00 00
      48 c7 44 24 08 00 00 00 00 8b bb 30 01 00 00 85 ff 0f 84
      88 fd ff ff <0f> 0b 48 8b 43 48 48 c7 c6 40 93 92 c0 48
      c7 c7 70 2c 93 c0 48 85
Call Trace:
 md_run+0x4d6/0xbc0
 ? super_validate+0x2e1/0x4b0 [dm_raid]
 raid_ctr+0x133e/0x281b [dm_raid]
 dm_table_add_target+0x167/0x330
 table_load+0x103/0x350
 ctl_ioctl+0x1b4/0x430
 ? dev_suspend+0x2c0/0x2c0
 dm_ctl_ioctl+0xa/0x10
 __x64_sys_ioctl+0x82/0xb0
 do_syscall_64+0x33/0x40
 entry_SYSCALL_64_after_hwframe+0x44/0xae
2021-04-12 12:04:50 +02:00
Zdenek Kabelac
9eca131256 make: generate
Oops, previous generate was not correct.
2021-04-12 11:12:40 +02:00
Zdenek Kabelac
396d93937d tests: enable for 5.12+ kernels
Should not longer kill kernel.
2021-04-12 10:47:06 +02:00
Zdenek Kabelac
31410447fd makefiles: add devmapper for devmapper-event
Older linkers do not take this dependency automatically from
libdevmapper-event so need to be passed with linker command.
2021-04-12 10:35:55 +02:00
Zdenek Kabelac
a5f83cb612 WHATS_NEW: updates 2021-04-12 09:54:16 +02:00
Zdenek Kabelac
151377dd50 make: generate 2021-04-12 09:54:16 +02:00
Zdenek Kabelac
19ff0d983e man: hyphenation improvements 2021-04-12 09:54:16 +02:00
Zdenek Kabelac
53fa1582d9 man-generator: spaces 2021-04-12 09:54:16 +02:00
Zdenek Kabelac
e01ce8e2ae man-generator: option description indented
Left indention is needed only for options, but is actually
unwanted for decription itself.
2021-04-12 09:54:16 +02:00
Zdenek Kabelac
441b702362 man-generator: remove ',' between some options
It would be complicated to handle ',' alignment after hyphenation
changes ATM, but these commas seems to be there rather unneeded
so remove them and make the man output more clear.
2021-04-12 09:54:16 +02:00
Zdenek Kabelac
d86b583644 man-generator: improve hyphenation for longer option list
Disable hyphenation around longer option lists (>42 chars)
and use \: to markup places for line splits.

The code ATM is somewhat mixtured so it's not easy to encapsulate
section .nh ... .hy.

ATM global _was_hyphen is used to properly finish sections after
disabled hyphenation.
2021-04-12 09:54:16 +02:00
Zdenek Kabelac
b76283c4b3 man: use commas in SEE ALSO
Add ',' between each ref.
Use left alignment and no hyphenation.
2021-04-12 09:54:16 +02:00
Zdenek Kabelac
f5efe1beb5 makefiles: no need for double Q
We already use $(Q) while calling macros
2021-04-12 09:54:16 +02:00
Zdenek Kabelac
2e84dd47d4 makefiles: reuse CSCOPE_DIRS for ctags
Create ctags only from real source files.
2021-04-12 09:54:16 +02:00
Zdenek Kabelac
ebf33323b9 makefiles: deps also for cxx
Generate deps also for .cxx.
Remove include dir deps - there is nothing to build.
2021-04-12 09:54:16 +02:00
Zdenek Kabelac
75424dd692 libdm: replace deprecated security_context_t
Use 'char *' instead of deprecated security_context_t.
In more details i.e.:

https://gitlab.gnome.org/GNOME/glib/-/merge_requests/1776
2021-04-12 09:54:16 +02:00
Zdenek Kabelac
57b5bc9c87 configure: make aio optional
Add support for external AIO_CFLAGS and AIO_LIBS so user
can point to his own build - this might be useful when
user wants to use own libaio library.
2021-04-12 09:54:15 +02:00
Zdenek Kabelac
744afec6c0 configure: better support for use of --without
When --with-... option is used as --without-... it gets
assigned value 'no' - so support it better where we can.

Also remove 'shared' from help as it's not supported.
2021-04-12 09:54:15 +02:00
Zdenek Kabelac
aee0cd6530 makefiles: static linking enhancements 2021-04-12 09:54:15 +02:00
David Teigland
01f108c4d0 tests: skip autoactivation-metadata with lvmlockd
shared vgs are not autoactivated
2021-04-08 16:08:45 -05:00
David Teigland
0a28e3c44b Add metadata-based autoactivation property for VG and LV
The autoactivation property can be specified in lvcreate
or vgcreate for new LVs/VGs, and the property can be changed
by lvchange or vgchange for existing LVs/VGs.

 --setautoactivation y|n
 enables|disables autoactivation of a VG or LV.

Autoactivation is enabled by default, which is consistent with
past behavior.  The disabled state is stored as a new flag
in the VG metadata, and the absence of the flag allows
autoactivation.

If autoactivation is disabled for the VG, then no LVs in the VG
will be autoactivated (the LV autoactivation property will have
no effect.)  When autoactivation is enabled for the VG, then
autoactivation can be controlled on individual LVs.

The state of this property can be reported for LVs/VGs using
the "-o autoactivation" option in lvs/vgs commands, which will
report "enabled", or "" for the disabled state.

Previous versions of lvm do not recognize this property.  Since
autoactivation is enabled by default, the disabled setting will
have no effect in older lvm versions.  If the VG is modified by
older lvm versions, the disabled state will also be dropped from
the metadata.

The autoactivation property is an alternative to using the lvm.conf
auto_activation_volume_list, which is still applied to to VGs/LVs
in addition to the new property.

If VG or LV autoactivation is disabled either in metadata or in
auto_activation_volume_list, it will not be autoactivated.

An autoactivation command will silently skip activating an LV
when the autoactivation property is disabled.

To determine the effective autoactivation behavior for a specific
LV, multiple settings would need to be checked:
the VG autoactivation property, the LV autoactivation property,
the auto_activation_volume_list.  The "activation skip" property
would also be relevant, since it applies to both normal and auto
activation.
2021-04-07 15:32:49 -05:00
Zdenek Kabelac
6f6583afed libdm: fix compiling with older gcc 2021-04-06 22:31:23 +02:00
Zdenek Kabelac
9980ed9527 WHATS_NEW: updates 2021-04-06 22:02:31 +02:00
Zdenek Kabelac
79a168d119 tests: pvmove updates
Switch to plain 'kill' we should no longer need SIGKILL
as polling can be interrupted.

Resolve problem in aux wait_pvmove_lv_ready() that was using
lvm command to check for UUID - but this was interferring with
VG lock and it's been delaying confirmation.

So reducing slow-down of test - so it can run faster.
2021-04-06 22:02:31 +02:00
Zdenek Kabelac
b99f7d0df9 lib: remove unused macros
Internally lvm2 is not using versioning for device-mapper.
2021-04-06 22:02:31 +02:00
Zdenek Kabelac
e86cd9c5ba makefiles: remove unneeded var changes 2021-04-06 22:02:31 +02:00
Zdenek Kabelac
9452e62efb makefiles: cscope only predefined dirs
Avoid scanning for source duplicates in various build dirs.
2021-04-06 22:02:31 +02:00
Zdenek Kabelac
f1bfc0621b makefiles: plugins can be build after shared library 2021-04-06 22:02:31 +02:00
Zdenek Kabelac
d2522f4a05 polldaemon: improve support for interruptions
Enhance handling of interruptions of polling process and lvmpoll daemon.
Daemon should now react much faster on interrups (i.e. shutdown
sequence) and avoid taking lenghty sleep waiting on pvmove signaling.
2021-04-06 22:02:31 +02:00
Zdenek Kabelac
ff8aaadec9 mirror_percent: support interruptible check
When checking for mirror percentage with WAITEVENT (i.e. during pvmove)
handle intrruption (^C) of such wait.
2021-04-06 22:02:31 +02:00
Zdenek Kabelac
1f17b1c565 daemon-server: handle reaping threads better
Avoid sleeping in pselect when thread missed reap() handling.
This speedup handling of daemon shutdown sequences.
2021-04-06 21:26:57 +02:00
Zdenek Kabelac
fe4f83171d signals: support also SIGTERM for breaking command
If we are signaled with SIGTERM it should be at least as good
as with SIGINT - as the command should stop ASAP.
So when lvm2 command allows signal handling we also
enable SIGTERM handling. If there are some other signals
we should handle equally -  we could just extend array.
2021-04-06 21:26:57 +02:00
Zdenek Kabelac
287565fd5d lvreduce: support --yes
Missed support for --yes with 'lvreduce' to answer 'y' to prompt.
2021-04-06 21:26:57 +02:00
Zdenek Kabelac
f1d3648dc7 libdm: eliminate some abi-dumper errors
ABI dumper does not like missing enum/union/struct names,
so add them with _e, _u suffix.

Usage reference:

https://doc.dpdk.org/guides-16.04/contributing/versioning.html
2021-04-06 21:26:57 +02:00
Zdenek Kabelac
14ea63cfc7 symver: sorting 2021-04-06 21:26:57 +02:00
Zdenek Kabelac
60eb608d66 symver: restore and uncomment some symbols 2021-04-06 21:26:57 +02:00
Zdenek Kabelac
c23f4c8075 makefiles: add check for versioned symbols
Simple check produced library has the latest symbol as well as its versioned
older version with check for dm_stats_create_region().
2021-04-06 21:26:57 +02:00
Zdenek Kabelac
40b277ae17 makefiles: slight change in .export.sym
Avoid emitting Local symbol and sort symbols from
start and add dependency on previous version
Should not change anything, just better followup
linkage guidlines.
2021-04-06 21:26:57 +02:00
Zdenek Kabelac
1398e66a55 libdm: move dm_task_get_info_with_deferred_remove
Version is only needed for dm_task_get_info().
dm_task_get_info_with_deferred_remove() shall be compiled for
non-versioned library as well.
2021-04-06 21:26:57 +02:00
Zdenek Kabelac
a8480f0f6e libdm: symbol versioning with -flto
Gcc10 introduced different strategy how to build
shared libraries with their new LTO optimizer.

Insired by:

https://akkadia.org/drepper/symbol-versioning
https://sourceware.org/pipermail/elfutils-devel/attachments/20200414/1c0c2903/attachment.bin
https://github.com/InBetweenNames/gentooLTO/issues/459
https://github.com/linux-rdma/rdma-core/blob/master/util/symver.h
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=48200
2021-04-06 21:26:57 +02:00
David Teigland
12949ea886 hints: don't use hints when --sysinit is used
Devices are not in a steady state during system init,
so hints are repeatedly invalidated, and hardly used,
so maintaining them is wasted effort.
2021-04-01 14:37:24 -05:00
Samanta Navarro
01d5e4d1ca all: fix typos 2021-03-30 13:08:14 +02:00
Zdenek Kabelac
d5b0c72f40 man: show config options with comments 2021-03-30 13:08:14 +02:00
Zdenek Kabelac
ff5776024f man: describe profile support lvmcache.7
Add missing description for profile usage with cache pool.
List cache-pools as first option for dm-cache as it provides
better performance and more functionality over cachevols.
2021-03-30 13:08:14 +02:00
Zdenek Kabelac
2aaea13aaa man: writecache missed for --type
Add missing writecache type into man pages.
2021-03-30 13:08:14 +02:00
Zdenek Kabelac
648188df2a libdm: use libdm header util.h
Avoid using lvm header for libdm build.
2021-03-30 13:08:14 +02:00
Zdenek Kabelac
f1e8437c59 device_mapper: remove unused lines
No need for versioning history in internal version.
2021-03-30 13:07:51 +02:00
Zdenek Kabelac
1cedbaf137 configure: support builds without versioning
Not all libc (like musl, uclibc dietlibc) libraries support full symbol
version resolution in runtime like glibc.
Add support to not generate symbol versions when compiling against them.

Additionally libdevmapper.so was broken when compiled against
uclibc. Runtime linker loader caused calling dm_task_get_info_base()
function recursively, leading to segmentation fault.

Introduce --with-symvers=STYLE option, which allows to choose
between gnu and disabled symbol versioning. By default gnu symbol
versioning is used.
__GNUC__ check is replaced now with GNU_SYMVER.
Additionally ld version script is included only in
case of gnu option, which slightly reduces output size.

Providing --without-symvers to configure script when building against
uclibc library fixes segmentation fault error described above, due to
lack of several versions of the same symbol in libdevmapper.so
library.

Based on:
https://patchwork.kernel.org/project/dm-devel/patch/20180831144817.31207-1-m.niestroj@grinn-global.com/

Suggested-by: Marcin Niestroj <m.niestroj@grinn-global.com>
2021-03-30 13:06:19 +02:00
Zdenek Kabelac
1a17a5ab80 tests: sleep tunning
Check different sleep properties for lvmpolld.
Use aux remove_dm_devs.
2021-03-28 14:22:11 +02:00
Zdenek Kabelac
d9b9751032 tests: add aux remove_dm_devs
Add function to remove DM devices and dies
if some device can't be removed.
2021-03-28 14:22:11 +02:00
Zdenek Kabelac
0ddbc4c5cd tests: bash quotes 2021-03-28 11:39:58 +02:00
Zdenek Kabelac
8a550fa3e8 tests: test_pv_symlinks works only with /dev dir
Skip test with LVM_TEST_DEVDIR != /dev
2021-03-28 00:21:38 +01:00
Zdenek Kabelac
afbaab20c7 tests: fix unfinished check for 4.18 kernel 2021-03-28 00:21:38 +01:00
Zdenek Kabelac
f584f0cd9e tests: ensure raid is synchronized 2021-03-27 23:19:08 +01:00
Zdenek Kabelac
5ec7992e29 tests: reoder killing order
We need to stop pvmove while still in progress,
so restart lvmpolld after pvmoving devices are gone
2021-03-27 23:19:08 +01:00
Zdenek Kabelac
feb7fef6c8 tests: fight with losetup creation error
Try losetup few times in loop if we can succeed.
2021-03-27 23:19:08 +01:00
Zdenek Kabelac
1f7bd719d0 tests: restore removed prefix
During debugging this prefix was unintentionally lost, restore.
2021-03-27 23:19:08 +01:00
Zdenek Kabelac
12222add1a tests: use known path for test in find
Actually make sure which 'test' binary is executed.
Since we used to have 'test' binary in tests.
2021-03-27 23:18:38 +01:00
Zdenek Kabelac
37d603268f tests: for 4.18 use already 1.20 logic
Looks like there was some missed versioning increase during devel.
So with kernel >= 4.18 version 1.19 is enough to look like 1.20

However backported 1.19 targets seems to not provide all
the capabilities.
2021-03-27 23:16:52 +01:00
Zdenek Kabelac
f07a793813 tests: correct thin-pool version
Use thin-pool target version 1.20 for changed behavior.
2021-03-27 00:34:00 +01:00
Zdenek Kabelac
53338cf566 tests: increase mirror throttling 2021-03-27 00:29:28 +01:00
Zdenek Kabelac
8e9bc52b15 tests: more skipped tests for lvmpolld 2021-03-26 22:13:37 +01:00
Zdenek Kabelac
a55f4a8fe2 tests: use shell comment 2021-03-26 22:12:42 +01:00
Zdenek Kabelac
93336685f6 tests: update dbus test_nesting
Test has to use PV with suffix  pv[0..9]  otherwise
it's ignored by test suite filter.

Better fix for VG names to use prefix LVMTEST.

Skip the test for runs without LVM_TEST_DEVDIR != /dev
2021-03-26 20:39:41 +01:00
Zdenek Kabelac
1d6e1d08a8 tests: update for newer thin-pool
Newer thin-pool handle metadata read-only recovery better.
2021-03-26 20:39:41 +01:00
Zdenek Kabelac
51ac56a05e tests: use blkid without caching
Always use blkid without caching to avoid poluting
cache stored in /run/blkid or /etc on older distros
2021-03-26 20:39:41 +01:00
Zdenek Kabelac
02e02a5ccc tests: use aux mdadm_assemble wrapper 2021-03-26 20:39:41 +01:00
Zdenek Kabelac
4c59b2aa21 tests: add aux mdadm_assemble
Wrapper for slowed version of mdadm --assemble
2021-03-26 20:39:41 +01:00
Zdenek Kabelac
5ef8d84569 tests: better reporting of problematic services 2021-03-26 20:39:40 +01:00
Zdenek Kabelac
49575a6ce1 tests: skip more tests for lvmpolld pass
These test do not test polling, so skip them for lvmpolld pass.
2021-03-26 20:39:40 +01:00
Zdenek Kabelac
7768650d87 tests: add commented example
How to run individual test.
2021-03-26 13:16:44 +01:00
Zdenek Kabelac
25c665d555 tests: dbus update
Always use  PREFIX for vg header - all tests must use this prefix,
VGs without are not allowed.

Modify pv_symlink test - as the test was checking unsupportable
combination - since lvm2 commands withing testsuite are only
allowed to manipulate with /dev/mapper/LVMTESTXXXX path -
nothing else allowed and fails on being filtered.
2021-03-26 13:13:26 +01:00
Zdenek Kabelac
6db533c439 tests: try to observe some unusual problem
Lets see, why it's very occasionaly able to active LV.
2021-03-26 11:36:22 +01:00
Zdenek Kabelac
3ed79d8dfe tests: move setting of dmeventd pid
Added comment the  'lvs' already initiates dmeventd

Note: we don't have any query mechanism to check if dmeventd
is already running except access of socket which basically
starts dmeventd if it's not running.
2021-03-26 11:16:32 +01:00
Zdenek Kabelac
85fae836c0 tests: add basic validation of running services
For determinist test results lvm2/dm service shall not be present
and running in the system as it may randomize test results.

In case they are found present, this test ends with warning (not failure).
2021-03-26 11:13:56 +01:00
Zdenek Kabelac
9bcc76b63c tests: add should for racy test
Depending on kernel, the race may or may not happen.
2021-03-26 00:43:44 +01:00
Zdenek Kabelac
5feb99dda6 tests: add workaround for older mdadm
Some older instancies of 'mdadm' opened legs in RW and
closed and opened again and expected exlusive access.
But here udev rule can be fired - so on these versions
slow down whole mdadm runtime by using strace, to
give system a bit more time to finish udev rule.
2021-03-26 00:35:28 +01:00
Zdenek Kabelac
0558b223b8 tests: aux fix check_lvmpolld_init_rq_count
Make check_lvmpolld_init_rq_count() more compatible with older gawk,
where some functionality was not working properly.
Also change 'not not' condition.
2021-03-26 00:33:21 +01:00
Zdenek Kabelac
73710b87fb WHATS_NEW: updates 2021-03-24 16:41:08 +01:00
Zdenek Kabelac
c1f5ca6751 tests: improve check raid_leg_status
Enhance function to wait until raid status gets consisten
(shifts from 0/xxxxx to something else)

If it would took too long fail the check.
2021-03-24 16:38:12 +01:00
Zdenek Kabelac
0783c661b9 tests: handle case of missing /dev/disk
In case there is no symlink - udev can optimize /dev/disk away,
thus find would fail in teardown.
2021-03-24 16:38:12 +01:00
Zdenek Kabelac
2151b71819 tests: check fsadm with missing filesystem 2021-03-24 16:38:12 +01:00
Zdenek Kabelac
28865f971e fsadm: handle error from blkid
Fsadm wants to print its own error message when it can't detect
type of the filesystem on a block device.
Otherwise fsadm exits with no message on an unused block device.
2021-03-24 16:37:09 +01:00
Zdenek Kabelac
63c58d2a5d fsadm: fix condition when using --getsize64
When blocksize --getsize64 gives empty result we want to fallback
to ancient  --getsize * --getss  calculation (RHBZ #1942486).

Reported by: ajschorr@alumni.princeton.edu
2021-03-24 16:34:34 +01:00
Zdenek Kabelac
9684e82cc4 tests: ignore incosistent raid status
Just like lvm command ignores  0/xxxx report from judging the status.
Avoid using infinite loop and limit report checking to 100 checks.
If it would need more - something is not right.
2021-03-24 12:40:17 +01:00
Zdenek Kabelac
afd43a75f2 tests: skip stray testing on real dev dir
Do not modify /dev dir maintained by udev.
2021-03-24 12:23:07 +01:00
Zdenek Kabelac
a126dde069 tests: remove more file in teardonw
Our tests may result in producation of huge set of
invalid links in /dev/disk directory depeding on version
of udev and various kinds of failures.

Also we happen to invoke some on-system pvscans generating
local /etc/lvm/archive & backups - remove them when
test is finished.
2021-03-24 12:23:07 +01:00
Zdenek Kabelac
18f2475fa1 tests: query info instead of table
No need to access table when we just check presence,
so generate smaller error message about missing device.
2021-03-24 12:22:27 +01:00
Zdenek Kabelac
8df0a32abb tests: this test has race in it depending on kernel
Some kernel seems to keep 'lvextend' busy so long,
that actual resize already happens.

So ATM use 'should'  until something better is invented.
2021-03-23 21:32:51 +01:00
Zdenek Kabelac
dd1f5f9a24 tests: aux clean DM on top of MD
Before cleaning MD, try to remove any DM on top such MD.
Check is made through DM table check.
Maybe parse /proc/mdstat for this???
2021-03-23 21:28:28 +01:00
Zdenek Kabelac
93f2d194ac tests: wipefs with udev_wait
Try to synchronize with colliding udev.
Also retry once if there is some failure with some
sleep between next retry.

Use oflag=direct for wipping without wipefs.
2021-03-23 14:57:10 +01:00
Zdenek Kabelac
14a3c34983 tests: increase required version
Seems like version 1.13.2 remains crashing kernel - so increase
the required version for this reshaping test.
2021-03-23 14:39:13 +01:00
Zdenek Kabelac
d0644fb2c3 tests: use prefix for VG name 2021-03-23 14:38:54 +01:00
Zdenek Kabelac
712f7dfb4c tests: ignore failure of zeroing
Older mdadm fails the command, when the signature is already gone.
2021-03-23 12:05:55 +01:00
Zdenek Kabelac
26d76d31c5 tests: use mirror throttling
Combination of throttling and slowed device is a bit faster.

Also add FIXME about the mutliple spawn polling processing
when activating invidual LV for a pvmove.
2021-03-23 11:34:34 +01:00
Zdenek Kabelac
a5fc6a0fe7 tests: set default basic flavour 2021-03-23 11:33:30 +01:00
Zdenek Kabelac
0b2a037c80 tests: try to move more date
Throttling was not helping with race - try to use more data.
2021-03-23 10:53:02 +01:00
Zdenek Kabelac
e8b4306eb0 WHATS_NEW: update 2021-03-23 09:59:26 +01:00
Zdenek Kabelac
acac3cb524 tests: test needs to have playable locking dir 2021-03-23 09:48:47 +01:00
Zdenek Kabelac
b19e036918 tests: aux updates
Select unused md from /proc/mdstat
Check for wipefs once.
2021-03-23 09:48:03 +01:00
Zdenek Kabelac
370749a4b8 tests: enhance mdadm_create
For older mdadm its hard to support new names - to simplify things
keep using  /dev/mdXXX name which is automatically selected.
2021-03-23 01:16:21 +01:00
Zdenek Kabelac
7575c7ae5c tests: set known locking dir
Tests running in the system may use locking dir of the system.
2021-03-23 01:15:29 +01:00
Zdenek Kabelac
f370cda716 make: add few more predef symbols for cflow 2021-03-22 22:51:24 +01:00
Zdenek Kabelac
0993355300 configure: use rawhide version 2021-03-22 22:51:24 +01:00
Zdenek Kabelac
077040199d tests: remove unused wait_md_create 2021-03-22 22:51:24 +01:00
Zdenek Kabelac
7166bbd9c2 tests: avoid sleep on kill path
Before sleeping, check if pid is still there.
2021-03-22 22:51:24 +01:00
Zdenek Kabelac
a7d7471906 tests: convert to use mdadm_create
Flip usage from prepare_md_dev to mdadm_create.
2021-03-22 22:50:36 +01:00
Zdenek Kabelac
b1483dcbac tests: more usage of new aux mdadm_create
Condense tests and use the new mdadm_create.
2021-03-22 22:49:11 +01:00
Zdenek Kabelac
76d203517b tests: use mdadm support
Use for testing new mdadm_create  aux wrapper.
Place functionality into a 2 pass loop - one for 'auto' other for 'start'.
Share same tests between raid level 0 and level 1 version of raid.
2021-03-22 22:46:21 +01:00
Zdenek Kabelac
ada99f939f tests: new aux mdadm_create
Add generic wrapper for mdadm --create which takes
normal 'mdadm' args - but allows us to handle differences of
mdadm usage across various version of mdadm tool.

Resulting MD device is availalble in  $(< MD_DEV).

Automatic cleaning is made through   cleanup_md_dev

Calling of mdadm_create cleans previous MD dev if it exists.
2021-03-22 22:42:52 +01:00
Zdenek Kabelac
77432ee137 tests: remove local changes
Use aux for preparing profile.
Avoid playing with LVM_BINARY localy - we already
preset this variable in lib/utils.
2021-03-22 22:36:37 +01:00
Zdenek Kabelac
daca6e2c22 tests: even more aggressive throttling
Try if the test gets slowed down with slower mirroring (1)
or we would need something better to beat the race.
2021-03-22 22:36:37 +01:00
Zdenek Kabelac
bee8027cfa tests: skip only portion of test
Seems this kernel bug is taking more time to get it fixed,
so skipping only failing portion of test and ending with WARNING.
2021-03-22 22:36:37 +01:00
Zdenek Kabelac
8d2ad4419a tests: more system defaults for installed tests
When testing installed binaries on system, use more 'built-in'
predefined settings to usethem with their  compiled-in values.

Also it's better to use same locking dir so the system's pvscan
is not unexpectedly interferring with test commands.
2021-03-22 22:36:37 +01:00
Zdenek Kabelac
f1858d209d tests: remove incorrect check
We would need to be check same status value - otherwise
we can hit race in validating 2 different states.
2021-03-22 22:36:37 +01:00
Zdenek Kabelac
09621725d0 gcc: declaration of tmpfile shadows a global
Rename tmpfile to tmppath to avoid declaration shadowing of:

/usr/include/stdio.h:174: warning: shadowed declaration is here
2021-03-22 22:35:56 +01:00
Marian Csontos
b6cff47bde lvm: Fix editline compilation 2021-03-22 11:37:19 +01:00
Zdenek Kabelac
d6bc11bf72 tests: use mirror throttling
With small mirrors its better to throttle speed of mirror in dm-mirror.
2021-03-20 10:52:24 +01:00
Zdenek Kabelac
2dd43a7314 tests: slow down device more
Make the race with too fast merging less likely to occure.
2021-03-20 10:52:24 +01:00
Zdenek Kabelac
94c4af232c tests: prohibit 4K brd device with integrity
Older kernels hit these errors:

device-mapper: integrity: Bio not aligned on 8 sectors: 0x8ffc, 0x4
2021-03-20 10:52:24 +01:00
Zdenek Kabelac
179f59a0ca tests: add FIXME to raid test
We have here some kind of catch-22 - since older kernels do
use 'resync' while new 'recover' for initial raid synchronization.

So now - how do we recognize in which state of raid we are.
ATM seems to be simplest to simply keep disabled droping of primary raid
leg unless we are in sync.

FIXME: we should add a target version check and enable removal
2021-03-20 10:52:24 +01:00
Zdenek Kabelac
05920e3818 raid: restore mirror handling in _raid_in_sync
Function is not having the best name since it does check
no just raid LVs to be in sync.

Restore the mirror percentage checking - although without retries,
since only raid target is currently known to need it - for other
types it would be ATM a bug to get inconsistent result.
2021-03-20 10:52:24 +01:00
Zdenek Kabelac
edcc410835 tests: fix condition for exclusion of /dev 2021-03-20 00:28:13 +01:00
Zdenek Kabelac
d5b37f24f4 tests: aux reject /dev as testing dir
If LVM_TEST_DIR would be set to /dev, reject such selection.
2021-03-20 00:05:01 +01:00
Zdenek Kabelac
e27baa791f tests: drop status workaround
lvconvert should now recognize resync from older kernels.
2021-03-20 00:05:01 +01:00
Zdenek Kabelac
ed90a3d9b4 tests: copy more data
Give pvmove --abort bigger aborting window.
2021-03-20 00:05:01 +01:00
Zdenek Kabelac
fe3ef6867f tests: require newer raid version
Tests needs reshape support - so require newer target version
as quick fix.

TODO: inspect indiviual supportable conversion with older versions.
2021-03-20 00:05:01 +01:00
Zdenek Kabelac
3d26bde1c0 make: cflow target works again
Restored 'make cflow' functinality.
Produces some quick referece of function chaining and usage.
2021-03-20 00:05:01 +01:00
Zdenek Kabelac
e86798203e make: simplify dependency loading
No need for extra ifdefs around.
2021-03-19 23:21:18 +01:00
Zdenek Kabelac
48d04afaa2 make: restore buildir != srcdir support
Our new faster deps generation missed support for
buildirs != srcdir - as it can be usable to have
several builds from unchanged directory with sources.
2021-03-19 23:21:18 +01:00
Zdenek Kabelac
c6a76c1ffe make: generate
Add new lvmdevices.8_pregen and vgimportdevices.8_pregen.
2021-03-19 23:21:18 +01:00
Zdenek Kabelac
81d3639955 git: update .gitignore
Hide some files from older builds.
2021-03-19 23:21:18 +01:00
Zdenek Kabelac
d3d28b1b64 cleanup: reduce code dupliction 2021-03-19 23:21:18 +01:00
Zdenek Kabelac
d37b19aaaa gcc: ensure buffer ends with 0 2021-03-19 23:21:18 +01:00
Zdenek Kabelac
79d8d06217 raid: move non dm functions from DEVMAPPER ifdef
When lvm is compiled without device-mapper - this functions
do not need this kernel support so move them from ifdef DEVMAPPER
sections.
2021-03-19 23:20:23 +01:00
Zdenek Kabelac
cc140f68a5 raid: resync cannot lose primary leg
Prohibity droping primary leg while resyncing.
2021-03-19 23:19:31 +01:00
Zdenek Kabelac
076e155697 raid: interruptible usleep when waiting for sync
Whiel waiting for raid to return consistent status,
use interruptible sleep - so command can break quickly.

Use lv_raid_status() to get percentage easily from status.
2021-03-19 23:17:03 +01:00
Zdenek Kabelac
b4ab2a1051 WHATS_NEW: updates 2021-03-18 19:12:35 +01:00
Zdenek Kabelac
26fb6b5e8d tests: check for raid sync in progress
TODO: this needs to be built-in in lvm command itself.
2021-03-18 19:12:00 +01:00
Zdenek Kabelac
accf324ccb tests: add check for lvconvert without zeroing
Check lvconvert -Zn does not zero thin-pool metadata.
Also check --type zero is usable for thin-pool data.
2021-03-18 18:57:45 +01:00
Zdenek Kabelac
c06325263f tests: check mixing striped with error and zero 2021-03-18 18:57:45 +01:00
Zdenek Kabelac
1880b573f3 tests: aux always shift emulated devices by 1MiB
Always shift created virtual PVs on backing device by 1MiB
and leave 1MiB free space at the end of device.

This way the system doesn't see same PV headers at multiple devices.
2021-03-18 18:57:45 +01:00
Zdenek Kabelac
8e7690b798 thinpool: support lvconvert without zeroing
Since lvm does support external users of thin-pool when thin devices
are managed outside it can be useful to support conversion to
thin pool from data and metadata LV without zeroing.
TransactionID will be 0 in lvm2 metadata.

  lvconvert -Zn --thinpool vg/data --poolmetadata vg/meta
2021-03-18 18:57:45 +01:00
Zdenek Kabelac
1c3774c7a8 pool: allow data on zero and error segtypes
Renables usage of --type zero and --type error LVs to serve as
backend for _tdata device. Clearly not very useful in practice,
as it can't store any real data, but usable for some testing
and some sort of perfomance checking.

  lvcreate --type zero -L1T -n pool vg
  lvconvert --thinpool vg/pool

Will create a thin-pool with zero device backend.
2021-03-18 18:57:45 +01:00
Zdenek Kabelac
7a9efc5fae lvresize: allow mixing striped with errors or zero
Enabled extension/mixing of stripes/linears, error and zero
segtype LVs with stripes/linear, error and zero segtypes.

It is not very useful in practice, as the user cannot store any real
data on error or zero segtypes, but it may get some uses in
some scenarios where i.e. some portion of the device should not be
readable. Mixing of types happens on 'extent_size' level:

  lvcreate -L1 -n lv vg
  lvextend --type error  -L+1 vg/lv
  lvextend --type zero   -L+1 vg/lv
  lvextend --type linear -L+1 vg/lv
  lvextend --type striped -L+1 vg/lv

  lvs -o+segtype,seg_size vg

Note: when the type is not specified, the last segment type is
automatically selected.

It's also a small 'can of worms' since we can't tell LVs if
the LV is linear/error/zero or their mixtures. So the meaning behind
them may need some updates.

We already have this types of LV created i.e by:

  vgreduce --removemissing --force

where missing LV segments have been replaced by either
error or zero segtype (lvm.conf).

TODO: it might be worth adding a message while such device is activated.
2021-03-18 18:56:49 +01:00
Zdenek Kabelac
b35ef9d67c segtypes: macros for error and zero segtypes 2021-03-18 18:34:57 +01:00
Zdenek Kabelac
22554c3ff0 lvremove: extra code for handling thinpool data
Add some extra code to handle differently sized thin-pool
from thin-pool data volume.

ATM this can't really happen, but once we start to use multiple
commits while resizing stacked LV, we may actually get into
the position, where data LV has been already resized,
but thin-pool stayed with old size.

But for now - report difference as internal error.
2021-03-18 18:34:57 +01:00
Zdenek Kabelac
5a73399b73 lvresize: support resize of stacked virtual LV
Update the LV stack with the size also for virtual LVs.
2021-03-18 18:34:57 +01:00
Zdenek Kabelac
adc238062d dev_manager: skip also zero targets
Devices made only from 'error' target cannot be used,
but if the device is also combined from 'zero' target
the same rule can be applied as such device cannot be used.
2021-03-18 18:34:57 +01:00
Zdenek Kabelac
a9b4acd511 dev_manager: add lv_raid_status
Just like with other segtype use this function to get whole
raid status info available per a single ioctl call.

Also it nicely simplifies read of percentage info about
in_sync portion of raid volume.

TODO: drop use of other calls then lv_raid_status call,
since all such calls could already use status - so it just
adds unnecessary duplication.
2021-03-18 18:34:57 +01:00
Zdenek Kabelac
e5a600860c dev_manager: status check with info check included
Reduce ioctl count and avoid separate info check,
when we can get the same info from status ioctl.

When devmanager calls return 0, then the exists value 0
means the reason of failure is missing device in table.
In such case we avoid stack trace.

Swap the flush parameter for the vdo status function
to match thin pool status.
2021-03-18 18:34:57 +01:00
Zdenek Kabelac
a60c8748ea thin: ignore parallel merge while polling
If the thin volume has no merging snapshot,
(being already merged) there is nothing to check.
2021-03-18 18:34:57 +01:00
Zdenek Kabelac
8cbe4a171e thin: add extra protection
Check explicitely created LV already has thin segment.
As currenlty it's the only user - this patch should have no impact.
2021-03-18 18:34:57 +01:00
Zdenek Kabelac
d682ad619a cleanup: simplier check first 2021-03-18 18:34:57 +01:00
David Teigland
a481fdaa35 man: lvmlockd use of lvmlockctl_kill_command 2021-03-17 13:02:51 -05:00
Zdenek Kabelac
583cf413d5 tests: avoid leaking unkilled commands
Between each new test here we want to kill previous commands,
otherwise they will influence results of next test.
2021-03-17 00:59:50 +01:00
Zdenek Kabelac
fda7bc1297 tests: wait for Aa status 2021-03-17 00:59:50 +01:00
Zdenek Kabelac
80d0f200d0 tests: increase version of targets for progress 2021-03-17 00:59:50 +01:00
Zdenek Kabelac
e793ff1e18 tests: workaround for some raid targets
Problem with some target is that shortly after initialization it
returns incorrect status letters.
2021-03-17 00:59:50 +01:00
Zdenek Kabelac
db37905d7f tests: no further fixes likely to be expected
Skip tests for these kernels.
2021-03-17 00:59:50 +01:00
Zdenek Kabelac
87659256f0 tests: require newer version of raid target 2021-03-17 00:59:50 +01:00
Zdenek Kabelac
92ee16f7c0 tests: update mirror test
Log results of uniq.
Remove few unneeded lvs calls.
2021-03-17 00:59:50 +01:00
Zdenek Kabelac
53bad89a7b tests: added check for kernel version
With older kernels this test can't work reliable,
since 'suspend' used to clean all dirty blocks
(taking even several seconds).
2021-03-17 00:59:50 +01:00
Zdenek Kabelac
8b2cdd8d3a debug: start with upper case
Use upper case letter to start sentence.
Also drop unneded check for vg as it's already non-null.
2021-03-17 00:50:40 +01:00
Zdenek Kabelac
94701b700b cleanup: use dm_strncpy
Use own function.
2021-03-17 00:50:22 +01:00
Zdenek Kabelac
4d75c4f597 device_is_usable: minor improve
Replace allocated buffer with local vg_name which doesn't
pass pointer to allocation.

Join some conditions together.
2021-03-17 00:49:11 +01:00
Zdenek Kabelac
0363e4de70 cleanup: typo 2021-03-15 18:59:15 +01:00
Zdenek Kabelac
e6912cc61c WHATS_NEW: updates 2021-03-15 11:13:24 +01:00
Zdenek Kabelac
b4a74d1008 tests: add test for merging
Check we handle mething of thin snapshot that is itself thick snapshot
origin.
Also use  lvpoll to better wait for finish of merging.
2021-03-15 11:13:24 +01:00
Zdenek Kabelac
800a93d4ac tests: wait till fs is synchronized
Adding full filesystem sync, trying to fight with strange error from losetup:

losetup: loopa: failed to set up loop device: Resource temporarily unavailable

loop0: detected capacity change from 0 to 4096
loop_set_block_size: loop0 () has still dirty pages (nrpages=13)

Also reuse internal aux wipefs_a
2021-03-15 11:13:24 +01:00
Zdenek Kabelac
78406ef617 tests: update handling of thin-pool removal
We shall no longer activate thin-pool, when
it's going away together with all thin volumes.
2021-03-15 11:13:24 +01:00
Zdenek Kabelac
e5e957e330 shellcheck: avoid assign warnings
Shellcheck seems to be happier when assigning variables with quotes.
2021-03-15 11:13:24 +01:00
Zdenek Kabelac
8a92f70709 cov: void unused result 2021-03-15 11:13:24 +01:00
Zdenek Kabelac
f69ff4b84a debug: update message 2021-03-15 11:13:24 +01:00
Zdenek Kabelac
6e9ccf7b6f debug: keep microseconds aligned 2021-03-15 11:13:24 +01:00
Zdenek Kabelac
bc1bc4cffc debug: drop stack from regular code flow 2021-03-15 11:13:24 +01:00
Zdenek Kabelac
eadd58a97d lvpoll: improve merge polling
When multiple polling tasks are watching for same LV, clearly
when some of them wins the game - other polling tasks will fail.
Improve the logic and report success if the merged LV is
actually not a merging origin anymore (since likely someone
else has already finished merging).
2021-03-15 11:13:24 +01:00
Zdenek Kabelac
1a451207b8 pooldaemon: increase min polling interval
Although we support '0' interval - it's highly inefficent to
do so many scans in busy-loop.

So ATM raise minimal rescan time to 100ms.

TODO: revisit whole timing logic here as it does have some sideeffect
hiddent impact and can considerably eat CPU in some cases.
2021-03-15 11:13:24 +01:00
Zdenek Kabelac
5edb353062 lvremove: use to_remove for snapshot removal
Reuse similar 'acceleration' as used for dependent volumes also
for snapshot  - so when origin is being removed with all thick
snapshots, don't bother with individual 'COW' detachments
and write&commits, and when possible handle this all within
a single commit.
2021-03-15 11:11:35 +01:00
Zdenek Kabelac
0a2d7c57a1 lvremove: use common routine for prompting
Move code for prompting about removed LV to a single function
and use it also to prompt for removal of origin and all its thick
snapshots and also when removing merging origin.

Function does handle postponed write_and_commit so there is
no 'in-flight' operation while waiting on [y|n] answer.
2021-03-15 11:08:47 +01:00
Zdenek Kabelac
a18409b6d1 vg_validate: fix validation of merging thin origin
Compat code and handle unusual case, where
thin snapshot is also a 'thick snapshot origin' and such
snapshot gets merged into a thin origin.

However since now lv_is_visible() (which is complex function)
replaced &VISIBLE_LV check, the whole this check seems to be
no longer useful as sum of all 3 will always match??
2021-03-15 10:59:09 +01:00
Zdenek Kabelac
ff712987a5 config: correct option name 2021-03-14 16:59:24 +01:00
Zdenek Kabelac
b4dfe026dd config: keep issue_discards in config struct
Avoid quering for this config option and keep it for removing in struct.
Also drop unused cache_vgmetadata variable.
2021-03-14 16:59:24 +01:00
Zdenek Kabelac
fab9987ad7 cleanup: move common condition 2021-03-14 16:34:38 +01:00
Zdenek Kabelac
b563c926ba cleanup: simplify 2021-03-14 16:34:38 +01:00
Zdenek Kabelac
664d3b0f22 lvremove: drop flushing dm cache before remove
Since cached LV is going to be removed together with its cache,
there is not much to gain if we try to flush cache first.
User may use 'vgcfgrestore' to get back origin + cache.
Assuming user is not using issue_discards.
When data are discarded after remove there is nothing to restore!

This change allows to futher reduce number of commits
during lvremove/vgremove.
2021-03-14 16:34:38 +01:00
Zdenek Kabelac
5141a510bd lv_info: missing check for info.exists
When &info is passed in, user needs to check for exists.
When there is NULL, return value includes check for exists.
2021-03-14 16:34:38 +01:00
Zdenek Kabelac
3608e8aee7 cache: use interruptible_usleep
Reuse code for interruptible sleeping.
2021-03-14 16:34:38 +01:00
Zdenek Kabelac
a3bb8f2ec1 activation: use interruptible_usleep
Support interruption while waiting on device close.
2021-03-14 16:34:38 +01:00
Zdenek Kabelac
941f67ed09 signals: add interruptible usleep
Add small wrapper that temporarily enables signal handling during
usleep() and return  '0' when interrupted.
2021-03-14 16:34:38 +01:00
Zdenek Kabelac
bbac843268 thinpool: correct condition
Actually we do want to flush thin-pool message for particular LV first.
Existing condition evaluated to noop.
2021-03-12 12:59:55 +01:00
Wu Guanghao
262008f1ce unit-test: modify for systems with PGSIZE of 64K
This modification supports dynamically obtaining the value of PAGE_SIZE,
which is compatible with systems with PAGE_SIZE of (4K/64K)

Signed-off-by: wuguanghao <wuguanghao3@huawei.com>
2021-03-11 00:56:43 +01:00
Zdenek Kabelac
236a45dfc5 toollib: preserve return code 5 2021-03-11 00:56:43 +01:00
Zdenek Kabelac
4bbaff1fa6 tests: settle after wiping
Add call to settle after wiping device so there is reduced
change to meet watch rule race during tests.
2021-03-11 00:18:01 +01:00
Zdenek Kabelac
2cbe88d6a1 debug: display_lvname 2021-03-11 00:18:01 +01:00
Zdenek Kabelac
a654148b76 gcc: adding const 2021-03-11 00:18:01 +01:00
Zdenek Kabelac
d7bb23dd15 cov: initialize value
Coverity can't understand conditions together, so just keep it quiet.
2021-03-11 00:18:01 +01:00
Zdenek Kabelac
23afad8247 cleanup: use already set vg_complete
Already set to 0.
2021-03-11 00:18:01 +01:00
Zdenek Kabelac
c4f5d93122 cleanup: eliminate unused assign 2021-03-11 00:18:01 +01:00
Zdenek Kabelac
d86e943b80 toollib: use EINIT_FAILED for missing devs
There is really no practical reason to continue running
when we fail on allocation.

It seems we may need further fine frained errors, as for
some error type we simply need to exit ASAP, while
others may still produce usable results.
2021-03-11 00:18:01 +01:00
Zdenek Kabelac
f4543aca15 lvremove: support faster removal of thin-pools
When lvremove/vgremove removes thin volumes with its thin-pool as well,
try to skip any updates of such thin-pool, so when everything properly
deactivates, there is no message send to this thin-pool and whole
thin-pool is removed with a single commit.
2021-03-11 00:18:01 +01:00
Zdenek Kabelac
dac8274701 toollib: prioritize processing thin-pool first
When generating list of processed LV, add thin-pool to the head of the
list, while other LVs are added on tail.

This makes it easier when removing many thin volumes, to recognize easily
when its thin-pool is also supposed to be removed.
2021-03-11 00:18:01 +01:00
Zdenek Kabelac
7a99dac9ad lvconvert: fix error path on writecache removal
After setting ret=0 there was missing 'goto out_release'.
Simplify with setting ret to 0 at front and to 1
at succesful end.
2021-03-10 23:32:12 +01:00
Zdenek Kabelac
127c2fc6e2 lv_check_not_in_use: correct check
Since lv_info() may return 0 without setting info struct,
make the test correct and even more readable.
2021-03-10 23:32:12 +01:00
Marian Csontos
d4293b579d tests: Skip test killing kernel
Fix the pattern and for now skip all RHEL-8.4 kernels

Bug 1916891
2021-03-10 16:31:04 +01:00
Zdenek Kabelac
6097dfb9ad cov: happier with defined extent_size
Set extent_size with != 0 value so there is not division by 0
in any code path.
2021-03-10 01:35:02 +01:00
Zdenek Kabelac
94712e3233 cov: defined flv 2021-03-10 01:35:02 +01:00
Zdenek Kabelac
a66380ea3e cov: ensure settings is set 2021-03-10 01:35:02 +01:00
Zdenek Kabelac
f7912635a0 cov: ensure buffer is initialized 2021-03-10 01:35:02 +01:00
Zdenek Kabelac
8a03675241 cov: variable initialization 2021-03-10 01:34:58 +01:00
Zdenek Kabelac
bee9b5c1d8 cov: mask uninitialized value
Coverity doesn't track ioctl() too well, so let's just make it quiet.
2021-03-10 01:34:27 +01:00
Zdenek Kabelac
74936f53f7 cov: unused value 2021-03-10 01:29:44 +01:00
Zdenek Kabelac
d95c0e977c cov: remove unnecessary headers 2021-03-10 01:29:44 +01:00
Zdenek Kabelac
a6075fe2f2 cov: memleak on error path 2021-03-10 01:29:44 +01:00
Zdenek Kabelac
241c63f7a7 cov: fix iter memleak in vgimportclose
Add missing release of iterator on error path.
2021-03-10 01:29:06 +01:00
Zdenek Kabelac
131ca0eb95 activation: use existing LV as best effort
Returning NULL for lv_committed is basically instant crash,
so instead try with passed LV instead.
It shouldn't matter as this is internall error path anyway,
but coverity should be happier.
2021-03-10 01:29:06 +01:00
Zdenek Kabelac
15c588f931 gcc: match size of holder name to direcnt d_name
As d_name is defined as 256 avoid gcc warning - although
in our case the used size will be much smaller.
2021-03-10 01:28:08 +01:00
Zdenek Kabelac
75037bee5d debug: more tracing
Check result of device_ids_write() and at least provide stack;
2021-03-10 01:27:13 +01:00
Zdenek Kabelac
d01c17ff22 debug: more use of display_lvname 2021-03-10 01:11:52 +01:00
Zdenek Kabelac
7342ab06fc debug: change sys_error to sys_debug
These messages do not cause command error - so changing logging level
to just 'sys_debug' (so visible only with -vvvv)
2021-03-10 01:11:52 +01:00
Zdenek Kabelac
5f7a7af7f2 cleanup: no backtraces needed after log_error
Reduce double backtracing.
2021-03-10 01:11:52 +01:00
Zdenek Kabelac
c05077f4d4 cleanup: easier print of historical lv
Drop unneeded macros.
2021-03-10 01:11:52 +01:00
Zdenek Kabelac
177b63becc backup: set in vg_commit
Another step towards better automatic handling of backup,
and automatically setup needs_backup after commit.

In some next step we should reduce number of backups and takem
then only at the command finish with  vg_committed content.
2021-03-10 01:09:46 +01:00
Zdenek Kabelac
88d04e9173 lvm-file: remove duplication of dm_is_empty_dir 2021-03-10 01:09:14 +01:00
Zdenek Kabelac
413a114cdb thin: correct ptr test for thin snapshot merging
The correct test needs to actually check  'lv->snapshot' is not NULL,
so the 'find_snapshot()' can work.

Test lv_is_snapshot was actually irrelavant for this case.

Also initialize device_id.
2021-03-10 01:09:14 +01:00
Zdenek Kabelac
b2616cd456 device_mapper: keep bigger size for most ioctls
Actually the idea was to keep 2K ioctl only for certain command,
so keep 16 for them.
2021-03-10 01:07:16 +01:00
Zdenek Kabelac
d2a3bfe6ca vg_write: shift check for exported metadata
Since we now immediatelly use created buffer for CFT creation,
the result needs to be validate before such use.
2021-03-10 01:00:18 +01:00
Zdenek Kabelac
17802084c9 bcache: fix incorrect pointer check
With commit b44db5d1a7
needs to check allocated pointer for failed malloc().

Existing check was actually no checking anything so failing
malloc here would result in segfault (although with very
low chance to ever happen).
2021-03-10 00:59:05 +01:00
David Teigland
d5f3239de4 tests: check_devicesfile
make check_devicesfile T=...

(A number of tests should probably get a new
SKIP_WITH_DEVICES_FILE.)
2021-03-08 17:19:26 -06:00
Zdenek Kabelac
843ee943ab lvremove: correct return code
Need to return ECMD_FAILED from toollib code.
Add missing stack traces.
2021-03-08 20:24:04 +01:00
Zdenek Kabelac
3cbb751815 WHATS_NEW: updates 2021-03-08 15:43:27 +01:00
Zdenek Kabelac
6d6e1ae887 cleanup: compare only LV uuid part
Match VG uuid just once per list of all LVs in VG.

TODO: maybe some more efficeint tree or hash could be better here,
but since it's used not so often, the total benefit is not so great,
so ATM just reducing amount of checked bytes.
2021-03-08 15:43:27 +01:00
Zdenek Kabelac
64447e9d9b cleanup: move code
just evaluate later in code path.
2021-03-08 15:43:27 +01:00
Zdenek Kabelac
e5456c259f cleanup: simpler checks first
Minor optimizatoins...
2021-03-08 15:43:27 +01:00
Zdenek Kabelac
f4200acac2 cleanup: on stack structure instead of allocation 2021-03-08 15:43:27 +01:00
Zdenek Kabelac
dac990ae03 cleanup: avoid allocating memory for hash key
Hash always allocates its own copy of the key so avoid
this extra uuid copy.
2021-03-08 15:43:27 +01:00
Zdenek Kabelac
d3cff64408 libdm-config: replace check for 0
No need to call strlen() when checking for zero length string.
2021-03-08 15:43:27 +01:00
Zdenek Kabelac
ca12dae32b hints: keep strings aligned in structure
Preffer aligned string access.
2021-03-08 15:33:15 +01:00
Zdenek Kabelac
ff21723512 hash: replace hash with better function
Add Bob Jenkins hash function to get better working hash function,
which does genarate way less colisions (especially with similar
strings).

For a comparision also a kernel function used in DM kernel is include.
While it's better then our existing one, it's still far worse,
then Bob Jenkins hash.
2021-03-08 15:33:15 +01:00
Zdenek Kabelac
d602837b91 hash: speed up hash tables
Enhance hash perfomance by remembering the computed
hash value for the hashed node - this allows to speedup
lookup of nodes with the hash collision when
different keys map to the same masked hash value.

For the easier use 'num_slots' become 'mask_slots',
so we only add '1' in rare case of need of the original
num_slots value.

Also add statistic counters for hashes and print stats in
debug build (-DDEBUG) on hash wiping.
(so badly performing hash can be optimized.)
2021-03-08 15:33:15 +01:00
Zdenek Kabelac
84679d254f hash: use unsigned size
There is not much point in using 64bit hash size, since we hash
with way less bits anyway. So keep size 32bit.
2021-03-08 15:33:15 +01:00
Zdenek Kabelac
2d64ffaee5 hash: use individual hint sizes
Use different 'hint' size for dm_hash_create() call - so
when debug info about hash is printed we can recognize which
hash was in use.

This patch doesn't change actual used size since that is always
rounded to be power of 2 and >=16 - so as such is only a
help to developer.

We could eventually use 'name' arg, but since this would have changed
API and this patchset will be routed to libdm & stable - we will
just use this small trick.
2021-03-08 15:33:15 +01:00
Zdenek Kabelac
78c7ae7cd2 lvremove: reduce ioctl count
Just like with deactivation, call of 'lv_is_not_in_use()'
now has embeded report for inactivate LV.

Note: this patch cannot be backported to stable-2.02 - as
there lv_is_active() has 'cluster' meaning and differs from lvinfo().
2021-03-08 15:32:10 +01:00
Zdenek Kabelac
dceef4709d deactivation: reduce ioctl count
When LV is deactivativate, we check for presence, and later
for some LV types also for being in use.

We can however do this check in 1 step for them a remove extra ioctl.

Add return value '2' to lv_check_not_in_use() to recognize LV is not
present.

Existing users were just testing for 0, so no change for them.
2021-03-08 15:30:18 +01:00
Zdenek Kabelac
936c7b5104 vg_read: reuse already parsed config tree
When parsing VG metadata we can create from a single config tree
also 'vg_committed' that is always created for writable VG.

This avoids extra uncessary step of serializing and deserilizing
just parsed VG.
2021-03-08 15:30:18 +01:00
Zdenek Kabelac
bc0cb66304 vg_write: optimize caching of precommitted VG
Every vg_write stores new 'metadata' into precommitted slot.
For this step we use 'serialized buffer' to ascii metadata.

Instead of recreating this buffer after whole 'vg_write()' we
use this buffer instantly for creating of precommitted VG.

This has also the advantage of catching any problems with
reparsing of ascii metadata back to VG early before any write.
2021-03-08 15:30:18 +01:00
Zdenek Kabelac
a125a3bb50 lv_remove: reduce commits for removed LVs
This patch postpones update of lvm metadata for each removed
LV for later moment depending on LV type.

It also queues messages to be printed after such write & commit.

As such there is some change in the behavior - although before
prompt we do make  write&commit happens automatically in some
other error case we rather keep 'existing' state - so there
could be difference in amount of removed & commited LVs.

IMHO introduce logic is slightly better and more save.

But some cases still need the early commit - i.e. thin-removal
and fixing this needs some more thinking.

TODO: improve removal at least with the case of the whole thin-pool.
i.e. we can simply recognize removal of 'all LVs/whole VG'.
2021-03-08 15:25:05 +01:00
Zdenek Kabelac
ee9488488f makefiles: fix location of basedir 2021-03-08 15:22:27 +01:00
Marian Csontos
7df4a13282 makefiles: make rpm respect --disable-silent-rules 2021-03-08 14:10:17 +01:00
Marian Csontos
e10633394d makefiles: Revert most of 456b659
Must not use DESTDIR with --basedir.

Reverts: 456b659b4e
2021-03-08 13:59:26 +01:00
Marian Csontos
2244a56021 make: generate 2021-03-05 12:53:35 +01:00
Marian Csontos
3bea893733 man: Fix wording in lvmthin(7) 2021-03-05 12:49:54 +01:00
David Teigland
f5fbb1b76f lvmlockctl: replace popen and system
with fork and exec to avoid use of shell.
largely copied from lib/misc/lvm-exec.c

require lvmlockctl_kill_command to be full path

use lvm config instead of lvmconfig to avoid need for LVM_DIR
2021-03-03 17:43:29 -06:00
David Teigland
89a3440fc0 lvmlockctl: use lvm.conf lvmlockctl_kill_command
which specifies a command to run by lvmlockctl --kill.
2021-03-03 13:57:15 -06:00
David Teigland
e9d10f3711 filters: better message for excluding LV
Make the generic "device is not usable" message from filter-usable
more specific in case the device is not usable because it's an LV.
(i.e. when scan_lvs=0)
2021-03-03 12:07:57 -06:00
Zdenek Kabelac
d0b0c20077 WHATS_NEW: updates 2021-03-02 22:57:35 +01:00
Zdenek Kabelac
9cb913ab4b make: generate 2021-03-02 22:57:35 +01:00
Zdenek Kabelac
8e1771f857 debug: use enclusing "" for debug 2021-03-02 22:57:35 +01:00
Zdenek Kabelac
1042cd9a61 cleanup: simplify condition 2021-03-02 22:57:35 +01:00
Zdenek Kabelac
eb3dcc72eb cleanup: free already checks for NULL 2021-03-02 22:57:35 +01:00
Zdenek Kabelac
0b7a4503e5 integrity: mark as user of secure_data
Use the secure_data with integrity target. Not so big difference,
as the secure feature of the integrity target is not used by lvm2.
2021-03-02 22:57:35 +01:00
Zdenek Kabelac
67790d7e3b device_mapper: reduce min_size for flatten
For most ioctl() we do not need to pass so big buffers
and we can reduce amount of zeroed memory blocks.
2021-03-02 22:57:35 +01:00
Zdenek Kabelac
73bea16c92 device_mapper: zero only secure buffers
Securely erase before free() only dm_tasks marked as secure_data.
TODO: think about also using this for libdm/.
2021-03-02 22:56:32 +01:00
Zdenek Kabelac
00531186fc label: check only with active device for rescan
When 'lv_info()' is called with &info structure,
the presence of node has to be checked from this structure.
Without this we were needlesly trying to look out 0:0 device.
2021-03-02 22:54:40 +01:00
Zdenek Kabelac
56620b9039 toolib: move sigint_caught
Move the check for catched signal to the loop front.
Currently not much usable - but we can improve it later.
2021-03-02 22:54:40 +01:00
Zdenek Kabelac
2a9a3346e7 archive: support interruption
When lvm2 calls archive() or backup() it can be useful to allow handling
break signal so the command can be interrupted at some consistent point.

Signal is accepted during processing these calls - and can be evaluated
later during even lengthy processing loops.

So now user can interrupt lengthy lvremove().
2021-03-02 22:54:40 +01:00
Zdenek Kabelac
eb1160ee42 lvremove: backup at the end of loop
Taking backup with each removed LV is slowing down the process
considerable and is largerly uneeded. We are supposed to take
backup only on significant points and making sure the backup
is correct when the command is finished.

TODO: check how many other commands can be improved.
2021-03-02 22:54:40 +01:00
Zdenek Kabelac
fa64c51428 dev-cache: optimize dir scanning
Use 'C' for alphasort - there is no need to use localized and slower
sorting for internal directory scanning.

Ensure on all code paths allocated dirent entries are released.

Optimize full path construction.
2021-03-02 22:54:40 +01:00
Zdenek Kabelac
9dd759c6b1 dev-cache: replace inefficient looking for dev
Use btree loopkup to find dev structure by major:minor.
This could have slow down lvm2 commands significantly with
higher amount of LVs.
2021-03-02 22:54:40 +01:00
Zdenek Kabelac
081e47912e cmdline: use binary search
Reduce strcmp() call count by using binary search to find
commands in cmd_names[] and command_names[] arrays.
2021-03-02 22:54:40 +01:00
Zdenek Kabelac
589c654562 cmdline: drop MAX and check NULL
Remove MAX_COMMAND_NAMES and check for the last element as NULL pointer.
2021-03-02 22:54:40 +01:00
Zdenek Kabelac
e946a5e690 cmdline: lvcreate adds vdopool as vg name provider
Add same logic as with thinpool or cachepool.
2021-03-02 22:54:40 +01:00
Zdenek Kabelac
f87d1a2abb commands.h: keep entries alphabetically sorted
For binary search usage commands need to be sorted.
Later patch also adds check if the order would be broken.
2021-03-02 22:54:40 +01:00
Zdenek Kabelac
6846af6612 makefiles: retry faster deps again
From commit 29abba3785 we have hopefully
fixed most of troubles for deps tracking we had in past - so retry
again.

Drop explicit configure.h from DEPS - as it's automatically gathered
by gcc dependency tracking anyway.
2021-03-02 22:54:40 +01:00
Zdenek Kabelac
39eee85fff makefiles: better logging
Show only filename instead of full path name when building
in builddir != srcdir
2021-03-02 22:54:40 +01:00
Zdenek Kabelac
456b659b4e makefiles: integrate DESTDIR
Always use lvmdbusdir with DESTDIR.
2021-03-02 22:54:40 +01:00
Zdenek Kabelac
8bfa4439e1 makefiles: fix pofile generation
If there is any user of --enable-nls  and wants to get
usable .po language file  -  use 'make pofile'
2021-03-02 22:54:40 +01:00
Zdenek Kabelac
4e976d9960 makefiles: cmirrord install through install_cluster
There is not much left for this target...
2021-03-02 22:54:40 +01:00
Zdenek Kabelac
e080e35c83 makefiles: sed 2021-03-02 22:54:40 +01:00
Zdenek Kabelac
520bd9356e makefiles: simplify and cleanup
Print all installed man pages with INSTALL
Simplify distclean handling.
2021-03-02 22:54:40 +01:00
Zdenek Kabelac
da29afe028 makefiles: drop invalid dependency on all 2021-03-02 22:54:40 +01:00
Zdenek Kabelac
5509e764f1 makefiles: add alias for device-mapper
Support also 'make device_mapper' so user is less confused.
2021-03-02 22:54:40 +01:00
Zdenek Kabelac
8d93d8b7b7 makefiles: fix man-generate rule
Symlink and compiled man-generate binary has to go to builddir.
2021-03-02 22:54:40 +01:00
Zdenek Kabelac
824230e1e2 makefiles: avoid sorting by locales
Localized sort for building source file is not wanted.
2021-03-02 22:54:40 +01:00
Zdenek Kabelac
9d190d6b46 makefiles: support help target
Usable targets for top-level make.
2021-03-02 22:54:40 +01:00
Zdenek Kabelac
8d3ce32880 tests: make test complaint to local dev dir
For test running in 'local' dev dir we want to see loop devices there.
Also add missing notification to lvmetad after wipefs.
2021-03-02 22:24:51 +01:00
Zdenek Kabelac
7528a33630 tests: update setting LVM_BINARY for testing
When testing is running on uninstealled system - prefer our own binary
in tests.
2021-03-02 22:24:51 +01:00
David Teigland
3bab1a1026 config: remove redundant comment for deprecated settings
Drop the comment "This setting is no longer used." which
was printed just before the standard deprecation comment:
"This configuration option is deprecated."
2021-03-02 14:15:17 -06:00
David Teigland
db4af67b37 lvmconfig: fix deprecation message
When lvmconfig --typeconfig full printed a deprecated
entry it would attempt to print a non-existing
deprecation comment resulting in output like:
  # (null)        # This setting is no longer used.
2021-03-02 14:14:28 -06:00
David Teigland
aa34da6ecc Revert "tests: enable tests for lvmlockd"
This reverts commit 99b6173f10.

These tests are disabled with lvmlockd because they use
snapshots without an origin which is not permitted in a
shared vg.
2021-02-24 10:30:51 -06:00
David Teigland
6fad7f2eac tests: real_devs remove mistakenly added test
devicesfile-realdevs is the correct one
2021-02-24 10:21:18 -06:00
David Teigland
91d6822534 WHATS_NEW: devices file 2021-02-23 16:43:38 -06:00
David Teigland
b36b4b82d8 tests: for devices file 2021-02-23 16:43:38 -06:00
David Teigland
135c226e26 tests: allow tests to use real devices
user creates a file listing real devices they want
lvm tests to use, and sets LVM_TEST_DEVICE_LIST.
lvm tests can use these with prepare_real_devs
and get_real_devs.
Other aux functions do not work with these devs.
2021-02-23 16:43:37 -06:00
David Teigland
83fe6e720f device usage based on devices file
The LVM devices file lists devices that lvm can use.  The default
file is /etc/lvm/devices/system.devices, and the lvmdevices(8)
command is used to add or remove device entries.  If the file
does not exist, or if lvm.conf includes use_devicesfile=0, then
lvm will not use a devices file.  When the devices file is in use,
the regex filter is not used, and the filter settings in lvm.conf
or on the command line are ignored.

LVM records devices in the devices file using hardware-specific
IDs, such as the WWID, and attempts to use subsystem-specific
IDs for virtual device types.  These device IDs are also written
in the VG metadata.  When no hardware or virtual ID is available,
lvm falls back using the unstable device name as the device ID.
When devnames are used, lvm performs extra scanning to find
devices if their devname changes, e.g. after reboot.

When proper device IDs are used, an lvm command will not look
at devices outside the devices file, but when devnames are used
as a fallback, lvm will scan devices outside the devices file
to locate PVs on renamed devices.  A config setting
search_for_devnames can be used to control the scanning for
renamed devname entries.

Related to the devices file, the new command option
--devices <devnames> allows a list of devices to be specified for
the command to use, overriding the devices file.  The listed
devices act as a sort of devices file in terms of limiting which
devices lvm will see and use.  Devices that are not listed will
appear to be missing to the lvm command.

Multiple devices files can be kept in /etc/lvm/devices, which
allows lvm to be used with different sets of devices, e.g.
system devices do not need to be exposed to a specific application,
and the application can use lvm on its own set of devices that are
not exposed to the system.  The option --devicesfile <filename> is
used to select the devices file to use with the command.  Without
the option set, the default system devices file is used.

Setting --devicesfile "" causes lvm to not use a devices file.

An existing, empty devices file means lvm will see no devices.

The new command vgimportdevices adds PVs from a VG to the devices
file and updates the VG metadata to include the device IDs.
vgimportdevices -a will import all VGs into the system devices file.

LVM commands run by dmeventd not use a devices file by default,
and will look at all devices on the system.  A devices file can
be created for dmeventd (/etc/lvm/devices/dmeventd.devices)  If
this file exists, lvm commands run by dmeventd will use it.

Internal implementaion:

- device_ids_read - read the devices file
  . add struct dev_use (du) to cmd->use_devices for each devices file entry
- dev_cache_scan - get /dev entries
  . add struct device (dev) to dev_cache for each device on the system
- device_ids_match - match devices file entries to /dev entries
  . match each du on cmd->use_devices to a dev in dev_cache, using device ID
  . on match, set du->dev, dev->id, dev->flags MATCHED_USE_ID
- label_scan - read lvm headers and metadata from devices
  . filters are applied, those that do not need data from the device
  . filter-deviceid skips devs without MATCHED_USE_ID, i.e.
    skips /dev entries that are not listed in the devices file
  . read lvm label from dev
  . filters are applied, those that use data from the device
  . read lvm metadata from dev
  . add info/vginfo structs for PVs/VGs (info is "lvmcache")
- device_ids_find_renamed_devs - handle devices with unstable devname ID
  where devname changed
  . this step only needed when devs do not have proper device IDs,
    and their dev names change, e.g. after reboot sdb becomes sdc.
  . detect incorrect match because PVID in the devices file entry
    does not match the PVID found when the device was read above
  . undo incorrect match between du and dev above
  . search system devices for new location of PVID
  . update devices file with new devnames for PVIDs on renamed devices
  . label_scan the renamed devs
- continue with command processing
2021-02-23 16:43:32 -06:00
Zdenek Kabelac
f7d9542aed WHATS_NEW: updates 2021-02-23 15:01:05 +01:00
Zdenek Kabelac
5d820b0201 cleanup: comment typo 2021-02-23 14:56:48 +01:00
Zdenek Kabelac
0c842ee8ad cleanup: improving message
lvconvert -Z can be used with snaps & pools.
2021-02-23 14:56:48 +01:00
Zdenek Kabelac
5237175cb6 cleanup: simplify initilization
Simplier code and also drop duplicate check for active LV.
2021-02-23 14:56:48 +01:00
Zdenek Kabelac
b5f906e984 cleanup: simply code 2021-02-23 14:56:48 +01:00
Zdenek Kabelac
5ecd65e6f2 lvconvert: change errors to internal ones
Since these errors should never happen, change them to  internal errors.
2021-02-23 14:56:47 +01:00
Zdenek Kabelac
b140bba9fe cache: fix warning test
The cache here is not 'writethough' - so print proper state
(writeback or passthrough)
2021-02-23 14:56:47 +01:00
Zdenek Kabelac
ac09fa08aa lvextend: enable resize of writecached LV 2021-02-23 14:56:47 +01:00
Zdenek Kabelac
e43b5f1e3c tests: remove local setting of LVM_BINARY
To better test actually fsadm in test suite - avoid setting
LVM_BINARY locally - since test setup already modifies
PATH to find test's lvm binary as the 1st. in path.
2021-02-23 14:56:47 +01:00
Zdenek Kabelac
646e3280dd fsadm: avoid access to unbound variable 2021-02-23 14:56:47 +01:00
David Teigland
9e836c77a0 command defs: add missing commas
even though the parser seems to work fine without them
2021-02-22 10:44:01 -06:00
David Teigland
12667e9897 fix check for md raid imsm signature on 4k devices
On devices with 4k logical block size, the imsm signature
is located 8k from the end of the device, not 1k as is
the case for devices with 512 LBS.
2021-02-18 11:42:32 -06:00
Marian Csontos
3cba071254 tests: Skip test killing kernel
Bug 1916891
2021-02-17 13:28:56 +01:00
Zdenek Kabelac
26a09c84c9 WHATS_NEW: updates 2021-02-17 11:53:19 +01:00
Zdenek Kabelac
2c5e034cd3 make: generate 2021-02-17 11:53:19 +01:00
Zdenek Kabelac
b9846bdc3e tests: readonly snapshot thick origin can't be merged
When user sets snapshot thick origin as read-only - lvconvert --merge refuses
to merge until user swiches origin to 'read-write'.
2021-02-17 11:53:19 +01:00
Zdenek Kabelac
868b733588 lvmlocdk: correct creation of dm path vg sanlock LV
Vgname may contain '-' and needs escaping '--' for /dev/mapper path.
2021-02-17 11:53:19 +01:00
Zdenek Kabelac
fbaf5a32bb tests: lvconvert vdo profile support 2021-02-17 11:53:19 +01:00
Zdenek Kabelac
9c0ce4daa2 man: vdo drop resize restriction comment
lvm2 supports resize of cached vdo pool volumes.
2021-02-17 11:53:19 +01:00
Zdenek Kabelac
19e1373580 tests: check resize of cached vdopool 2021-02-17 11:53:18 +01:00
Zdenek Kabelac
5bf1dba9eb vdo: just one probe is enough
target_present_version() can handle modprobing no need to try it
twice.
2021-02-17 11:21:35 +01:00
Zdenek Kabelac
a7cb25c877 lvconvert: VDO kernel support before converting
Early check for kernel support of VDO target before starting any
conversion work.
2021-02-17 11:21:35 +01:00
Zdenek Kabelac
a915cd5a46 lvconvert: vdo may convert already formated vdo
User use 'lvconvert -Zn --type vdo-pool' to convert an existing
vdo formated volume and skip lvm2 internal formating.
This however requires user is passing proper matching parameters.
For them user can use --profile|--metadataprofile option whos
support has been also enhanced.

TODO: add support to read values directly from formated volume.
2021-02-17 11:21:35 +01:00
Zdenek Kabelac
f87ff95e32 lvchange: remove unneeded call
Sync is already happining in activate_and_wipe_lvlist().
2021-02-17 11:21:35 +01:00
Zdenek Kabelac
096edeee71 lv_manip: avoid removing LV when converting
In some cases we use 'creation' also during conversion.
Here it can be actually unwanted side effect we may remove
not just newly created layers - but also original converted LV.

So until we make clear how to properly revert from some errors
in middle of conversion, disable removal for any 'lvconvert' commands.
2021-02-17 11:21:35 +01:00
Zdenek Kabelac
3ef0861355 tests: lvdisplay does not crash for merged thin 2021-02-17 11:21:35 +01:00
Zdenek Kabelac
14008ead2a lvdisplay: fix show of merged thin snapshot
When lvdisplay was executed and thin snaphost has be merged to
thin origin and the operation has been postponed till devices
are closed, command crashed.

Check LV is COW before trying to check snapshot percentage.
2021-02-17 11:21:35 +01:00
Zdenek Kabelac
3af61d8646 tests: lvconvert thin profile conversion 2021-02-17 11:21:35 +01:00
Zdenek Kabelac
53666d6ee3 lvconvert: thin errorwhenfull and recalculation
When converting an existing LV to thin-pool,
user may now pass also '--errorwhenfull' option
like with 'lvcreate'.

Also recalculate chunksize when performace profile is
used with conversion (again matching lvcreate).

Adds missing flagging for uncropped metadata sizes.
2021-02-17 11:21:35 +01:00
David Teigland
4486f08d51 include lvm version in debug output 2021-02-12 10:51:41 -06:00
David Teigland
c94d78f068 scan: wipe filters when dropping scanned data
Fix clearing persistent filter state when clearing all
the state from a label_scan.

label_scan reads devs and saves info in bcache, lvmcache,
and in the persistent filter.  In some uncommon cases, an
lvm command wants to clear all info from a prior label_scan,
and repeat label_scan from scratch.  In these cases, info
in lvmcache, bcache and the persistent filter all need to
be cleared before repeating label_scan.

By missing the persistent filter wiping, outdated persistent
filter info, from a prior label_scan, could cause lvm to
incorrectly filter devices that change between polling intervals.
(i.e. if the device changes in such a way that the filtering
results change.)

A case where lvm wants to do multiple label_scans is a
polling command (like lvconvert --merge), when lvmpolld
has been disabled, so that the command itself needs to
to do repeated polling checks.
2021-02-10 15:34:45 -06:00
Zdenek Kabelac
f49bedc029 WHATS_NEW: update 2021-02-10 15:39:03 +01:00
Zdenek Kabelac
04cd4df847 gcc: drop unused assingment 2021-02-10 15:39:03 +01:00
Zdenek Kabelac
a1e2541333 gcc: ensure pointer is always defined 2021-02-10 15:39:03 +01:00
Zdenek Kabelac
82bffa99ad libdm: simplify line emitter checking 2021-02-10 15:39:03 +01:00
Zdenek Kabelac
4b371246f5 device_mapper: simplify line emitter checking 2021-02-10 15:39:03 +01:00
Zdenek Kabelac
a383586177 label: avoid rescaning unusable DM devices 2021-02-10 15:39:03 +01:00
Zdenek Kabelac
f90082ce8f lvconvert: read-only origin cannot be merged
When user sets snapshost origin as read-only,
lvm will not allow simple merge and user needs to
flip permission,
2021-02-10 15:39:03 +01:00
Zdenek Kabelac
2895180058 lvchange: snapshot thick origin permission rw/r
User is allowed to change permission for thick origin.
FIXME: it's not quite clear why few others are prohibited to change.
2021-02-10 15:39:03 +01:00
Zdenek Kabelac
3cc9efc0ed snapshot: create origin of virtual snap read only
When creating old fashioned way thick virtual snapshot,
use read-only 'zero' _vorigin device.
2021-02-10 15:39:03 +01:00
Zdenek Kabelac
96910de4c7 dev-cache: remove duplicated allocation
Merge mistake missed to remove allocation that is now postponed
until it's really needed.
2021-02-10 15:38:18 +01:00
David Teigland
f74f94c2dd dev_get_primary_dev: fix invalid path check
Fix commit bee9f4efdd "filter-mpath: work with nvme devices"
which removed setting the path for readlink.
2021-02-09 09:52:53 -06:00
Zdenek Kabelac
427121efc7 dev-type: sysfs attrs without sectors
Split function for reading attrs in sectors.
2021-02-09 00:49:14 +01:00
Zdenek Kabelac
ef2e0d3d68 typo: fixes
forgotten merge from last batch.
2021-02-08 23:53:41 +01:00
Zdenek Kabelac
d280999b62 WHATS_NEW: updates 2021-02-08 23:43:38 +01:00
Zdenek Kabelac
d422aa7924 dev-type: convert to use log_warn
Keep log_error designated only for 'erroring' condition of command
and replace these errors with log_warn() WARNING.

Also do some indent changes.
2021-02-08 23:43:38 +01:00
Zdenek Kabelac
3bf2ca11d9 dev-type: use fopen for sysfs file
Directly open sysfs files and save extra stat() call which
is not adding any extra safety in sysfs dir.
2021-02-08 23:43:38 +01:00
Zdenek Kabelac
e429e69b65 dev-type: dev_is_pmem reuses topology read code 2021-02-08 23:43:38 +01:00
Zdenek Kabelac
2c597c73a8 dev-cache: better code reuse for _add_alias
Move path copying into _add_alish together with hashing.
Remove duplicated code.
2021-02-08 23:43:38 +01:00
Zdenek Kabelac
be9b731f44 dev-cache: check for nvme name while adding alias
Instead of repeated list retest, compare name once during add of alias.
2021-02-08 23:43:38 +01:00
Zdenek Kabelac
9b173bb931 targets: use target_present_version
Skip duplicated  dm version   ioctl() on every startup.
2021-02-08 23:43:38 +01:00
Zdenek Kabelac
6373f39092 tests: check event_activation can be disabled 2021-02-08 23:43:38 +01:00
Zdenek Kabelac
b86eb913c1 tests: support for resized cached LVs
Support for cached LVs is now enabled.
2021-02-08 23:43:38 +01:00
Zdenek Kabelac
5ec24dfb0b lv_resize: support resizing of cached volumes
Automatically figure out resizable layer in the LV stack and
resize it online.

Split check for reshaped raids and postpone removal of
unused space after finished reshaping after metadata archiving.

Drop warning about unsupported automatic resize of monitored thin-pool.

Currently there is not yet support for resize of writecache.
2021-02-08 23:43:10 +01:00
Zdenek Kabelac
39dec26508 lv_manip: reuse function also during reduction
Move function _setup_lv_size() in front of _lv_reduce() so
it can be reused also in this function.
Avoid propagating 0 length to upper layer.
2021-02-08 23:18:44 +01:00
Zdenek Kabelac
bdc2f4c704 lv_resize: use 'bad' code path for error case 2021-02-08 23:18:44 +01:00
Zdenek Kabelac
eed060f040 thin: check for overprovisioning only once 2021-02-08 23:18:44 +01:00
Zdenek Kabelac
99e168162a thinpool: use lv_config_profil for crop_metadata
Better support for thin-pools with individual profiles introduced
in the recent patch b4212be2e7.
2021-02-08 23:18:44 +01:00
Zdenek Kabelac
2be585b79c pvscan: support disabled event_activation
In past we had this control with use_lvmetad check for
pvscan --cache -aay

Howerer this got lost with lvmetad removal commit:
117160b27e

When user sets lvm.conf global/event_activation=0
pvscan service will no longer auto activate any LVs on appeared PVs.
2021-02-08 23:18:44 +01:00
David Teigland
018bba897c fix for md component detection changes
And some fine tuning of when the checks are applied
in "start" mode.
2021-02-08 11:23:42 -06:00
David Teigland
df4c50396b lvmcache: remove unused variable from last commit 2021-02-08 10:22:56 -06:00
David Teigland
87ee401eea md component detection changes
Move extra md component detection into the label scan phase.
It had been in set_pv_devices which was deep within the vg_read
phase, which wasn't a good place (better to detect that earlier.)
Now that pv metadata info is available in the scan phase, the pv
details (size and device_hint) can be used for extra md checking.

Use the device_hint from the pv metadata to trigger a full md
component check if the device_hint begins with /dev/md.

Stop triggering full md component checks based on missing
udev info for a dev.

Changes to tests to reflect that the code is now detecting
md components in some test case that it wasn't before.
2021-02-05 16:23:51 -06:00
David Teigland
67d8fb1e83 dm: add debugging to include table differences
When dm tables are reloaded, include log_debug info
that will show the details of why the reload is needed.
2021-02-03 13:44:10 -06:00
David Teigland
834cba000a hints: clean up comment and init settings
no behavior change
2021-02-02 15:14:05 -06:00
David Teigland
cb54d0801d cachevol: allow forced detaching of damaged or invalid cachevol
A cachevol can be forcibly detached when it's missing devices.
Also allow this if it's damaged/invalid and unrepairable.
This would be needed to recover data from the origin LV after
a cachevol is lost or damaged beyond repair.
2021-02-02 14:31:23 -06:00
Zdenek Kabelac
ae2af1d5ed test: check read_only_volume_list tagging works 2021-02-02 21:23:39 +01:00
Zdenek Kabelac
51c83f1483 lvcreate: use lv_passes_readonly_filter
Check if created LV is going to be activated read-only
because such LV cannot be zeroed (equals to use
option '-pr').
2021-02-02 21:23:39 +01:00
David Teigland
8454ce66c5 writecache: let block_size setting override device block sizes
In cases where lvconvert does not detect a fs block size on the
device, it falls back to choosing a writecache block size based
on the device's LBS and PBS (tries to match those.)

If the user specifies a writecache block size on the command
line (--cachesettings block_size=4096|512), lvconvert currently
fails and reports an error if the user-specified value does not
match the value lvconvert would have chosen based on LBS and PBS.

The purpose of allowing a user-specified value on the command line
is to override what lvconvert would otherwise do, so change this
to just print a warning that the user value does not match the
value that would be chosen based on the LBS/PBS, and then take
the user-specified value as the writecache block size.
2021-02-02 13:52:31 -06:00
David Teigland
bee9f4efdd filter-mpath: work with nvme devices
Recognize when a device is nvme, and apply filter-mpath to
nvme devices in addition to scsi devices.
2021-02-02 13:01:20 -06:00
Zdenek Kabelac
48dfc388f7 tests: increase required target version
Require 1.7.0 for raid0.
2021-02-01 20:10:07 +01:00
Zdenek Kabelac
6e8a32e4fd tests: avoid killing test machines with kernel bug
Bug 1916891  still applies:

https://bugzilla.redhat.com/show_bug.cgi?id=1916891
2021-02-01 15:02:38 +01:00
Zdenek Kabelac
bfafd2b4e9 tests: check for raid target support 2021-02-01 15:01:04 +01:00
Zdenek Kabelac
026d94d882 gcc: hide uninitialized warning with older gcc 2021-02-01 14:54:49 +01:00
Zdenek Kabelac
48030389ce libdm: add dm_tree_node_add_thin_pool_target_v1
Supports thin-pool without crop.
2021-02-01 14:52:32 +01:00
Zdenek Kabelac
25b942a8ac aux: update thin_restore_needs_more_volumes
Version 0.8.5-2.el7 needs to return 0;
2021-02-01 12:13:49 +01:00
Zdenek Kabelac
b26e565ee5 tests: check for cache support presence 2021-02-01 12:13:49 +01:00
Zdenek Kabelac
19ddad12ca tests: update thin and cache checked messages
Slightly changed messages for allocation of pool metadata.
2021-02-01 12:13:49 +01:00
Zdenek Kabelac
b17b556e26 tests: check 16G thin pool metadata size 2021-02-01 12:13:49 +01:00
Zdenek Kabelac
9fa4c099fb lvconvert: ensure device_name is defined 2021-02-01 12:13:49 +01:00
Zdenek Kabelac
a9fd207192 pvscan: enhance _count_pvid_files_from_lookup_file
Ensure all vars are always properly defined in all paths.
2021-02-01 12:13:49 +01:00
Zdenek Kabelac
3acf6040b5 wipe: reformat message for failure case
Use the same error message layout to match BLKZEROUT look.
Makes testing easier.
2021-02-01 12:13:49 +01:00
Zdenek Kabelac
8f5695fa71 WHATS_NEW: updates 2021-02-01 12:13:49 +01:00
Zdenek Kabelac
be0bf43d74 allocation: report allocation error instead of crash
Current allocation limitation requires to fit metadata/log LV on
a single PV. This is usually not a big problem, but since
thin-pool and cache-pool is using this for allocating extents
for their metadata LVs it might be eventually causing errors
where the remaining free spaces for large metadata size is spread
over several PV.
2021-02-01 12:13:49 +01:00
Zdenek Kabelac
45f0c48365 pvmove: automatically resolve whole stacked LV
When passing 'pvmove --name arg' try to automatically move
all associated dependencies with given LV.

i.e. 'pvmove --name thinpool vg vgnew'
moves all thins and data and metadata LV into a new VG vgnew.
2021-02-01 12:06:13 +01:00
Zdenek Kabelac
abc9265a06 cache: reuse code for metadata min_max
Use update_pool_metadata_min_max() which is shared with
thin-pool metadata min-max updating.

Gives improved messages when converting volumes to metadata.
2021-02-01 12:06:13 +01:00
Zdenek Kabelac
f96b455506 pool: limit pmspare to 16GiB
There is not much point to let allocate more then this size
even when i.e. converted LV is bigger then 16GiB (%extent_size)
ATM neither thin-pool nor cache-pool supports bigger metadata.
2021-02-01 12:06:13 +01:00
Zdenek Kabelac
b4212be2e7 thin: improve 16g support for thin pool metadata
Initial support for thin-pool used slightly smaller max size 15.81GiB
for thin-pool metadata. However the real limit later settled at 15.88GiB
(difference is ~64MiB - 16448 4K blocks).

lvm2 could not simply increase the size as it has been using hard cropping
of the loaded metadata device to avoid warnings printing warning of kernel
when the size was bigger (i.e. due to bigger extent_size).

This patch adds the new lvm.conf configurable setting:
allocation/thin_pool_crop_metadata
which defaults to 0 -> no crop of metadata beyond 15.81GiB.
Only user with these sizes of metadata will be affected.

Without cropping lvm2 now limits metadata allocation size to 15.88GiB.
Any space beyond is currently not used by thin-pool target.
Even if i.e. bigger LV is used for metadata via lvconvert,
or allocated bigger because of to large extent size.

With cropping enabled (=1) lvm2 preserves the old limitation
15.81GiB and should allow to work in the evironement with
older lvm2 tools (i.e. older distribution).

Thin-pool metadata with size bigger then 15.81G is now using CROP_METADATA
flag within lvm2 metadata, so older lvm2 recognizes an
incompatible thin-pool and cannot activate such pool!

Users should use uncropped version as it is not suffering
from various issues between thin_repair results and allocated
metadata LV as thin_repair limit is 15.88GiB
Users should use cropping only when really needed!

Patch also better handles resize of thin-pool metadata and prevents resize
beoyond usable size 15.88GiB. Resize beyond 15.81GiB automatically
switches pool to no-crop version. Even with existing bigger thin-pool
metadata command 'lvextend -l+1 vg/pool_tmeta' does the change.

Patch gives better controls 'coverted' metadata LV and
reports less confusing message during conversion.

Patch set also moves the code for updating min/max into pool_manip.c
for better sharing with cache_pool code.
2021-02-01 12:06:13 +01:00
Zdenek Kabelac
b218a7cfe7 man: update lvmthin
Add few more notes about thin-pool repair.
Fix couple typos.
2021-02-01 12:06:13 +01:00
David Teigland
a690d16d29 writecache: use cleaner message instead of table reload
When detaching writecache, make the first stage send a message
to dm-writecache to set the cleaner option.  This is instead of
reloading the dm table with the cleaner option set.  Reloading
the table causes udev to process/probe the dm dev, which gets
stalled because of the writeback activity, and the stalled udev
in turn stalls the lvconvert command when it tries to sync with
udev events.

When getting writecache status we do not need to get
open_count or read_head info, which can cause extra steps.
2021-01-28 15:14:25 -06:00
Heinz Mauelshagen
f08ef23856 lvdisplay: enhance LV status output for raid(0)
In case legs of a raid0 LV are removed, the lvdisplay command still
reports 'available' though raid0 is not providing any resilience
compared to the other raid levels.

Also lvdisplay does not display '(partial)' in case of missing raid0
legs as oposed to the lvs command.

Enhance lvdisplay to report "NOT available" for any RaidLV type in case
too many legs are inaccessible hence causing data loss.  I.e. any leg
for raid0, all for raid1, more than 1 for raid4/5, more than 2 for raid6
and in case of completely lost mirror groups for raid10.

Add test/shell/lvdisplay-raid.sh.

Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1872678
2021-01-27 16:56:22 +01:00
Zdenek Kabelac
665d265349 WHATS_NEW: update 2021-01-22 16:09:38 +01:00
Zdenek Kabelac
fa2fa9f36d pvscan: ensure read buffer ends with 0
Read buffersize - 1 so the last byte is always 0.
Simplify init of 0 buffers.
Check snprintf result for error and report internal error as it could
happen only via bad compile parameters.
2021-01-22 15:30:37 +01:00
Zdenek Kabelac
ce6e74f485 filters: avoid duplicated //
sysfs_dir already goes with '/sys/'.
2021-01-22 15:30:37 +01:00
Zdenek Kabelac
5485ec10e2 pvscan: make ret value defined 2021-01-22 15:30:37 +01:00
Zdenek Kabelac
cddeaed6e9 tests: check support for online vdo rename
kvdo 6.2.3 module version supports online rename.
Add cache and raid stacked renames.
2021-01-22 15:30:37 +01:00
Zdenek Kabelac
8532b1ca97 vdo: support online rename
New VDO targets v6.2.3 corrects support for online rename of VDO device.
If needed if can be disable via new lvm.conf setting:

vdo_disabled_features = [ "online_rename" ]
2021-01-22 15:30:37 +01:00
Zdenek Kabelac
4b8e5ad595 pools: fix removal of spare volume
When removing pool LV from a stacked LV setup, it's been possible
to leak _pmspare and such hidden LV then required manual
user removal.

Fix it by moving automatic removal into _lv_reduce().
2021-01-22 15:30:37 +01:00
Zdenek Kabelac
9ae1935b74 config: avoid printing spaces before end of line
Empty comments were generating unnecessary space char before new line.
2021-01-22 15:30:37 +01:00
David Teigland
74adbec77f pvck: fix warning and exit code for non-4k mda1 offset
Print a warning if mda1 is not 4k, 8k or 64k.
Don't exit with an error for any unexpected mda1 offset.
2021-01-19 11:21:20 -06:00
David Teigland
2ec29d0677 label_scan: fix missing free of filtered_devs
missing free of devl entries on filtered_devs list in
commit 2c9bb67604
2021-01-18 16:26:02 -06:00
Marian Csontos
9757b4726c make: generate 2021-01-18 14:46:22 +01:00
David Teigland
37227b8ad6 devs: remove invalid path name aliases
Make dev_cache_get() verify aliases and drop any
that are invalid before returning a dev for a given
name.
2021-01-15 16:31:50 -06:00
David Teigland
0534723a2d integrity: fix segfault on error path when replacing images
When adding replacement raid+integrity images (lvconvert --repair
after a raid image is lost), various errors can cause the function
to exit with an error.  On this exit path, the function attempts
to revert new images that had been created but not yet used.  The
cleanup failed to account for the fact that not all images needed
to be reverted.
2021-01-13 13:39:33 -06:00
Zdenek Kabelac
ff1324d595 tests: check full zeroing of thin-pool metadata
Check zeroing works on whole thin-pool metadata device.
2021-01-13 12:54:45 +01:00
Zdenek Kabelac
71162b2b4e tests: check thin-pool corner case allocs 2021-01-13 12:54:45 +01:00
Zdenek Kabelac
0b6ee6a912 alloc: enhance estimation of sufficient_pes_free
Since commit 77fdc17d70 always include
log_len size into needed extents - however now we may need sometimes
more extents then necessary - mainly when multiple PVs are involved
into allocation.

Add logs_still_needed into calculation of sufficient_pes_free()
2021-01-13 12:54:45 +01:00
David Teigland
a4c56a3bc3 lvmlockd: sscanf buffer size warnings 2021-01-08 12:13:05 -06:00
Marian Csontos
6308365d48 post-release 2021-01-08 10:08:36 +01:00
Marian Csontos
3e8bd8d1bd pre-release 2021-01-08 10:07:25 +01:00
David Teigland
e9503f257a lvconvert: chunksize option was missing with cachedevice 2021-01-07 13:30:48 -06:00
David Teigland
b84a9927b7 partial flag for writecache and integrity
When a writecache sublv or an integrity metadata sublv
are partial (missing a dev), set the partial flag on
the upper level LV also, as is done for other sublvs.
2020-12-11 16:25:25 -06:00
Marian Csontos
23ef677762 configure: update 2020-12-11 12:16:16 +01:00
David Teigland
5dbe2fdd9d writecache: fix uncache for two step detach
Fix the two-step writecache detach in commit c32d7fed4f.
In the case of uncache, the cachevol is removed after
detaching the writecache.  When the detach is finished
in the second step, the remove must wait until then.
2020-12-10 15:42:01 -06:00
David Teigland
9fe7aba251 cache: activation cache_check on cachevol
When using cache with a cachevol, the cache_check tool was
not being run on the cache metadata during activation.
cache_check clears the needs_check flag in the cache
metadata, so if the flag was set due to an unclean
shutdown, the activation would fail.
2020-12-09 17:36:09 -06:00
Zdenek Kabelac
57594fe673 tests: few more fsadm checks 2020-12-08 20:32:34 +01:00
Zdenek Kabelac
47608ff49b fsadm: fix unbound variable usage
When 'fsadm resize vg/lv' is used without size, it should just
resize filesystem to match device - but since we now check
for unbound variable in bash - the previous usage no longer
works and needs explicit check.
2020-12-08 20:32:34 +01:00
Zdenek Kabelac
7691213a91 man: update lvmvdo
Fix vdo example.
Update some sentences.
2020-12-08 20:32:34 +01:00
David Teigland
9b3458d5a9 man lvmcache: add writecache cleaner info 2020-12-02 15:29:21 -06:00
Marek Suchánek
a2affffed5 man: update writing style of the lvmvdo man page
This patch improves the clarity, writing style, and language
of the lvmvdo(7) man page.

See https://bugzilla.redhat.com/show_bug.cgi?id=1855804.
2020-12-02 10:31:11 +01:00
Marian Csontos
205fb35b50 build: make generate 2020-11-26 17:37:32 +01:00
David Teigland
10a095a58b udev rule: remove lvmetad comments 2020-11-25 16:57:54 -06:00
David Teigland
b68141a49d lvm.conf: remove reference to locking_type 2020-11-17 11:19:55 -06:00
David Teigland
9c0253d930 man: vgsplit source and destination VGs
make clearer which is source and which is destination
2020-11-17 11:00:40 -06:00
David Teigland
aba9652e58 lvchange: fix error for foreign vg activation
was using ECMD_FAILED instead of 0.
2020-11-17 09:22:40 -06:00
David Teigland
1cc75317f9 tests: integrity mismatch checks for all raid levels
Verify that corruption is corrected for raid levels other
than raid1.  For other raid levels, attempt to corrupt the
given file pattern on each underlying device, since we don't
know which device contains the file being corrupted.
This ensures that corruption is actually be introduced
when testing the other raid levels.

Verify that corruption is being corrected by checking
the integritymismatches count is non-zero for the raid LV,
which includes the total from all images (since we don't
know which image will have the corruption.)
2020-11-11 15:13:46 -06:00
David Teigland
5fef89361d integrity: display total mismatches at raid LV level
Each integrity image in a raid LV reports its own number
of integrity mismatches, e.g.

lvs -o integritymismatches vg/lv_rimage_0
lvs -o integritymismatches vg/lv_rimage_1

In addition to this, allow the total number of integrity
mismatches from all images to be displayed for the raid LV.

lvs -o integritymismatches vg/lv

shows the number of mismatches from both lv_rimage_0 and
lv_rimage_1.
2020-11-11 15:10:15 -06:00
David Teigland
2317ba3934 tests: update integrity tests
simplified the method of corrupting data, the old method
was not working reliably.  moved syncation tests to a
different file
2020-11-10 17:41:04 -06:00
David Teigland
d7058cfa98 writecache: supported in dm-writecache version 3
not version 2
2020-11-09 09:47:01 -06:00
Zdenek Kabelac
8801a86a3e man: update vdo
Enhance VDO man page with description of memory usage
and space requirements chapter.

Remove some unneeded blank lines in man page.

Use more precise terminology.

Correct examples since  cpool and vpool are protected names.
2020-11-03 16:34:46 +01:00
David Teigland
6316959438 pvck: fix previous commit
line to setup bcache was misplaced in
commit 5a94126e7a
2020-10-28 16:50:47 -05:00
David Teigland
125da10d47 Revert "tests: revert lvm shell use in pvck-dump"
This reverts commit 05d23b2dd8.

this required enabling editline in configure
2020-10-28 16:45:04 -05:00
David Teigland
05d23b2dd8 tests: revert lvm shell use in pvck-dump
doesn't work on my machine
2020-10-27 15:44:56 -05:00
David Teigland
5a94126e7a pvck: fix dev filtering
filters needing io weren't being run because bcache
wasn't set up.  Read the first 4k of the device
before doing filtering or reading ondisk structs to
reduce reads.
2020-10-27 15:43:15 -05:00
David Teigland
c96645781c pvck: handle first mda at non-4096 offset
It's possible for a machine with a non-4k page size
to create a PV with an mda_header at an offset other
than 4k.  Fix pvck --dump to work with these other
mda offsets.  pvck --repair will write a new first
mda at 4096 but lvm with other page sizes will work
with this.
2020-10-27 14:28:54 -05:00
David Teigland
020d1edaa0 writecache: disallow partial or degraded activation
when either main or fast lvs are incomplete
2020-10-26 15:48:58 -05:00
David Teigland
830c20d33c lvchange: allow syncaction check with integrity
syncaction check will detect and correct integrity checksum mismatches.
2020-10-26 14:16:33 -05:00
David Teigland
2c31939827 pvcreate: clean up opening and filtering of args
The args for pvcreate/pvremove (and vgcreate/vgextend
when applicable) were not efficiently opened, scanned,
and filtered.  This change reorganizes the opening
and filtering in the following steps:

- label scan and filter all devs
  . open ro
  . standard label scan at the start of command

- label scan and filter dev args
  . open ro
  . uses full md component check
  . typically the first scan and filter of pvcreate devs

- close and reopen dev args
  . open rw and excl

- repeat label scan and filter dev args
  . using reopened rw excl fd

- wipe and write new headers
  . using reopened rw excl fd
2020-10-26 11:13:27 -05:00
Zdenek Kabelac
7bafae48bb gcc: cleanup warns from older gcc 2020-10-26 13:06:53 +01:00
Zdenek Kabelac
e793f34eb7 tests: minor update 2020-10-26 13:06:52 +01:00
Zdenek Kabelac
b033384135 fsadm: better check for getsize64 support
Older blockdev tool return failure error code with --help,
and since now the tool abort on command failure, lets
detect missing --getsize64 support directly by running
command and check if it returns something usable.

It's likely very hard to have the system with
such old blockdev tool and newer lvm2 compiled.
2020-10-26 13:06:52 +01:00
Zdenek Kabelac
2183af62e5 WHATS_NEW: update 2020-10-24 01:42:16 +02:00
Zdenek Kabelac
edb55b767a man: regenerate 2020-10-24 01:42:16 +02:00
Zdenek Kabelac
413c88116d man: more precise UNIT
Since 'kilobytes' could be seen in 2 way - SI as '1000',
while all programmers sees it as '1024' - switch to
commonly acceptted  KiB, MiB....

Resolves RHBZ 1496255.
2020-10-24 01:42:16 +02:00
Zdenek Kabelac
9740e98cbd lv_manip: add space into message
Just add space between %s(.
2020-10-24 01:42:16 +02:00
Zdenek Kabelac
be94410446 tests: fsadm test continue after fs repair
Test case where filesystem has been corrected via fsck.
In such case fsck returns '1' as success and should be
handled in a same way as '0' since fs is correct.
2020-10-24 01:42:16 +02:00
Zdenek Kabelac
8c2779ba34 fsadm: enhance error handling
Set more secure bash failure mode for pipilines.
Avoid using unset variables.
Enhnace error reporting for failing command.
Avoid using error via 'case..esac || error'.
2020-10-24 01:42:16 +02:00
Zdenek Kabelac
51a532719c fsadm: handle fsck return 1 for corrected fs 2020-10-24 01:42:16 +02:00
Zdenek Kabelac
73ef86ae3f fsadm: use NULL
Use consistently $NULL as in other places.
2020-10-24 01:42:16 +02:00
David Teigland
6226512ad2 get dev size when setting pv device
In some cases the dev size may not have been read yet
in set_pv_devices().  In this case get the dev size
before comparing the dev size with the pv size.
2020-10-22 13:19:17 -05:00
David Teigland
f3b723cd8d pvscan: rework to improve PVs without metadata
Restructure the pvscan code, and add new temporary files
that list pvids in a VG, used for processing PVs that
have no metadata.

The new temp files, in /run/lvm/pvs_lookup/<vgname>, allow a
proper pvscan --cache to be done on PVs that have no metadata.
pvscan --cache <dev> is only supposed to read <dev>, but when
<dev> has no metadata, this had not been possible.  The
command had to fall back to scanning all devices to read all
VG metadata to get the list of all PVIDs needed to check for
a complete VG.  Now, the temp file can be used in place of
reading metadata from all PVs on the system.
2020-10-22 13:14:31 -05:00
David Teigland
a7f195b7e8 add label_scan_devs_cached
label_scan_devs without invalidating data first
for cases where the caller wants to use any
bcache data they have already read.
2020-10-21 16:24:16 -05:00
David Teigland
677f829e54 add label_read_pvid
To read the lvm headers and set dev->pvid if the
device is a PV.  Difference from label_scan_ functions
is this does not read any vg metadata or add any info
to lvmcache.
2020-10-21 16:24:16 -05:00
David Teigland
c7311d4722 lvmcache: rename label_read label_scan_dev
for consistent naming with other similar functions
2020-10-21 16:24:16 -05:00
David Teigland
b3cdf0d881 lvmcache: add lvmcache_get_dev_mda
for future patch
2020-10-21 16:24:16 -05:00
David Teigland
2c9bb67604 scanning: improve filtering control
Filtering in label_scan was controlled indirectly by
the fact that bcache was not yet set up when label_scan
first ran.  The result is that filters that needed data
would not run and would return -EAGAIN, which would
result in the dev flag FILTER_AFTER_SCAN being set.
After the dev header was read for checking the label,
filters would be rechecked because of FILTER_AFTER_SCAN.
All filters would be checked this time because bcache
was now set up, and the filters needing data would
largely use data already scanned for reading the label.
This design worked but is hard to adjust for future
cases where bcache is already set up.

Replace this method (based on setting up bcache, or not)
with a new cmd flag filter_nodata_only.  When this flag
is set filters that need data will not run.  This allows
the same label_scan behavior when bcache has been set up.
There are no expected changes in behavior.
2020-10-21 16:24:16 -05:00
David Teigland
c74ccd5201 filters: nodata option
When filter_nodata_only is set, a filter that uses
data is skipped.
2020-10-21 16:24:16 -05:00
David Teigland
c601ec0d6e filters: allow filter wipe for one device
as passes_filter already does
2020-10-21 16:24:16 -05:00
David Teigland
83d0818523 tests: writecache-misc disable with lvmlockd
in a shared vg pvmove requires a named lv
2020-10-21 12:47:28 -05:00
Zdenek Kabelac
6be29e1179 tests: check dmevent with bigger reserved_stack
Check dmeventd remains working when reserved_stack
is above 300KiB.
2020-10-20 22:28:58 +02:00
Zdenek Kabelac
fdec4cd3e6 memlock: allocate at most halve of rlimit stack
Touch of stack allocation validated given size with rlimit
and if the reserved_stack was above rlimit, its been completely
ignored - now we will always touch stack upto rlimit/2 size.
2020-10-20 22:26:44 +02:00
Zdenek Kabelac
bd272e3bce lvmcmdlib: lvm2_init_threaded
cmd context has 'threaded' value that used be set
by clvmd - and allowed proper memory locking management.
Reuse same bit for dmeventd.

Since dmeventd is using 300KiB stack per thread,
we will ignore any user settings for allocation/reserved_stack
until some better solution is find.
This avoids crashing of dmevend when user changes this value
and because in most cases lvm2 should work ok with 64K stack
size, this change should not cause any problems.
2020-10-20 22:22:52 +02:00
Zdenek Kabelac
756066a2e8 libdm: relocate code for sending messages
To be able to send messages for recently resumed devices,
move code into inner loop.
Matching commit c1a6b10d09.
2020-10-19 16:53:19 +02:00
Zdenek Kabelac
3e06061d82 cov: split check for type assignment
Check that type is always defined, if not make it explicit internal
error (although logged as debug - so catched only with proper lvm.conf
setting).
This ensures later type being NULL can't be dereferenced with coredump.
2020-10-19 16:53:19 +02:00
Zdenek Kabelac
a17ec7e0ba dm: remove created devices on error path
DM tree keeps track of created device while preloading a device tree.
When fail occures during such preload, it will now try to remove
all created and preloaded device. This makes it easier to maintain
stacking of device, since we do not need to check in-depth for
existance of all possible created devices during the failure.
2020-10-19 16:53:19 +02:00
Zdenek Kabelac
b75c2dfe1b debug: shorten error message
Just check for sigint during log_error().
2020-10-19 16:53:18 +02:00
Zdenek Kabelac
b2a326b511 libdm: validate thin-pool before sending messages
Alhtough lvm2 does validation on its side, ensure DM code
is not sending messages to failed thin pool.
2020-10-19 16:53:18 +02:00
Zdenek Kabelac
4b0565b82f libdm: enhance error message 2020-10-19 16:53:18 +02:00
Zdenek Kabelac
4c1caa7e26 libdm: split code for sending message
Move message sending from _thin_pool_node_message to
new _node_message for possible better code sharing.
2020-10-19 16:53:18 +02:00
Zdenek Kabelac
58976ccc34 properties: fix data_usage typo
Patch 4de6f58085 introduce typo,
we need to use data_usage.

Note: this code was used by lvmapp library and currently is unused.
2020-10-19 16:53:18 +02:00
Zdenek Kabelac
d2bdad28d1 tests: extend area covered by error target
Since 'BLKZEROOUT' streams out more block at once, at can easily
zero-out larger set of blocks after 1st. failing one.

So the test is adapted to fully 'hide' swap header under error target.
2020-10-19 16:53:18 +02:00
Marian Csontos
b50134dc14 make: generate 2020-10-15 11:16:54 +02:00
Marian Csontos
616e5b854c gitignore: ignore gcov files 2020-10-15 11:13:13 +02:00
Marian Csontos
53db14171c Revert "tests: Adapt RAID test to changes"
The cpnversion of degraded RAID should still report a failure.

This reverts commit e12bdd591a.
2020-10-13 13:15:16 +02:00
Zdenek Kabelac
ee43ec5782 rpm: bare words are no longer supported
Update for new rpm requirement and use "..." words.
2020-10-02 22:27:00 +02:00
Zdenek Kabelac
99b6173f10 tests: enable tests for lvmlockd 2020-10-02 22:27:00 +02:00
Zdenek Kabelac
5e26a2b74d tests: aux hides zero and error device
When ERR_DEV and ZERO_DEV are used, they are automatically
taken down when the last user no longer needs them,
so hide them from 'forgotten' device check.
2020-10-02 22:27:00 +02:00
Zdenek Kabelac
8d9b4c624f tests: rename shown debug trace
As there could be few invokes of stacktrace, avoid
repeatedly display logs from commands.
So after first display rename  debug.log* -> debug_log
so the file still can remain for reading in test dir.
2020-10-02 22:27:00 +02:00
Zdenek Kabelac
73a3a0d347 debug: drop vgid from debug
From the code can be seen the VGID will be always NULL here
as vgid != NULL is already handled before.
Thus drop from being displayed.
2020-10-02 22:27:00 +02:00
Zdenek Kabelac
117fc64e6e debug: no backtrace
As the path already printed verbose message drop backtrace.
2020-10-02 21:04:16 +02:00
Zdenek Kabelac
1b8c6f09bc debug: show actually reason for taking this code path
Instead of not so useful backtrace, report what was the reason.
2020-10-02 21:04:16 +02:00
Zdenek Kabelac
e1af80c81c debug: drop FD from error message
Since now the error path already has device close and set -1,
there is not much in printing this info - actually shouldn't be
there at all..
2020-10-02 21:04:16 +02:00
Zdenek Kabelac
dd8212365d debug: update messages 2020-10-02 21:04:16 +02:00
Zdenek Kabelac
e7fff97b8d wipe_lv: use BLKZEROOUT when possible
Since BLKZEROOUT ioctl should be supposedly fastest
way how to clear block device start using this ioctl
for zeroing a device. Commonly we do zero typically
small portion of a device (8KiB) - however since we now
also started to zero metadata devices, in the case
of i.e. thin-pool metadata this can go upto ~16GiB
and here the performance starts to be noticable.
2020-10-02 21:04:16 +02:00
Zdenek Kabelac
c65d3a6b8a wipe_lv: interruptible wiping
Since we now block signals and wiping may take unexpectedly long
time - support breaking command while wipe is in progress.
2020-10-02 21:03:19 +02:00
Zdenek Kabelac
7396f1cfee wipe_lv: drop label_scan_invalidate on error path
Since dev_set_bytes() now closes  dev on error path itself,
remove this unneeded call now (introduced few commits back
in history thus removing comment from WHATS_NEW)
2020-10-02 21:02:04 +02:00
Zdenek Kabelac
b44db5d1a7 bcache: use flexible arrays
Cleanup, allocate whole struct with a single malloc call.
2020-10-02 21:00:26 +02:00
Zdenek Kabelac
b3c7a2b3f0 bcache: support interrupts when waiting on IO
Since lvm2 normally block signals during protected
phase where it does not want to be interrupted.
Support interruptible processing when allowed
in section between sigint_allow() ... sigint_restore())
and let the 'io_getenvents()'  finish with EINTR.
2020-10-02 20:57:50 +02:00
Zdenek Kabelac
0fe58fc54f bcache: fix busy loop with too many errors
When bcache tries to write data to a faulty device,
it may get out of caching blocks and then just busy-loops
on a CPU - so this check protects this by checking
if there is already max_io (~64) errored blocks.
2020-10-02 20:56:55 +02:00
Zdenek Kabelac
41f9e372c0 bcache: fix waiting problem for completed IO
Call _wait_all() which does check whether there is still
some pending IO before sleep. Otherwise it may happen
our submitted IO operations have been already dispatched
and this call then endlessly waits for IO which are all done.
This can be reproduced when device returns quickly errors
on write requests.
2020-10-02 20:53:41 +02:00
Zdenek Kabelac
9885c9b43a configure: use our ordered list of python names
Since it seems it's prefered now to use python3 in path name,
prefer this name as first in the list.
2020-10-02 20:52:38 +02:00
Zdenek Kabelac
2df7ef58a5 configure: update with latest AM_PATH_PYTHON
World has moved towards python3.9.
Although we still don't like path ordering.
2020-10-02 20:48:41 +02:00
Zdenek Kabelac
ae96a43f05 configure: check for BLKZEROOUT support 2020-10-02 20:48:41 +02:00
David Teigland
91f869e43c lvconvert: move log message to fix segfault
log message was printing lv name from released vg
2020-10-02 09:23:25 -05:00
David Teigland
0143c7aebe improve message for invalid device arg in process_each_pv
Multiple commands process pvs by name using process_each_pv()
and will now have an improved error message for a device
that's excluded by filters.
2020-10-01 12:34:36 -05:00
David Teigland
74ed6e8a99 improve message for invalid device arg
for pvcreate, pvremove, vgcreate, vgextend.
2020-10-01 12:20:16 -05:00
David Teigland
450f272b31 devices: support printing the filter that rejects a device
Use of this new message function needs to be added
to various commands to improve the output.
2020-10-01 12:00:09 -05:00
David Teigland
ff3945777b tests: enable writecache test that uses cleaner 2020-10-01 11:33:02 -05:00
David Teigland
c32d7fed4f writecache: use two step detach
When detaching a writecache, use the cleaner setting
by default to writeback data prior to suspending the
lv to detach the writecache.  This avoids potentially
blocking for a long period with the device suspended.

Detaching a writecache first sets the cleaner option, waits
for a short period of time (less than a second), and checks
if the writecache has quickly become clean.  If so, the
writecache is detached immediately.  This optimizes the case
where little writeback is needed.

If the writecache does not quickly become clean, then the
detach command leaves the writecache attached with the
cleaner option set.  This leaves the LV in the same state
as if the user had set the cleaner option directly with
lvchange --cachesettings cleaner=1 LV.

After leaving the LV with the cleaner option set, the
detach command will wait and watch the writeback progress,
and will finally detach the writecache when the writeback
is finished.  The detach command does not need to wait
during the writeback phase, and can be canceled, in which
case the LV will remain with the writecache attached and
the cleaner option set.  When the user runs the detach
command again it will complete the detach.

To detach a writecache directly, without using the cleaner
step (which has been the approach previously), add the
option --cachesettings cleaner=0 to the detach command.
2020-10-01 11:33:02 -05:00
David Teigland
d1b7438c9f pvcreate/pvremove: reimplement device checks
Reorganize checking the device args for pvcreate/pvremove
to prepare for future changes.  There should be no change
in behavior.  Stop the inverted use of process_each_pv,
which pulled in a lot of unnecessary processing, and call
the check functions on each device directly.
2020-10-01 10:09:09 -05:00
Marian Csontos
46e5908759 test: grep -q may fail and it does
The script runs with pipefail, grep -q exits immediately sending SIGPIPE
to lvm segtype which fails whole pipe.
2020-10-01 11:33:57 +02:00
David Teigland
2272a32e6f lvmlockd vdo: add support
lvmlockd handling for vdo lv and vdo pool is like
thin lv and thin pool.
2020-09-29 14:43:27 -05:00
David Teigland
82e270c18a lvmlockd vdo: disallow use of shared lock on LV
vdo cannot be active on multiple hosts concurrently
2020-09-29 14:43:26 -05:00
Zdenek Kabelac
af8044da3a tests: thin-flags 2020-09-29 10:43:56 +02:00
Zdenek Kabelac
6728788bf5 debug: remove stacktrace on regular path
Here _insert is expected to also fail, so just regular 'return 0'.
2020-09-29 10:43:56 +02:00
Zdenek Kabelac
0c89c5a40f debug: update debug message 2020-09-29 10:43:56 +02:00
Zdenek Kabelac
bd0d4de4e2 active: fix compilation without devmapper
Better support for compilation without device-mapper.
2020-09-29 10:43:56 +02:00
Zdenek Kabelac
4cd356b26b thin: remove unneeded code test
Since we detect already transaction if before starting
to build dm tree - this extra check is a duplicate
that would only capture very tiny 'race' and we later
validate transaction_id with suspended snapshot origin.
2020-09-29 10:43:56 +02:00
Zdenek Kabelac
18c74666ee thin: validate thin-pool state before sending messages
Alhtough lvm2 does validation on its side, ensure DM code
is not sending messages to failed thin pool.
2020-09-29 10:43:56 +02:00
Zdenek Kabelac
4de6f58085 thin: use lv_status_thin and lv_status_thin_pool
Introduce structures lv_status_thin_pool and
lv_status_thin  (pair to lv_status_cache, lv_status_vdo)

Convert lv_thin_percent() -> lv_thin_status()
and  lv_thin_pool_percent() + lv_thin_pool_transaction_id() ->
lv_thin_pool_status().

This way a function user can see not only percentages, but also
other important status info about thin-pool.

TODO:
This patch tries to not change too many other things,
but pool_below_threshold() now uses new thin-pool info to return
failure if thin-pool cannot be actually modified.
This should be handle separately in a better way.
2020-09-29 10:43:56 +02:00
Zdenek Kabelac
92c0e8c17f writecache: archive before modification of metadata
Archive before we start to modify metadata.
2020-09-29 10:43:56 +02:00
Zdenek Kabelac
08e838f488 cleanup: avoid unneeded check
Since creation of thin snapshot already makes sure,
the message list is empty, there is no need to check
this again.
2020-09-29 10:43:56 +02:00
Zdenek Kabelac
af5f29c7e2 activation: move locking of critical section
Move begining of 'suspending' critical section closer to _lv_suspend_lv()
for better correctness of error paths.
2020-09-29 10:43:56 +02:00
Zdenek Kabelac
3ed11170da configure: update help
Help shows new defaults.
2020-09-29 10:43:56 +02:00
Zdenek Kabelac
655342427d configure: editline updates
Update configure file.
2020-09-29 10:43:45 +02:00
Bastian Germann
168e2ffbcd lvm: add readline alternative editline
LVM2 is distributed under GPLv2 only. The readline library changed its
license long ago to GPLv3. Given that those licenses are incompatible
and you follow the FSF in their interpretation that dynamically linking
creates a derivative work, distributing LVM2 linked against a current
readline version might be legally problematic.

Add support for the BSD licensed editline library as an alternative for
readline.

Link: https://thrysoee.dk/editline
2020-09-29 10:13:24 +02:00
David Teigland
fb96e9ab21 tests: add case for metadata checksum differences
Cover the case where two copies of metadata have the
same seqno but different checksums.  Also elaborate
on an existing fixme in the code for this case, since
we should be doing something better for this case.

This had been uncovering an issue with reopening
fds in readwrite mode.
2020-09-28 13:25:57 -05:00
David Teigland
df6f16c081 lvpoll: don't use hints
There's a bug when lvpoll attempts to write new hints,
related to the fact that lvpoll does not follow the same
scanning process as standard commands.
Fix by disabling the use of hints in lvpoll.  We may want
to renable hints in lvpoll in a way that they can be used,
if valid, but not updated if they don't exist or are invalid.
2020-09-28 13:25:57 -05:00
David Teigland
da14cf68cb scanning: keep open an lvm device with scanning problem
The command may want to update it.
2020-09-28 13:25:57 -05:00
David Teigland
890c7ef451 devices: fix reopen for unopened device
If there's a request to reopen rw a device that's not
open, then just call the normal open function.
2020-09-28 13:25:57 -05:00
Heinz Mauelshagen
8952dcbff0 Revert "lvconvert: display warning if raid1 LV image count does not change"
This reverts superfluous commit 3c9177fdc0 as
_lv_raid_change_image_count() already checks for non-changed image count.

Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1872130
2020-09-28 17:14:03 +02:00
Zdenek Kabelac
bbc164991a tests: add small delay
Prevent there is no i.e. udev trying to open our device.
2020-09-25 22:59:35 +02:00
Zdenek Kabelac
a89ac3bf6f tests: also add thick snap of thin volume 2020-09-25 22:59:35 +02:00
Zdenek Kabelac
ccb58c109f tests: check some common errors
Collect some cases users are hitting when working
with thin-pools which has mismatching kernel metadata content with
lvm2 metadata.
2020-09-25 22:59:35 +02:00
Zdenek Kabelac
3e003320a7 tests: vgsplit of vdo volumes 2020-09-25 22:59:35 +02:00
Zdenek Kabelac
e2577c037d makefiles: document supported var in make help 2020-09-25 22:59:35 +02:00
Zdenek Kabelac
e414ebef6e thin: pass through whole code
Instead of early 'return 0' let the whole code finish
in case of an error with syncing.
2020-09-25 22:59:35 +02:00
Zdenek Kabelac
2bfa868f91 device_mapper: enhance error message 2020-09-25 22:59:35 +02:00
Zdenek Kabelac
8b22e38087 thin: improve error message
Add more info, explaing why the suspend of thin snapshot origin was omitted.
2020-09-25 22:59:35 +02:00
Zdenek Kabelac
ef59c83f2d thin: enhance lvcreate error paths
Improve error response and reporting, when creating thin snapshots.
If the thin pool kernel metadata already have device with ID lvm2
tries to create, give more meanigful error message and also properly
restore transaction id to the value known to thin-pool in this case.

Before it's been possible to divert by one from kernel TID value,
and lvm2 stacked delete message for such thin device.
2020-09-25 22:56:40 +02:00
Zdenek Kabelac
e2eb1dc501 thin: no delete message for device_id 0
Since we always use device_id > 0, we could use
device_id == 0 to actually mark thinLV as an
LV we want to remove without delete message.
2020-09-25 22:54:07 +02:00
Zdenek Kabelac
fc9e732811 vgsplit: support for VDO volumes
Enable support and ensure VDO always moves with VDOPOOL.
2020-09-25 22:51:50 +02:00
Zdenek Kabelac
502b895bb4 tests: basic test for vdo on raid LV
Check stacing of VDO on top of raid LV works.
2020-09-23 14:58:24 +02:00
Zdenek Kabelac
39cdc1469d tests: add check for rename of cached vdopool 2020-09-23 14:47:30 +02:00
Zdenek Kabelac
cfc4dd4c7c tests: a bit bigger mirrors
Seems even with throttling we occasinally need slightly more.
2020-09-23 14:47:30 +02:00
Zdenek Kabelac
90c50c1b53 lvconvert: suppport vdo raid conversion also through vpool
User could directly use 'vdopool' LV name for conversion into raid.
(lvconvert --type raid1 vg/vdopool)
2020-09-23 14:47:30 +02:00
Zdenek Kabelac
50a37948b5 vdo: allow passing renamed vdopool name to kernel
Although kernel does not allow to load a new dm table
with renamed vdopool, at least make lvm2 code ready
it it every will get supported.
2020-09-23 13:20:28 +02:00
Zdenek Kabelac
7c19186271 vdo: disable support for online rename of vdopool LV
Since ATM kernel does not support this operation,
disable 'lvrename' of an active vdopool.

As a workaround, user may simply deactivate, rename and activate.
2020-09-23 13:18:23 +02:00
Zdenek Kabelac
3869c9c4f6 tests: use aux wrapper and add more notes
This test seems to be hitting some corner case in handling
out-of-metadata space condintion in thin-pool.

Add few more aid notes and functionality.

Also add missing '|| true' with now direct-IO dd command.
2020-09-22 23:43:26 +02:00
Zdenek Kabelac
e280f56dd3 tests: move function to aux for reuse 2020-09-22 23:43:26 +02:00
Zdenek Kabelac
adead83dc2 tests: update test
Shorten running time of the test.
Fix some issues in invoked resizing script to it returns
correct return code and dmeventd can be a little bit quicker
in this test.
2020-09-22 23:28:43 +02:00
Zdenek Kabelac
cbed63eeb9 tests: check vdopool policy extension
Check pool will grow even with small policy amount.
2020-09-22 23:28:43 +02:00
Zdenek Kabelac
3a3307c0d8 vdo: enhance vdo pool extension
When user tries to extend vdo pool - he needs to go always
at least by 1 full VDO slab  (defined as  vdo_slab_size_mb).

To avoid all trouble around find 'workable' size - lvm2 automatically
increases the passed (or by --use-policies calculated) extension size
(and informs a user about sometimes possibly large increase as slab
size can go upto 32GiB)

With VDO users need to always 'think-big' anyway and expect such
operation to be in GiB domain range.
2020-09-22 23:28:43 +02:00
Zdenek Kabelac
f38b7afd62 vdo: extend vdo segment validation
Try to catch all suspicious VDO segments in metadata early.
2020-09-22 23:25:16 +02:00
Zdenek Kabelac
642ef54399 vdo: correct message about policy extend support
Policy extend is already supported for vdo pools as well,
so correct the error message.
2020-09-22 23:25:16 +02:00
Zdenek Kabelac
e08a0421a3 vdo: drop unnecessary tabulator from metadata output 2020-09-22 23:25:16 +02:00
Zdenek Kabelac
5bc66532c7 activation: use revert_lv on tree suspend failure
When thetable reload fails during suspend() - we were only calling
plain resume() - and this will reload only those devices,
which were left suspend, but will not try to restore
metadata state according to lvm2 reverted metadata.
So if we were reloading device tree - we have restored
only top-level LV and rest of reverted device manipulation
were left alone and possibly mismatched what is in committed
metadata.

FIXME: There are several cases were such revert will likely not work
properly anyway as some operation are currenly handled in single commit,
while they need multiple commits, but it's step towards better correctness.
At least we catch there errors now earlier.
2020-09-22 21:02:14 +02:00
Zdenek Kabelac
bc9bb534ff tests: fix cleanup for unbound variables
When loop can't handle sector-size option - failure caused double fail
for access of unbound variable
Also fix expression for 'rm' and remove loops after loop release.
2020-09-20 00:37:21 +02:00
Zdenek Kabelac
f507a2564c tests: add FIXME case 2020-09-20 00:37:21 +02:00
Zdenek Kabelac
f2878a801c tests: use DIRECT io for zeroing whenver we can
Performance with direct I/O here is noticable better,
so use it instead of buffered write whenever we can.
2020-09-20 00:37:21 +02:00
Zdenek Kabelac
531a475afc tests: use 4K with mkfs.xfs
If the test runs of loop device backend with 512 sectors,
xfs selects this smaller sector size and then data do not fit
(we would need -l9 with most of 'raids').
With 4K sectors data always fits.
2020-09-20 00:37:21 +02:00
Zdenek Kabelac
a1074da20d tests: skip with fail of first prepare_scsi 2020-09-19 23:03:06 +02:00
Zdenek Kabelac
e556c7b7c6 tests: check for cvol
Check for cvol.
Add check for cmeta.
2020-09-19 23:02:17 +02:00
Zdenek Kabelac
6c769eb460 bache: fix error return value
Return 0 as failure (as checked for).
Also add INTERNAL_ERROR if  'DI' would be -1.
2020-09-19 23:00:50 +02:00
Zdenek Kabelac
6b168afcad tests: use parametrized function
Shorten and make the test easily readable by moving same code into
function and removed one duplicated test for 512,4096 combination.

Always use scsi_debug - since default ramdisk or loop device backend
is unpredictible.
2020-09-19 17:30:51 +02:00
Zdenek Kabelac
f63aac5309 tests: use zero backend
Since we are not reading read - just use zero device as backend for
test, so we do not eat real disk space.
2020-09-19 17:30:51 +02:00
Zdenek Kabelac
f7c58c636d tests: use faster awk generator
Shortens log length.
2020-09-19 17:30:51 +02:00
Zdenek Kabelac
8e3e2c74ed tests: ensure mnt is defined before trap install 2020-09-19 17:30:51 +02:00
Zdenek Kabelac
530fc17b38 tests: reduce disk usage 2020-09-19 17:30:51 +02:00
David Teigland
1404e5ee61 metadata: open rw fd before closing ro fd
lvm opens devices readonly to scan them, but
needs to open then readwrite to update the metadata.
Previously, the ro fd was closed before the rw fd
was opened, leaving a small gap where the dev was
not held open, and during which the dev could
possibly change which storage it referred to.

With the bcache_change_fd() interface, lvm opens a
rw fd on a device to be written, tells bcache to
change to the new rw fd, and closes the ro fd.

. open dev ro
. read dev with the ro fd (label_scan)
. lock vg (ex for writing)
. open dev rw
. close ro fd
. rescan dev to check if the metadata changed
  between the scan and the lock
. if the metadata did change, reread in full
. write the metadata
2020-09-18 15:10:11 -05:00
David Teigland
1570e76233 bcache: use indirection table for fd
Add a "device index" (di) for each device, and use this
in the bcache api to the rest of lvm.  This replaces the
file descriptor (fd) in the api.  The rest of lvm uses
new functions bcache_set_fd(), bcache_clear_fd(), and
bcache_change_fd() to control which fd bcache uses for
io to a particular device.

. lvm opens a dev and gets and fd.
  fd = open(dev);

. lvm passes fd to the bcache layer and gets a di
  to use in the bcache api for the dev.
  di = bcache_set_fd(fd);

. lvm uses bcache functions, passing di for the dev.
  bcache_write_bytes(di, ...), etc.

. bcache translates di to fd to do io.

. lvm closes the device and clears the di/fd bcache state.
  close(fd);
  bcache_clear_fd(di);

In the bcache layer, a di-to-fd translation table
(int *_fd_table) is added.  When bcache needs to
perform io on a di, it uses _fd_table[di].

In the following commit, lvm will make use of the new
bcache_change_fd() function to change the fd that
bcache uses for the dev, without dropping cached blocks.
2020-09-18 15:10:11 -05:00
Zdenek Kabelac
4b07ae55f1 tests: printf to awk
Shorten trace logs.
2020-09-18 17:30:45 +02:00
Zdenek Kabelac
9fbcba1c40 tests: update integrity-dmeventd
Use tee.
Switch to more simple generator with awk
(which doesn't produce long debug trace)
Sync before sleep to provoke raid action.
2020-09-18 17:30:45 +02:00
Zdenek Kabelac
9448476202 tests: enhance low-disk-space behavior
Use new SKIP_WITH_LOW_SPACE and set higher requirement for free space.

But still this test can't run on system's tmpfs directories -
as they typically provide less then 2G of space and when the test
runs there it also provisioning for all READ pages!)
BRD (ramdisk) device should work.

Extend a _wait_recalc() loop for slower hw.
When creating large raid which do not need to be fully synchronized use
them on delay devices - so even less data needs read/write.
Remove unneeded lvchange as lvcreate is already leaving LV inactive.
Replace printf with awk as generator.

mm
2020-09-18 17:30:45 +02:00
Zdenek Kabelac
206620018e tests: inittest supports SKIP_WITH_LOW_SPACE
Test can set individually a higher value for required free space on
storage.

Note: it is not fully reliable since when 'brd' (ramdisk) device is used
this free space value is rather meanigul, but it might help
in case where a real filesystem is doing back-end for test devices.
2020-09-18 17:30:31 +02:00
Zdenek Kabelac
048e04e417 tests: utils better handle ouf of disk space
When the test exhausts all the available free space on storage device,
then during the fail we cannot write anything as well - yet
the teardown needs to finish it's work - otherwise we leave
basicaly overfilled filesystem for all remaining tests.
2020-09-18 17:29:26 +02:00
Zdenek Kabelac
b77595ac8b tests: aux better handle invalid table
In cases where internal functions like zero_dev, delay_dev pass-in
invalid parameter so resulting table can't work, resume at least
previous table line before failing out - so the cleaning process
later on is not stuck waiting on a suspended device.
2020-09-18 14:23:20 +02:00
Zdenek Kabelac
a4137412bf tests: also use sed to shorten log output 2020-09-18 00:31:59 +02:00
Zdenek Kabelac
8d40859e29 tests: resolve missing removal of loopdevice on error path
In case of test failure, loop device leaked and occupied space forever.
2020-09-18 00:31:11 +02:00
Zdenek Kabelac
a5e867139d tests: bigger data still needed for 0.7.0 2020-09-17 23:27:52 +02:00
Zdenek Kabelac
7f019f2580 tests: lower memory usage
Reduce memory needed by test at one time.
2020-09-17 23:27:45 +02:00
David Teigland
72b931d664 configure: enable integrity by default 2020-09-16 15:14:51 -05:00
David Teigland
46f43589d0 hints: enhance debug messages 2020-09-16 15:01:10 -05:00
David Teigland
491eb25832 label: cleanup set_byte error exit 2020-09-16 13:54:16 -05:00
David Teigland
37bcd7ce84 Revert "label: use formaters FMTu64 and FMTsize_t"
This reverts commit d0ccb2521b.
2020-09-16 13:47:06 -05:00
Zdenek Kabelac
52d3c4de6e tests: smaller delay and lowered version
See if this will still work. Some boxes are delayed too much.
Also try to check for raid extend progress from version 1.13.
2020-09-16 14:08:05 +02:00
Zdenek Kabelac
49292bccc3 tests: fix bash regex syntax
Typo before last commit.
2020-09-16 14:08:05 +02:00
Zdenek Kabelac
2c6bd480b2 tests: switch for checking version of installed tools
It looks like older tools were compacting metadata more.
2020-09-15 23:07:06 +02:00
Zdenek Kabelac
cf4fed3761 tests: skip kernel for this test
Kills this kernel ATM
2020-09-15 23:07:06 +02:00
Zdenek Kabelac
d0ccb2521b label: use formaters FMTu64 and FMTsize_t
Produces code without casts to differntly signed types
and also shortens and enhances readbility.
2020-09-15 23:07:06 +02:00
Zdenek Kabelac
2b36542f41 wipe: dev_set_bytes resolves zeroing
Since dev_write_zeros() is just subset of dev_set_bytes()
use it directly and simplify code.
2020-09-15 23:07:06 +02:00
Zdenek Kabelac
d588de77aa wipe: convert zero_value to uint8_t
We always write this value as byte.
2020-09-15 22:52:25 +02:00
Zdenek Kabelac
ec4e8b5c0e wipe: zeroing of 8 sectors is granted
With do_zero min is always 8 sectors, so use 0 as default.
2020-09-15 22:52:25 +02:00
Zdenek Kabelac
7bcc994776 label: deduplicate dev_set_bytes
As dev_write_zeros() is same as dev_set_bytes() reused the code
directly.
2020-09-15 22:52:25 +02:00
Zdenek Kabelac
7b08133844 label: code deduplication 2020-09-15 22:52:25 +02:00
Zdenek Kabelac
6d344b4ac0 hints: enhance debug with log_sys_debug 2020-09-15 22:52:25 +02:00
Zdenek Kabelac
187cc8d344 lvcreate: change error message
Provide more useful error message.
2020-09-15 22:52:25 +02:00
Zdenek Kabelac
39198eb2ce lvcreate: add extra synchronization at error path
Put explict udev synchronization before we try to deactive devices.
2020-09-15 22:52:25 +02:00
Zdenek Kabelac
18a60c6340 tests: protect this test for another kernel
Thisi 3.10.0-862 kernel also dies with this test.
2020-09-14 00:15:14 +02:00
Zdenek Kabelac
9c0d11ecc9 tests: tune usage of smaller metadata
While the previous commit c9b40083fc
decresed version to 1.19 for using bigger datasets,  it's not
been quite right - so from our bb machine it looks like
bigger metadata consumption started with 1.19 and kernel 4.18
(fc27)
2020-09-14 00:15:14 +02:00
Zdenek Kabelac
1005fd7b06 tests: raise needed target version
Require higher version to avoid early bugs.
2020-09-14 00:15:14 +02:00
Zdenek Kabelac
57e1e037b6 tests: improve cache abort test
Use bigger volume and slowdown writing to cache device.
This allows more simple to reach 'dirty' state.
Also document exactly 1 SIGINT has to fire aborting of flushing.
2020-09-14 00:15:14 +02:00
Zdenek Kabelac
64c8827cf3 tests: check in_sync prints also dm status
It's more useful to see how the progress of status checking is moving.
2020-09-14 00:15:14 +02:00
Zdenek Kabelac
b2978efbff cache: simplier signal handling
Use just single sigint_allow()/restore() within flushing loop
and void one extra signal manipulation.
2020-09-14 00:15:14 +02:00
Zdenek Kabelac
c285bf2f37 headers: remove unused headers 2020-09-14 00:15:14 +02:00
Zdenek Kabelac
27383a4b3d configure: just upper case start of sentence 2020-09-14 00:15:14 +02:00
Zdenek Kabelac
2101e324f9 locking: restore blocking signal for VG_GLOBAL lck
During removal of a lot of locking code the signal blocking got lost
and signal processing got broken leading to unpredictable
behavior of i.e. activation code the can get interrupted in the
middle of DM table processing.

lvm2 code always expects signals are blocked while lock is held
unless it is explictelly placed into section of:
sigint_allow();....;sigint_restore();
For checking catched interrupt there is sigint_catched();
2020-09-14 00:15:14 +02:00
Zdenek Kabelac
fe77d1a710 tests: avoid using string
String 'TEST WARNING' may not be present in the test script itself.
Add '\ ' to avoid 'grep' matching test as the test with warning.
2020-09-12 13:24:03 +02:00
Zdenek Kabelac
3008e1be08 tests: support for 16T is needed
Likely 32bit machines can't pass here.
2020-09-12 13:24:03 +02:00
Zdenek Kabelac
17dbb24f7c tests: change skip to die for upstream crash
So the failing test is not lost from sight.
2020-09-12 13:24:03 +02:00
Zdenek Kabelac
7bd015861d tests: skip test on failing kernel 2020-09-12 13:24:03 +02:00
Zdenek Kabelac
a940979ff7 cov: drop checking for EWOULDBLOCK
Reduce cov warning and remove this really ancient define
as lvm2 was never compilable on such platform.
2020-09-12 13:24:03 +02:00
Zdenek Kabelac
740d5bf6cd cov: check sscanf result 2020-09-12 13:24:03 +02:00
Zdenek Kabelac
a5d45b237d cov: drop model for origin_from_cow 2020-09-12 13:23:49 +02:00
Zdenek Kabelac
a9cb96f146 lvconvert: check if LV has cow type
Cow may not be a COW type, the return value of origin_from_cow(cow) may be NULL.

Reported-by: Wu Guanghao <wuguanghao3@huawei.com>
Reported-by: Zhiqiang Liu <liuzhiqiang26@huawei.com>
2020-09-12 12:55:20 +02:00
Zdenek Kabelac
463a61e62e revert "lvconvert: check if LV has snapshot type"
This reverts commit 7db124774a.
Actually we need to check for lv_is_cow().
2020-09-12 12:55:17 +02:00
Zdenek Kabelac
93e252c4a3 tests: check for boundary allocation sizes 2020-09-11 21:52:55 +02:00
Zdenek Kabelac
f84a7266bc tests: reduce disk space usage by pvck-dump
Lower disk usage for 'dd'.
2020-09-11 21:52:55 +02:00
Zdenek Kabelac
c9b40083fc tests: lower at_least to version 1.19
With this version already can be seen different metadata usage on
kernel side, so lower the target version.
2020-09-11 21:52:55 +02:00
Zdenek Kabelac
f233d9a909 tests: have_cache function checks for cache-pool
Check for cache-pool segment as plain cache can match writecache.
2020-09-11 21:52:55 +02:00
Zdenek Kabelac
77fdc17d70 alloc: improve estimation of sufficient_pes_free
Metadata size was calculated correctly only for raids.

Fixes problem for crash during lvcreate when thin-pool was created
on a VG where remaining free space had the size to only fit a single
metadata LV and not also its _pmspare.

Lvcreate crashed with this assert message:

lvcreate: metadata/pv_map.c:198: consume_pv_area: Assertion `to_go <= pva->count' failed.
Aborted (core dumped)

TODO: there is probably to large overload of several alloc_handle
variables.

Reported-by: Wu Guanghao<wuguanghao3@huawei.com>
Reported-by: Zhiqiang Liu <liuzhiqiang26@huawei.com>
2020-09-11 21:51:24 +02:00
Wu Guanghao
7db124774a lvconvert: check if LV has snapshot type
Cow may not be a snapshot type, the return value of origin_from_cow(cow) may be NULL

Signed-off-by: Wu Guanghao <wuguanghao3@huawei.com>
Signed-off-by: Zhiqiang Liu <liuzhiqiang26@huawei.com>
2020-09-11 21:48:37 +02:00
Wu Guanghao
223b75ee91 lvconvert_poll: ensure LV has snapshot type
LV may not be a snapshot type, the return value of find_snapshot(lv) may be NULL.
Here, we will call stack if LV is not a snapshot type.

Signed-off-by: Wu Guanghao <wuguanghao3@huawei.com>
Signed-off-by: Zhiqiang Liu <liuzhiqiang26@huawei.com>
2020-09-11 21:47:34 +02:00
Wu Guanghao
d71199920f pvmove: check return value of top_level_lv_name()
The return value of top_level_lv_name() may be NULL, so we should
check return value of top_level_lv_name before calling
strcmp(lv->name, top_level_lv_name(vg, lv_name)).

Signed-off-by: Wu Guanghao <wuguanghao3@huawei.com>
Signed-off-by: Zhiqiang Liu <liuzhiqiang26@huawei.com>
2020-09-11 21:43:08 +02:00
Zhao Heming
c38c4d9d36 gitignore: ignore all cscope generated files
When using cscope to read code, it will generate below 3 files for speedup
cross-refer: cscope.files, cscope.in.out, cscope.po.out

The .gitignore only contains "/cscope.out". It a little bit messy when
executing 'git status', and other git commands.
This patch add all cscope generated files in .gitignore.

Signed-off-by: Zhao Heming <heming.zhao@suse.com>
2020-09-11 21:42:38 +02:00
Zdenek Kabelac
9f78acfee9 thin: compensate metadata size by extra percent
When using --use-policy for automatic extension of thin-pool,
the extension of thin-pool's metadata itself can actually take
some extra space.
Since I'm not aware of exact compensation formula, add just
1% extra to calculated amount and hope it fits.

Wanted target is to always have usable thin-pool that fits
bellow pool_metadata_min_threshold().
2020-09-11 21:42:37 +02:00
Zdenek Kabelac
b798554a20 lv_manip: even better rounding 2020-09-11 13:37:04 +02:00
Zdenek Kabelac
3f2e9e3546 tests: aux collects stack trace when stuck is assumed
Automatically collect traces in this case.
2020-09-10 23:55:03 +02:00
Zdenek Kabelac
49d2b27a68 tests: adding "" around DM_DEV_DIR 2020-09-10 23:55:03 +02:00
Zdenek Kabelac
3dcd61d3d7 tests: disable dbustest with valgrind testing 2020-09-10 23:55:03 +02:00
Zdenek Kabelac
678951f635 cleanup: comment typo 2020-09-10 23:55:03 +02:00
Zdenek Kabelac
e7bd3ba22d debug: drop debug trace from regular path
Since we query on regular code these:
  lv_raid_has_integrity()
  lv_has_integrity_recalculate_metadata()
without prior checking for lv_is_raid() - these 'return 0' should
not use <stacktrace> as they are expected.
2020-09-10 23:55:03 +02:00
Zdenek Kabelac
bc09803628 lv_manip: relocate check to proper function 2020-09-10 23:54:33 +02:00
Zdenek Kabelac
e7f5acdfa6 lvextend: improve percentage estimation
Correcting rounding rules for percentage evaluation.

Validate supported range of percentage.
(although ranges are already validated earlier on code path)
2020-09-10 23:54:31 +02:00
Zdenek Kabelac
6d392776b0 configure: compile with vdo and writecache by default
Enable compilation of vdo and writecache support as internaly
supported segment types by default.

For disabling use:

--with-vdo=none
--with-writcache=none
2020-09-10 23:54:10 +02:00
David Teigland
1f54129c4e integrity: fix segfault reporting integrity for other lvs 2020-09-09 10:22:07 -05:00
Zdenek Kabelac
0210c7076d man: correcting vdo issues
Fixing reported bugs within provided examples - so examples
can be used via cut&paste.
2020-09-09 15:16:34 +02:00
Zdenek Kabelac
763342016c man: correctly use configured directories 2020-09-09 13:22:37 +02:00
Zdenek Kabelac
af33a00847 Revert "raid: add _rimage and _rmeta as origin_only"
This reverts commit 3388e19489.
More thinking needed.
2020-09-09 00:58:52 +02:00
Zdenek Kabelac
a8ea1817ab Revert "raid: do not enforce flushing of raids when it is not required"
This reverts commit ce5ea07411.
More thinking needed.
2020-09-09 00:58:32 +02:00
Zdenek Kabelac
bb62af5b3d tests: tune extend test
For proper checking of extension progress require version 1.15

It looks with older versoin extension happens during very slow
resume within lvm command - although speed is still somewhat slow
with latest version.
2020-09-08 21:23:03 +02:00
Zdenek Kabelac
676ce47754 tests: check for writecache being compiled in 2020-09-08 21:23:03 +02:00
Zdenek Kabelac
8dea63d30f tests: check for cache_version that supports v2 2020-09-08 21:23:03 +02:00
Zdenek Kabelac
ce5ea07411 raid: do not enforce flushing of raids when it is not required
This is probably somewhat experimantal patch - but when i.e. raid device
is just extend, there should not be a technical need for flush,
unless the target would stricly need it.  It should allow faster
processing of lvm command not being blocked by possibly longer flush.
2020-09-08 21:23:03 +02:00
Zdenek Kabelac
3388e19489 raid: add _rimage and _rmeta as origin_only
Since we do not support rimage & rmeta for snapshots - we can
avoid quering for -cow devices and add them as origin_only -
since their snapshots (-cow) could have never existed.
This redumes several ioctl operation during table preloading.
2020-09-08 21:23:03 +02:00
Zdenek Kabelac
3e6bb77228 lv_manip: add synchronization points 2020-09-08 21:23:03 +02:00
Zdenek Kabelac
8d6f1f9768 lvconvert: flip return value of _raid_split_image_conversion
Use '0' for error and '1' as success.
Also drop INTERNAL_ERROR from path - as this error
is ATM used for invalid devices.
(i.e. test lvconvert-raid1-split-trackchanges.sh)
2020-09-08 21:23:03 +02:00
David Teigland
dddf63ebc3 tests: fix pvck repair in hints.sh 2020-09-04 11:23:25 -05:00
Zdenek Kabelac
10fc3610c4 tests: use delayzero_dev
Speed-up a bit the first synchronization with just 50ms write delay,
but later set also delay on read to slowdown lvextend.

FIXME: there are still things to look at:

0 229376 raid raid1 2 AA 229376/229376 idle 0 0
0 229376 raid raid1 2 AA 0/229376 frozen 0 0 -
0 262144 raid raid1 2 AA 229376/262144 repair 0 0 -
0 262144 raid raid1 2 AA 229376/262144 repair 0 0 -
0 262144 raid raid1 2 AA 245888/262144 repair 0 0 -
2020-09-04 18:11:42 +02:00
Zdenek Kabelac
76b1f43e81 tests: add aux delayzero_dev support
Just like we have 'writeerror_dev' supporting creation of device
which 'readable' segment and segments where write will fail we
have now support for delay zero mappings.

This is useful if we want to 'fake' large writing areas where we do
not really care about the actual 'disk' content - since we test
operation logic and it doesn't matter we read and write zeroes.
With combination with 'delay' target we can create specific mappings
and avoid using large memory areas of ramdisk.
2020-09-04 18:11:42 +02:00
David Teigland
d8bb85d963 writecache: allow pvmove on origin
The removed check didn't actually prevent pvmoving the origin,
which was possible by naming the wcorig lv, or naming no lv.
2020-09-02 14:45:52 -05:00
David Teigland
f5a669f314 pvck: repair should clear hints
repairing a pv can cause the hint file to become incorrect
2020-09-02 14:21:17 -05:00
David Teigland
8b9028bbe7 hints: remove warning when clearing hint file
When the hint file cannot be accessed, silently
ignore hints, like other instances do.
2020-09-02 14:06:46 -05:00
David Teigland
d1019a6434 integrity: improve lv type checks 2020-09-02 12:40:45 -05:00
David Teigland
9a7b81fb72 integrity: fix segfault for lv with no seg
in lv_raid_has_integrity
2020-09-02 09:15:58 -05:00
David Teigland
739827ef1c tests: add new integrity reporting fields 2020-09-01 17:13:46 -05:00
David Teigland
ed249a2c53 integrity: report mismatches
with lvs -o integritymismatches

reported for integrity images, which may report
different values
2020-09-01 17:13:21 -05:00
David Teigland
47b5fb138c integrity: report raidintegritymode randintegrityblocksize
reported for the raid lv and the integrity images
2020-09-01 17:12:36 -05:00
David Teigland
f2c1de783c integrity: always default to journal mode
lvconvert was defaulting to bitmap mode,
and lvcreate was defaulting to journal mode.
2020-09-01 17:12:28 -05:00
Zdenek Kabelac
9a06700017 tests: skip this test for current 5.8 5.9 kernels
Kernel is hitting not yet fixed kernel bug.
Skip the test to avoid killing testing machine.
2020-09-01 23:40:24 +02:00
Zdenek Kabelac
fa1290f40e tests: slightly faster
Use lvm shell to agregrate lots of lvm commands
Reduce initial zeroing.
2020-09-01 23:40:24 +02:00
Zdenek Kabelac
38d460ed6e tests: set skipping autoactivation
On test system with 'default' filter  (aka accept all) test
after enabling device can suffer from automatic system
activation - so for created LVs setup skipping this automatic
activation. This should prevent getting LVs into table
with pvscan service.
2020-09-01 23:40:24 +02:00
Zdenek Kabelac
ada5728c72 tests: skip test when gcore cannot catch securetest 2020-09-01 23:40:24 +02:00
Zdenek Kabelac
bc13c7d246 gcc: avoid shadowing of dev_name and pvs
Since we declare dev_name in lib/device/device.h
and pvs in commands.h
rename local dev_name to device_name
and pvs to pvs_list to prevent shadowing warning.

m
2020-09-01 23:40:24 +02:00
Zdenek Kabelac
672d5ad98b gcc: hide warn about possible uninitialized use of dev_ret
Older gcc reports this fp problem.
2020-09-01 23:40:24 +02:00
Zdenek Kabelac
11f08dacc9 pvck: add simple check for fwrite
Add at least very light check for result code of fwrite().
2020-09-01 23:40:24 +02:00
Zdenek Kabelac
66803586ef pvck: use array of bytes
Fix typo in use array of pointers instead of array of bytes.
This fixes 'break strict-aliasing rules' warning printed with older gcc.
2020-09-01 23:40:24 +02:00
Zdenek Kabelac
1ff1e86deb cleanup: better expressing passing key arg to _hash 2020-09-01 17:57:50 +02:00
Zdenek Kabelac
4baedfc578 cleanup: add spaces between literals 2020-09-01 17:57:50 +02:00
Zdenek Kabelac
a375657092 cleanup: user force_t enums instead of ints 2020-09-01 17:57:50 +02:00
Zdenek Kabelac
dbb19f6ace cleanup: matching declaration order
Cosmetic
2020-09-01 17:57:50 +02:00
Zdenek Kabelac
56c41b7522 cov: avoid duplicated assign 2020-09-01 17:57:50 +02:00
Zdenek Kabelac
a481f42630 cov: always initialized values
Make sure values are initialized for all possible paths.
2020-09-01 17:57:50 +02:00
Zdenek Kabelac
85e2c7e14d cov: explicitely ignore function result 2020-09-01 17:57:50 +02:00
Zdenek Kabelac
1705b439b1 cov: always sure we end with '0'
Use easier dm_strncpy().
2020-09-01 17:57:50 +02:00
Zdenek Kabelac
de837c15a5 gcc: keep using unsigned type 2020-09-01 17:57:50 +02:00
Zdenek Kabelac
534760398c gcc: preserve constness of buffer 2020-09-01 17:57:50 +02:00
Zdenek Kabelac
fd96f1014b gcc: zero-sized array to fexlible array C99
Switch remaining zero sized struct to flexible arrays to be C99
complient.

These simple rules should apply:

- The incomplete array type must be the last element within the structure.
- There cannot be an array of structures that contain a flexible array member.
- Structures that contain a flexible array member cannot be used as a member of another structure.
- The structure must contain at least one named member in addition to the flexible array member.

Although some of the code pieces should be still improved.
2020-09-01 17:57:50 +02:00
Zhao Heming
cc2218b401 gcc: change zero-sized array to fexlible array
this patch makes gcc happy with compiling option: [-Wstringop-overflow=]

Signed-off-by: Zhao Heming <heming.zhao@suse.com>
2020-09-01 17:57:50 +02:00
Zdenek Kabelac
0f377a04e5 dmsetup: initilize winsize struct
Ensure winsize struct is always defined.
2020-09-01 17:57:50 +02:00
Zdenek Kabelac
2fbc578cfa tests: filefrag needs to support -e
Skip on systems with 'too old' filefrag without -e support
2020-09-01 17:57:48 +02:00
Zdenek Kabelac
ef389603dd cachevol: correcting 64b math
Widen to 64bit for correct 64b multiplication math.
2020-09-01 17:50:48 +02:00
Zdenek Kabelac
f0614e7cf0 WHATS_NEW: update 2020-08-28 21:43:03 +02:00
Zdenek Kabelac
b722ce2f10 gcc: drop bogus ; 2020-08-28 21:43:03 +02:00
Zdenek Kabelac
19e9c88faf gcc: do not use return with void function
Follow C norm and do not use 'return' in void function to call other
functions.
2020-08-28 21:43:03 +02:00
Zdenek Kabelac
ee0cb17608 gcc: use apropriate type for reading and printing values 2020-08-28 21:43:03 +02:00
Zdenek Kabelac
b918afb693 tools: move struct element before variable lenght list
Move prio field before 'variable' struct array field.
Interesting why this has not been catched yet.

TODO: think about test case
2020-08-28 21:43:02 +02:00
Zdenek Kabelac
7880896f0d gcc: calc size in compile time 2020-08-28 21:43:02 +02:00
Zdenek Kabelac
fd8d926fc5 gcc: avoid stack alloc arithmetic 2020-08-28 21:43:02 +02:00
Zdenek Kabelac
ce202c3b1c gcc: keep unsigned arithmetic
Avoid conversion to int.
2020-08-28 21:43:02 +02:00
Zdenek Kabelac
ff4827ffb1 lv_manip: get_default_region_size return uint32_t 2020-08-28 21:43:02 +02:00
Zdenek Kabelac
93c9055591 lvmcache: use uint32_t for seqno caching 2020-08-28 21:43:02 +02:00
Zdenek Kabelac
03f9cd95b4 writecache: correct usage of const struct 2020-08-28 21:43:02 +02:00
Zdenek Kabelac
fb7a3fe8d6 container_of: drop needless const converion 2020-08-28 21:43:02 +02:00
Zdenek Kabelac
ca54afd701 tests: check we detect lvm.conf read failure
No coredumps with unreadable lvm.conf.
2020-08-28 21:43:02 +02:00
Zdenek Kabelac
e3e04b99f2 config: drop reading file with mmap
While normally the 'mmap' file reading is better utilizing resources,
it has also its odd side with handling errors - so while we normally
use the mmap only for reading regular files from root filesystem
(i.e. lvm.conf) we can't prevent error to happen during the read
of these file - and such error unfortunately ends with SIGBUS error.
Maintaing signal handler would be compilated - so switch to slightly
less effiecient but more error resistant read() functinality.
2020-08-28 21:43:02 +02:00
David Teigland
9a88a9c4ce Revert "lvdisplay: dispaly correct status when underlying devs missing"
This reverts commit 1d0dc74f91.

We should avoid adding anything new to lvdisplay and report
new information via lvs reporting fields.
2020-08-28 13:28:15 -05:00
Zhao Heming
1d0dc74f91 lvdisplay: dispaly correct status when underlying devs missing
reproducible steps:
1. vgcreate vg1 /dev/sda /dev/sdb
2. lvcreate --type raid0 -l 100%FREE -n raid0lv vg1
3. do remove the /dev/sdb action
4. lvdisplay show wrong 'LV Status'

After removing raid0 type LV underlying dev, lvdisplay still display
'available'. This is wrong status for raid0.

This patch add a new function raid_is_available(), which will handle
all raid case.

With this patch, lvdisplay will show
from:
  LV Status              available
to:
  LV Status              NOT available (partial)

Reviewed-by: Enzo Matsumiya <ematsumiya@suse.com>
Signed-off-by: Zhao Heming <heming.zhao@suse.com>
2020-08-24 09:47:04 -05:00
Zdenek Kabelac
46d15b5e4d wipe_lv: close devices on error path
Device was kept open preventing its deactivated and removed
on error path.
2020-08-19 15:09:09 +02:00
Zdenek Kabelac
3e9664baca man: vdo improvals
Add some more notes about discard.
Correct enumeration.
2020-08-19 15:09:09 +02:00
Zdenek Kabelac
7b41ea61b2 config: move some config setting into commented part
It's better to set most of option as 'commented' with some
documented defaults instead of providing strict values.

This has the advantage we can eventually 'change' defualts
and get them working in future. Otherwise once the setting
is stored in lvm.conf in /etc, such setting has strictly
defined value and that can be only change with file update.
2020-08-19 15:07:09 +02:00
Marian Csontos
135d16fbb8 Update README 2020-08-12 12:05:36 +02:00
Marian Csontos
231cdd0efb post-release 2020-08-09 16:17:15 +02:00
Marian Csontos
4d9f0606be pre-release 2020-08-09 16:17:15 +02:00
Marian Csontos
c1d136fea3 WHATS_NEW 2020-08-09 16:17:15 +02:00
Marian Csontos
9f8c331760 build: make generate 2020-08-09 15:20:22 +02:00
Tony Asleson
4f44841045 WHATS_NEW: Add writecache lvmdbusd 2020-08-06 15:42:49 -05:00
Vojtech Trefny
d4d060acd5 lvmdbusd: Bump LVM DBus API version
So users can check for writecache support.
2020-08-06 13:54:45 -05:00
Vojtech Trefny
8f1068c02d lvmdbusd: Add support for LVM writecache 2020-08-06 13:54:34 -05:00
Marian Csontos
e12bdd591a tests: Adapt RAID test to changes
Change 3c9177fdc0 causes a conversion of raid1 volume to a raid1 with
the same number of legs succeed with a warning.
2020-07-28 17:36:57 +02:00
David Teigland
7a507583d9 cachevol: add LV type restrictions to command defs
LV type restrictions were missed on the command definitions.
2020-07-23 15:10:35 -05:00
David Teigland
085760992d cachevol: generate a unique name when creating
When a cachevol is automatically created, if the default name
conflicts with an existing name, generate a new unique name.
2020-07-23 13:18:22 -05:00
Heinz Mauelshagen
3c9177fdc0 lvconvert: display warning if raid1 LV image count does not change
Fix "lvconvert -mN $RaidLV" to display a warning in
case the same number of images is being requested.

Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1774696
2020-07-20 15:42:15 +02:00
David Teigland
119d594788 integrity: allow type option to be set when changing mirrors
Allow the optional '--type raid1' to be included in the lvconvert
command when adding or removing raid images with integrity.
It does not change the meaning of the command (specifying a type
that matches the current type is redundant but generally allowed.)
2020-07-15 10:57:05 -05:00
David Teigland
4667c4b35b lvmdbusd: recognize lv attr letter g for integrity 2020-07-15 10:07:28 -05:00
Heinz Mauelshagen
8f421bdd7a lvconvert: preset raid1 in case of striped conversions
Fixed invoking "lvconvert -m+1 $StripedLV" to cause errors
(preset raid conversion implied by '-m').

Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1781406
2020-07-13 19:07:26 +02:00
David Teigland
00c9a788cc devices: simplify md superblock checking code 2020-07-09 10:48:34 -05:00
David Teigland
23774f997e devices: detect md ddf and imsm superblocks 2020-07-09 10:48:21 -05:00
Heinz Mauelshagen
286a793c12 lvconvert: fix conversion to 'mirrored' mirror log with larger regionsize
merge.c:_check_lv_segment() was checking regionsize vs. mirrored LV size on
any 'mirror/raid1/raid10' segment type including type 'mirrored' mirror logs.

Avoid the check only for 'mirrored' mirror logs to allow conversion from log
type 'disk' with regionsize > mirror log SubLV size.

As we disabled support for 'mirrored' mirror logs with
commit e82303fd6a which still conditionally
allows to enable it via global/support_mirrored_mirror_logs=1,
patch is mandatory for all distributions.

Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1712983
2020-07-09 14:39:50 +02:00
Zdenek Kabelac
d0faad0db3 debug: missing stacktrace 2020-07-08 11:40:55 +02:00
Zdenek Kabelac
9b9bf8786f raid: no wiping when zeroing raid metadata device
Currently lvm2 is not wiping signatures when creating 'metadata' volumes
and raid _rmeta was the only exception - so make the behavior consistent
with other metadata devices and drop wiping ATM.
Drop also some extra debug since they are now more explanatory in
wipe_lv() function.
Also note - although lvm2 now does not wipe signatures - the error
from such wipping used to be actually 'ignored' before wipe_lv()
started to return error (with recent commit) and raid creation
continued with 'unzeroed' metadata device.

TODO: Several issues to resolve:

1. We may want to flip to wipping with all LVs (in that case we need to
support passing --yet & --force).

2. Also we may want to clear whole metadata device - however current
function is also used for wipping i.e. snapshot COW device which
is likely not a good candidate for full device zeroing.
We may also need to think about better logic when extent size is
enforcing very large LVs, when only a small portion of LV is ever
being used.

3. Using TRIM instead of zeroing metadata device might be worth to
implement.

mm
2020-07-08 11:40:55 +02:00
Zdenek Kabelac
b7f3667ce2 lvconvert: more support for yes conversion
When converting volume to pool LV use also wiping of other signatures.
For writecache & pool conversion support --yet and --force
to bypass prompting for signature wiping.
For writecache drop unneded zero_sectors.

Note: currently we have lvconvert doing convertion and prompting
for confirmation of conversion - and then again wipe_lv() prompts
for removing i.e. filesystem signature - we should unify this
prompting into 1 message  - althought the 'filesystem' discovery
needs active volume - while the 1st. conversion prompt can
work without active converted volume.
2020-07-08 11:37:33 +02:00
Zdenek Kabelac
fe78cd4082 wipe_lv: always zero at least 4K
When zero_sectors passed value like 1 - we could zero only 1 sector.
Reinstantiate we always zero at least 4K block.
2020-07-08 11:12:54 +02:00
David Teigland
40266faaab writecache: skip fs block size check in test mode
if doing so requires activating the LV
2020-07-07 13:20:18 -05:00
David Teigland
ad773511c5 integrity: add initial size to metadata size
The metadata device size needs to include space for
the dm-integrity "initial_sectors" which hold journals.
2020-06-30 16:43:05 -05:00
Zdenek Kabelac
3f32f9811e tests: check pool metadata are zeroed 2020-06-24 15:01:03 +02:00
Zdenek Kabelac
094d6f80dd tests: failure of zeroing fails command 2020-06-24 15:01:03 +02:00
Zdenek Kabelac
88b92d4225 make: make generate
update
2020-06-24 15:01:03 +02:00
Zdenek Kabelac
b7885dbb73 man: update cache page
Few more sentences around migration threshold.
2020-06-24 15:01:03 +02:00
Zdenek Kabelac
cca2a652d1 cov: avoid double call of free_hints() on error path
Since we 'free_hints()' on return error path from call of
_read_hint_file(), avoid calling it twice in the middle of
error path process.
2020-06-24 15:01:03 +02:00
Zdenek Kabelac
eb06832b37 cov: remove unused header 2020-06-24 15:01:03 +02:00
Zdenek Kabelac
dccaab3d79 cov: use 64bit arithmetic
Although values of VDO block_map_cache_size, index_memory_size, slab_size
should not overflow here - use proper 64bit math.
2020-06-24 15:01:03 +02:00
Zdenek Kabelac
bc39d5bec6 pool: zero metadata
To avoid polution of metadata with some 'garbage' content or eventualy
some leak of stale data in case user want to upload metadata somewhere,
ensure upon allocation the metadata device is fully zeroed.

Behaviour may slow down allocation of thin-pool or cache-pool a bit
so the old behaviour can be restored with lvm.conf setting:
allocation/zero_metadata=0

TODO: add zeroing for extension of metadata volume.
2020-06-24 15:01:03 +02:00
Zdenek Kabelac
edbc5a62b2 wipe_lv: make error a fatal event
Failure in wiping/zeroing stop the command.
If user wants to avoid command abortion he should use -Zn or -Wn
to avoid wiping.

Note: there is no easy way to distinguish which kind of failure has
happend - so it's safe to not proceed any futher.
2020-06-24 15:01:03 +02:00
Zdenek Kabelac
6eb9eba59b bcache: support longer writes
When initiated larger write request, it may have happened, bcache
got out of free chunks - fix the loop, that is supposed to wait
until next free chunk becomes avain available.
2020-06-24 15:01:03 +02:00
Heinz Mauelshagen
04bba5ea42 lv{resize,extend,reduce}: also check for 2-legged raid4
Users can also convert 2-legged raid1 to raid4 thus causing 'Bus error'
on resize requests.

Related: https://bugzilla.redhat.com/show_bug.cgi?id=1784351
2020-06-24 14:02:31 +02:00
Heinz Mauelshagen
2cf0f90780 lv{resize,extend,reduce}: reject size change on 2-legged raid5*
Reject size changing request in to avoid 'Bus error' and
display hint to convert to more stripes.

Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1784351
2020-06-24 13:52:56 +02:00
David Teigland
3bd9d81b29 man: lvmcache info about cachedevice usage 2020-06-22 11:24:02 -05:00
David Teigland
ae5634a8be tests: cachevol-cachedevice 2020-06-22 11:23:58 -05:00
David Teigland
2aed2a41f7 lvcreate: new cache or writecache lv with single command
To create a new cache or writecache LV with a single command:

lvcreate --type cache|writecache
    -n Name -L Size --cachedevice PVfast VG [PVslow ...]

- A new main linear|striped LV is created as usual, using the
  specified -n Name and -L Size, and using the optionally
  specified PVslow devices.
- Then, a new cachevol LV is created internally, using PVfast
  specified by the cachedevice option.
- Then, the cachevol is attached to the main LV, converting the
  main LV to type cache|writecache.

Include --cachesize Size to specify the size of cache|writecache
to create from the specified --cachedevice PVs, otherwise the
entire cachedevice PV is used.  The --cachedevice option can be
repeated to create the cache from multiple devices, or the
cachedevice option can contain a tag name specifying a set of PVs
to allocate the cache from.

To create a new cache or writecache LV with a single command
using an existing cachevol LV:

lvcreate --type cache|writecache
    -n Name -L Size --cachevol LVfast VG [PVslow ...]

- A new main linear|striped LV is created as usual, using the
  specified -n Name and -L Size, and using the optionally
  specified PVslow devices.
- Then, the cachevol LVfast is attached to the main LV, converting
  the main LV to type cache|writecache.

In cases where more advanced types (for the main LV or cachevol LV)
are needed, they should be created independently and then combined
with lvconvert.

Example
-------

user creates a new VG with one slow device and one fast device:

$ vgcreate vg /dev/slow1 /dev/fast1

user creates a new 8G main LV on /dev/slow1 that uses all of
/dev/fast1 as a writecache:

$ lvcreate --type writecache --cachedevice /dev/fast1
    -n main -L 8G vg /dev/slow1

Example
-------

user creates a new VG with two slow devs and two fast devs:

$ vgcreate vg /dev/slow1 /dev/slow2 /dev/fast1 /dev/fast2

user creates a new 8G main LV on /dev/slow1 and /dev/slow2
that uses all of /dev/fast1 and /dev/fast2 as a writecache:

$ lvcreate --type writecache --cachedevice /dev/fast1 --cachedevice /dev/fast2
    -n main -L 8G vg /dev/slow1 /dev/slow2

Example
-------

A user has several slow devices and several fast devices in their VG,
the slow devs have tag @slow, the fast devs have tag @fast.

user creates a new 8G main LV on the slow devs with a
2G writecache on the fast devs:

$ lvcreate --type writecache -n main -L 8G
    --cachedevice @fast --cachesize 2G vg @slow
2020-06-16 13:46:51 -05:00
David Teigland
21b37964eb lvconvert: single step cachevol creation and attachment
To add a cache or writecache to a main LV with a single command:

lvconvert --type cache|writecache --cachedevice /dev/ssd vg/main

A cachevol LV will be allocated from the specified cache device,
then attached to the main LV.  Include --cachesize to specify the
size of cachevol to create, otherwise the entire cachedevice is
used.  The cachedevice option can be repeated to create a cachevol
from multiple devices.

Example
-------

A user has an existing main LV that they want to speed up
using a new ssd.

user adds the new ssd to the VG:

$ vgextend vg /dev/ssd

user attaches the new ssd their main LV:

$ lvconvert --type writecache --cachedevice /dev/ssd vg/main

Example
-------

A user has two existing main LVs that they want to speed up
with a new ssd.

user adds the new 16G ssd to the VG:

$ vgextend vg /dev/ssd

user attaches some of the new ssd to the first main LV,
using half of the space:

$ lvconvert --type writecache --cachedevice /dev/ssd
    --cachesize 8G vg/main1

user attaches some of the new ssd to the second main LV,
using the other half of the space:

$ lvconvert --type writecache --cachedevice /dev/ssd
    --cachesize 8G vg/main2

Example
-------

A user has an existing main LV that they want to speed up using
two new ssds.

user adds the new two ssds the VG:

$ vgextend vg /dev/ssd1
$ vgextend vg /dev/ssd2

user attaches both ssds their main LV:

$ lvconvert --type writecache
    --cachedevice /dev/ssd1 --cachedevice /dev/ssd2 vg/main
2020-06-16 13:46:51 -05:00
David Teigland
950d2d59c1 integrity: wait for raid sync to complete 2020-06-16 12:29:41 -05:00
David Teigland
48872b0369 integrity: avoid increasing logical block size of active LV
When adding integrity to an active LV, avoid choosing an
integrity block size that would result in increasing the
logical block size of the LV.
2020-06-16 12:27:22 -05:00
David Teigland
a014c4f341 tests: integrity and block size 2020-06-15 16:04:40 -05:00
David Teigland
8e2938c963 improve get_fs_block_size string to number 2020-06-11 15:05:47 -05:00
David Teigland
9f38e95a2f tests: fix typo in writecache-blocksize 2020-06-11 13:15:38 -05:00
David Teigland
f32e85ae51 tests: expand integrity-blocksize 2020-06-11 12:46:47 -05:00
David Teigland
b528a9ce90 integrity: fix block size check when inactive
Checking fs block size requires the LV to be active.
2020-06-11 12:43:52 -05:00
David Teigland
9fbad5bb0f fix libblkid BLOCK_SIZE check 2020-06-11 12:43:07 -05:00
David Teigland
6ea3654868 tests: writecache tests
backport updates from later commits
2020-06-10 16:09:36 -05:00
David Teigland
ba27b9ee2a writecache: activate to check block size
backport fixes from later commit
2020-06-10 15:58:25 -05:00
David Teigland
38eaa1035b writecache: allow snapshot of LV with writecache 2020-06-10 12:18:00 -05:00
David Teigland
712c9efbf6 fix bad result from _cache_min_metadata_size
fixes regression from switching to use _cache_min_metadata_size
(commit c08704cee7) which returns
a bogus value when the cachevol size is 8MB.
2020-06-10 12:17:34 -05:00
David Teigland
48c1a295a2 tests: writecache-blocksize 2020-06-10 12:16:31 -05:00
David Teigland
a7b2fc8f57 writecache: add settings cleaner and max_age
available in dm-writecache 1.2
2020-06-10 12:15:50 -05:00
David Teigland
d15c466f95 writecache: attach while active using fs block size
Use libblkid to detect sector/block size of the fs on the LV.
Use this to choose a compatible writecache block size.
Enable attaching writecache to an active LV.
2020-06-10 12:15:34 -05:00
David Teigland
1ee42f1391 writecache: cachesettings in lvchange and lvs
lvchange --cachesettings
lvs -o+cache_settings
2020-06-10 12:14:00 -05:00
David Teigland
ce772bfab9 writecache: show error in lv_health_status and lv_attr
lv_attr is 'E' and lv_health_status is 'error'
when dm-writecache status reports error.
2020-06-10 12:13:48 -05:00
David Teigland
240062a183 writecache: remove from an active lv 2020-06-10 12:13:31 -05:00
Peter Rajnoha
8806f2d5ed blkdeactivate: add missing VDO_AVAILABLE check in deactivate_vdo 2020-06-08 15:41:35 +02:00
David Teigland
fa9eb76a5d improve info about vgck updatemetadata
Add man page info about this option, and add log messages
pointing to this option.
2020-06-03 12:38:27 -05:00
Zhao Heming
b59127a838 Change dev->bcache_fd default value from 0 to -1
This fix can avoid bcache_fd will mistakenly open/close in later.

Signed-off-by: Zhao Heming <heming.zhao@suse.com>
2020-06-01 12:22:15 -05:00
David Teigland
d14a8040d4 Revert "pvck: dump headers_only to skip metadata text"
This reverts commit 5410dd5441.

Accidental push.
2020-05-29 13:26:43 -05:00
David Teigland
ae029fcced integrity: skip calling add when removing images
When lvconvert is used to remove raid images, we can
skip calling lv_add_integrity_to_raid(), which finds
nothing to do, but the the blocksize validation would
be called unnecessarily and trigger spurious errors.
2020-05-29 13:18:24 -05:00
David Teigland
7b04ed07ba tests: integrity wait for sync
The test was using a raid+integrity LV without
first waiting for the integrity sync, which could
cause the test to fail (depending on init speed)
where it depends on integrity to work in uninitialized
areas.

Also use cmp instead of diff.
2020-05-29 10:57:56 -05:00
David Teigland
5410dd5441 pvck: dump headers_only to skip metadata text
pvck --dump headers reads the metadata text area
to compute the text metadata checksum to compare
with the mda_header checksum.
The new header_only will skip reading the metadata
text and not validate the mda_header checksum.
2020-05-28 15:51:59 -05:00
Marian Csontos
be61bd6ff5 test: Warn and exit on problematic integrity device behavior
The first leg of integrity enabled raid device sometimes does not get
recalculated.
2020-05-28 17:04:35 +02:00
David Teigland
74a211cfd3 lvconvert: error when using existing cachevol
Check if LV is an existing cachevol before attempting
to use it again as a cachevol or cachepool.
2020-05-22 14:12:34 -05:00
Zdenek Kabelac
bb41ca86fa tests: also udev wait on clean-up path 2020-05-21 16:03:41 +02:00
Marian Csontos
53803821de test: Use printf to generate data
...to avoid unnecessary dependency on python
2020-05-21 15:33:24 +02:00
Marian Csontos
b5811b7c9c tests: Use python single liner to generate data 2020-05-21 15:11:22 +02:00
Marian Csontos
70a45c44e8 build: make generate 2020-05-21 15:02:31 +02:00
Zdenek Kabelac
d3b515cea5 tests: add wait on udev processing
Trying to avoid collision with udev watch rule preventing to
succeed 'dmsetup remove' becuase it keeps device open.
2020-05-20 16:01:20 +02:00
Zdenek Kabelac
deb5160181 list: use container_of
Reuse macro
2020-05-20 16:01:20 +02:00
Zdenek Kabelac
16da6651a1 pvck: set dump on one call
arg_str_value() has built-in  arg_is_set().

Also this makes it obvious to coverity 'dump != NULL' & 'repair != NULL'
at the branch code path.
2020-05-20 15:55:39 +02:00
Zdenek Kabelac
cf74123830 cov: lvconvert: missing check for function failure 2020-05-20 15:55:39 +02:00
Zdenek Kabelac
ce8277b47e cov: check strdup for NULL 2020-05-20 15:55:39 +02:00
Zdenek Kabelac
33fdeaf3f1 cov: check for deactivation failure 2020-05-20 15:55:39 +02:00
David Teigland
2a304d7a75 lvmcache: free vginfo lock_type 2020-05-14 10:20:08 -05:00
David Teigland
5c095400de hints: free hint structs on exit
and free on a couple error paths.
2020-05-13 17:20:16 -05:00
David Teigland
2f29765e7f devs: add some checks for a dev with no path name
It's possible for a dev-cache entry to remain after all
paths for it have been removed, and other parts of the
code expect that a dev always has a name.  A better fix
may be to remove a device from dev-cache after all paths
to it have been removed.
2020-05-13 16:26:26 -05:00
David Teigland
2d1fe38d84 lvmlockd: use 4K sector size when any dev is 4K
When either logical block size or physical block size is 4K,
then lvmlockd creates sanlock leases based on 4K sectors,
but the lvm client side would create the internal lvmlock LV
based on the first logical block size it saw in the VG,
which could be 512.  This could cause the lvmlock LV to be
too small to hold all the sanlock leases. Make the lvm client
side use the same sizing logic as lvmlockd.
2020-05-11 13:14:55 -05:00
Marian Csontos
33265467f9 spec: Enable integrity 2020-05-05 14:12:32 +02:00
David Teigland
5263551a2d lvmlockd: replace lock adopt info source
The lock adopt feature was disabled since it had used
lvmetad as a source of info.  This replaces the lvmetad
info with a local file and enables the adopt feature again
(enabled with lvmlockd --adopt 1).
2020-05-04 13:35:03 -05:00
David Teigland
d945b53ff7 remove vg_read_error
Once converted results to error numbers but is now just a null check.
2020-04-24 11:14:29 -05:00
David Teigland
4047a32128 use refresh_filters only where needed
Filters are changed and need refresh in only one
place (vgimportclone), so avoid doing the refresh
for every other command that doesn't need it.
2020-04-22 14:08:54 -05:00
Maxim Plotnikov
a509776588 Fix scripts/lvmlocks.service.in using nonexistent --lock-opt autowait
The --lock-opt autowait was dropped back in 9ab6bdce01,
and attempting to specify it has quite an opposite effect:
no waiting is done, which makes the unit almost useless.
2020-04-21 16:52:45 -05:00
David Teigland
d79afd4084 lvmcache: rework handling of VGs with duplicate vgnames
The previous method of managing duplicate vgnames prevented
vgreduce from working if a foreign vg with the same name
existed.
2020-04-21 14:40:34 -05:00
David Teigland
cc4051eec0 pass cmd struct through more functions
no functional change
2020-04-21 10:58:05 -05:00
David Teigland
3854931aea lvmcache_get_mda: remove unused function 2020-04-21 10:58:05 -05:00
David Teigland
2aa36209eb vgrename: fix error value when name exists 2020-04-21 09:33:56 -05:00
David Teigland
211eaa284c WHATS_NEW: integrity with raid 2020-04-15 12:10:39 -05:00
David Teigland
d9e8895a96 Allow dm-integrity to be used for raid images
dm-integrity stores checksums of the data written to an
LV, and returns an error if data read from the LV does
not match the previously saved checksum.  When used on
raid images, dm-raid will correct the error by reading
the block from another image, and the device user sees
no error.  The integrity metadata (checksums) are stored
on an internal LV allocated by lvm for each linear image.
The internal LV is allocated on the same PV as the image.

Create a raid LV with an integrity layer over each
raid image (for raid levels 1,4,5,6,10):

lvcreate --type raidN --raidintegrity y [options]

Add an integrity layer to images of an existing raid LV:

lvconvert --raidintegrity y LV

Remove the integrity layer from images of a raid LV:

lvconvert --raidintegrity n LV

Settings

Use --raidintegritymode journal|bitmap (journal is default)
to configure the method used by dm-integrity to ensure
crash consistency.

Initialization

When integrity is added to an LV, the kernel needs to
initialize the integrity metadata/checksums for all blocks
in the LV.  The data corruption checking performed by
dm-integrity will only operate on areas of the LV that
are already initialized.  The progress of integrity
initialization is reported by the "syncpercent" LV
reporting field (and under the Cpy%Sync lvs column.)

Example: create a raid1 LV with integrity:

$ lvcreate --type raid1 -m1 --raidintegrity y -n rr -L1G foo
  Creating integrity metadata LV rr_rimage_0_imeta with size 12.00 MiB.
  Logical volume "rr_rimage_0_imeta" created.
  Creating integrity metadata LV rr_rimage_1_imeta with size 12.00 MiB.
  Logical volume "rr_rimage_1_imeta" created.
  Logical volume "rr" created.
$ lvs -a foo
  LV                  VG  Attr       LSize  Origin              Cpy%Sync
  rr                  foo rwi-a-r---  1.00g                     4.93
  [rr_rimage_0]       foo gwi-aor---  1.00g [rr_rimage_0_iorig] 41.02
  [rr_rimage_0_imeta] foo ewi-ao---- 12.00m
  [rr_rimage_0_iorig] foo -wi-ao----  1.00g
  [rr_rimage_1]       foo gwi-aor---  1.00g [rr_rimage_1_iorig] 39.45
  [rr_rimage_1_imeta] foo ewi-ao---- 12.00m
  [rr_rimage_1_iorig] foo -wi-ao----  1.00g
  [rr_rmeta_0]        foo ewi-aor---  4.00m
  [rr_rmeta_1]        foo ewi-aor---  4.00m
2020-04-15 12:10:32 -05:00
David Teigland
b6b4ad8e28 move pv_list code into lib 2020-04-13 10:04:14 -05:00
Peter Rajnoha
0dd905c959 blkdeactivate: add support for VDO in blkdeactivate script
Make it possible to tear down VDO volumes with blkdeactivate if VDO is
part of a device stack (and if VDO binary is installed). Also, support
optional -o|--vdooptions configfile=file.
2020-04-09 15:29:29 +02:00
Zdenek Kabelac
e10f20bc23 WHATS_NEWS: update 2020-04-08 15:37:24 +02:00
Zdenek Kabelac
3dd11d9ea8 test: repair of thin-pool used by foreign apps 2020-04-08 15:37:24 +02:00
Zdenek Kabelac
98e33ee3fb lvconvert: no validation for thin-pools not used by lvm2
lvm2 supports thin-pool to be later used by other tools doing
virtual volumes themself (i.e. docker) - in this case we
shall not validate transaction Id - is this is used by
other tools and lvm2 keeps value 0 - so the transationId
validation need to be skipped in this case.
2020-04-08 15:22:44 +02:00
Marian Csontos
06cbe3cfc6 post-release 2020-03-26 12:22:09 +01:00
Marian Csontos
e1c2b41265 pre-release 2020-03-26 12:21:16 +01:00
Zdenek Kabelac
caff31df19 vdo: make vdopool wrapping device is read-only
When vdopool is activated standalone - we use a wrapping linear device
to hold actual vdo device active - for this we can set-up read-only
device to ensure there cannot be made write through this device to
actual pool device.
2020-03-23 17:13:26 +01:00
Marian Csontos
e6b93dc24e test: Fix previous commit 2020-03-18 18:03:12 +01:00
Marian Csontos
fc32787c1b test: Can not attach writecache to active volume 2020-03-18 14:35:58 +01:00
David Teigland
957904933b reduce device path error messsages
When /dev entries or sysfs entries are changing
due to concurrent lvm commands, it can cause
warning/error messages about missing paths.
2020-03-12 10:18:51 -05:00
David Teigland
fbdcc45255 man: lvm2-activation-generator fix vgchange comment
generated services use vgchange -aay (not -ay)
2020-03-10 14:41:51 -05:00
David Teigland
dd0fdd846d lvmlockd: use transient LV lock when creating snapshot
Creating a snapshot was using a persistent LV lock
on the origin, so if the origin LV was inactive at
the time of the snapshot the LV lock would remain.
(Running lvchange -an on the inactive LV would
clear the LV lock.)  Use a transient LV lock so it
will be dropped if it was not locked previously.
2020-03-09 12:25:26 -05:00
David Teigland
a5b1b52903 writecache: require inactive LV to attach
Prevent attaching writecache to an active LV until
we can determine the block size of the fs on the LV,
and use that to enforce an appropriate writecache
block size.  Changing the block size under a mounted
fs can cause panic/corruption.
2020-03-09 11:18:10 -05:00
Zdenek Kabelac
c9526e859e WHATS_NEW_DM: update 2020-03-05 17:38:55 +01:00
Zdenek Kabelac
f439716b75 container_of: use offsetof from stddef
Use standardized offsetof() macro from stddef.
Helps to build valid code with latest gcc10 with -O2.
2020-03-05 17:38:55 +01:00
Zdenek Kabelac
b3fa71fbd8 libdm: fix dm_list pointer arithmentic for new gcc 10 optimization 2020-03-05 17:38:55 +01:00
Zdenek Kabelac
212cf8efbd dmeventd: enhance time waiting loop
dmeventd is 'scanning' statuses in loop (most usually in 10sec
intervals) - and meanwhile it sleeps within:
pthread_cond_timedwait()

However this function call tends to wakeup sometimes a short amount of
time sooner - and our code still believe the 'right time' has not yet
arrived and basically for a moment 'busy-looped' on calling this
function - so for systems with 'clock_gettime()' present we obtain
time and we go 10ms to the future second - this avoids unneeded
repeated invocation of our time scheduling loop.

TODO: monitoring during 1 hour 'time-change'...
2020-03-05 17:38:55 +01:00
David Teigland
caecbcbeac pvck: use dm_config_parse_without_dup_node_check
instead of dm_config_parse.  Some strange case could
cause dm_config_parse to print duplicate warnings about
all the metadata fileds.
2020-03-04 11:32:13 -06:00
David Teigland
4b5bfa779a tests: reduce sizes in pvck-dump and improve checks
Smaller devs can be used so tests can be run on small vms.
Improve checks.
2020-03-04 11:30:50 -06:00
David Teigland
f6667f94cb tests: pvck dump from larger metadata areas 2020-03-03 13:47:07 -06:00
David Teigland
1b711b955d pvck: allow dump from file 2020-03-03 13:47:07 -06:00
David Teigland
f140620043 pvck: fix reading large mda1
When mda_size is larger than io_memory_size, reading
the entire mda fails unless the previous read of the
label has been invalidated.
2020-03-03 13:47:07 -06:00
David Teigland
c6746181a3 pvck: improve mda_offset mda_size choices
Attempt to calculate an offset or size if one only
value was specified in the settings.

Use header values when available.
2020-03-03 13:47:07 -06:00
David Teigland
1b79673845 pvck: print longer command description 2020-03-03 13:47:07 -06:00
David Teigland
b19b7b6111 pvck: ensure text lines are terminated 2020-03-03 13:47:07 -06:00
David Teigland
f50e7ce76c hints: free hint list in error exit path 2020-03-03 12:25:34 -06:00
Jonathan Brassow
c392ccaa47 man: lvmcache raid1 references 2020-02-27 11:33:55 -06:00
Zdenek Kabelac
9532bb577a tests: validate vdo slab_size
New vdoformat can print this size - so check we pass proper bit count
matching preset value.
2020-02-26 13:29:21 +01:00
Zdenek Kabelac
d02d7bc560 vdo: fix slab size bits calculation
When formating VDO volume, the calculated amound of bits
for 'vdoformat --slab-bits' parameter was shifted by 2 bits
(calculated size was making 2MiB vdo_slab_size_mb value appear like if
user would be specifying only 512KiB)

Fixed by properly converting internal size_mb value to KiB.
2020-02-25 17:43:16 +01:00
David Teigland
84eab461c8 writecache: check watermark value 2020-02-25 10:34:30 -06:00
David Teigland
81d0333067 writecache: allow removing wcorig lv
like removing corig
2020-02-21 12:41:52 -06:00
David Teigland
2284f845b0 writecache: fix watermark error message 2020-02-21 08:13:32 -06:00
David Teigland
8153c5f1e6 writecache: working real dm uuid suffix for wcorig lv 2020-02-20 17:13:43 -06:00
David Teigland
4829f27b76 writecache: drop real dm suffix
fixes the problem of adding writecache to an active LV
2020-02-17 13:07:06 -06:00
613 changed files with 51190 additions and 28531 deletions

7
.gitignore vendored
View File

@@ -30,14 +30,19 @@ make.tmpl
/config.log
/config.status
/configure.scan
/cscope.out
/cscope.*
/html/
/python/
/reports/
/tags
/tmp/
coverity/coverity_model.xml
# gcov files:
*.gcda
*.gcno
tools/man-generator
tools/man-generator.c

View File

@@ -18,7 +18,7 @@ top_builddir = @top_builddir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
SUBDIRS = conf daemons include lib libdaemon libdm man scripts tools
SUBDIRS = libdm conf daemons include lib libdaemon man scripts tools
ifeq ("@UDEV_RULES@", "yes")
SUBDIRS += udev
@@ -47,8 +47,6 @@ include $(top_srcdir)/base/Makefile
include $(top_srcdir)/device_mapper/Makefile
include $(top_srcdir)/test/unit/Makefile
libdm: include
libdaemon: include
lib: libdaemon $(BASE_TARGET) $(DEVICE_MAPPER_TARGET)
daemons: lib libdaemon tools
scripts: lib
@@ -56,16 +54,13 @@ tools: lib libdaemon
po: tools daemons
man: tools
all_man: tools
scripts: libdm
test: tools daemons
unit-test run-unit-test: test
lib.device-mapper: include.device-mapper
libdm.device-mapper: include.device-mapper
daemons.device-mapper: libdm.device-mapper
tools.device-mapper: libdm.device-mapper
scripts.device-mapper: include.device-mapper
device-mapper: tools.device-mapper daemons.device-mapper man.device-mapper
device_mapper: device-mapper
ifeq ("@INTL@", "yes")
lib.pofile: include.pofile
@@ -81,9 +76,10 @@ daemons.cflow: tools.cflow
cflow: include.cflow
endif
CSCOPE_DIRS = base daemons device_mapper include lib libdaemon scripts tools libdm test
ifneq ("@CSCOPE_CMD@", "")
cscope.out:
@CSCOPE_CMD@ -b -R -s$(top_srcdir)
@CSCOPE_CMD@ -b -R $(patsubst %,-s%,$(addprefix $(srcdir)/,$(CSCOPE_DIRS)))
all: cscope.out
endif
DISTCLEAN_TARGETS += cscope.out
@@ -116,11 +112,11 @@ rpm: dist
$(LN_S) -f $(abs_top_srcdir)/spec/packages.inc $(rpmbuilddir)/SOURCES
DM_VER=$$(cut -d- -f1 $(top_srcdir)/VERSION_DM);\
GIT_VER=$$(cd $(top_srcdir); git describe | cut -d- --output-delimiter=. -f2,3 || echo 0);\
sed -e "s,\(device_mapper_version\) [0-9.]*$$,\1 $$DM_VER," \
$(SED) -e "s,\(device_mapper_version\) [0-9.]*$$,\1 $$DM_VER," \
-e "s,^\(Version:[^0-9%]*\)[0-9.]*$$,\1 $(LVM_VER)," \
-e "s,^\(Release:[^0-9%]*\)[0-9.]\+,\1 $$GIT_VER," \
$(top_srcdir)/spec/source.inc >$(rpmbuilddir)/SOURCES/source.inc
rpmbuild -v --define "_topdir $(rpmbuilddir)" -ba $(top_srcdir)/spec/lvm2.spec
V=$(V) rpmbuild -v --define "_topdir $(rpmbuilddir)" -ba $(top_srcdir)/spec/lvm2.spec
generate: conf.generate man.generate
$(MAKE) -C conf generate
@@ -154,6 +150,31 @@ install_all_man:
install_tmpfiles_configuration:
$(MAKE) -C scripts install_tmpfiles_configuration
help:
@echo -e "\nAvailable targets:"
@echo " all Default target."
@echo " all_man Build all man pages with generators."
@echo " clean Remove all compile files."
@echo " device-mapper Device mapper part of lvm2."
@echo " dist Generate distributable file."
@echo " distclean Remove all build files."
@echo " generate Generate man pages for sources."
@echo " help Display callable targets."
@echo " install Install all files."
@echo " install_all_man Install all man pages."
@echo " install_cluster Install cmirrord."
@echo " install_device-mapper Install device mapper files."
@echo " install_initscripts Install initialization scripts."
@echo " install_lvm2 Install lvm2 files."
@echo " install_systemd_units Install systemd units."
@echo " lcov Generate lcov output."
@echo " lcov-dated Generate lcov with timedate suffix."
@echo " lcov-reset Reset lcov counters"
@echo " man Build man pages."
@echo " rpm Build rpm."
@echo " run-unit-test Run unit tests."
@echo " tags Generate c/etags."
ifneq ("$(LCOV)", "")
.PHONY: lcov-reset lcov lcov-dated
@@ -183,8 +204,8 @@ endif
ifneq ($(shell which ctags 2>/dev/null),)
.PHONY: tags
tags:
test -z "$(shell find $(top_srcdir) -type f -name '*.[ch]' -newer tags 2>/dev/null | head -1)" || $(RM) tags
test -f tags || find $(top_srcdir) -maxdepth 5 -type f -name '*.[ch]' -exec ctags -a '{}' +
test -z "$(shell find $(addprefix $(top_srcdir)/,$(CSCOPE_DIRS)) -type f -name '*.[ch]' -newer tags 2>/dev/null | head -1)" || $(RM) tags
test -f tags || find $(addprefix $(top_srcdir)/,$(CSCOPE_DIRS)) -maxdepth 5 -type f -name '*.[ch]' -exec ctags -a '{}' +
CLEAN_TARGETS += tags
endif

11
README
View File

@@ -1,7 +1,6 @@
This tree contains the LVM2 and device-mapper tools and libraries.
This is development branch, for stable 2.02 release see 2018-06-01-stable
branch.
This is development branch, for stable 2.02 release see stable-2.02 branch.
For more information about LVM2 read the changelog in the WHATS_NEW file.
Installation instructions are in INSTALL.
@@ -10,7 +9,6 @@ There is no warranty - see COPYING and COPYING.LIB.
Tarballs are available from:
ftp://sourceware.org/pub/lvm2/
ftp://sources.redhat.com/pub/lvm2/
https://github.com/lvmteam/lvm2/releases
The source code is stored in git:
@@ -45,6 +43,9 @@ Report upstream bugs at:
or open issues at:
https://github.com/lvmteam/lvm2/issues
The source code repository used until 7th June 2012 is accessible here:
http://sources.redhat.com/cgi-bin/cvsweb.cgi/LVM2/?cvsroot=lvm2.
The source code repository used until 7th June 2012 is accessible using CVS:
cvs -d :pserver:cvs@sourceware.org:/cvs/lvm2 login cvs
cvs -d :pserver:cvs@sourceware.org:/cvs/lvm2 checkout LVM2
The password is cvs.

View File

@@ -1 +1 @@
2.03.09(2)-git (2020-02-11)
2.03.16(2)-git (2022-02-07)

View File

@@ -1 +1 @@
1.02.171-git (2020-02-11)
1.02.185-git (2022-02-07)

166
WHATS_NEW
View File

@@ -1,5 +1,166 @@
Version 2.03.09 -
Version 2.03.16 -
====================================
Version 2.03.15 - 07th February 2022
====================================
Remove service based autoactivation. global/event_activation = 0 is NOOP.
Improve support for metadata profiles for --type writecache.
Use cache or active DM device when available with new kernels.
Introduce function to utilize UUIDs from DM_DEVICE_LIST.
Increase some hash table size to better support large device sets.
Version 2.03.14 - 20th October 2021
===================================
Device scanning is skipping directories on different filesystems.
Print info message with too many or too large archived files.
Reduce metadata readings during scanning phase.
Optimize computation of crc32 check sum with multiple PVs.
Enhance recover path on cache creation failure.
Filter out unsupported MQ/SMQ cache policy setting.
Fix memleak in mpath filter.
Support newer location for VDO statistics.
Add support for VDO async-unsafe write policy.
Improve lvm_import_vdo script.
Support VDO LV with lvcreate -ky.
Fix lvconvert for VDO LV bigger then 2T.
Create VDO LVs automatically without zeroing.
Rename vdoimport to lvm_import_vdo.
Version 2.03.13 - 11th August 2021
==================================
Changes in udev support:
- obtain_device_list_from_udev defaults to 0.
- see devices/external_device_info_source,
devices/obtain_device_list_from_udev, and devices/multipath_wwids_file help
in lvm.conf
Fix devices file handling of loop with deleted backing file.
Fix devices file handling of scsi_debug WWIDs.
Fix many static analysis issues.
Support --poolmetadataspare with vgsplit and vgmerge.
Fix detection of active components of external origin volume.
Add vdoimport tool to support conversion of VDO volumes.
Support configurable allocation/vdo_pool_header_size.
Fix handling of lvconvert --type vdo-pool --virtualsize.
Simplified handling of archive() and backup() internal calls.
Add 'idm' locking type for IDM lock manager.
Fix load of kvdo target when it is not present in memory (2.03.12).
Version 2.03.12 - 07th May 2021
===============================
Allow attaching cache to thin data volume.
Fix memleak when generating list of outdated pvs.
Better hyphenation usage in man pages.
Replace use of deprecated security_context_t with char*.
Configure supports AIO_LIBS and AIO_CFLAGS.
Improve build process for static builds.
New --setautoactivation option to modify LV or VG auto activation.
New metadata based autoactivation property for LVs and VGs.
Improve signal handling with lvmpolld.
Signal handler can interrupt command also for SIGTERM.
Lvreduce --yes support.
Add configure option --with/out-symvers for non-glibc builds.
Report error when the filesystem is missing on fsadm resized volume.
Handle better blockdev with --getsize64 support for fsadm.
Do not include editline/history.h when using editline library.
Support error and zero segtype for thin-pool data for testing.
Support mixed extension for striped, error and zero segtypes.
Support resize also for stacked virtual volumes.
Skip dm-zero devices just like with dm-error target.
Reduce ioctl() calls when checking target status.
Merge polling does not fail, when LV is found to be already merged.
Poll volumes with at least 100ms delays.
Do not flush dm cache when cached LV is going to be removed.
New lvmlockctl_kill_command configuration option.
Support interruption while waiting on device close before deactivation.
Flush thin-pool messages before removing more thin volumes.
Improve hash function with less collisions and make it faster.
Reduce ioctl count when deactivating volumes.
Reduce number of metadata parsing.
Enhance performance of lvremove and vgremove commands.
Support interruption when taking archive and backup.
Accelerate large lvremoves.
Speedup search for cached device nodes.
Speedup command initialization.
Add devices file feature, off by default for now.
Support extension of writecached volumes.
Fix problem with unbound variable usage within fsadm.
Fix IMSM MD RAID detection on 4k devices.
Check for presence of VDO target before starting any conversion.
Support metatadata profiles with volume VDO pool conversions.
Support -Zn for conversion of already formated VDO pools.
Avoid removing LVs on error path of lvconvert during creation volumes.
Fix crashing lvdisplay when thin volume was waiting for merge.
Support option --errorwhenfull when converting volume to thin-pool.
Improve thin-performance profile support conversion to thin-pool.
Add workaround to avoid read of internal 'converted' devices.
Prohibit merging snapshot into the read-only thick snapshot origin.
Restore support for flipping rw/r permissions for thin snapshot origin.
Support resize of cached volumes.
Disable autoactivation with global/event_activation=0.
Check if lvcreate passes read_only_volume_list with tags and skips zeroing.
Allocation prints better error when metadata cannot fit on a single PV.
Pvmove can better resolve full thin-pool tree move.
Limit pool metadata spare to 16GiB.
Improves conversion and allocation of pool metadata.
Support thin pool metadata 15.88GiB, adds 64MiB, thin_pool_crop_metadata=0.
Enhance lvdisplay to report raid available/partial.
Support online rename of VDO pools.
Improve removal of pmspare when last pool is removed.
Fix problem with wiping of converted LVs.
Fix memleak in scanning (2.03.11).
Fix corner case allocation for thin-pools.
Version 2.03.11 - 08th January 2021
===================================
Fix pvck handling MDA at offset different from 4096.
Partial or degraded activation of writecache is not allowed.
Enhance error handling for fsadm and handle correct fsck result.
Dmeventd lvm plugin ignores higher reserved_stack lvm.conf values.
Support using BLKZEROOUT for clearing devices.
Support interruption when wipping LVs.
Support interruption for bcache waiting.
Fix bcache when device has too many failing writes.
Fix bcache waiting for IO completion with failing disks.
Configure use own python path name order to prefer using python3.
Add configure --enable-editline support as an alternative to readline.
Enhance reporting and error handling when creating thin volumes.
Enable vgsplit for VDO volumes.
Lvextend of vdo pool volumes ensure at least 1 new VDO slab is added.
Use revert_lv() on reload error path after vg_revert().
Configure --with-integrity enabled.
Restore lost signal blocking while VG lock is held.
Improve estimation of needed extents when creating thin-pool.
Use extra 1% when resizing thin-pool metadata LV with --use-policy.
Enhance --use-policy percentage rounding.
Configure --with-vdo and --with-writecache as internal segments.
Improving VDO man page examples.
Allow pvmove of writecache origin.
Report integrity fields.
Integrity volumes defaults to journal mode.
Switch code base to use flexible array syntax.
Fix 64bit math when calculation cachevol size.
Preserve uint32_t for seqno handling.
Switch from mmap to plain read when loading regular files.
Update lvmvdo man page and better explain DISCARD usage.
Version 2.03.10 - 09th August 2020
==================================
Add writecache and integrity support to lvmdbusd.
Generate unique cachevol name when default required from lvcreate.
Converting RAID1 volume to one with same number of legs now succeeds with a
warning.
Fix conversion to raid from striped lagging type.
Fix conversion to 'mirrored' mirror log with larger regionsize.
Zero pool metadata on allocation (disable with allocation/zero_metadata=0).
Failure in zeroing or wiping will fail command (bypass with -Zn, -Wn).
Add lvcreate of new cache or writecache lv with single command.
Fix running out of free buffers for async writing for larger writes.
Add integrity with raid capability.
Fix support for lvconvert --repair used by foreign apps (i.e. Docker).
Version 2.03.09 - 26th March 2020
=================================
Fix formating of vdopool (vdo_slab_size_mb was smaller by 2 bits).
Fix showing of a dm kernel error when uncaching a volume with cachevol.
Version 2.03.08 - 11th February 2020
@@ -147,7 +308,6 @@ Version 2.03.00 - 10th October 2018
Remove clvmd
Remove lvmlib (api)
Remove lvmetad
lvconvert: provide possible layouts between linear and striped/raid
Use versionsort to fix archive file expiry beyond 100000 files.
Version 2.02.178-rc1 - 24th May 2018
@@ -1667,7 +1827,7 @@ Version 2.02.105 - 20th January 2014
Allow lvmetad to reuse stale socket.
Only unlink lvmetad socket on error if created by the same process.
Append missing newline to lvmetad missing socket path error message.
Check for non-zero aligment in _text_pv_add_metadata_area() to not div by 0.
Check for non-zero alignment in _text_pv_add_metadata_area() to not div by 0.
Add allocation/use_blkid_wiping to lvm.conf to enable blkid wiping.
Enable blkid_wiping by default if the blkid library is present.
Add configure --disable-blkid_wiping to disable libblkid signature detection.

View File

@@ -1,6 +1,39 @@
Version 1.02.171 -
Version 1.02.185 -
=====================================
Version 1.02.183 - 07th February 2022
=====================================
Unmangle UUIDs for DM_DEVICE_LIST ioctl.
Version 1.02.181 - 20th October 2021
====================================
Add IMA support with 'dmsetup measure' command.
Add defines DM_NAME_LIST_FLAG_HAS_UUID, DM_NAME_LIST_FLAG_DOESNT_HAVE_UUID.
Enhance tracking of activated devices when preloading dm tree.
Fix bug in construction of cache table line (regression from 1.02.159).
Version 1.02.179 - 11th August 2021
===================================
Version 1.02.177 - 07th May 2021
================================
Configure proceeds without libaio to allow build of device-mapper only.
Fix symbol versioning build with -O2 -flto.
Add dm_tree_node_add_thin_pool_target_v1 with crop_metadata support.
Version 1.02.175 - 08th January 2021
====================================
Version 1.02.173 - 09th August 2020
===================================
Add support for VDO in blkdeactivate script.
Version 1.02.171 - 26th March 2020
==================================
Try to remove all created devices on dm preload tree error path.
Fix dm_list interators with gcc 10 optimization (-ftree-pta).
Dmeventd handles timer without looping on short intervals.
Version 1.02.169 - 11th February 2020
=====================================
Enhance error messages for device creation.
@@ -541,7 +574,7 @@ Version 1.02.86 - 23rd June 2014
Add DM_REPORT_FIELD_TYPE_STRING_LIST: separate string and string list fields.
Add dm_str_list to libdevmapper for string list type definition and its reuse.
Add dmsetup -S/--select to define selection criteria for dmsetup reports.
Add dm_report_init_with_selection to intialize report with selection criteria.
Add dm_report_init_with_selection to initialize report with selection criteria.
Add DM_REPORT_FIELD_TYPE_SIZE: separate number and size reporting fields.
Use RemoveOnStop for dm-event.socket systemd unit.
Document env var 'DM_DEFAULT_NAME_MANGLING_MODE' in dmsetup man page.

26
aclocal.m4 vendored
View File

@@ -1,6 +1,6 @@
# generated automatically by aclocal 1.15.1 -*- Autoconf -*-
# generated automatically by aclocal 1.16.2 -*- Autoconf -*-
# Copyright (C) 1996-2017 Free Software Foundation, Inc.
# Copyright (C) 1996-2020 Free Software Foundation, Inc.
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -413,7 +413,7 @@ AS_IF([test "$AS_TR_SH([with_]m4_tolower([$1]))" = "yes"],
[AC_DEFINE([HAVE_][$1], 1, [Enable ]m4_tolower([$1])[ support])])
])dnl PKG_HAVE_DEFINE_WITH_MODULES
# Copyright (C) 1999-2017 Free Software Foundation, Inc.
# Copyright (C) 1999-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -446,10 +446,12 @@ AC_DEFUN([AM_PATH_PYTHON],
[
dnl Find a Python interpreter. Python versions prior to 2.0 are not
dnl supported. (2.0 was released on October 16, 2000).
dnl FIXME: Remove the need to hard-code Python versions here.
m4_define_default([_AM_PYTHON_INTERPRETER_LIST],
[python python2 python3 python3.5 python3.4 python3.3 python3.2 python3.1 python3.0 python2.7 dnl
python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python2.0])
[python python2 python3 dnl
python3.9 python3.8 python3.7 python3.6 python3.5 python3.4 python3.3 dnl
python3.2 python3.1 python3.0 dnl
python2.7 python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 dnl
python2.0])
AC_ARG_VAR([PYTHON], [the Python interpreter])
@@ -494,12 +496,14 @@ AC_DEFUN([AM_PATH_PYTHON],
m4_default([$3], [AC_MSG_ERROR([no suitable Python interpreter found])])
else
dnl Query Python for its version number. Getting [:3] seems to be
dnl the best way to do this; it's what "site.py" does in the standard
dnl library.
dnl Query Python for its version number. Although site.py simply uses
dnl sys.version[:3], printing that failed with Python 3.10, since the
dnl trailing zero was eliminated. So now we output just the major
dnl and minor version numbers, as numbers. Apparently the tertiary
dnl version is not of interest.
AC_CACHE_CHECK([for $am_display_PYTHON version], [am_cv_python_version],
[am_cv_python_version=`$PYTHON -c "import sys; sys.stdout.write(sys.version[[:3]])"`])
[am_cv_python_version=`$PYTHON -c "import sys; print('%u.%u' % sys.version_info[[:2]])"`])
AC_SUBST([PYTHON_VERSION], [$am_cv_python_version])
dnl Use the values of $prefix and $exec_prefix for the corresponding
@@ -649,7 +653,7 @@ for i in list(range(0, 4)): minverhex = (minverhex << 8) + minver[[i]]
sys.exit(sys.hexversion < minverhex)"
AS_IF([AM_RUN_LOG([$1 -c "$prog"])], [$3], [$4])])
# Copyright (C) 2001-2017 Free Software Foundation, Inc.
# Copyright (C) 2001-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,

View File

@@ -22,17 +22,26 @@ struct dm_hash_node {
void *data;
unsigned data_len;
unsigned keylen;
unsigned hash;
char key[0];
};
struct dm_hash_table {
unsigned num_nodes;
unsigned num_slots;
unsigned num_hint;
unsigned mask_slots; /* (slots - 1) -> used as hash mask */
unsigned collisions; /* Collissions of hash keys */
unsigned search; /* How many keys were searched */
unsigned found; /* How many nodes were found */
unsigned same_hash; /* Was there a colision with same masked hash and len ? */
struct dm_hash_node **slots;
};
/* Permutation of the Integers 0 through 255 */
static unsigned char _nums[] = {
#if 0 /* TO BE REMOVED */
static unsigned _hash(const void *key, unsigned len)
{
/* Permutation of the Integers 0 through 255 */
static unsigned char _nums[] = {
1, 14, 110, 25, 97, 174, 132, 119, 138, 170, 125, 118, 27, 233, 140, 51,
87, 197, 177, 107, 234, 169, 56, 68, 30, 7, 173, 73, 188, 40, 36, 65,
49, 213, 104, 190, 57, 211, 148, 223, 48, 115, 15, 2, 67, 186, 210, 28,
@@ -57,29 +66,16 @@ static unsigned char _nums[] = {
44, 38, 31, 149, 135, 0, 216, 52, 63, 23, 37, 69, 39, 117, 146, 184,
163, 200, 222, 235, 248, 243, 219, 10, 152, 131, 123, 229, 203, 76, 120,
209
};
};
static struct dm_hash_node *_create_node(const char *str, unsigned len)
{
struct dm_hash_node *n = malloc(sizeof(*n) + len);
if (n) {
memcpy(n->key, str, len);
n->keylen = len;
}
return n;
}
static unsigned long _hash(const char *str, unsigned len)
{
unsigned long h = 0, g;
const uint8_t *str = key;
unsigned h = 0, g;
unsigned i;
for (i = 0; i < len; i++) {
h <<= 4;
h += _nums[(unsigned char) *str++];
g = h & ((unsigned long) 0xf << 16u);
h += _nums[*str++];
g = h & ((unsigned) 0xf << 16u);
if (g) {
h ^= g >> 16u;
h ^= g >> 5u;
@@ -89,30 +85,99 @@ static unsigned long _hash(const char *str, unsigned len)
return h;
}
/* In-kernel DM hashing, still lots of collisions */
static unsigned _hash_in_kernel(const char *key, unsigned len)
{
const unsigned char *str = (unsigned char *)key;
const unsigned hash_mult = 2654435387U;
unsigned hash = 0, i;
for (i = 0; i < len; ++i)
hash = (hash + str[i]) * hash_mult;
return hash;
}
#endif
#undef get16bits
#if (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)))
#define get16bits(d) (*((const uint16_t *) (d)))
#endif
#if !defined (get16bits)
#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)\
+(uint32_t)(((const uint8_t *)(d))[0]) )
#endif
/*
* Adapted Bob Jenkins hash to read by 2 bytes if possible.
* https://secure.wikimedia.org/wikipedia/en/wiki/Jenkins_hash_function
*
* Reduces amount of hash collisions
*/
static unsigned _hash(const void *key, unsigned len)
{
const uint8_t *str = (uint8_t*) key;
unsigned hash = 0, i;
unsigned sz = len / 2;
for(i = 0; i < sz; ++i) {
hash += get16bits(str + 2 * i);
hash += (hash << 10);
hash ^= (hash >> 6);
}
if (len & 1) {
hash += str[len - 1];
hash += (hash << 10);
hash ^= (hash >> 6);
}
hash += (hash << 3);
hash ^= (hash >> 11);
hash += (hash << 15);
return hash;
}
static struct dm_hash_node *_create_node(const void *key, unsigned len)
{
struct dm_hash_node *n = malloc(sizeof(*n) + len);
if (n) {
memcpy(n->key, key, len);
n->keylen = len;
}
return n;
}
struct dm_hash_table *dm_hash_create(unsigned size_hint)
{
size_t len;
unsigned new_size = 16u;
struct dm_hash_table *hc = zalloc(sizeof(*hc));
if (!hc)
return_0;
if (!hc) {
log_error("Failed to allocate memory for hash.");
return 0;
}
hc->num_hint = size_hint;
/* round size hint up to a power of two */
while (new_size < size_hint)
new_size = new_size << 1;
hc->num_slots = new_size;
hc->mask_slots = new_size - 1;
len = sizeof(*(hc->slots)) * new_size;
if (!(hc->slots = zalloc(len)))
goto_bad;
if (!(hc->slots = zalloc(len))) {
free(hc);
log_error("Failed to allocate slots for hash.");
return 0;
}
return hc;
bad:
free(hc->slots);
free(hc);
return 0;
}
static void _free_nodes(struct dm_hash_table *t)
@@ -120,7 +185,16 @@ static void _free_nodes(struct dm_hash_table *t)
struct dm_hash_node *c, *n;
unsigned i;
for (i = 0; i < t->num_slots; i++)
#ifdef DEBUG
log_debug("Free hash hint:%d slots:%d nodes:%d (s:%d f:%d c:%d h:%d)",
t->num_hint, t->mask_slots + 1, t->num_nodes,
t->search, t->found, t->collisions, t->same_hash);
#endif
if (!t->num_nodes)
return;
for (i = 0; i <= t->mask_slots; i++)
for (c = t->slots[i]; c; c = n) {
n = c->next;
free(c);
@@ -134,23 +208,32 @@ void dm_hash_destroy(struct dm_hash_table *t)
free(t);
}
static struct dm_hash_node **_find(struct dm_hash_table *t, const void *key,
uint32_t len)
static struct dm_hash_node **_findh(struct dm_hash_table *t, const void *key,
uint32_t len, unsigned hash)
{
unsigned h = _hash(key, len) & (t->num_slots - 1);
struct dm_hash_node **c;
for (c = &t->slots[h]; *c; c = &((*c)->next)) {
if ((*c)->keylen != len)
continue;
if (!memcmp(key, (*c)->key, len))
break;
++t->search;
for (c = &t->slots[hash & t->mask_slots]; *c; c = &((*c)->next)) {
if ((*c)->keylen == len && (*c)->hash == hash) {
if (!memcmp(key, (*c)->key, len)) {
++t->found;
break;
}
++t->same_hash;
}
++t->collisions;
}
return c;
}
static struct dm_hash_node **_find(struct dm_hash_table *t, const void *key,
uint32_t len)
{
return _findh(t, key, len, _hash(key, len));
}
void *dm_hash_lookup_binary(struct dm_hash_table *t, const void *key,
uint32_t len)
{
@@ -162,7 +245,8 @@ void *dm_hash_lookup_binary(struct dm_hash_table *t, const void *key,
int dm_hash_insert_binary(struct dm_hash_table *t, const void *key,
uint32_t len, void *data)
{
struct dm_hash_node **c = _find(t, key, len);
unsigned hash = _hash(key, len);
struct dm_hash_node **c = _findh(t, key, len, hash);
if (*c)
(*c)->data = data;
@@ -173,6 +257,7 @@ int dm_hash_insert_binary(struct dm_hash_table *t, const void *key,
return 0;
n->data = data;
n->hash = hash;
n->next = 0;
*c = n;
t->num_nodes++;
@@ -216,7 +301,7 @@ static struct dm_hash_node **_find_str_with_val(struct dm_hash_table *t,
struct dm_hash_node **c;
unsigned h;
h = _hash(key, len) & (t->num_slots - 1);
h = _hash(key, len) & t->mask_slots;
for (c = &t->slots[h]; *c; c = &((*c)->next)) {
if ((*c)->keylen != len)
@@ -247,7 +332,7 @@ int dm_hash_insert_allow_multiple(struct dm_hash_table *t, const char *key,
n->data = (void *)val;
n->data_len = val_len;
h = _hash(key, len) & (t->num_slots - 1);
h = _hash(key, len) & t->mask_slots;
first = t->slots[h];
@@ -315,7 +400,7 @@ void *dm_hash_lookup_with_count(struct dm_hash_table *t, const char *key, int *c
*count = 0;
h = _hash(key, len) & (t->num_slots - 1);
h = _hash(key, len) & t->mask_slots;
for (c = &t->slots[h]; *c; c = &((*c)->next)) {
if ((*c)->keylen != len)
@@ -344,7 +429,7 @@ void dm_hash_iter(struct dm_hash_table *t, dm_hash_iterate_fn f)
struct dm_hash_node *c, *n;
unsigned i;
for (i = 0; i < t->num_slots; i++)
for (i = 0; i <= t->mask_slots; i++)
for (c = t->slots[i]; c; c = n) {
n = c->next;
f(c->data);
@@ -354,8 +439,8 @@ void dm_hash_iter(struct dm_hash_table *t, dm_hash_iterate_fn f)
void dm_hash_wipe(struct dm_hash_table *t)
{
_free_nodes(t);
memset(t->slots, 0, sizeof(struct dm_hash_node *) * t->num_slots);
t->num_nodes = 0u;
memset(t->slots, 0, sizeof(struct dm_hash_node *) * (t->mask_slots + 1));
t->num_nodes = t->collisions = t->search = t->same_hash = 0u;
}
char *dm_hash_get_key(struct dm_hash_table *t __attribute__((unused)),
@@ -375,7 +460,7 @@ static struct dm_hash_node *_next_slot(struct dm_hash_table *t, unsigned s)
struct dm_hash_node *c = NULL;
unsigned i;
for (i = s; i < t->num_slots && !c; i++)
for (i = s; i <= t->mask_slots && !c; i++)
c = t->slots[i];
return c;
@@ -388,7 +473,5 @@ struct dm_hash_node *dm_hash_get_first(struct dm_hash_table *t)
struct dm_hash_node *dm_hash_get_next(struct dm_hash_table *t, struct dm_hash_node *n)
{
unsigned h = _hash(n->key, n->keylen) & (t->num_slots - 1);
return n->next ? n->next : _next_slot(t, h + 1);
return n->next ? n->next : _next_slot(t, (n->hash & t->mask_slots) + 1);
}

View File

@@ -1,6 +1,8 @@
#ifndef BASE_DATA_STRUCT_LIST_H
#define BASE_DATA_STRUCT_LIST_H
#include "base/memory/container_of.h"
//----------------------------------------------------------------
/*
@@ -98,7 +100,7 @@ struct dm_list *dm_list_next(const struct dm_list *head, const struct dm_list *e
* contained in a structure of type t, return the containing structure.
*/
#define dm_list_struct_base(v, t, head) \
((t *)((const char *)(v) - (const char *)&((t *) 0)->head))
container_of(v, t, head)
/*
* Given the address v of an instance of 'struct dm_list list' contained in
@@ -111,7 +113,7 @@ struct dm_list *dm_list_next(const struct dm_list *head, const struct dm_list *e
* return another element f.
*/
#define dm_struct_field(v, t, e, f) \
(((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->e))->f)
(((t *)((uintptr_t)(v) - offsetof(t, e)))->f)
/*
* Given the address v of a known element e in a known structure of type t,

View File

@@ -47,7 +47,7 @@ struct value_chain {
struct prefix_chain {
struct value child;
unsigned len;
uint8_t prefix[0];
uint8_t prefix[];
};
struct node4 {
@@ -1032,7 +1032,7 @@ void radix_tree_iterate(struct radix_tree *rt, uint8_t *kb, uint8_t *ke,
{
struct lookup_result lr = _lookup_prefix(&rt->root, kb, ke);
if (lr.kb == ke || _prefix_chain_matches(&lr, ke))
_iterate(lr.v, it);
(void) _iterate(lr.v, it);
}
//----------------------------------------------------------------

View File

@@ -1,4 +1,4 @@
// Copyright (C) 2018 Red Hat, Inc. All rights reserved.
// Copyright (C) 2018 - 2020 Red Hat, Inc. All rights reserved.
//
// This file is part of LVM2.
//
@@ -13,10 +13,12 @@
#ifndef BASE_MEMORY_CONTAINER_OF_H
#define BASE_MEMORY_CONTAINER_OF_H
#include <stddef.h> // offsetof
//----------------------------------------------------------------
#define container_of(v, t, head) \
((t *)((const char *)(v) - (const char *)&((t *) 0)->head))
((t *)((char *)(v) - offsetof(t, head)))
//----------------------------------------------------------------

File diff suppressed because it is too large Load Diff

View File

@@ -28,13 +28,13 @@ local {
# main configuration file, e.g. lvm.conf. When used, it must be set to
# a unique value among all hosts sharing access to the storage,
# e.g. a host name.
#
#
# Example
# Set no system ID:
# system_id = ""
# Set the system_id to a specific name:
# system_id = "host1"
#
#
# This configuration option has an automatic default value.
# system_id = ""

875
configure vendored

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -46,6 +46,7 @@ const char *find_config_tree_str(struct cmd_context *cmd, int id, struct profile
return "STRING";
}
/*
struct logical_volume *origin_from_cow(const struct logical_volume *lv)
{
if (lv)
@@ -53,6 +54,7 @@ struct logical_volume *origin_from_cow(const struct logical_volume *lv)
__coverity_panic__();
}
*/
/* simple_memccpy() from glibc */
void *memccpy(void *dest, const void *src, int c, size_t n)

View File

@@ -22,6 +22,9 @@ SOURCES = clogd.c cluster.c compat.c functions.c link_mon.c local.c logging.c
TARGETS = cmirrord
CFLOW_SOURCES = $(addprefix $(srcdir)/, $(SOURCES))
CFLOW_TARGET := $(TARGETS)
include $(top_builddir)/make.tmpl
LMLIBS += $(CPG_LIBS)
@@ -33,6 +36,8 @@ cmirrord: $(OBJECTS)
$(Q) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJECTS) \
$(LMLIBS) -L$(top_builddir)/libdm -ldevmapper $(LIBS)
install: $(TARGETS)
install_cluster: $(TARGETS)
@echo " [INSTALL] $<"
$(Q) $(INSTALL_PROGRAM) -D cmirrord $(usrsbindir)/cmirrord
$(Q) $(INSTALL_PROGRAM) -D $< $(usrsbindir)/$(<F)
install: install_cluster

View File

@@ -245,6 +245,7 @@ static void daemonize(void)
}
LOG_OPEN("cmirrord", LOG_PID, LOG_DAEMON);
/* coverity[leaked_handle] devnull cannot leak here */
}
/*

View File

@@ -108,7 +108,7 @@ static SaVersionT version = { 'B', 1, 1 };
#endif
#define DEBUGGING_HISTORY 100
#define DEBUGGING_BUFLEN 128
#define DEBUGGING_BUFLEN 270
#define LOG_SPRINT(cc, f, arg...) do { \
cc->idx++; \
cc->idx = cc->idx % DEBUGGING_HISTORY; \
@@ -1383,7 +1383,7 @@ static void cpg_leave_callback(struct clog_cpg *match,
size_t member_list_entries)
{
unsigned i;
int j, fd;
int j, fd = -1;
uint32_t lowest = match->lowest_id;
struct clog_request *rq, *n;
struct checkpoint_data *p_cp, *c_cp;
@@ -1548,7 +1548,7 @@ static void cpg_config_callback(cpg_handle_t handle, const struct cpg_name *gnam
member_list, member_list_entries);
}
cpg_callbacks_t cpg_callbacks = {
static cpg_callbacks_t cpg_callbacks = {
.cpg_deliver_fn = cpg_message_callback,
.cpg_confchg_fn = cpg_config_callback,
};

View File

@@ -39,7 +39,7 @@ struct clog_request {
* machine. If the two are equal, there is no need
* to do endian conversions.
*/
union {
union version_u {
uint64_t version[2]; /* LE version and native version */
struct dm_list list;
} u;

View File

@@ -34,7 +34,7 @@
#define LOG_OFFSET 2
#define RESYNC_HISTORY 50
#define RESYNC_BUFLEN 128
#define RESYNC_BUFLEN 270
//static char resync_history[RESYNC_HISTORY][128];
//static int idx = 0;
#define LOG_SPRINT(_lc, f, arg...) do { \
@@ -378,7 +378,7 @@ static int _clog_ctr(char *uuid, uint64_t luid,
uint32_t block_on_error = 0;
int disk_log;
char disk_path[PATH_MAX];
char disk_path[PATH_MAX] = { 0 };
int unlink_path = 0;
long page_size;
int pages;
@@ -658,8 +658,7 @@ static int clog_dtr(struct dm_ulog_request *rq)
if (lc->disk_fd != -1 && close(lc->disk_fd))
LOG_ERROR("Failed to close disk log: %s",
strerror(errno));
if (lc->disk_buffer)
free(lc->disk_buffer);
free(lc->disk_buffer);
free(lc->clean_bits);
free(lc->sync_bits);
free(lc);

View File

@@ -14,11 +14,21 @@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
top_builddir = @top_builddir@
abs_srcdir = @abs_srcdir@
SOURCES = libdevmapper-event.c
SOURCES2 = dmeventd.c
TARGETS = dmeventd
CFLOW_SOURCES = $(addprefix $(srcdir)/, $(SOURCES) $(SOURCES2) \
plugins/lvm2/dmeventd_lvm.c \
plugins/mirror/dmeventd_mirror.c \
plugins/raid/dmeventd_raid.c \
plugins/snapshot/dmeventd_snapshot.c \
plugins/thin/dmeventd_thin.c \
plugins/vdo/dmeventd_vdo.c \
)
CFLOW_TARGET := $(TARGETS)
.PHONY: install_lib_dynamic install_lib_static install_include \
install_pkgconfig install_dmeventd_dynamic install_dmeventd_static \
@@ -37,6 +47,7 @@ endif
LIB_VERSION = $(LIB_VERSION_DM)
LIB_SHARED = $(LIB_NAME).$(LIB_SUFFIX)
LIBS = $(PTHREAD_LIBS) -L$(interfacebuilddir) -ldevmapper
CLEAN_TARGETS = dmeventd.static $(LIB_NAME).a
@@ -46,7 +57,6 @@ endif
CFLOW_LIST = $(SOURCES)
CFLOW_LIST_TARGET = $(LIB_NAME).cflow
CFLOW_TARGET = dmeventd
EXPORTED_HEADER = $(srcdir)/libdevmapper-event.h
EXPORTED_FN_PREFIX = dm_event
@@ -55,34 +65,26 @@ include $(top_builddir)/make.tmpl
all: device-mapper
device-mapper: $(TARGETS)
plugins.device-mapper: $(LIB_SHARED)
CFLAGS_dmeventd.o += $(EXTRA_EXEC_CFLAGS)
LIBS += $(PTHREAD_LIBS) -L$(top_builddir)/libdm -ldevmapper
dmeventd: $(LIB_SHARED) dmeventd.o
@echo " [CC] $@"
$(Q) $(CC) $(CFLAGS) -L. $(LDFLAGS) $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS) dmeventd.o \
-o $@ $(DL_LIBS) $(DMEVENT_LIBS) $(LIBS) -lm
$(Q) $(CC) $(CFLAGS) $(LDFLAGS) $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS) dmeventd.o \
-o $@ $(DL_LIBS) $(DMEVENT_LIBS) $(LIBS)
dmeventd.static: $(LIB_STATIC) dmeventd.o
@echo " [CC] $@"
$(Q) $(CC) $(CFLAGS) $(LDFLAGS) -static -L. -L$(interfacebuilddir) dmeventd.o \
$(Q) $(CC) $(CFLAGS) $(LDFLAGS) -static dmeventd.o \
-o $@ $(DL_LIBS) $(DMEVENT_LIBS) $(LIBS) $(STATIC_LIBS)
ifeq ("@PKGCONFIG@", "yes")
INSTALL_LIB_TARGETS += install_pkgconfig
endif
ifneq ("$(CFLOW_CMD)", "")
CFLOW_SOURCES = $(addprefix $(srcdir)/, $(SOURCES))
-include $(top_builddir)/lib/liblvm-internal.cflow
-include $(top_builddir)/lib/liblvm2cmd.cflow
-include $(top_builddir)/daemons/dmeventd/$(LIB_NAME).cflow
-include $(top_builddir)/daemons/dmeventd/plugins/mirror/$(LIB_NAME)-lvm2mirror.cflow
endif
install_include: $(srcdir)/libdevmapper-event.h
@echo " [INSTALL] $<"
@echo " [INSTALL] $(<F)"
$(Q) $(INSTALL_DATA) -D $< $(includedir)/$(<F)
install_pkgconfig: libdevmapper-event.pc

View File

@@ -678,6 +678,9 @@ static int _get_status(struct message_data *message_data)
char **buffers;
char *message;
if (!message_data->id)
return -EINVAL;
_lock_mutex();
count = dm_list_size(&_thread_registry);
buffers = alloca(sizeof(char*) * count);
@@ -752,7 +755,7 @@ static void _exit_timeout(void *unused __attribute__((unused)))
static void *_timeout_thread(void *unused __attribute__((unused)))
{
struct thread_status *thread;
struct timespec timeout;
struct timespec timeout, real_time;
time_t curr_time;
int ret;
@@ -763,7 +766,16 @@ static void *_timeout_thread(void *unused __attribute__((unused)))
while (!dm_list_empty(&_timeout_registry)) {
timeout.tv_sec = 0;
timeout.tv_nsec = 0;
#ifndef HAVE_REALTIME
curr_time = time(NULL);
#else
if (clock_gettime(CLOCK_REALTIME, &real_time)) {
log_error("Failed to read clock_gettime().");
break;
}
/* 10ms back to the future */
curr_time = real_time.tv_sec + ((real_time.tv_nsec > (1000000000 - 10000000)) ? 1 : 0);
#endif
dm_list_iterate_items_gen(thread, &_timeout_registry, timeout_list) {
if (thread->next_time <= curr_time) {
@@ -1063,6 +1075,7 @@ out:
* "label at end of compound statement" */
;
/* coverity[lock_order] _global_mutex is kept locked */
pthread_cleanup_pop(1);
return NULL;
@@ -1733,7 +1746,8 @@ static void _init_thread_signals(void)
sigset_t my_sigset;
struct sigaction act = { .sa_handler = _sig_alarm };
sigaction(SIGALRM, &act, NULL);
if (sigaction(SIGALRM, &act, NULL))
log_sys_debug("sigaction", "SIGLARM");
sigfillset(&my_sigset);
/* These are used for exiting */
@@ -2019,8 +2033,8 @@ static int _reinstate_registrations(struct dm_event_fifos *fifos)
static void _restart_dmeventd(void)
{
struct dm_event_fifos fifos = {
.server = -1,
.client = -1,
.server = -1,
/* FIXME Make these either configurable or depend directly on dmeventd_path */
.client_path = DM_EVENT_FIFO_CLIENT,
.server_path = DM_EVENT_FIFO_SERVER
@@ -2059,7 +2073,7 @@ static void _restart_dmeventd(void)
++count;
}
if (!(_initial_registrations = malloc(sizeof(char*) * (count + 1)))) {
if (!(_initial_registrations = zalloc(sizeof(char*) * (count + 1)))) {
fprintf(stderr, "Memory allocation registration failed.\n");
goto bad;
}
@@ -2071,7 +2085,6 @@ static void _restart_dmeventd(void)
}
message += strlen(message) + 1;
}
_initial_registrations[count] = NULL;
if (version >= 2) {
if (daemon_talk(&fifos, &msg, DM_EVENT_CMD_GET_PARAMETERS, "-", "-", 0, 0)) {

View File

@@ -615,8 +615,8 @@ static int _do_event(int cmd, char *dmeventd_path, struct dm_event_daemon_messag
{
int ret;
struct dm_event_fifos fifos = {
.server = -1,
.client = -1,
.server = -1,
/* FIXME Make these either configurable or depend directly on dmeventd_path */
.client_path = DM_EVENT_FIFO_CLIENT,
.server_path = DM_EVENT_FIFO_SERVER
@@ -709,15 +709,11 @@ int dm_event_unregister_handler(const struct dm_event_handler *dmevh)
static char *_fetch_string(char **src, const int delimiter)
{
char *p, *ret;
size_t len = (p = strchr(*src, delimiter)) ?
(size_t)(p - *src) : strlen(*src);
if ((p = strchr(*src, delimiter)))
*p = 0;
if ((ret = strdup(*src)))
*src += strlen(ret) + 1;
if (p)
*p = delimiter;
if ((ret = strndup(*src, len)))
*src += len + 1;
return ret;
}

View File

@@ -71,7 +71,7 @@ int dmeventd_lvm2_init(void)
if (!_lvm_handle) {
lvm2_log_fn(_lvm2_print_log);
if (!(_lvm_handle = lvm2_init()))
if (!(_lvm_handle = lvm2_init_threaded()))
goto out;
/*

View File

@@ -25,9 +25,6 @@ LIB_NAME = libdevmapper-event-lvm2mirror
LIB_SHARED = $(LIB_NAME).$(LIB_SUFFIX)
LIB_VERSION = $(LIB_VERSION_LVM)
CFLOW_LIST = $(SOURCES)
CFLOW_LIST_TARGET = $(LIB_NAME).cflow
include $(top_builddir)/make.tmpl
install_lvm2: install_dm_plugin

View File

@@ -24,9 +24,6 @@ LIB_NAME = libdevmapper-event-lvm2raid
LIB_SHARED = $(LIB_NAME).$(LIB_SUFFIX)
LIB_VERSION = $(LIB_VERSION_LVM)
CFLOW_LIST = $(SOURCES)
CFLOW_LIST_TARGET = $(LIB_NAME).cflow
include $(top_builddir)/make.tmpl
install_lvm2: install_dm_plugin

View File

@@ -77,7 +77,7 @@ static int _process_raid_event(struct dso_state *state, char *params, const char
if (dead) {
/*
* Use the first event to run a repair ignoring any additonal ones.
* Use the first event to run a repair ignoring any additional ones.
*
* We presume lvconvert to do pre-repair
* checks to avoid bloat in this plugin.

View File

@@ -24,9 +24,6 @@ LIB_NAME = libdevmapper-event-lvm2thin
LIB_SHARED = $(LIB_NAME).$(LIB_SUFFIX)
LIB_VERSION = $(LIB_VERSION_LVM)
CFLOW_LIST = $(SOURCES)
CFLOW_LIST_TARGET = $(LIB_NAME).cflow
include $(top_builddir)/make.tmpl
install_lvm2: install_dm_plugin

View File

@@ -24,9 +24,6 @@ LIB_NAME = libdevmapper-event-lvm2vdo
LIB_SHARED = $(LIB_NAME).$(LIB_SUFFIX)
LIB_VERSION = $(LIB_VERSION_LVM)
CFLOW_LIST = $(SOURCES)
CFLOW_LIST_TARGET = $(LIB_NAME).cflow
include $(top_builddir)/make.tmpl
install_lvm2: install_dm_plugin

View File

@@ -22,6 +22,7 @@
* in runtime we are linked agains systems libdm 'older' library
* which does not provide this symbol and plugin fails to load
*/
/* coverity[unnecessary_header] used for parsing */
#include "device_mapper/vdo/status.c"
#include <sys/wait.h>

View File

@@ -15,7 +15,8 @@ srcdir = @srcdir@
top_srcdir = @top_srcdir@
top_builddir = @top_builddir@
lvmdbusdir = $(python3dir)/lvmdbusd
lvmdbuspydir = $(python3dir)/lvmdbusd
lvmdbusdir = $(DESTDIR)$(lvmdbuspydir)
LVMDBUS_SRCDIR_FILES = \
automatedproperties.py \
@@ -53,16 +54,16 @@ include $(top_builddir)/make.tmpl
all:
$(Q) test -x $(LVMDBUSD) || chmod 755 $(LVMDBUSD)
install_lvmdbusd:
install_lvmdbusd: $(LVMDBUSD)
@echo " [INSTALL] $<"
$(Q) $(INSTALL_DIR) $(sbindir)
$(Q) $(INSTALL_SCRIPT) $(LVMDBUSD) $(sbindir)
$(Q) $(INSTALL_DIR) $(DESTDIR)$(lvmdbusdir)
$(Q) (cd $(srcdir); $(INSTALL_DATA) $(LVMDBUS_SRCDIR_FILES) $(DESTDIR)$(lvmdbusdir))
$(Q) $(INSTALL_DATA) $(LVMDBUS_BUILDDIR_FILES) $(DESTDIR)$(lvmdbusdir)
$(Q) PYTHON=$(PYTHON3) $(PYCOMPILE) --destdir "$(DESTDIR)" --basedir "$(lvmdbusdir)" $(LVMDBUS_SRCDIR_FILES) $(LVMDBUS_BUILDDIR_FILES)
$(Q) $(CHMOD) 755 $(DESTDIR)$(lvmdbusdir)/__pycache__
$(Q) $(CHMOD) 444 $(DESTDIR)$(lvmdbusdir)/__pycache__/*.py[co]
$(Q) $(INSTALL_DIR) $(lvmdbusdir)
$(Q) (cd $(srcdir); $(INSTALL_DATA) $(LVMDBUS_SRCDIR_FILES) $(lvmdbusdir))
$(Q) $(INSTALL_DATA) $(LVMDBUS_BUILDDIR_FILES) $(lvmdbusdir)
$(Q) PYTHON=$(PYTHON3) $(PYCOMPILE) --destdir "$(DESTDIR)" --basedir "$(lvmdbuspydir)" $(LVMDBUS_SRCDIR_FILES) $(LVMDBUS_BUILDDIR_FILES)
$(Q) $(CHMOD) 755 $(lvmdbusdir)/__pycache__
$(Q) $(CHMOD) 444 $(lvmdbusdir)/__pycache__/*.py[co]
install_lvm2: install_lvmdbusd

View File

@@ -157,14 +157,15 @@ class AutomatedProperties(dbus.service.Object):
if not self._ap_search_method:
return 0
search = self.lvm_id
if search_key:
search = search_key
# Either we have the new object state or we need to go fetch it
if object_state:
new_state = object_state
else:
if search_key:
search = search_key
else:
search = self.lvm_id
new_state = self._ap_search_method([search])[0]
assert isinstance(new_state, State)

View File

@@ -9,13 +9,14 @@
import subprocess
from . import cfg
from .cmdhandler import options_to_cli_args, LvmExecutionMeta
from .cmdhandler import options_to_cli_args, LvmExecutionMeta, call_lvm
import dbus
from .utils import pv_range_append, pv_dest_ranges, log_error, log_debug,\
add_no_notify
import os
mt_async_call
from .request import RequestEntry
import threading
import time
import traceback
def pv_move_lv_cmd(move_options, lv_full_name,
@@ -39,58 +40,50 @@ def lv_merge_cmd(merge_options, lv_full_name):
return cmd
def _load_wrapper(ignored):
cfg.load()
def _move_callback(job_state, line_str):
try:
if line_str.count(':') == 2:
(device, ignore, percentage) = line_str.split(':')
job_state.Percent = int(round(
float(percentage.strip()[:-1]), 1))
# While the move is in progress we need to periodically update
# the state to reflect where everything is at. we will do this
# by scheduling the load to occur in the main work queue.
r = RequestEntry(
-1, _load_wrapper, ("_move_callback: load",), None, None, False)
cfg.worker_q.put(r)
except ValueError:
log_error("Trying to parse percentage which failed for %s" % line_str)
def _move_merge(interface_name, command, job_state):
# We need to execute these command stand alone by forking & exec'ing
# the command always as we will be getting periodic output from them on
# the status of the long running operation.
command.insert(0, cfg.LVM_CMD)
# Instruct lvm to not register an event with us
command = add_no_notify(command)
#(self, start, ended, cmd, ec, stdout_txt, stderr_txt)
meta = LvmExecutionMeta(time.time(), 0, command, -1000, None, None)
cfg.blackbox.add(meta)
process = subprocess.Popen(command, stdout=subprocess.PIPE,
env=os.environ,
stderr=subprocess.PIPE, close_fds=True)
log_debug("Background process for %s is %d" %
(str(command), process.pid))
lines_iterator = iter(process.stdout.readline, b"")
for line in lines_iterator:
line_str = line.decode("utf-8")
# Check to see if the line has the correct number of separators
try:
if line_str.count(':') == 2:
(device, ignore, percentage) = line_str.split(':')
job_state.Percent = round(
float(percentage.strip()[:-1]), 1)
# While the move is in progress we need to periodically update
# the state to reflect where everything is at.
cfg.load()
except ValueError:
log_error("Trying to parse percentage which failed for %s" %
line_str)
out = process.communicate()
ec, stdout, stderr = call_lvm(command, line_cb=_move_callback,
cb_data=job_state)
with meta.lock:
meta.ended = time.time()
meta.ec = process.returncode
meta.stderr_txt = out[1]
meta.ec = ec
meta.stderr_txt = stderr
if process.returncode == 0:
if ec == 0:
job_state.Percent = 100
else:
raise dbus.exceptions.DBusException(
interface_name,
'Exit code %s, stderr = %s' % (str(process.returncode), out[1]))
'Exit code %s, stderr = %s' % (str(ec), stderr))
cfg.load()
return '/'

View File

@@ -8,6 +8,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from subprocess import Popen, PIPE
import select
import time
import threading
from itertools import chain
@@ -16,7 +17,8 @@ import traceback
import os
from lvmdbusd import cfg
from lvmdbusd.utils import pv_dest_ranges, log_debug, log_error, add_no_notify
from lvmdbusd.utils import pv_dest_ranges, log_debug, log_error, add_no_notify,\
make_non_block, read_decoded
from lvmdbusd.lvm_shell_proxy import LVMShellProxy
try:
@@ -82,16 +84,23 @@ def _debug_c(cmd, exit_code, out):
log_error(("STDERR=\n %s\n" % out[1]))
def call_lvm(command, debug=False):
def call_lvm(command, debug=False, line_cb=None,
cb_data=None):
"""
Call an executable and return a tuple of exitcode, stdout, stderr
:param command: Command to execute
:param debug: Dump debug to stdout
"""
# print 'STACK:'
# for line in traceback.format_stack():
# print line.strip()
:param command: Command to execute
:param debug: Dump debug to stdout
:param line_cb: Call the supplied function for each line read from
stdin, CALL MUST EXECUTE QUICKLY and not *block*
otherwise call_lvm function will fail to read
stdin/stdout. Return value of call back is ignored
:param cb_data: Supplied to callback to allow caller access to
its own data
# Callback signature
def my_callback(my_context, line_read_stdin)
pass
"""
# Prepend the full lvm executable so that we can run different versions
# in different locations on the same box
command.insert(0, cfg.LVM_CMD)
@@ -99,10 +108,44 @@ def call_lvm(command, debug=False):
process = Popen(command, stdout=PIPE, stderr=PIPE, close_fds=True,
env=os.environ)
out = process.communicate()
stdout_text = bytes(out[0]).decode("utf-8")
stderr_text = bytes(out[1]).decode("utf-8")
stdout_text = ""
stderr_text = ""
stdout_index = 0
make_non_block(process.stdout)
make_non_block(process.stderr)
while True:
try:
rd_fd = [process.stdout.fileno(), process.stderr.fileno()]
ready = select.select(rd_fd, [], [], 2)
for r in ready[0]:
if r == process.stdout.fileno():
stdout_text += read_decoded(process.stdout)
elif r == process.stderr.fileno():
stderr_text += read_decoded(process.stderr)
if line_cb is not None:
# Process the callback for each line read!
while True:
i = stdout_text.find("\n", stdout_index)
if i != -1:
try:
line_cb(cb_data, stdout_text[stdout_index:i])
except:
st = traceback.format_exc()
log_error("call_lvm: line_cb exception: \n %s" % st)
stdout_index = i + 1
else:
break
# Check to see if process has terminated, None when running
if process.poll() is not None:
break
except IOError as ioe:
log_debug("call_lvm:" + str(ioe))
pass
if debug or process.returncode != 0:
_debug_c(command, process.returncode, (stdout_text, stderr_text))
@@ -453,6 +496,15 @@ def lv_cache_lv(cache_pool_full_name, lv_full_name, cache_options):
return call(cmd)
def lv_writecache_lv(cache_lv_full_name, lv_full_name, cache_options):
# lvconvert --type writecache --cachevol VG/CacheLV VG/OriginLV
cmd = ['lvconvert']
cmd.extend(options_to_cli_args(cache_options))
cmd.extend(['-y', '--type', 'writecache', '--cachevol',
cache_lv_full_name, lv_full_name])
return call(cmd)
def lv_detach_cache(lv_full_name, detach_options, destroy_cache):
cmd = ['lvconvert']
if destroy_cache:
@@ -575,7 +627,13 @@ def lvm_full_report_json():
assert(type(out) == dict)
return out
else:
return json.loads(out)
try:
return json.loads(out)
except json.decoder.JSONDecodeError as joe:
log_error("JSONDecodeError %s, \n JSON=\n%s\n" %
(str(joe), out))
raise joe
return None

View File

@@ -20,22 +20,30 @@ import traceback
def _main_thread_load(refresh=True, emit_signal=True):
num_total_changes = 0
to_remove = []
num_total_changes += load_pvs(
(changes, remove) = load_pvs(
refresh=refresh,
emit_signal=emit_signal,
cache_refresh=False)[1]
num_total_changes += load_vgs(
refresh=refresh,
emit_signal=emit_signal,
cache_refresh=False)[1]
cache_refresh=False)[1:]
num_total_changes += changes
to_remove.extend(remove)
lv_changes = load_lvs(
(changes, remove) = load_vgs(
refresh=refresh,
emit_signal=emit_signal,
cache_refresh=False)[1]
cache_refresh=False)[1:]
num_total_changes += changes
to_remove.extend(remove)
(lv_changes, remove) = load_lvs(
refresh=refresh,
emit_signal=emit_signal,
cache_refresh=False)[1:]
num_total_changes += lv_changes
to_remove.extend(remove)
# When the LVs change it can cause another change in the VGs which is
# missed if we don't scan through the VGs again. We could achieve this
@@ -44,10 +52,23 @@ def _main_thread_load(refresh=True, emit_signal=True):
# changes causing the dbus object representing it to be removed and
# recreated.
if refresh and lv_changes > 0:
num_total_changes += load_vgs(
(changes, remove) = load_vgs(
refresh=refresh,
emit_signal=emit_signal,
cache_refresh=False)[1]
cache_refresh=False)[1:]
num_total_changes += changes
to_remove.extend(remove)
# Remove any objects that are no longer needed. We do this after we process
# all the objects to ensure that references still exist for objects that
# are processed after them.
to_remove.reverse()
for i in to_remove:
dbus_obj = cfg.om.get_object_by_path(i)
if dbus_obj:
cfg.om.remove_object(dbus_obj, True)
num_total_changes += 1
return num_total_changes

View File

@@ -75,11 +75,10 @@ def common(retrieve, o_type, search_keys,
object_path = None
to_remove = []
if refresh:
for k in list(existing_paths.keys()):
cfg.om.remove_object(cfg.om.get_object_by_path(k), True)
num_changes += 1
to_remove = list(existing_paths.keys())
num_changes += len(rc)
return rc, num_changes
return rc, num_changes, to_remove

View File

@@ -388,7 +388,7 @@ class LvCommon(AutomatedProperties):
'l': 'mirror log device', 'c': 'under conversion',
'V': 'thin Volume', 't': 'thin pool', 'T': 'Thin pool data',
'e': 'raid or pool metadata or pool metadata spare',
'd': 'vdo pool', 'D': 'vdo pool data',
'd': 'vdo pool', 'D': 'vdo pool data', 'g': 'integrity',
'-': 'Unspecified'}
return self.attr_struct(0, type_map)
@@ -743,6 +743,49 @@ class Lv(LvCommon):
cb, cbe, return_tuple=False)
cfg.worker_q.put(r)
@staticmethod
def _writecache_lv(lv_uuid, lv_name, lv_object_path, cache_options):
# Make sure we have a dbus object representing it
dbo = LvCommon.validate_dbus_object(lv_uuid, lv_name)
# Make sure we have dbus object representing lv to cache
lv_to_cache = cfg.om.get_object_by_path(lv_object_path)
if lv_to_cache:
fcn = lv_to_cache.lv_full_name()
rc, out, err = cmdhandler.lv_writecache_lv(
dbo.lv_full_name(), fcn, cache_options)
if rc == 0:
# When we cache an LV, the cache pool and the lv that is getting
# cached need to be removed from the object manager and
# re-created as their interfaces have changed!
mt_remove_dbus_objects((dbo, lv_to_cache))
cfg.load()
lv_converted = cfg.om.get_object_path_by_lvm_id(fcn)
else:
raise dbus.exceptions.DBusException(
LV_INTERFACE,
'Exit code %s, stderr = %s' % (str(rc), err))
else:
raise dbus.exceptions.DBusException(
LV_INTERFACE, 'LV to cache with object path %s not present!' %
lv_object_path)
return lv_converted
@dbus.service.method(
dbus_interface=LV_INTERFACE,
in_signature='oia{sv}',
out_signature='(oo)',
async_callbacks=('cb', 'cbe'))
def WriteCacheLv(self, lv_object, tmo, cache_options, cb, cbe):
r = RequestEntry(
tmo, Lv._writecache_lv,
(self.Uuid, self.lvm_id, lv_object,
cache_options), cb, cbe)
cfg.worker_q.put(r)
# noinspection PyPep8Naming
@utils.dbus_property(VDO_POOL_INTERFACE, 'OperatingMode', 's')
@utils.dbus_property(VDO_POOL_INTERFACE, 'CompressionState', 's')

View File

@@ -13,7 +13,6 @@
import subprocess
import shlex
from fcntl import fcntl, F_GETFL, F_SETFL
import os
import traceback
import sys
@@ -29,7 +28,8 @@ except ImportError:
from lvmdbusd.cfg import LVM_CMD
from lvmdbusd.utils import log_debug, log_error, add_no_notify
from lvmdbusd.utils import log_debug, log_error, add_no_notify, make_non_block,\
read_decoded
SHELL_PROMPT = "lvm> "
@@ -43,13 +43,6 @@ def _quote_arg(arg):
class LVMShellProxy(object):
@staticmethod
def _read(stream):
tmp = stream.read()
if tmp:
return tmp.decode("utf-8")
return ''
# Read until we get prompt back and a result
# @param: no_output Caller expects no output to report FD
# Returns stdout, report, stderr (report is JSON!)
@@ -75,11 +68,11 @@ class LVMShellProxy(object):
for r in ready[0]:
if r == self.lvm_shell.stdout.fileno():
stdout += LVMShellProxy._read(self.lvm_shell.stdout)
stdout += read_decoded(self.lvm_shell.stdout)
elif r == self.report_stream.fileno():
report += LVMShellProxy._read(self.report_stream)
report += read_decoded(self.report_stream)
elif r == self.lvm_shell.stderr.fileno():
stderr += LVMShellProxy._read(self.lvm_shell.stderr)
stderr += read_decoded(self.lvm_shell.stderr)
# Check to see if the lvm process died on us
if self.lvm_shell.poll():
@@ -124,11 +117,6 @@ class LVMShellProxy(object):
assert (num_written == len(cmd_bytes))
self.lvm_shell.stdin.flush()
@staticmethod
def _make_non_block(stream):
flags = fcntl(stream, F_GETFL)
fcntl(stream, F_SETFL, flags | os.O_NONBLOCK)
def __init__(self):
# Create a temp directory
@@ -162,8 +150,8 @@ class LVMShellProxy(object):
stderr=subprocess.PIPE, close_fds=True, shell=True)
try:
LVMShellProxy._make_non_block(self.lvm_shell.stdout)
LVMShellProxy._make_non_block(self.lvm_shell.stderr)
make_non_block(self.lvm_shell.stdout)
make_non_block(self.lvm_shell.stderr)
# wait for the first prompt
errors = self._read_until_prompt(no_output=True)[2]

View File

@@ -27,7 +27,7 @@ class Manager(AutomatedProperties):
@property
def Version(self):
return dbus.String('1.0.0')
return dbus.String('1.1.0')
@staticmethod
def handle_execute(rc, out, err):

View File

@@ -52,8 +52,8 @@ def filter_event(action, device):
# when appropriate.
refresh = False
if '.ID_FS_TYPE_NEW' in device:
fs_type_new = device['.ID_FS_TYPE_NEW']
if 'ID_FS_TYPE' in device:
fs_type_new = device['ID_FS_TYPE']
if 'LVM' in fs_type_new:
refresh = True

View File

@@ -14,6 +14,7 @@ import ctypes
import os
import string
import datetime
from fcntl import fcntl, F_GETFL, F_SETFL
import dbus
from lvmdbusd import cfg
@@ -681,3 +682,16 @@ def _remove_objects(dbus_objects_rm):
# Remove dbus objects from main thread
def mt_remove_dbus_objects(objs):
MThreadRunner(_remove_objects, objs).done()
# Make stream non-blocking
def make_non_block(stream):
flags = fcntl(stream, F_GETFL)
fcntl(stream, F_SETFL, flags | os.O_NONBLOCK)
def read_decoded(stream):
tmp = stream.read()
if tmp:
return tmp.decode("utf-8")
return ''

View File

@@ -30,33 +30,39 @@ ifeq ("@BUILD_LOCKDDLM@", "yes")
LOCK_LIBS += -ldlmcontrol
endif
ifeq ("@BUILD_LOCKDIDM@", "yes")
SOURCES += lvmlockd-idm.c
LOCK_LIBS += -lseagate_ilm -lblkid
endif
SOURCES2 = lvmlockctl.c
TARGETS = lvmlockd lvmlockctl
.PHONY: install_lvmlockd
CFLOW_SOURCES = $(addprefix $(srcdir)/, $(SOURCES))
CFLOW_TARGET = lvmlockd
.PHONY: install_lvmlockd install_lvmlockctl
include $(top_builddir)/make.tmpl
CFLAGS += $(EXTRA_EXEC_CFLAGS)
INCLUDES += -I$(top_srcdir)/libdaemon/server
LDFLAGS += -L$(top_builddir)/libdaemon/server $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS)
LIBS += $(RT_LIBS) $(DAEMON_LIBS) $(PTHREAD_LIBS)
LIBS += $(DAEMON_LIBS) $(PTHREAD_LIBS)
ifeq ($(USE_SD_NOTIFY),yes)
CFLAGS += $(shell pkg-config --cflags libsystemd) -DUSE_SD_NOTIFY
LIBS += $(shell pkg-config --libs libsystemd)
endif
lvmlockd: $(OBJECTS) $(top_builddir)/libdaemon/client/libdaemonclient.a \
$(top_builddir)/libdaemon/server/libdaemonserver.a
lvmlockd: $(OBJECTS) $(top_builddir)/libdaemon/server/libdaemonserver.a $(INTERNAL_LIBS)
@echo " [CC] $@"
$(Q) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJECTS) $(LOCK_LIBS) -ldaemonserver $(INTERNAL_LIBS) $(LIBS)
$(Q) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $+ $(LOCK_LIBS) $(LIBS)
lvmlockctl: lvmlockctl.o $(top_builddir)/libdaemon/client/libdaemonclient.a
lvmlockctl: lvmlockctl.o $(INTERNAL_LIBS)
@echo " [CC] $@"
$(Q) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ lvmlockctl.o $(INTERNAL_LIBS) $(LIBS)
$(Q) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $+ $(LIBS)
install_lvmlockd: lvmlockd
@echo " [INSTALL] $<"

View File

@@ -18,8 +18,11 @@
#include <errno.h>
#include <fcntl.h>
#include <syslog.h>
#include <ctype.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <sys/wait.h>
static int quit = 0;
static int info = 0;
@@ -30,6 +33,7 @@ static int kill_vg = 0;
static int drop_vg = 0;
static int gl_enable = 0;
static int gl_disable = 0;
static int use_stderr = 0;
static int stop_lockspaces = 0;
static char *arg_vg_name = NULL;
@@ -47,6 +51,22 @@ do { \
printf(fmt "\n", ##args); \
} while (0)
#define log_sys_emerg(fmt, args...) \
do { \
if (use_stderr) \
fprintf(stderr, fmt "\n", ##args); \
else \
syslog(LOG_EMERG, fmt, ##args); \
} while (0)
#define log_sys_warn(fmt, args...) \
do { \
if (use_stderr) \
fprintf(stderr, fmt "\n", ##args); \
else \
syslog(LOG_WARNING, fmt, ##args); \
} while (0)
#define MAX_LINE 512
/* copied from lvmlockd-internal.h */
@@ -437,6 +457,7 @@ retry:
if (count < dump_len)
goto retry;
dump_buf[count] = 0;
rv = 0;
if ((info && dump) || !strcmp(req_name, "dump"))
printf("%s\n", dump_buf);
@@ -502,51 +523,274 @@ static int do_stop_lockspaces(void)
return rv;
}
static int do_kill(void)
static int _reopen_fd_to_null(int fd)
{
daemon_reply reply;
int result;
int rv;
int null_fd;
int r = 0;
syslog(LOG_EMERG, "Lost access to sanlock lease storage in VG %s.", arg_vg_name);
/* These two lines explain the manual alternative to the FIXME below. */
syslog(LOG_EMERG, "Immediately deactivate LVs in VG %s.", arg_vg_name);
syslog(LOG_EMERG, "Once VG is unused, run lvmlockctl --drop %s.", arg_vg_name);
/*
* It may not be strictly necessary to notify lvmlockd of the kill, but
* lvmlockd can use this information to avoid attempting any new lock
* requests in the VG (which would fail anyway), and can return an
* error indicating that the VG has been killed.
*/
reply = _lvmlockd_send("kill_vg",
"cmd = %s", "lvmlockctl",
"pid = " FMTd64, (int64_t) getpid(),
"vg_name = %s", arg_vg_name,
NULL);
if (!_lvmlockd_result(reply, &result)) {
log_error("lvmlockd result %d", result);
rv = result;
} else {
rv = 0;
if ((null_fd = open("/dev/null", O_RDWR)) == -1) {
log_error("open error /dev/null %d", errno);
return 0;
}
daemon_reply_destroy(reply);
if (close(fd)) {
log_error("close error fd %d %d", fd, errno);
goto out;
}
/*
* FIXME: here is where we should implement a strong form of
* blkdeactivate, and if it completes successfully, automatically call
* do_drop() afterward. (The drop step may not always be necessary
* if the lvm commands run while shutting things down release all the
* leases.)
*
* run_strong_blkdeactivate();
* do_drop();
*/
if (dup2(null_fd, fd) == -1) {
log_error("dup2 error %d", errno);
goto out;
}
return rv;
r = 1;
out:
if (close(null_fd)) {
log_error("close error fd %d %d", null_fd, errno);
return 0;
}
return r;
}
#define MAX_AV_COUNT 32
#define ONE_ARG_LEN 1024
static void _run_command_pipe(const char *cmd_str, pid_t *pid_out, FILE **fp_out)
{
char arg[ONE_ARG_LEN];
char *av[MAX_AV_COUNT + 1]; /* +1 for NULL */
char *arg_dup;
int av_count = 0;
int cmd_len;
int arg_len;
pid_t pid = 0;
FILE *fp = NULL;
int pipefd[2];
int i;
for (i = 0; i < MAX_AV_COUNT + 1; i++)
av[i] = NULL;
cmd_len = strlen(cmd_str);
memset(&arg, 0, sizeof(arg));
arg_len = 0;
for (i = 0; i < cmd_len; i++) {
if (!cmd_str[i])
break;
if (av_count == MAX_AV_COUNT)
goto out;
if (cmd_str[i] == '\\') {
if (i == (cmd_len - 1))
break;
i++;
if (cmd_str[i] == '\\') {
arg[arg_len++] = cmd_str[i];
continue;
}
if (isspace(cmd_str[i])) {
arg[arg_len++] = cmd_str[i];
continue;
} else {
break;
}
}
if (isalnum(cmd_str[i]) || ispunct(cmd_str[i])) {
arg[arg_len++] = cmd_str[i];
} else if (isspace(cmd_str[i])) {
if (arg_len) {
if (!(arg_dup = strdup(arg)))
goto out;
av[av_count++] = arg_dup;
}
memset(arg, 0, sizeof(arg));
arg_len = 0;
} else {
break;
}
}
if (arg_len) {
if (av_count >= MAX_AV_COUNT)
goto out;
if (!(arg_dup = strdup(arg)))
goto out;
av[av_count++] = arg_dup;
}
if (pipe(pipefd)) {
log_error("pipe error %d", errno);
goto out;
}
pid = fork();
if (pid < 0) {
log_error("fork error %d", errno);
pid = 0;
goto out;
}
if (pid == 0) {
/* Child -> writer, convert pipe[0] to STDOUT */
if (!_reopen_fd_to_null(STDIN_FILENO))
log_error("reopen STDIN error");
else if (close(pipefd[0 /*read*/]))
log_error("close error pipe[0] %d", errno);
else if (close(STDOUT_FILENO))
log_error("close error STDOUT %d", errno);
else if (dup2(pipefd[1 /*write*/], STDOUT_FILENO) == -1)
log_error("dup2 error STDOUT %d", errno);
else if (close(pipefd[1]))
log_error("close error pipe[1] %d", errno);
else {
execvp(av[0], av);
log_error("execvp error %d", errno);
}
_exit(errno);
}
/* Parent -> reader */
if (close(pipefd[1 /*write*/]))
log_error("close error STDOUT %d", errno);
if (!(fp = fdopen(pipefd[0 /*read*/], "r"))) {
log_error("fdopen STDIN error %d", errno);
if (close(pipefd[0]))
log_error("close error STDIN %d", errno);
}
out:
for (i = 0; i < MAX_AV_COUNT + 1; i++)
free(av[i]);
*pid_out = pid;
*fp_out = fp;
}
/* Returns -1 on error, 0 on success. */
static int _close_command_pipe(pid_t pid, FILE *fp)
{
int status, estatus;
int ret = -1;
if (waitpid(pid, &status, 0) != pid) {
log_error("waitpid error pid %d %d", pid, errno);
goto out;
}
if (WIFEXITED(status)) {
/* pid exited with an exit code */
estatus = WEXITSTATUS(status);
/* exit status 0: child success */
if (!estatus) {
ret = 0;
goto out;
}
/* exit status not zero: child error */
log_error("child exit error %d", estatus);
goto out;
}
if (WIFSIGNALED(status)) {
/* pid terminated due to a signal */
log_error("child exit from signal");
goto out;
}
log_error("child exit problem");
out:
if (fp && fclose(fp))
log_error("fclose error STDIN %d", errno);
return ret;
}
/* Returns -1 on error, 0 on success. */
static int _get_kill_command(char *kill_cmd)
{
char config_cmd[PATH_MAX + 128] = { 0 };
char config_val[1024] = { 0 };
char line[PATH_MAX] = { 0 };
pid_t pid = 0;
FILE *fp = NULL;
snprintf(config_cmd, PATH_MAX, "%s config --typeconfig full global/lvmlockctl_kill_command", LVM_PATH);
_run_command_pipe(config_cmd, &pid, &fp);
if (!pid) {
log_error("failed to run %s", config_cmd);
return -1;
}
if (!fp) {
log_error("failed to get output %s", config_cmd);
_close_command_pipe(pid, fp);
return -1;
}
if (!fgets(line, sizeof(line), fp)) {
log_error("no output from %s", config_cmd);
goto bad;
}
if (sscanf(line, "lvmlockctl_kill_command=\"%256[^\n\"]\"", config_val) != 1) {
log_error("unrecognized config value from %s", config_cmd);
goto bad;
}
if (!config_val[0] || (config_val[0] == ' ')) {
log_error("invalid config value from %s", config_cmd);
goto bad;
}
if (config_val[0] != '/') {
log_error("lvmlockctl_kill_command must be full path");
goto bad;
}
printf("Found lvmlockctl_kill_command: %s\n", config_val);
snprintf(kill_cmd, PATH_MAX, "%s %s", config_val, arg_vg_name);
kill_cmd[PATH_MAX-1] = '\0';
_close_command_pipe(pid, fp);
return 0;
bad:
_close_command_pipe(pid, fp);
return -1;
}
/* Returns -1 on error, 0 on success. */
static int _run_kill_command(char *kill_cmd)
{
pid_t pid = 0;
FILE *fp = NULL;
int rv;
_run_command_pipe(kill_cmd, &pid, &fp);
rv = _close_command_pipe(pid, fp);
if (!pid)
return -1;
if (rv < 0)
return -1;
return 0;
}
static int do_drop(void)
@@ -555,7 +799,7 @@ static int do_drop(void)
int result;
int rv;
syslog(LOG_WARNING, "Dropping locks for VG %s.", arg_vg_name);
log_sys_warn("Dropping locks for VG %s.", arg_vg_name);
/*
* Check for misuse by looking for any active LVs in the VG
@@ -583,6 +827,84 @@ static int do_drop(void)
return rv;
}
static int do_kill(void)
{
char kill_cmd[PATH_MAX] = { 0 };
daemon_reply reply;
int no_kill_command = 0;
int result;
int rv;
log_sys_emerg("lvmlockd lost access to locks in VG %s.", arg_vg_name);
rv = _get_kill_command(kill_cmd);
if (rv < 0) {
log_sys_emerg("Immediately deactivate LVs in VG %s.", arg_vg_name);
log_sys_emerg("Once VG is unused, run lvmlockctl --drop %s.", arg_vg_name);
no_kill_command = 1;
}
/*
* It may not be strictly necessary to notify lvmlockd of the kill, but
* lvmlockd can use this information to avoid attempting any new lock
* requests in the VG (which would fail anyway), and can return an
* error indicating that the VG has been killed.
*/
_lvmlockd = lvmlockd_open(NULL);
if (_lvmlockd.socket_fd < 0 || _lvmlockd.error) {
log_error("Cannot connect to lvmlockd for kill_vg.");
goto run;
}
reply = _lvmlockd_send("kill_vg",
"cmd = %s", "lvmlockctl",
"pid = " FMTd64, (int64_t) getpid(),
"vg_name = %s", arg_vg_name,
NULL);
if (!_lvmlockd_result(reply, &result))
log_error("lvmlockd result %d kill_vg", result);
daemon_reply_destroy(reply);
lvmlockd_close(_lvmlockd);
run:
if (no_kill_command)
return 0;
rv = _run_kill_command(kill_cmd);
if (rv < 0) {
log_sys_emerg("Failed to run VG %s kill command %s", arg_vg_name, kill_cmd);
log_sys_emerg("Immediately deactivate LVs in VG %s.", arg_vg_name);
log_sys_emerg("Once VG is unused, run lvmlockctl --drop %s.", arg_vg_name);
return -1;
}
log_sys_warn("Successful VG %s kill command %s", arg_vg_name, kill_cmd);
/*
* If kill command was successfully, call do_drop(). (The drop step
* may not always be necessary if the lvm commands run while shutting
* things down release all the leases.)
*/
rv = 0;
_lvmlockd = lvmlockd_open(NULL);
if (_lvmlockd.socket_fd < 0 || _lvmlockd.error) {
log_sys_emerg("Failed to connect to lvmlockd to drop locks in VG %s.", arg_vg_name);
return -1;
}
reply = _lvmlockd_send("drop_vg",
"cmd = %s", "lvmlockctl",
"pid = " FMTd64, (int64_t) getpid(),
"vg_name = %s", arg_vg_name,
NULL);
if (!_lvmlockd_result(reply, &result)) {
log_sys_emerg("Failed to drop locks in VG %s", arg_vg_name);
rv = result;
}
daemon_reply_destroy(reply);
lvmlockd_close(_lvmlockd);
return rv;
}
static void print_usage(void)
{
printf("lvmlockctl options\n");
@@ -600,7 +922,7 @@ static void print_usage(void)
printf("--force | -f 0|1>\n");
printf(" Force option for other commands.\n");
printf("--kill | -k <vgname>\n");
printf(" Kill access to the VG when sanlock cannot renew lease.\n");
printf(" Kill access to the VG locks are lost (see lvmlockctl_kill_command).\n");
printf("--drop | -r <vgname>\n");
printf(" Clear locks for the VG when it is unused after kill (-k).\n");
printf("--gl-enable | -E <vgname>\n");
@@ -609,6 +931,8 @@ static void print_usage(void)
printf(" Tell lvmlockd to disable the global lock in a sanlock VG.\n");
printf("--stop-lockspaces | -S\n");
printf(" Stop all lockspaces.\n");
printf("--stderr | -e\n");
printf(" Send kill and drop messages to stderr instead of syslog\n");
}
static int read_options(int argc, char *argv[])
@@ -628,6 +952,7 @@ static int read_options(int argc, char *argv[])
{"gl-enable", required_argument, 0, 'E' },
{"gl-disable", required_argument, 0, 'D' },
{"stop-lockspaces", no_argument, 0, 'S' },
{"stderr", no_argument, 0, 'e' },
{0, 0, 0, 0 }
};
@@ -637,7 +962,7 @@ static int read_options(int argc, char *argv[])
}
while (1) {
c = getopt_long(argc, argv, "hqidE:D:w:k:r:S", long_options, &option_index);
c = getopt_long(argc, argv, "hqidE:D:w:k:r:Se", long_options, &option_index);
if (c == -1)
break;
@@ -663,23 +988,30 @@ static int read_options(int argc, char *argv[])
break;
case 'k':
kill_vg = 1;
free(arg_vg_name);
arg_vg_name = strdup(optarg);
break;
case 'r':
drop_vg = 1;
free(arg_vg_name);
arg_vg_name = strdup(optarg);
break;
case 'E':
gl_enable = 1;
free(arg_vg_name);
arg_vg_name = strdup(optarg);
break;
case 'D':
gl_disable = 1;
free(arg_vg_name);
arg_vg_name = strdup(optarg);
break;
case 'S':
stop_lockspaces = 1;
break;
case 'e':
use_stderr = 1;
break;
default:
print_usage();
exit(1);
@@ -698,8 +1030,12 @@ int main(int argc, char **argv)
if (rv < 0)
return rv;
_lvmlockd = lvmlockd_open(NULL);
/* do_kill handles lvmlockd connections itself */
if (kill_vg)
return do_kill();
_lvmlockd = lvmlockd_open(NULL);
if (_lvmlockd.socket_fd < 0 || _lvmlockd.error) {
log_error("Cannot connect to lvmlockd.");
return -1;
@@ -720,11 +1056,6 @@ int main(int argc, char **argv)
goto out;
}
if (kill_vg) {
rv = do_kill();
goto out;
}
if (drop_vg) {
rv = do_drop();
goto out;

View File

@@ -14,6 +14,7 @@
#include "libdaemon/client/daemon-client.h"
#define LVMLOCKD_SOCKET DEFAULT_RUN_DIR "/lvmlockd.socket"
#define LVMLOCKD_ADOPT_FILE DEFAULT_RUN_DIR "/lvmlockd.adopt"
/* Wrappers to open/close connection */
@@ -22,9 +23,9 @@ static inline daemon_handle lvmlockd_open(const char *sock)
daemon_info lvmlockd_info = {
.path = "lvmlockd",
.socket = sock ?: LVMLOCKD_SOCKET,
.autostart = 0,
.protocol = "lvmlockd",
.protocol_version = 1,
.autostart = 0
};
return daemon_open(lvmlockd_info);
@@ -32,7 +33,7 @@ static inline daemon_handle lvmlockd_open(const char *sock)
static inline void lvmlockd_close(daemon_handle h)
{
return daemon_close(h);
daemon_close(h);
}
/*

File diff suppressed because it is too large Load Diff

View File

@@ -119,6 +119,7 @@ static int read_cluster_name(char *clustername)
log_error(close_error_msg, fd);
return rv;
}
clustername[rv] = 0;
n = strstr(clustername, "\n");
if (n)
@@ -327,8 +328,7 @@ int lm_rem_resource_dlm(struct lockspace *ls, struct resource *r)
log_error("S %s R %s rem_resource_dlm unlock error %d", ls->name, r->name, rv);
}
out:
if (rdd->vb)
free(rdd->vb);
free(rdd->vb);
memset(rdd, 0, sizeof(struct rd_dlm));
r->lm_init = 0;
@@ -398,12 +398,18 @@ static int lm_adopt_dlm(struct lockspace *ls, struct resource *r, int ld_mode,
(void *)1, (void *)1, (void *)1,
NULL, NULL);
if (rv == -1 && errno == -EAGAIN) {
if (rv == -1 && (errno == EAGAIN)) {
log_debug("S %s R %s adopt_dlm adopt mode %d try other mode",
ls->name, r->name, ld_mode);
rv = -EUCLEAN;
goto fail;
}
if (rv == -1 && (errno == ENOENT)) {
log_debug("S %s R %s adopt_dlm adopt mode %d no lock",
ls->name, r->name, ld_mode);
rv = -ENOENT;
goto fail;
}
if (rv < 0) {
log_debug("S %s R %s adopt_dlm mode %d flags %x error %d errno %d",
ls->name, r->name, mode, flags, rv, errno);
@@ -785,17 +791,18 @@ int lm_is_running_dlm(void)
int lm_refresh_lv_start_dlm(struct action *act)
{
char path[PATH_MAX];
char path[PATH_MAX] = { 0 };
char command[DLMC_RUN_COMMAND_LEN];
char run_uuid[DLMC_RUN_UUID_LEN];
char *p, *vgname, *lvname;
int rv;
/* split /dev/vgname/lvname into vgname and lvname strings */
strncpy(path, act->path, strlen(act->path));
strncpy(path, act->path, PATH_MAX-1);
/* skip past dev */
p = strchr(path + 1, '/');
if (!(p = strchr(path + 1, '/')))
return -EINVAL;
/* skip past slashes */
while (*p == '/')

View File

@@ -0,0 +1,837 @@
/*
* Copyright (C) 2020-2021 Seagate Ltd.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v.2.1.
*/
#define _XOPEN_SOURCE 500 /* pthread */
#define _ISOC99_SOURCE
#include "tools/tool.h"
#include "daemon-server.h"
#include "lib/mm/xlate.h"
#include "lvmlockd-internal.h"
#include "daemons/lvmlockd/lvmlockd-client.h"
#include "ilm.h"
#include <blkid/blkid.h>
#include <ctype.h>
#include <dirent.h>
#include <errno.h>
#include <poll.h>
#include <regex.h>
#include <stddef.h>
#include <syslog.h>
#include <sys/sysmacros.h>
#include <time.h>
#define IDM_TIMEOUT 60000 /* unit: millisecond, 60 seconds */
/*
* Each lockspace thread has its own In-Drive Mutex (IDM) lock manager's
* connection. After established socket connection, the lockspace has
* been created in IDM lock manager and afterwards use the socket file
* descriptor to send any requests for lock related operations.
*/
struct lm_idm {
int sock; /* IDM lock manager connection */
};
struct rd_idm {
struct idm_lock_id id;
struct idm_lock_op op;
uint64_t vb_timestamp;
struct val_blk *vb;
};
int lm_data_size_idm(void)
{
return sizeof(struct rd_idm);
}
static uint64_t read_utc_us(void)
{
struct timespec cur_time;
clock_gettime(CLOCK_REALTIME, &cur_time);
/*
* Convert to microseconds unit. IDM reserves the MSB in 8 bytes
* and the low 56 bits are used for timestamp; 56 bits can support
* calendar year to 2284, so it has 260 years for overflow. Thus it
* is quite safe for overflow issue when wrote this code.
*/
return cur_time.tv_sec * 1000000 + cur_time.tv_nsec / 1000;
}
static int uuid_read_format(char *uuid_str, const char *buffer)
{
int out = 0;
/* just strip out any dashes */
while (*buffer) {
if (*buffer == '-') {
buffer++;
continue;
}
if (out >= 32) {
log_error("Too many characters to be uuid.");
return -1;
}
uuid_str[out++] = *buffer;
buffer++;
}
if (out != 32) {
log_error("Couldn't read uuid: incorrect number of "
"characters.");
return -1;
}
return 0;
}
#define SYSFS_ROOT "/sys"
#define BUS_SCSI_DEVS "/bus/scsi/devices"
static struct idm_lock_op glb_lock_op;
static void lm_idm_free_dir_list(struct dirent **dir_list, int dir_num)
{
int i;
for (i = 0; i < dir_num; ++i)
free(dir_list[i]);
free(dir_list);
}
static int lm_idm_scsi_directory_select(const struct dirent *s)
{
regex_t regex;
int ret;
/* Only select directory with the format x:x:x:x */
ret = regcomp(&regex, "^[0-9]+:[0-9]+:[0-9]+:[0-9]+$", REG_EXTENDED);
if (ret)
return 0;
ret = regexec(&regex, s->d_name, 0, NULL, 0);
if (!ret) {
regfree(&regex);
return 1;
}
regfree(&regex);
return 0;
}
static int lm_idm_scsi_find_block_dirctory(const char *block_path)
{
struct stat stats;
if ((stat(block_path, &stats) >= 0) && S_ISDIR(stats.st_mode))
return 0;
return -1;
}
static int lm_idm_scsi_block_node_select(const struct dirent *s)
{
if (DT_LNK != s->d_type && DT_DIR != s->d_type)
return 0;
if (DT_DIR == s->d_type) {
/* Skip this directory: '.' and parent: '..' */
if (!strcmp(s->d_name, ".") || !strcmp(s->d_name, ".."))
return 0;
}
return 1;
}
static int lm_idm_scsi_find_block_node(const char *blk_path, char **blk_dev)
{
struct dirent **dir_list;
int dir_num;
dir_num = scandir(blk_path, &dir_list, lm_idm_scsi_block_node_select, NULL);
if (dir_num < 0) {
log_error("Cannot find valid directory entry in %s", blk_path);
return -1;
}
/*
* Should have only one block name under the path, if the dir_num is
* not 1 (e.g. 0 or any number bigger than 1), it must be wrong and
* should never happen.
*/
if (dir_num == 1)
*blk_dev = strdup(dir_list[0]->d_name);
else
*blk_dev = NULL;
lm_idm_free_dir_list(dir_list, dir_num);
if (!*blk_dev)
return -1;
return dir_num;
}
static int lm_idm_scsi_search_propeller_partition(char *dev)
{
int i, nparts;
blkid_probe pr;
blkid_partlist ls;
int found = -1;
pr = blkid_new_probe_from_filename(dev);
if (!pr) {
log_error("%s: failed to create a new libblkid probe", dev);
return -1;
}
/* Binary interface */
ls = blkid_probe_get_partitions(pr);
if (!ls) {
log_error("%s: failed to read partitions", dev);
return -1;
}
/* List partitions */
nparts = blkid_partlist_numof_partitions(ls);
if (!nparts)
goto done;
for (i = 0; i < nparts; i++) {
const char *p;
blkid_partition par = blkid_partlist_get_partition(ls, i);
p = blkid_partition_get_name(par);
if (p) {
log_debug("partition name='%s'", p);
if (!strcmp(p, "propeller"))
found = blkid_partition_get_partno(par);
}
if (found >= 0)
break;
}
done:
blkid_free_probe(pr);
return found;
}
static char *lm_idm_scsi_get_block_device_node(const char *scsi_path)
{
char *blk_path = NULL;
char *blk_dev = NULL;
char *dev_node = NULL;
int ret;
/*
* Locate the "block" directory, such like:
* /sys/bus/scsi/devices/1:0:0:0/block
*/
ret = asprintf(&blk_path, "%s/%s", scsi_path, "block");
if (ret < 0) {
log_error("Fail to allocate block path for %s", scsi_path);
goto fail;
}
ret = lm_idm_scsi_find_block_dirctory(blk_path);
if (ret < 0) {
log_error("Fail to find block path %s", blk_path);
goto fail;
}
/*
* Locate the block device name, such like:
* /sys/bus/scsi/devices/1:0:0:0/block/sdb
*
* After return from this function and if it makes success,
* the global variable "blk_dev" points to the block device
* name, in this example it points to string "sdb".
*/
ret = lm_idm_scsi_find_block_node(blk_path, &blk_dev);
if (ret < 0) {
log_error("Fail to find block node");
goto fail;
}
ret = asprintf(&dev_node, "/dev/%s", blk_dev);
if (ret < 0) {
log_error("Fail to allocate memory for blk node path");
goto fail;
}
ret = lm_idm_scsi_search_propeller_partition(dev_node);
if (ret < 0)
goto fail;
free(blk_path);
free(blk_dev);
return dev_node;
fail:
free(blk_path);
free(blk_dev);
free(dev_node);
return NULL;
}
static int lm_idm_get_gl_lock_pv_list(void)
{
struct dirent **dir_list;
char scsi_bus_path[PATH_MAX];
char *drive_path;
int i, dir_num, ret;
if (glb_lock_op.drive_num)
return 0;
snprintf(scsi_bus_path, sizeof(scsi_bus_path), "%s%s",
SYSFS_ROOT, BUS_SCSI_DEVS);
dir_num = scandir(scsi_bus_path, &dir_list,
lm_idm_scsi_directory_select, NULL);
if (dir_num < 0) { /* scsi mid level may not be loaded */
log_error("Attached devices: none");
return -1;
}
for (i = 0; i < dir_num; i++) {
char *scsi_path;
ret = asprintf(&scsi_path, "%s/%s", scsi_bus_path,
dir_list[i]->d_name);
if (ret < 0) {
log_error("Fail to allocate memory for scsi directory");
goto failed;
}
if (glb_lock_op.drive_num >= ILM_DRIVE_MAX_NUM) {
log_error("Global lock: drive number %d exceeds limitation (%d) ?!",
glb_lock_op.drive_num, ILM_DRIVE_MAX_NUM);
free(scsi_path);
goto failed;
}
drive_path = lm_idm_scsi_get_block_device_node(scsi_path);
if (!drive_path) {
free(scsi_path);
continue;
}
glb_lock_op.drives[glb_lock_op.drive_num] = drive_path;
glb_lock_op.drive_num++;
free(scsi_path);
}
lm_idm_free_dir_list(dir_list, dir_num);
return 0;
failed:
lm_idm_free_dir_list(dir_list, dir_num);
for (i = 0; i < glb_lock_op.drive_num; i++) {
if (glb_lock_op.drives[i]) {
free(glb_lock_op.drives[i]);
glb_lock_op.drives[i] = NULL;
}
}
return -1;
}
static void lm_idm_update_vb_timestamp(uint64_t *vb_timestamp)
{
uint64_t utc_us = read_utc_us();
/*
* It's possible that the multiple nodes have no clock
* synchronization with microsecond prcision and the time
* is going backward. For this case, simply increment the
* existing timestamp and write out to drive.
*/
if (*vb_timestamp >= utc_us)
(*vb_timestamp)++;
else
*vb_timestamp = utc_us;
}
int lm_prepare_lockspace_idm(struct lockspace *ls)
{
struct lm_idm *lm = NULL;
lm = malloc(sizeof(struct lm_idm));
if (!lm) {
log_error("S %s prepare_lockspace_idm fail to allocate lm_idm for %s",
ls->name, ls->vg_name);
return -ENOMEM;
}
memset(lm, 0x0, sizeof(struct lm_idm));
ls->lm_data = lm;
log_debug("S %s prepare_lockspace_idm done", ls->name);
return 0;
}
int lm_add_lockspace_idm(struct lockspace *ls, int adopt)
{
char killpath[IDM_FAILURE_PATH_LEN];
char killargs[IDM_FAILURE_ARGS_LEN];
struct lm_idm *lmi = (struct lm_idm *)ls->lm_data;
int rv;
if (daemon_test)
return 0;
if (!strcmp(ls->name, S_NAME_GL_IDM)) {
/*
* Prepare the pv list for global lock, if the drive contains
* "propeller" partition, then this drive will be considered
* as a member of pv list.
*/
rv = lm_idm_get_gl_lock_pv_list();
if (rv < 0) {
log_error("S %s add_lockspace_idm fail to get pv list for glb lock",
ls->name);
return -EIO;
} else {
log_error("S %s add_lockspace_idm get pv list for glb lock",
ls->name);
}
}
/*
* Construct the execution path for command "lvmlockctl" by using the
* path to the lvm binary and appending "lockctl".
*/
memset(killpath, 0, sizeof(killpath));
snprintf(killpath, IDM_FAILURE_PATH_LEN, "%slockctl", LVM_PATH);
/* Pass the argument "--kill vg_name" for killpath */
memset(killargs, 0, sizeof(killargs));
snprintf(killargs, IDM_FAILURE_ARGS_LEN, "--kill %s", ls->vg_name);
/* Connect with IDM lock manager per every lockspace. */
rv = ilm_connect(&lmi->sock);
if (rv < 0) {
log_error("S %s add_lockspace_idm fail to connect the lock manager %d",
ls->name, lmi->sock);
lmi->sock = 0;
rv = -EMANAGER;
goto fail;
}
rv = ilm_set_killpath(lmi->sock, killpath, killargs);
if (rv < 0) {
log_error("S %s add_lockspace_idm fail to set kill path %d",
ls->name, rv);
rv = -EMANAGER;
goto fail;
}
log_debug("S %s add_lockspace_idm kill path is: \"%s %s\"",
ls->name, killpath, killargs);
log_debug("S %s add_lockspace_idm done", ls->name);
return 0;
fail:
if (lmi && lmi->sock)
close(lmi->sock);
free(lmi);
return rv;
}
int lm_rem_lockspace_idm(struct lockspace *ls, int free_vg)
{
struct lm_idm *lmi = (struct lm_idm *)ls->lm_data;
int i, rv = 0;
if (daemon_test)
goto out;
rv = ilm_disconnect(lmi->sock);
if (rv < 0)
log_error("S %s rem_lockspace_idm error %d", ls->name, rv);
/* Release pv list for global lock */
if (!strcmp(ls->name, "lvm_global")) {
for (i = 0; i < glb_lock_op.drive_num; i++) {
if (glb_lock_op.drives[i]) {
free(glb_lock_op.drives[i]);
glb_lock_op.drives[i] = NULL;
}
}
}
out:
free(lmi);
ls->lm_data = NULL;
return rv;
}
static int lm_add_resource_idm(struct lockspace *ls, struct resource *r)
{
struct rd_idm *rdi = (struct rd_idm *)r->lm_data;
if (r->type == LD_RT_GL || r->type == LD_RT_VG) {
rdi->vb = zalloc(sizeof(struct val_blk));
if (!rdi->vb)
return -ENOMEM;
}
return 0;
}
int lm_rem_resource_idm(struct lockspace *ls, struct resource *r)
{
struct rd_idm *rdi = (struct rd_idm *)r->lm_data;
free(rdi->vb);
memset(rdi, 0, sizeof(struct rd_idm));
r->lm_init = 0;
return 0;
}
static int to_idm_mode(int ld_mode)
{
switch (ld_mode) {
case LD_LK_EX:
return IDM_MODE_EXCLUSIVE;
case LD_LK_SH:
return IDM_MODE_SHAREABLE;
default:
break;
};
return -1;
}
int lm_lock_idm(struct lockspace *ls, struct resource *r, int ld_mode,
struct val_blk *vb_out, char *lv_uuid, struct pvs *pvs,
int adopt)
{
struct lm_idm *lmi = (struct lm_idm *)ls->lm_data;
struct rd_idm *rdi = (struct rd_idm *)r->lm_data;
char **drive_path = NULL;
uint64_t timestamp;
int reset_vb = 0;
int rv, i;
if (!r->lm_init) {
rv = lm_add_resource_idm(ls, r);
if (rv < 0)
return rv;
r->lm_init = 1;
}
rdi->op.mode = to_idm_mode(ld_mode);
if (rv < 0) {
log_error("lock_idm invalid mode %d", ld_mode);
return -EINVAL;
}
log_debug("S %s R %s lock_idm", ls->name, r->name);
if (daemon_test) {
if (rdi->vb) {
vb_out->version = le16_to_cpu(rdi->vb->version);
vb_out->flags = le16_to_cpu(rdi->vb->flags);
vb_out->r_version = le32_to_cpu(rdi->vb->r_version);
}
return 0;
}
rdi->op.timeout = IDM_TIMEOUT;
/*
* Generate the UUID string, for RT_VG, it only needs to generate
* UUID string for VG level, for RT_LV, it needs to generate
* UUID strings for both VG and LV levels. At the end, these IDs
* are used as identifier for IDM in drive firmware.
*/
if (r->type == LD_RT_VG || r->type == LD_RT_LV)
log_debug("S %s R %s VG uuid %s", ls->name, r->name, ls->vg_uuid);
if (r->type == LD_RT_LV)
log_debug("S %s R %s LV uuid %s", ls->name, r->name, lv_uuid);
memset(&rdi->id, 0x0, sizeof(struct idm_lock_id));
if (r->type == LD_RT_VG) {
uuid_read_format(rdi->id.vg_uuid, ls->vg_uuid);
} else if (r->type == LD_RT_LV) {
uuid_read_format(rdi->id.vg_uuid, ls->vg_uuid);
uuid_read_format(rdi->id.lv_uuid, lv_uuid);
}
/*
* Establish the drive path list for lock, since different lock type
* has different drive list; the GL lock uses the global pv list,
* the VG lock uses the pv list spanned for the whole volume group,
* the LV lock uses the pv list for the logical volume.
*/
switch (r->type) {
case LD_RT_GL:
drive_path = glb_lock_op.drives;
rdi->op.drive_num = glb_lock_op.drive_num;
break;
case LD_RT_VG:
drive_path = (char **)ls->pvs.path;
rdi->op.drive_num = ls->pvs.num;
break;
case LD_RT_LV:
drive_path = (char **)pvs->path;
rdi->op.drive_num = pvs->num;
break;
default:
break;
}
if (!drive_path) {
log_error("S %s R %s cannot find the valid drive path array",
ls->name, r->name);
return -EINVAL;
}
if (rdi->op.drive_num >= ILM_DRIVE_MAX_NUM) {
log_error("S %s R %s exceeds limitation for drive path array",
ls->name, r->name);
return -EINVAL;
}
for (i = 0; i < rdi->op.drive_num; i++)
rdi->op.drives[i] = drive_path[i];
log_debug("S %s R %s mode %d drive_num %d timeout %d",
ls->name, r->name, rdi->op.mode,
rdi->op.drive_num, rdi->op.timeout);
for (i = 0; i < rdi->op.drive_num; i++)
log_debug("S %s R %s drive path[%d] %s",
ls->name, r->name, i, rdi->op.drives[i]);
rv = ilm_lock(lmi->sock, &rdi->id, &rdi->op);
if (rv < 0) {
log_debug("S %s R %s lock_idm acquire mode %d rv %d",
ls->name, r->name, ld_mode, rv);
return -ELOCKIO;
}
if (rdi->vb) {
rv = ilm_read_lvb(lmi->sock, &rdi->id, (char *)&timestamp,
sizeof(uint64_t));
/*
* If fail to read value block, which might be caused by drive
* failure, notify up layer to invalidate metadata.
*/
if (rv < 0) {
log_error("S %s R %s lock_idm get_lvb error %d",
ls->name, r->name, rv);
reset_vb = 1;
/* Reset timestamp */
rdi->vb_timestamp = 0;
/*
* If the cached timestamp mismatches with the stored value
* in the IDM, this means another host has updated timestamp
* for the new VB. Let's reset VB and notify up layer to
* invalidate metadata.
*/
} else if (rdi->vb_timestamp != timestamp) {
log_debug("S %s R %s lock_idm get lvb timestamp %lu:%lu",
ls->name, r->name, rdi->vb_timestamp,
timestamp);
rdi->vb_timestamp = timestamp;
reset_vb = 1;
}
if (reset_vb == 1) {
memset(rdi->vb, 0, sizeof(struct val_blk));
memset(vb_out, 0, sizeof(struct val_blk));
/*
* The lock is still acquired, but the vb values has
* been invalidated.
*/
rv = 0;
goto out;
}
/* Otherwise, copy the cached VB to up layer */
memcpy(vb_out, rdi->vb, sizeof(struct val_blk));
}
out:
return rv;
}
int lm_convert_idm(struct lockspace *ls, struct resource *r,
int ld_mode, uint32_t r_version)
{
struct lm_idm *lmi = (struct lm_idm *)ls->lm_data;
struct rd_idm *rdi = (struct rd_idm *)r->lm_data;
int mode, rv;
if (rdi->vb && r_version && (r->mode == LD_LK_EX)) {
if (!rdi->vb->version) {
/* first time vb has been written */
rdi->vb->version = VAL_BLK_VERSION;
}
rdi->vb->r_version = r_version;
log_debug("S %s R %s convert_idm set r_version %u",
ls->name, r->name, r_version);
lm_idm_update_vb_timestamp(&rdi->vb_timestamp);
log_debug("S %s R %s convert_idm vb %x %x %u timestamp %lu",
ls->name, r->name, rdi->vb->version, rdi->vb->flags,
rdi->vb->r_version, rdi->vb_timestamp);
}
mode = to_idm_mode(ld_mode);
if (mode < 0) {
log_error("S %s R %s convert_idm invalid mode %d",
ls->name, r->name, ld_mode);
return -EINVAL;
}
log_debug("S %s R %s convert_idm", ls->name, r->name);
if (daemon_test)
return 0;
if (rdi->vb && r_version && (r->mode == LD_LK_EX)) {
rv = ilm_write_lvb(lmi->sock, &rdi->id,
(char *)rdi->vb_timestamp, sizeof(uint64_t));
if (rv < 0) {
log_error("S %s R %s convert_idm write lvb error %d",
ls->name, r->name, rv);
return -ELMERR;
}
}
rv = ilm_convert(lmi->sock, &rdi->id, mode);
if (rv < 0)
log_error("S %s R %s convert_idm convert error %d",
ls->name, r->name, rv);
return rv;
}
int lm_unlock_idm(struct lockspace *ls, struct resource *r,
uint32_t r_version, uint32_t lmu_flags)
{
struct lm_idm *lmi = (struct lm_idm *)ls->lm_data;
struct rd_idm *rdi = (struct rd_idm *)r->lm_data;
int rv;
if (rdi->vb && r_version && (r->mode == LD_LK_EX)) {
if (!rdi->vb->version) {
/* first time vb has been written */
rdi->vb->version = VAL_BLK_VERSION;
}
if (r_version)
rdi->vb->r_version = r_version;
lm_idm_update_vb_timestamp(&rdi->vb_timestamp);
log_debug("S %s R %s unlock_idm vb %x %x %u timestamp %lu",
ls->name, r->name, rdi->vb->version, rdi->vb->flags,
rdi->vb->r_version, rdi->vb_timestamp);
}
log_debug("S %s R %s unlock_idm", ls->name, r->name);
if (daemon_test)
return 0;
if (rdi->vb && r_version && (r->mode == LD_LK_EX)) {
rv = ilm_write_lvb(lmi->sock, &rdi->id,
(char *)&rdi->vb_timestamp, sizeof(uint64_t));
if (rv < 0) {
log_error("S %s R %s unlock_idm set_lvb error %d",
ls->name, r->name, rv);
return -ELMERR;
}
}
rv = ilm_unlock(lmi->sock, &rdi->id);
if (rv < 0)
log_error("S %s R %s unlock_idm error %d", ls->name, r->name, rv);
return rv;
}
int lm_hosts_idm(struct lockspace *ls, int notify)
{
struct resource *r;
struct lm_idm *lmi = (struct lm_idm *)ls->lm_data;
struct rd_idm *rdi;
int count, self, found_others = 0;
int rv;
list_for_each_entry(r, &ls->resources, list) {
if (!r->lm_init)
continue;
rdi = (struct rd_idm *)r->lm_data;
rv = ilm_get_host_count(lmi->sock, &rdi->id, &rdi->op,
&count, &self);
if (rv < 0) {
log_error("S %s lm_hosts_idm error %d", ls->name, rv);
return rv;
}
/* Fixup: need to reduce self count */
if (count > found_others)
found_others = count;
}
return found_others;
}
int lm_get_lockspaces_idm(struct list_head *ls_rejoin)
{
/* TODO: Need to add support for adoption. */
return -1;
}
int lm_is_running_idm(void)
{
int sock, rv;
if (daemon_test)
return gl_use_idm;
rv = ilm_connect(&sock);
if (rv < 0) {
log_error("Fail to connect seagate IDM lock manager %d", rv);
return 0;
}
ilm_disconnect(sock);
return 1;
}

View File

@@ -11,6 +11,8 @@
#ifndef _LVM_LVMLOCKD_INTERNAL_H
#define _LVM_LVMLOCKD_INTERNAL_H
#include "base/memory/container_of.h"
#define MAX_NAME 64
#define MAX_ARGS 64
@@ -18,6 +20,7 @@
#define R_NAME_GL "GLLK"
#define R_NAME_VG "VGLK"
#define S_NAME_GL_DLM "lvm_global"
#define S_NAME_GL_IDM "lvm_global"
#define LVM_LS_PREFIX "lvm_" /* ls name is prefix + vg_name */
/* global lockspace name for sanlock is a vg name */
@@ -27,6 +30,7 @@ enum {
LD_LM_UNUSED = 1, /* place holder so values match lib/locking/lvmlockd.h */
LD_LM_DLM = 2,
LD_LM_SANLOCK = 3,
LD_LM_IDM = 4,
};
/* operation types */
@@ -116,6 +120,11 @@ struct client {
*/
#define DEFAULT_MAX_RETRIES 4
struct pvs {
char **path;
int num;
};
struct action {
struct list_head list;
uint32_t client_id;
@@ -138,6 +147,7 @@ struct action {
char vg_args[MAX_ARGS+1];
char lv_args[MAX_ARGS+1];
char vg_sysid[MAX_NAME+1];
struct pvs pvs; /* PV list for idm */
};
struct resource {
@@ -145,6 +155,7 @@ struct resource {
char name[MAX_NAME+1]; /* vg name or lv name */
int8_t type; /* resource type LD_RT_ */
int8_t mode;
int8_t adopt_mode;
unsigned int sh_count; /* number of sh locks on locks list */
uint32_t version;
uint32_t last_client_id; /* last client_id to lock or unlock resource */
@@ -155,7 +166,7 @@ struct resource {
struct list_head locks;
struct list_head actions;
char lv_args[MAX_ARGS+1];
char lm_data[0]; /* lock manager specific data */
char lm_data[]; /* lock manager specific data */
};
#define LD_LF_PERSISTENT 0x00000001
@@ -181,6 +192,7 @@ struct lockspace {
uint64_t free_lock_offset; /* for sanlock, start search for free lock here */
int free_lock_sector_size; /* for sanlock */
int free_lock_align_size; /* for sanlock */
struct pvs pvs; /* for idm: PV list */
uint32_t start_client_id; /* client_id that started the lockspace */
pthread_t thread; /* makes synchronous lock requests */
@@ -216,10 +228,6 @@ struct val_blk {
/* lm_unlock flags */
#define LMUF_FREE_VG 0x00000001
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
static inline void INIT_LIST_HEAD(struct list_head *list)
{
list->next = list;
@@ -326,10 +334,13 @@ static inline int list_empty(const struct list_head *head)
EXTERN int gl_type_static;
EXTERN int gl_use_dlm;
EXTERN int gl_use_sanlock;
EXTERN int gl_use_idm;
EXTERN int gl_vg_removed;
EXTERN char gl_lsname_dlm[MAX_NAME+1];
EXTERN char gl_lsname_sanlock[MAX_NAME+1];
EXTERN char gl_lsname_idm[MAX_NAME+1];
EXTERN int global_dlm_lockspace_exists;
EXTERN int global_idm_lockspace_exists;
EXTERN int daemon_test; /* run as much as possible without a live lock manager */
EXTERN int daemon_debug;
@@ -620,4 +631,102 @@ static inline int lm_support_sanlock(void)
#endif /* sanlock support */
#ifdef LOCKDIDM_SUPPORT
int lm_data_size_idm(void);
int lm_init_vg_idm(char *ls_name, char *vg_name, uint32_t flags, char *vg_args);
int lm_prepare_lockspace_idm(struct lockspace *ls);
int lm_add_lockspace_idm(struct lockspace *ls, int adopt);
int lm_rem_lockspace_idm(struct lockspace *ls, int free_vg);
int lm_lock_idm(struct lockspace *ls, struct resource *r, int ld_mode,
struct val_blk *vb_out, char *lv_uuid, struct pvs *pvs,
int adopt);
int lm_convert_idm(struct lockspace *ls, struct resource *r,
int ld_mode, uint32_t r_version);
int lm_unlock_idm(struct lockspace *ls, struct resource *r,
uint32_t r_version, uint32_t lmu_flags);
int lm_hosts_idm(struct lockspace *ls, int notify);
int lm_get_lockspaces_idm(struct list_head *ls_rejoin);
int lm_is_running_idm(void);
int lm_rem_resource_idm(struct lockspace *ls, struct resource *r);
static inline int lm_support_idm(void)
{
return 1;
}
#else
static inline int lm_data_size_idm(void)
{
return -1;
}
static inline int lm_init_vg_idm(char *ls_name, char *vg_name, uint32_t flags,
char *vg_args)
{
return -1;
}
static inline int lm_prepare_lockspace_idm(struct lockspace *ls)
{
return -1;
}
static inline int lm_add_lockspace_idm(struct lockspace *ls, int adopt)
{
return -1;
}
static inline int lm_rem_lockspace_idm(struct lockspace *ls, int free_vg)
{
return -1;
}
static inline int lm_lock_idm(struct lockspace *ls, struct resource *r, int ld_mode,
struct val_blk *vb_out, char *lv_uuid, struct pvs *pvs,
int adopt)
{
return -1;
}
static inline int lm_convert_idm(struct lockspace *ls, struct resource *r,
int ld_mode, uint32_t r_version)
{
return -1;
}
static inline int lm_unlock_idm(struct lockspace *ls, struct resource *r,
uint32_t r_version, uint32_t lmu_flags)
{
return -1;
}
static inline int lm_hosts_idm(struct lockspace *ls, int notify)
{
return -1;
}
static inline int lm_get_lockspaces_idm(struct list_head *ls_rejoin)
{
return -1;
}
static inline int lm_is_running_idm(void)
{
return 0;
}
static inline int lm_rem_resource_idm(struct lockspace *ls, struct resource *r)
{
return -1;
}
static inline int lm_support_idm(void)
{
return 0;
}
#endif /* Seagate IDM support */
#endif /* _LVM_LVMLOCKD_INTERNAL_H */

View File

@@ -227,6 +227,17 @@ int lm_data_size_sanlock(void)
static uint64_t daemon_test_lv_count;
/*
* Copy a null-terminated string "str" into a fixed
* size (SANLK_NAME_LEN) struct field "buf" which is
* not null terminated.
*/
static void strcpy_name_len(char *buf, char *str, int len)
{
/* coverity[buffer_size_warning] */
strncpy(buf, str, SANLK_NAME_LEN);
}
static int lock_lv_name_from_args(char *vg_args, char *lock_lv_name)
{
return last_string_from_args(vg_args, lock_lv_name);
@@ -574,7 +585,7 @@ int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_ar
}
}
strncpy(ss.name, ls_name, SANLK_NAME_LEN);
strcpy_name_len(ss.name, ls_name, SANLK_NAME_LEN);
memcpy(ss.host_id_disk.path, disk.path, SANLK_PATH_LEN);
ss.host_id_disk.offset = 0;
ss.flags = (sector_size == 4096) ? (SANLK_LSF_SECTOR4K | SANLK_LSF_ALIGN8M) :
@@ -607,7 +618,7 @@ int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_ar
gl_name = R_NAME_GL;
memcpy(rd.rs.lockspace_name, ss.name, SANLK_NAME_LEN);
strncpy(rd.rs.name, gl_name, SANLK_NAME_LEN);
strcpy_name_len(rd.rs.name, (char *)gl_name, SANLK_NAME_LEN);
memcpy(rd.rs.disks[0].path, disk.path, SANLK_PATH_LEN);
rd.rs.disks[0].offset = align_size * GL_LOCK_BEGIN;
rd.rs.num_disks = 1;
@@ -622,7 +633,7 @@ int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_ar
}
memcpy(rd.rs.lockspace_name, ss.name, SANLK_NAME_LEN);
strncpy(rd.rs.name, R_NAME_VG, SANLK_NAME_LEN);
strcpy_name_len(rd.rs.name, (char *)R_NAME_VG, SANLK_NAME_LEN);
memcpy(rd.rs.disks[0].path, disk.path, SANLK_PATH_LEN);
rd.rs.disks[0].offset = align_size * VG_LOCK_BEGIN;
rd.rs.num_disks = 1;
@@ -656,8 +667,8 @@ int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_ar
rd.rs.flags = (sector_size == 4096) ? (SANLK_RES_SECTOR4K | SANLK_RES_ALIGN8M) :
(SANLK_RES_SECTOR512 | SANLK_RES_ALIGN1M);
memcpy(rd.rs.disks[0].path, disk.path, SANLK_PATH_LEN);
strncpy(rd.rs.lockspace_name, ls_name, SANLK_NAME_LEN);
strcpy(rd.rs.name, "#unused");
strcpy_name_len(rd.rs.lockspace_name, ls_name, SANLK_NAME_LEN);
strcpy_name_len(rd.rs.name, (char *)"#unused", SANLK_NAME_LEN);
offset = align_size * LV_LOCK_BEGIN;
@@ -725,7 +736,7 @@ int lm_init_lv_sanlock(char *ls_name, char *vg_name, char *lv_name,
return 0;
}
strncpy(rd.rs.lockspace_name, ls_name, SANLK_NAME_LEN);
strcpy_name_len(rd.rs.lockspace_name, ls_name, SANLK_NAME_LEN);
rd.rs.num_disks = 1;
if ((rv = build_dm_path(rd.rs.disks[0].path, SANLK_PATH_LEN, vg_name, lock_lv_name)))
return rv;
@@ -800,7 +811,7 @@ int lm_init_lv_sanlock(char *ls_name, char *vg_name, char *lv_name,
log_debug("S %s init_lv_san %s found unused area at %llu",
ls_name, lv_name, (unsigned long long)offset);
strncpy(rd.rs.name, lv_name, SANLK_NAME_LEN);
strcpy_name_len(rd.rs.name, lv_name, SANLK_NAME_LEN);
rd.rs.flags = (sector_size == 4096) ? (SANLK_RES_SECTOR4K | SANLK_RES_ALIGN8M) :
(SANLK_RES_SECTOR512 | SANLK_RES_ALIGN1M);
@@ -899,7 +910,7 @@ int lm_rename_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_
if (!sector_size || !align_size)
return -1;
strncpy(ss.name, ls_name, SANLK_NAME_LEN);
strcpy_name_len(ss.name, ls_name, SANLK_NAME_LEN);
rv = sanlock_write_lockspace(&ss, 0, 0, sanlock_io_timeout);
if (rv < 0) {
@@ -924,7 +935,7 @@ int lm_rename_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_
return rv;
}
strncpy(rd.rs.lockspace_name, ss.name, SANLK_NAME_LEN);
memcpy(rd.rs.lockspace_name, ss.name, SANLK_NAME_LEN);
rv = sanlock_write_resource(&rd.rs, 0, 0, 0);
if (rv < 0) {
@@ -949,7 +960,7 @@ int lm_rename_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_
return rv;
}
strncpy(rd.rs.lockspace_name, ss.name, SANLK_NAME_LEN);
memcpy(rd.rs.lockspace_name, ss.name, SANLK_NAME_LEN);
rv = sanlock_write_resource(&rd.rs, 0, 0, 0);
if (rv < 0) {
@@ -983,7 +994,7 @@ int lm_rename_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_
break;
}
strncpy(rd.rs.lockspace_name, ss.name, SANLK_NAME_LEN);
memcpy(rd.rs.lockspace_name, ss.name, SANLK_NAME_LEN);
rv = sanlock_write_resource(&rd.rs, 0, 0, 0);
if (rv) {
@@ -1009,7 +1020,7 @@ int lm_free_lv_sanlock(struct lockspace *ls, struct resource *r)
if (daemon_test)
return 0;
strcpy(rs->name, "#unused");
strcpy_name_len(rs->name, (char *)"#unused", SANLK_NAME_LEN);
rv = sanlock_write_resource(rs, 0, 0, 0);
if (rv < 0) {
@@ -1043,14 +1054,14 @@ int lm_ex_disable_gl_sanlock(struct lockspace *ls)
memset(&rd1, 0, sizeof(rd1));
memset(&rd2, 0, sizeof(rd2));
strncpy(rd1.rs.lockspace_name, ls->name, SANLK_NAME_LEN);
strncpy(rd1.rs.name, R_NAME_GL, SANLK_NAME_LEN);
strcpy_name_len(rd1.rs.lockspace_name, ls->name, SANLK_NAME_LEN);
strcpy_name_len(rd1.rs.name, (char *)R_NAME_GL, SANLK_NAME_LEN);
strncpy(rd2.rs.lockspace_name, ls->name, SANLK_NAME_LEN);
strncpy(rd2.rs.name, R_NAME_GL_DISABLED, SANLK_NAME_LEN);
strcpy_name_len(rd2.rs.lockspace_name, ls->name, SANLK_NAME_LEN);
strcpy_name_len(rd2.rs.name, (char *)R_NAME_GL_DISABLED, SANLK_NAME_LEN);
rd1.rs.num_disks = 1;
strncpy(rd1.rs.disks[0].path, lms->ss.host_id_disk.path, SANLK_PATH_LEN-1);
memcpy(rd1.rs.disks[0].path, lms->ss.host_id_disk.path, SANLK_PATH_LEN-1);
rd1.rs.disks[0].offset = lms->align_size * GL_LOCK_BEGIN;
rd1.rs.flags = (lms->sector_size == 4096) ? (SANLK_RES_SECTOR4K | SANLK_RES_ALIGN8M) :
@@ -1112,11 +1123,11 @@ int lm_able_gl_sanlock(struct lockspace *ls, int enable)
memset(&rd, 0, sizeof(rd));
strncpy(rd.rs.lockspace_name, ls->name, SANLK_NAME_LEN);
strncpy(rd.rs.name, gl_name, SANLK_NAME_LEN);
strcpy_name_len(rd.rs.lockspace_name, ls->name, SANLK_NAME_LEN);
strcpy_name_len(rd.rs.name, (char *)gl_name, SANLK_NAME_LEN);
rd.rs.num_disks = 1;
strncpy(rd.rs.disks[0].path, lms->ss.host_id_disk.path, SANLK_PATH_LEN-1);
memcpy(rd.rs.disks[0].path, lms->ss.host_id_disk.path, SANLK_PATH_LEN-1);
rd.rs.disks[0].offset = lms->align_size * GL_LOCK_BEGIN;
rd.rs.flags = (lms->sector_size == 4096) ? (SANLK_RES_SECTOR4K | SANLK_RES_ALIGN8M) :
(SANLK_RES_SECTOR512 | SANLK_RES_ALIGN1M);
@@ -1153,12 +1164,12 @@ static int gl_is_enabled(struct lockspace *ls, struct lm_sanlock *lms)
memset(&rd, 0, sizeof(rd));
strncpy(rd.rs.lockspace_name, ls->name, SANLK_NAME_LEN);
strcpy_name_len(rd.rs.lockspace_name, ls->name, SANLK_NAME_LEN);
/* leave rs.name empty, it is what we're checking */
rd.rs.num_disks = 1;
strncpy(rd.rs.disks[0].path, lms->ss.host_id_disk.path, SANLK_PATH_LEN-1);
memcpy(rd.rs.disks[0].path, lms->ss.host_id_disk.path, SANLK_PATH_LEN-1);
offset = lms->align_size * GL_LOCK_BEGIN;
rd.rs.disks[0].offset = offset;
@@ -1224,9 +1235,9 @@ int lm_find_free_lock_sanlock(struct lockspace *ls, uint64_t *free_offset, int *
memset(&rd, 0, sizeof(rd));
strncpy(rd.rs.lockspace_name, ls->name, SANLK_NAME_LEN);
strcpy_name_len(rd.rs.lockspace_name, ls->name, SANLK_NAME_LEN);
rd.rs.num_disks = 1;
strncpy(rd.rs.disks[0].path, lms->ss.host_id_disk.path, SANLK_PATH_LEN-1);
memcpy(rd.rs.disks[0].path, lms->ss.host_id_disk.path, SANLK_PATH_LEN-1);
rd.rs.flags = (lms->sector_size == 4096) ? (SANLK_RES_SECTOR4K | SANLK_RES_ALIGN8M) :
(SANLK_RES_SECTOR512 | SANLK_RES_ALIGN1M);
@@ -1411,7 +1422,7 @@ int lm_prepare_lockspace_sanlock(struct lockspace *ls)
memcpy(lms->ss.name, lsname, SANLK_NAME_LEN);
lms->ss.host_id_disk.offset = 0;
lms->ss.host_id = ls->host_id;
strncpy(lms->ss.host_id_disk.path, disk_path, SANLK_PATH_LEN-1);
memcpy(lms->ss.host_id_disk.path, disk_path, SANLK_PATH_LEN-1);
if (daemon_test) {
if (!gl_lsname_sanlock[0]) {
@@ -1503,8 +1514,7 @@ out:
fail:
if (lms && lms->sock)
close(lms->sock);
if (lms)
free(lms);
free(lms);
return ret;
}
@@ -1566,10 +1576,8 @@ int lm_rem_lockspace_sanlock(struct lockspace *ls, int free_vg)
goto out;
rv = sanlock_rem_lockspace(&lms->ss, 0);
if (rv < 0) {
if (rv < 0)
log_error("S %s rem_lockspace_san error %d", ls->name, rv);
return rv;
}
if (free_vg) {
/*
@@ -1578,7 +1586,7 @@ int lm_rem_lockspace_sanlock(struct lockspace *ls, int free_vg)
* This shouldn't be generally necessary, but there may some races
* between nodes starting and removing a vg which this could help.
*/
strncpy(lms->ss.name, "#unused", SANLK_NAME_LEN);
strcpy_name_len(lms->ss.name, (char *)"#unused", SANLK_NAME_LEN);
rv = sanlock_write_lockspace(&lms->ss, 0, 0, sanlock_io_timeout);
if (rv < 0) {
@@ -1606,8 +1614,8 @@ static int lm_add_resource_sanlock(struct lockspace *ls, struct resource *r)
struct lm_sanlock *lms = (struct lm_sanlock *)ls->lm_data;
struct rd_sanlock *rds = (struct rd_sanlock *)r->lm_data;
strncpy(rds->rs.lockspace_name, ls->name, SANLK_NAME_LEN);
strncpy(rds->rs.name, r->name, SANLK_NAME_LEN);
strcpy_name_len(rds->rs.lockspace_name, ls->name, SANLK_NAME_LEN);
strcpy_name_len(rds->rs.name, r->name, SANLK_NAME_LEN);
rds->rs.num_disks = 1;
memcpy(rds->rs.disks[0].path, lms->ss.host_id_disk.path, SANLK_PATH_LEN);
rds->rs.flags = (lms->sector_size == 4096) ? (SANLK_RES_SECTOR4K | SANLK_RES_ALIGN8M) : (SANLK_RES_SECTOR512 | SANLK_RES_ALIGN1M);
@@ -1634,8 +1642,7 @@ int lm_rem_resource_sanlock(struct lockspace *ls, struct resource *r)
/* FIXME: assert r->mode == UN or unlock if it's not? */
if (rds->vb)
free(rds->vb);
free(rds->vb);
memset(rds, 0, sizeof(struct rd_sanlock));
r->lm_init = 0;
@@ -1651,7 +1658,7 @@ int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode,
struct sanlk_options opt;
uint64_t lock_lv_offset;
uint32_t flags = 0;
struct val_blk vb;
struct val_blk vb = { 0 };
int added = 0;
int rv;
@@ -2037,7 +2044,7 @@ static int release_rename(struct lockspace *ls, struct resource *r)
res1 = (struct sanlk_resource *)&rd1;
res2 = (struct sanlk_resource *)&rd2;
strcpy(res2->name, "invalid_removed");
strcpy_name_len(res2->name, (char *)"invalid_removed", SANLK_NAME_LEN);
res_args[0] = res1;
res_args[1] = res2;
@@ -2230,8 +2237,8 @@ int lm_get_lockspaces_sanlock(struct list_head *ls_rejoin)
ls->lm_type = LD_LM_SANLOCK;
ls->host_id = ss->host_id;
strncpy(ls->name, ss->name, MAX_NAME);
strncpy(ls->vg_name, ss->name + strlen(LVM_LS_PREFIX), MAX_NAME);
memcpy(ls->name, ss->name, SANLK_NAME_LEN);
memcpy(ls->vg_name, ss->name + strlen(LVM_LS_PREFIX), SANLK_NAME_LEN - strlen(LVM_LS_PREFIX));
list_add_tail(&ls->list, ls_rejoin);
ss++;

View File

@@ -19,11 +19,10 @@ SOURCES = lvmpolld-core.c lvmpolld-data-utils.c lvmpolld-cmd-utils.c
TARGETS = lvmpolld
.PHONY: install_lvmpolld
CFLOW_SOURCES = $(addprefix $(srcdir)/, $(SOURCES))
CFLOW_TARGET := $(TARGETS)
CFLOW_LIST = $(SOURCES)
CFLOW_LIST_TARGET = $(LIB_NAME).cflow
CFLOW_TARGET = lvmpolld
.PHONY: install_lvmpolld
include $(top_builddir)/make.tmpl

View File

@@ -92,6 +92,12 @@ const char **cmdargv_ctr(const struct lvmpolld_lv *pdlv, const char *lvm_binary,
if (!add_to_cmd_arr(&cmd_argv, "-An", &i))
goto err;
if (pdlv->devicesfile) {
if (!add_to_cmd_arr(&cmd_argv, "--devicesfile", &i) ||
!add_to_cmd_arr(&cmd_argv, pdlv->devicesfile, &i))
goto err;
}
/* terminating NULL */
if (!add_to_cmd_arr(&cmd_argv, NULL, &i))
goto err;

View File

@@ -149,7 +149,7 @@ static void _lvmpolld_global_unlock(struct lvmpolld_state *ls)
static int _fini(struct daemon_state *s)
{
int done;
const struct timespec t = { .tv_nsec = 250000000 }; /* .25 sec */
const struct timespec t = { .tv_nsec = 10000000 }; /* .01 sec */
struct lvmpolld_state *ls = s->private;
DEBUGLOG(s, "fini");
@@ -236,9 +236,7 @@ static int poll_for_output(struct lvmpolld_lv *pdlv, struct lvmpolld_thread_data
}
while (1) {
do {
r = poll(fds, 2, pdlv_get_timeout(pdlv) * 1000);
} while (r < 0 && errno == EINTR);
r = poll(fds, 2, pdlv_get_timeout(pdlv) * 1000);
DEBUGLOG(pdlv->ls, "%s: %s %d", PD_LOG_PREFIX, "poll() returned", r);
if (r < 0) {
@@ -374,7 +372,7 @@ static void debug_print(struct lvmpolld_state *ls, const char * const* ptr)
static void *fork_and_poll(void *args)
{
int outfd, errfd, state;
int outfd, errfd, state = 0;
struct lvmpolld_thread_data *data;
pid_t r;
@@ -555,14 +553,15 @@ static struct lvmpolld_lv *construct_pdlv(request req, struct lvmpolld_state *ls
const char *interval, const char *id,
const char *vgname, const char *lvname,
const char *sysdir, enum poll_type type,
unsigned abort_polling, unsigned uinterval)
unsigned abort_polling, unsigned uinterval,
const char *devicesfile)
{
const char **cmdargv, **cmdenvp;
struct lvmpolld_lv *pdlv;
unsigned handle_missing_pvs = daemon_request_int(req, LVMPD_PARM_HANDLE_MISSING_PVS, 0);
pdlv = pdlv_create(ls, id, vgname, lvname, sysdir, type,
interval, uinterval, pdst);
interval, uinterval, pdst, devicesfile);
if (!pdlv) {
ERROR(ls, "%s: %s", PD_LOG_PREFIX, "failed to create internal LV data structure.");
@@ -621,6 +620,7 @@ static response poll_init(client_handle h, struct lvmpolld_state *ls, request re
const char *lvname = daemon_request_str(req, LVMPD_PARM_LVNAME, NULL);
const char *vgname = daemon_request_str(req, LVMPD_PARM_VGNAME, NULL);
const char *sysdir = daemon_request_str(req, LVMPD_PARM_SYSDIR, NULL);
const char *devicesfile = daemon_request_str(req, LVMPD_PARM_DEVICESFILE, NULL);
unsigned abort_polling = daemon_request_int(req, LVMPD_PARM_ABORT, 0);
assert(type < POLL_TYPE_MAX);
@@ -680,7 +680,7 @@ static response poll_init(client_handle h, struct lvmpolld_state *ls, request re
pdlv->init_rq_count++; /* safe. protected by store lock */
} else {
pdlv = construct_pdlv(req, ls, pdst, interval, id, vgname,
lvname, sysdir, type, abort_polling, 2 * uinterval);
lvname, sysdir, type, abort_polling, 2 * uinterval, devicesfile);
if (!pdlv) {
pdst_unlock(pdst);
free(id);

View File

@@ -93,11 +93,13 @@ struct lvmpolld_lv *pdlv_create(struct lvmpolld_state *ls, const char *id,
const char *vgname, const char *lvname,
const char *sysdir, enum poll_type type,
const char *sinterval, unsigned pdtimeout,
struct lvmpolld_store *pdst)
struct lvmpolld_store *pdst,
const char *devicesfile)
{
char *lvmpolld_id = strdup(id), /* copy */
*full_lvname = _construct_full_lvname(vgname, lvname), /* copy */
*lvm_system_dir_env = _construct_lvm_system_dir_env(sysdir); /* copy */
char *devicesfile_dup = devicesfile ? strdup(devicesfile) : NULL;
struct lvmpolld_lv tmp = {
.ls = ls,
@@ -105,6 +107,7 @@ struct lvmpolld_lv *pdlv_create(struct lvmpolld_state *ls, const char *id,
.lvmpolld_id = lvmpolld_id,
.lvid = _get_lvid(lvmpolld_id, sysdir),
.lvname = full_lvname,
.devicesfile = devicesfile_dup,
.lvm_system_dir_env = lvm_system_dir_env,
.sinterval = strdup(sinterval), /* copy */
.pdtimeout = pdtimeout < MIN_POLLING_TIMEOUT ? MIN_POLLING_TIMEOUT : pdtimeout,
@@ -124,6 +127,7 @@ struct lvmpolld_lv *pdlv_create(struct lvmpolld_state *ls, const char *id,
return pdlv;
err:
free((void *)devicesfile_dup);
free((void *)full_lvname);
free((void *)lvmpolld_id);
free((void *)lvm_system_dir_env);
@@ -136,6 +140,7 @@ err:
void pdlv_destroy(struct lvmpolld_lv *pdlv)
{
free((void *)pdlv->lvmpolld_id);
free((void *)pdlv->devicesfile);
free((void *)pdlv->lvname);
free((void *)pdlv->sinterval);
free((void *)pdlv->lvm_system_dir_env);

View File

@@ -49,6 +49,7 @@ struct lvmpolld_lv {
const enum poll_type type;
const char *const lvid;
const char *const lvmpolld_id;
const char *const devicesfile;
const char *const lvname; /* full vg/lv name */
const unsigned pdtimeout; /* in seconds */
const char *const sinterval;
@@ -101,7 +102,8 @@ struct lvmpolld_lv *pdlv_create(struct lvmpolld_state *ls, const char *id,
const char *vgname, const char *lvname,
const char *sysdir, enum poll_type type,
const char *sinterval, unsigned pdtimeout,
struct lvmpolld_store *pdst);
struct lvmpolld_store *pdst,
const char *devicesfile);
/* only call with appropriate struct lvmpolld_store lock held */
void pdlv_destroy(struct lvmpolld_lv *pdlv);

View File

@@ -35,6 +35,7 @@
#define LVMPD_PARM_SYSDIR "sysdir"
#define LVMPD_PARM_VALUE "value" /* either retcode or signal value */
#define LVMPD_PARM_VGNAME "vgname"
#define LVMPD_PARM_DEVICESFILE "devicesfile"
#define LVMPD_RESP_FAILED "failed"
#define LVMPD_RESP_FINISHED "finished"

View File

@@ -164,20 +164,30 @@ struct dm_info {
struct dm_deps {
uint32_t count;
uint32_t filler;
uint64_t device[0];
uint64_t device[];
};
struct dm_names {
uint64_t dev;
uint32_t next; /* Offset to next struct from start of this struct */
char name[0];
char name[];
};
struct dm_active_device {
struct dm_list list;
int major;
int minor;
char *name; /* device name */
uint32_t event_nr; /* valid when DM_DEVICE_LIST_HAS_EVENT_NR is set */
char *uuid; /* valid uuid when DM_DEVICE_LIST_HAS_UUID is set */
};
struct dm_versions {
uint32_t next; /* Offset to next struct from start of this struct */
uint32_t version[3];
char name[0];
char name[];
};
int dm_get_library_version(char *version, size_t size);
@@ -210,6 +220,25 @@ const char *dm_task_get_message_response(struct dm_task *dmt);
*/
const char *dm_task_get_name(const struct dm_task *dmt);
struct dm_names *dm_task_get_names(struct dm_task *dmt);
/*
* Retrieve the list of devices and put them into easily accessible
* struct dm_active_device list elements.
* devs_features provides flag-set with used features so it's easy to check
* whether the kernel provides i.e. UUID info together with DM names
*/
#define DM_DEVICE_LIST_HAS_EVENT_NR 1
#define DM_DEVICE_LIST_HAS_UUID 2
int dm_task_get_device_list(struct dm_task *dmt, struct dm_list **devs_list,
unsigned *devs_features);
/*
* -1: no idea about uuid (not provided by DM_DEVICE_LIST ioctl)
* 0: uuid not present
* 1: listed and dm_active_device will be set for not NULL pointer
*/
int dm_device_list_find_by_uuid(struct dm_list *devs_list, const char *uuid,
const struct dm_active_device **dev);
/* Release all associated memory with list of active DM devices */
void dm_device_list_destroy(struct dm_list **devs_list);
int dm_task_set_ro(struct dm_task *dmt);
int dm_task_set_newname(struct dm_task *dmt, const char *newname);
@@ -234,6 +263,8 @@ int dm_task_suppress_identical_reload(struct dm_task *dmt);
int dm_task_secure_data(struct dm_task *dmt);
int dm_task_retry_remove(struct dm_task *dmt);
int dm_task_deferred_remove(struct dm_task *dmt);
int dm_task_ima_measurement(struct dm_task *dmt);
void dm_task_skip_reload_params_compare(struct dm_task *dmt);
/*
* Record timestamp immediately after the ioctl returns.
@@ -950,6 +981,8 @@ struct writecache_settings {
uint64_t autocommit_time; /* in milliseconds */
uint32_t fua;
uint32_t nofua;
uint32_t cleaner;
uint32_t max_age;
/*
* Allow an unrecognized key and its val to be passed to the kernel for
@@ -969,6 +1002,8 @@ struct writecache_settings {
unsigned autocommit_time_set:1;
unsigned fua_set:1;
unsigned nofua_set:1;
unsigned cleaner_set:1;
unsigned max_age_set:1;
};
int dm_tree_node_add_writecache_target(struct dm_tree_node *node,
@@ -982,14 +1017,14 @@ int dm_tree_node_add_writecache_target(struct dm_tree_node *node,
struct integrity_settings {
char mode[8];
uint32_t tag_size;
const char *internal_hash;
uint32_t block_size; /* optional table param always set by lvm */
const char *internal_hash; /* optional table param always set by lvm */
uint32_t journal_sectors;
uint32_t interleave_sectors;
uint32_t buffer_sectors;
uint32_t journal_watermark;
uint32_t commit_time;
uint32_t block_size;
uint32_t bitmap_flush_interval;
uint64_t sectors_per_bit;
@@ -998,7 +1033,6 @@ struct integrity_settings {
unsigned buffer_sectors_set:1;
unsigned journal_watermark_set:1;
unsigned commit_time_set:1;
unsigned block_size_set:1;
unsigned bitmap_flush_interval_set:1;
unsigned sectors_per_bit_set:1;
};
@@ -1015,6 +1049,7 @@ int dm_tree_node_add_integrity_target(struct dm_tree_node *node,
*/
int dm_tree_node_add_vdo_target(struct dm_tree_node *node,
uint64_t size,
const char *vdo_pool_name,
const char *data_uuid,
uint64_t data_size,
const struct dm_vdo_target_params *param);
@@ -1067,10 +1102,10 @@ int dm_tree_node_add_replicator_dev_target(struct dm_tree_node *node,
#define DM_THIN_MIN_DATA_BLOCK_SIZE (UINT32_C(128))
#define DM_THIN_MAX_DATA_BLOCK_SIZE (UINT32_C(2097152))
/*
* Max supported size for thin pool metadata device (17112760320 bytes)
* Limitation is hardcoded into the kernel and bigger device size
* is not accepted.
* Max supported size for thin pool metadata device (17045913600 bytes)
* drivers/md/dm-thin-metadata.h THIN_METADATA_MAX_SECTORS
* But here DM_THIN_MAX_METADATA_SIZE got defined incorrectly
* Correct size is (UINT64_C(255) * ((1 << 14) - 64) * (4096 / (1 << 9)))
*/
#define DM_THIN_MAX_METADATA_SIZE (UINT64_C(255) * (1 << 14) * (4096 / (1 << 9)) - 256 * 1024)
@@ -1083,6 +1118,16 @@ int dm_tree_node_add_thin_pool_target(struct dm_tree_node *node,
uint64_t low_water_mark,
unsigned skip_block_zeroing);
int dm_tree_node_add_thin_pool_target_v1(struct dm_tree_node *node,
uint64_t size,
uint64_t transaction_id,
const char *metadata_uuid,
const char *pool_uuid,
uint32_t data_block_size,
uint64_t low_water_mark,
unsigned skip_block_zeroing,
unsigned crop_metadata);
/* Supported messages for thin provision target */
typedef enum {
DM_THIN_MESSAGE_CREATE_SNAP, /* device_id, origin_id */
@@ -1313,7 +1358,7 @@ int dm_bit_get_next(dm_bitset_t bs, int last_bit);
int dm_bit_get_last(dm_bitset_t bs);
int dm_bit_get_prev(dm_bitset_t bs, int last_bit);
#define DM_BITS_PER_INT (sizeof(int) * CHAR_BIT)
#define DM_BITS_PER_INT ((unsigned)sizeof(int) * CHAR_BIT)
#define dm_bit(bs, i) \
((bs)[((i) / DM_BITS_PER_INT) + 1] & (0x1 << ((i) & (DM_BITS_PER_INT - 1))))

View File

@@ -150,7 +150,8 @@ dm_bitset_t dm_bitset_parse_list(const char *str, struct dm_pool *mem,
size_t min_num_bits)
{
unsigned a, b;
int c, old_c, totaldigits, ndigits, nmaskbits;
int c, old_c, totaldigits, ndigits;
size_t nmaskbits;
int at_start, in_range;
dm_bitset_t mask = NULL;
const char *start = str;
@@ -242,18 +243,3 @@ bad:
}
return NULL;
}
#if defined(__GNUC__)
/*
* Maintain backward compatibility with older versions that did not
* accept a 'min_num_bits' argument to dm_bitset_parse_list().
*/
dm_bitset_t dm_bitset_parse_list_v1_02_129(const char *str, struct dm_pool *mem);
dm_bitset_t dm_bitset_parse_list_v1_02_129(const char *str, struct dm_pool *mem)
{
return dm_bitset_parse_list(str, mem, 0);
}
#else /* if defined(__GNUC__) */
#endif

View File

@@ -205,7 +205,7 @@ static int _get_proc_number(const char *file, const char *name,
}
while (getline(&line, &len, fl) != -1) {
if (sscanf(line, "%d %255s\n", &num, &nm[0]) == 2) {
if (sscanf(line, "%u %255s\n", &num, &nm[0]) == 2) {
if (!strcmp(name, nm)) {
if (number) {
*number = num;
@@ -493,7 +493,10 @@ static void _dm_task_free_targets(struct dm_task *dmt)
for (t = dmt->head; t; t = n) {
n = t->next;
_dm_zfree_string(t->params);
if (dmt->secure_data)
_dm_zfree_string(t->params);
else
free(t->params);
free(t->type);
free(t);
}
@@ -504,7 +507,10 @@ static void _dm_task_free_targets(struct dm_task *dmt)
void dm_task_destroy(struct dm_task *dmt)
{
_dm_task_free_targets(dmt);
_dm_zfree_dmi(dmt->dmi.v4);
if (dmt->secure_data)
_dm_zfree_dmi(dmt->dmi.v4);
else
free(dmt->dmi.v4);
free(dmt->dev_name);
free(dmt->mangled_dev_name);
free(dmt->newname);
@@ -610,8 +616,7 @@ int dm_check_version(void)
int dm_cookie_supported(void)
{
return (dm_check_version() &&
_dm_version >= 4 &&
_dm_version_minor >= 15);
((_dm_version == 4) ? _dm_version_minor >= 15 : _dm_version > 4));
}
static int _dm_inactive_supported(void)
@@ -749,6 +754,159 @@ struct dm_deps *dm_task_get_deps(struct dm_task *dmt)
dmt->dmi.v4->data_start);
}
/*
* Round up the ptr to an 8-byte boundary.
* Follow kernel pattern.
*/
#define ALIGN_MASK 7
static size_t _align_val(size_t val)
{
return (val + ALIGN_MASK) & ~ALIGN_MASK;
}
static void *_align_ptr(void *ptr)
{
return (void *)_align_val((size_t)ptr);
}
static int _check_has_event_nr(void) {
static int _has_event_nr = -1;
if (_has_event_nr < 0)
_has_event_nr = dm_check_version() &&
((_dm_version == 4) ? _dm_version_minor >= 38 : _dm_version > 4);
return _has_event_nr;
}
struct dm_device_list {
struct dm_list list;
unsigned count;
unsigned features;
struct dm_hash_table *uuids;
};
int dm_task_get_device_list(struct dm_task *dmt, struct dm_list **devs_list,
unsigned *devs_features)
{
struct dm_names *names, *names1;
struct dm_active_device *dm_dev, *dm_new_dev;
struct dm_device_list *devs;
unsigned next = 0;
uint32_t *event_nr;
char *uuid_ptr;
size_t len;
int cnt = 0;
*devs_list = 0;
*devs_features = 0;
if ((names = dm_task_get_names(dmt)) && names->dev) {
names1 = names;
if (!names->name[0])
cnt = -1; /* -> cnt == 0 when no device is really present */
do {
names1 = (struct dm_names *)((char *) names1 + next);
next = names1->next;
++cnt;
} while (next);
}
if (!(devs = malloc(sizeof(*devs) + (cnt ? cnt * sizeof(*dm_dev) + (char*)names1 - (char*)names + 256 : 0))))
return_0;
dm_list_init(&devs->list);
devs->count = cnt;
devs->uuids = NULL;
if (!cnt) {
/* nothing in the list -> mark all features present */
*devs_features |= (DM_DEVICE_LIST_HAS_EVENT_NR | DM_DEVICE_LIST_HAS_UUID);
goto out; /* nothing else to do */
}
dm_dev = (struct dm_active_device *) (devs + 1);
do {
names = (struct dm_names *)((char *) names + next);
dm_dev->major = MAJOR(names->dev);
dm_dev->minor = MINOR(names->dev);
dm_dev->name = (char*)(dm_dev + 1);
dm_dev->event_nr = 0;
dm_dev->uuid = NULL;
strcpy(dm_dev->name, names->name);
len = strlen(names->name) + 1;
dm_new_dev = _align_ptr((char*)(dm_dev + 1) + len);
if (_check_has_event_nr()) {
/* Hash for UUIDs with some more bits to reduce colision count */
if (!devs->uuids && !(devs->uuids = dm_hash_create(cnt * 8))) {
free(devs);
return_0;
}
*devs_features |= DM_DEVICE_LIST_HAS_EVENT_NR;
event_nr = _align_ptr(names->name + len);
dm_dev->event_nr = event_nr[0];
if ((event_nr[1] & DM_NAME_LIST_FLAG_HAS_UUID)) {
*devs_features |= DM_DEVICE_LIST_HAS_UUID;
uuid_ptr = _align_ptr(event_nr + 2);
dm_dev->uuid = (char*) dm_new_dev;
dm_new_dev = _align_ptr((char*)dm_new_dev + strlen(uuid_ptr) + 1);
strcpy(dm_dev->uuid, uuid_ptr);
if (!dm_hash_insert(devs->uuids, dm_dev->uuid, dm_dev))
return_0; // FIXME
#if 0
log_debug("Active %s (%s) %d:%d event:%u",
dm_dev->name, dm_dev->uuid,
dm_dev->major, dm_dev->minor, dm_dev->event_nr);
#endif
}
}
dm_list_add(&devs->list, &dm_dev->list);
dm_dev = dm_new_dev;
next = names->next;
} while (next);
out:
*devs_list = (struct dm_list *)devs;
return 1;
}
int dm_device_list_find_by_uuid(struct dm_list *devs_list, const char *uuid,
const struct dm_active_device **dev)
{
struct dm_device_list *devs = (struct dm_device_list *) devs_list;
struct dm_active_device *dm_dev;
if (devs->uuids &&
(dm_dev = dm_hash_lookup(devs->uuids, uuid))) {
if (dev)
*dev = dm_dev;
return 1;
}
return 0;
}
void dm_device_list_destroy(struct dm_list **devs_list)
{
struct dm_device_list *devs = (struct dm_device_list *) *devs_list;
if (devs) {
if (devs->uuids)
dm_hash_destroy(devs->uuids);
free(devs);
*devs_list = NULL;
}
}
struct dm_names *dm_task_get_names(struct dm_task *dmt)
{
return (struct dm_names *) (((char *) dmt->dmi.v4) +
@@ -805,6 +963,11 @@ int dm_task_suppress_identical_reload(struct dm_task *dmt)
return 1;
}
void dm_task_skip_reload_params_compare(struct dm_task *dmt)
{
dmt->skip_reload_params_compare = 1;
}
int dm_task_set_add_node(struct dm_task *dmt, dm_add_node_t add_node)
{
switch (add_node) {
@@ -915,6 +1078,13 @@ int dm_task_secure_data(struct dm_task *dmt)
return 1;
}
int dm_task_ima_measurement(struct dm_task *dmt)
{
dmt->ima_measurement = 1;
return 1;
}
int dm_task_retry_remove(struct dm_task *dmt)
{
dmt->retry_remove = 1;
@@ -1107,7 +1277,7 @@ static int _add_params(int type)
static struct dm_ioctl *_flatten(struct dm_task *dmt, unsigned repeat_count)
{
const size_t min_size = 16 * 1024;
size_t min_size;
const int (*version)[3];
struct dm_ioctl *dmi;
@@ -1126,6 +1296,18 @@ static struct dm_ioctl *_flatten(struct dm_task *dmt, unsigned repeat_count)
else if (dmt->head)
log_debug_activation(INTERNAL_ERROR "dm '%s' ioctl should not define parameters.",
_cmd_data_v4[dmt->type].name);
switch (dmt->type) {
case DM_DEVICE_CREATE:
case DM_DEVICE_DEPS:
case DM_DEVICE_LIST:
case DM_DEVICE_STATUS:
case DM_DEVICE_TABLE:
case DM_DEVICE_TARGET_MSG:
min_size = 16 * 1024;
break;
default:
min_size = 2 * 1024;
}
if (count && (dmt->sector || dmt->message)) {
log_error("targets and message are incompatible");
@@ -1227,9 +1409,11 @@ static struct dm_ioctl *_flatten(struct dm_task *dmt, unsigned repeat_count)
/* FIXME Until resume ioctl supplies name, use dev_name for readahead */
if (DEV_NAME(dmt) && (dmt->type != DM_DEVICE_RESUME || dmt->minor < 0 ||
dmt->major < 0))
/* coverity[buffer_size_warning] */
strncpy(dmi->name, DEV_NAME(dmt), sizeof(dmi->name));
if (DEV_UUID(dmt))
/* coverity[buffer_size_warning] */
strncpy(dmi->uuid, DEV_UUID(dmt), sizeof(dmi->uuid));
if (dmt->type == DM_DEVICE_SUSPEND)
@@ -1268,6 +1452,14 @@ static struct dm_ioctl *_flatten(struct dm_task *dmt, unsigned repeat_count)
}
dmi->flags |= DM_UUID_FLAG;
}
if (dmt->ima_measurement) {
if (_dm_version_minor < 45) {
log_error("WARNING: IMA measurement unsupported by "
"kernel. Aborting operation.");
goto bad;
}
dmi->flags |= DM_IMA_MEASUREMENT_FLAG;
}
dmi->target_count = count;
dmi->event_nr = dmt->event_nr;
@@ -1329,7 +1521,7 @@ static int _process_mapper_dir(struct dm_task *dmt)
}
if (closedir(d))
log_sys_error("closedir", dir);
log_sys_debug("closedir", dir);
return r;
}
@@ -1401,8 +1593,7 @@ static int _udev_complete(struct dm_task *dmt)
static int _check_uevent_generated(struct dm_ioctl *dmi)
{
if (!dm_check_version() ||
_dm_version < 4 ||
_dm_version_minor < 17)
((_dm_version == 4) ? _dm_version_minor < 17 : _dm_version < 4))
/* can't check, assume uevent is generated */
return 1;
@@ -1463,6 +1654,7 @@ static int _create_and_load_v4(struct dm_task *dmt)
task->head = dmt->head;
task->tail = dmt->tail;
task->secure_data = dmt->secure_data;
task->ima_measurement = dmt->ima_measurement;
r = dm_task_run(task);
@@ -1575,11 +1767,36 @@ static int _reload_with_suppression_v4(struct dm_task *dmt)
len = strlen(t2->params);
while (len-- > 0 && t2->params[len] == ' ')
t2->params[len] = '\0';
if ((t1->start != t2->start) ||
(t1->length != t2->length) ||
(strcmp(t1->type, t2->type)) ||
(strcmp(t1->params, t2->params)))
if (t1->start != t2->start) {
log_debug("reload %u:%u diff start %llu %llu type %s %s", task->major, task->minor,
(unsigned long long)t1->start, (unsigned long long)t2->start, t1->type, t2->type);
goto no_match;
}
if (t1->length != t2->length) {
log_debug("reload %u:%u diff length %llu %llu type %s %s", task->major, task->minor,
(unsigned long long)t1->length, (unsigned long long)t2->length, t1->type, t2->type);
goto no_match;
}
if (strcmp(t1->type, t2->type)) {
log_debug("reload %u:%u diff type %s %s", task->major, task->minor, t1->type, t2->type);
goto no_match;
}
if (strcmp(t1->params, t2->params)) {
if (dmt->skip_reload_params_compare) {
log_debug("reload %u:%u diff params ignore for type %s",
task->major, task->minor, t1->type);
log_debug("reload params1 %s", t1->params);
log_debug("reload params2 %s", t2->params);
} else {
log_debug("reload %u:%u diff params for type %s",
task->major, task->minor, t1->type);
log_debug("reload params1 %s", t1->params);
log_debug("reload params2 %s", t2->params);
goto no_match;
}
}
t1 = t1->next;
t2 = t2->next;
}
@@ -1742,23 +1959,34 @@ static int _do_dm_ioctl_unmangle_string(char *str, const char *str_name,
static int _dm_ioctl_unmangle_names(int type, struct dm_ioctl *dmi)
{
char buf[DM_NAME_LEN];
struct dm_names *names;
char buf_uuid[DM_UUID_LEN];
struct dm_name_list *names;
unsigned next = 0;
char *name;
int r = 1;
uint32_t *event_nr;
char *uuid_ptr;
dm_string_mangling_t mangling_mode = dm_get_name_mangling_mode();
if ((name = dmi->name))
r = _do_dm_ioctl_unmangle_string(name, "name", buf, sizeof(buf),
dm_get_name_mangling_mode());
r &= _do_dm_ioctl_unmangle_string(name, "name", buf, sizeof(buf),
mangling_mode);
if (type == DM_DEVICE_LIST &&
((names = ((struct dm_names *) ((char *)dmi + dmi->data_start)))) &&
((names = ((struct dm_name_list *) ((char *)dmi + dmi->data_start)))) &&
names->dev) {
do {
names = (struct dm_names *)((char *) names + next);
r = _do_dm_ioctl_unmangle_string(names->name, "name",
buf, sizeof(buf),
dm_get_name_mangling_mode());
names = (struct dm_name_list *)((char *) names + next);
event_nr = _align_ptr(names->name + strlen(names->name) + 1);
r &= _do_dm_ioctl_unmangle_string(names->name, "name",
buf, sizeof(buf), mangling_mode);
/* Unmangle also UUID within same loop */
if (_check_has_event_nr() &&
(event_nr[1] & DM_NAME_LIST_FLAG_HAS_UUID)) {
uuid_ptr = _align_ptr(event_nr + 2);
r &= _do_dm_ioctl_unmangle_string(uuid_ptr, "UUID", buf_uuid,
sizeof(buf_uuid), mangling_mode);
}
next = names->next;
} while (next);
}
@@ -1851,7 +2079,7 @@ static struct dm_ioctl *_do_dm_ioctl(struct dm_task *dmt, unsigned command,
}
log_debug_activation("dm %s %s%s %s%s%s %s%.0d%s%.0d%s"
"%s[ %s%s%s%s%s%s%s%s%s] %.0" PRIu64 " %s [%u] (*%u)",
"%s[ %s%s%s%s%s%s%s%s%s%s] %.0" PRIu64 " %s [%u] (*%u)",
_cmd_data_v4[dmt->type].name,
dmt->new_uuid ? "UUID " : "",
dmi->name, dmi->uuid, dmt->newname ? " " : "",
@@ -1869,6 +2097,7 @@ static struct dm_ioctl *_do_dm_ioctl(struct dm_task *dmt, unsigned command,
dmt->retry_remove ? "retryremove " : "",
dmt->deferred_remove ? "deferredremove " : "",
dmt->secure_data ? "securedata " : "",
dmt->ima_measurement ? "ima_measurement " : "",
dmt->query_inactive_table ? "inactive " : "",
dmt->enable_checks ? "enablechecks " : "",
dmt->sector, _sanitise_message(dmt->message),
@@ -2161,52 +2390,3 @@ void dm_lib_exit(void)
_version_ok = 1;
_version_checked = 0;
}
#if defined(__GNUC__)
/*
* Maintain binary backward compatibility.
* Version script mechanism works with 'gcc' compatible compilers only.
*/
/*
* This following code is here to retain ABI compatibility after adding
* the field deferred_remove to struct dm_info in version 1.02.89.
*
* Binaries linked against version 1.02.88 of libdevmapper or earlier
* will use this function that returns dm_info without the
* deferred_remove field.
*
* Binaries compiled against version 1.02.89 onwards will use
* the new function dm_task_get_info_with_deferred_remove due to the
* #define.
*
* N.B. Keep this function at the end of the file to make sure that
* no code in this file accidentally calls it.
*/
int dm_task_get_info_base(struct dm_task *dmt, struct dm_info *info);
int dm_task_get_info_base(struct dm_task *dmt, struct dm_info *info)
{
struct dm_info new_info;
if (!dm_task_get_info(dmt, &new_info))
return 0;
memcpy(info, &new_info, offsetof(struct dm_info, deferred_remove));
return 1;
}
int dm_task_get_info_with_deferred_remove(struct dm_task *dmt, struct dm_info *info);
int dm_task_get_info_with_deferred_remove(struct dm_task *dmt, struct dm_info *info)
{
struct dm_info new_info;
if (!dm_task_get_info(dmt, &new_info))
return 0;
memcpy(info, &new_info, offsetof(struct dm_info, internal_suspend));
return 1;
}
#endif

View File

@@ -59,6 +59,7 @@ struct dm_task {
int skip_lockfs;
int query_inactive_table;
int suppress_identical_reload;
int skip_reload_params_compare;
dm_add_node_t add_node;
uint64_t existing_table_size;
int cookie_set;
@@ -69,6 +70,7 @@ struct dm_task {
int enable_checks;
int expected_errno;
int ioctl_errno;
int ima_measurement;
int record_timestamp;

View File

@@ -338,6 +338,7 @@ struct dm_task *dm_task_create(int type)
dmt->new_uuid = 0;
dmt->secure_data = 0;
dmt->record_timestamp = 0;
dmt->ima_measurement = 0;
return dmt;
}
@@ -382,7 +383,7 @@ static int _find_dm_name_of_device(dev_t st_rdev, char *buf, size_t buf_len)
}
if (closedir(d))
log_sys_error("closedir", _dm_dir);
log_sys_debug("closedir", _dm_dir);
return r;
}
@@ -512,7 +513,7 @@ int unmangle_string(const char *str, const char *str_name, size_t len,
int strict = mode != DM_STRING_MANGLING_NONE;
char str_rest[DM_NAME_LEN];
size_t i, j;
int code;
unsigned int code;
int r = 0;
if (!str || !buf)
@@ -931,7 +932,7 @@ int dm_task_add_target(struct dm_task *dmt, uint64_t start, uint64_t size,
#ifdef HAVE_SELINUX
static int _selabel_lookup(const char *path, mode_t mode,
security_context_t *scontext)
char **scontext)
{
#ifdef HAVE_SELINUX_LABEL_H
if (!_selabel_handle &&
@@ -974,7 +975,7 @@ static int _is_selinux_enabled(void)
int dm_prepare_selinux_context(const char *path, mode_t mode)
{
#ifdef HAVE_SELINUX
security_context_t scontext = NULL;
char *scontext = NULL;
if (_is_selinux_enabled() <= 0)
return 1;
@@ -1002,7 +1003,7 @@ int dm_prepare_selinux_context(const char *path, mode_t mode)
int dm_set_selinux_context(const char *path, mode_t mode)
{
#ifdef HAVE_SELINUX
security_context_t scontext = NULL;
char *scontext = NULL;
if (_is_selinux_enabled() <= 0)
return 1;
@@ -1224,7 +1225,7 @@ int get_dev_node_read_ahead(const char *dev_name, uint32_t major, uint32_t minor
int len;
int r = 1;
int fd;
long read_ahead_long;
long read_ahead_long = 0;
/*
* If we know the device number, use sysfs if we can.
@@ -1920,7 +1921,7 @@ static int _sysfs_find_kernel_name(uint32_t major, uint32_t minor, char *buf, si
continue;
if ((sz = dm_snprintf(path, sizeof(path), "%sblock/%s/dev",
_sysfs_dir, name)) == -1) {
_sysfs_dir, name)) < 5) {
log_warn("Couldn't create path for %s.", name);
continue;
}

View File

@@ -599,7 +599,7 @@ static struct dm_config_node *_section(struct parser *p, struct dm_config_node *
match(TOK_IDENTIFIER);
}
if (!strlen(str)) {
if (!*str) {
log_error("Parse error at byte %" PRIptrdiff_t " (line %d): empty section identifier",
p->tb - p->fb + 1, p->line);
return NULL;
@@ -983,7 +983,7 @@ static const char *_find_config_str(const void *start, node_lookup_fn find_fn,
}
if (fail)
log_very_verbose("%s not found in config: defaulting to %s",
log_very_verbose("%s not found in config: defaulting to \"%s\"",
path, fail);
return fail;
}

View File

@@ -274,6 +274,16 @@ struct load_properties {
*/
unsigned delay_resume_if_extended;
/*
* When comparing table lines to decide if a reload is
* needed, ignore any differences betwen the lvm device
* params and the kernel-reported device params.
* dm-integrity reports many internal parameters on the
* table line when lvm does not explicitly set them,
* causing lvm and the kernel to have differing params.
*/
unsigned skip_reload_params_compare;
/*
* Call node_send_messages(), set to 2 if there are messages
* When != 0, it validates matching transaction id, thus thin-pools
@@ -320,16 +330,7 @@ struct dm_tree_node {
dm_node_callback_fn callback;
void *callback_data;
/*
* TODO:
* Add advanced code which tracks of send ioctls and their
* proper revert operation for more advanced recovery
* Current code serves mostly only to recovery when
* thin pool metadata check fails and command would
* have left active thin data and metadata subvolumes.
*/
struct dm_list activated; /* Head of activated nodes for preload revert */
struct dm_list activated_list; /* List of activated nodes for preload revert */
int activated; /* tracks activation during preload */
};
struct dm_tree {
@@ -364,19 +365,18 @@ struct dm_tree *dm_tree_create(void)
dtree->root.dtree = dtree;
dm_list_init(&dtree->root.uses);
dm_list_init(&dtree->root.used_by);
dm_list_init(&dtree->root.activated);
dtree->skip_lockfs = 0;
dtree->no_flush = 0;
dtree->mem = dmem;
dtree->optional_uuid_suffixes = NULL;
if (!(dtree->devs = dm_hash_create(8))) {
if (!(dtree->devs = dm_hash_create(61))) {
log_error("dtree hash creation failed");
dm_pool_destroy(dtree->mem);
return NULL;
}
if (!(dtree->uuids = dm_hash_create(32))) {
if (!(dtree->uuids = dm_hash_create(31))) {
log_error("dtree uuid hash creation failed");
dm_hash_destroy(dtree->devs);
dm_pool_destroy(dtree->mem);
@@ -549,7 +549,6 @@ static struct dm_tree_node *_create_dm_tree_node(struct dm_tree *dtree,
dm_list_init(&node->uses);
dm_list_init(&node->used_by);
dm_list_init(&node->activated);
dm_list_init(&node->props.segs);
dev = MKDEV(info->major, info->minor);
@@ -605,7 +604,7 @@ static struct dm_tree_node *_find_dm_tree_node_by_uuid(struct dm_tree *dtree,
default_uuid_prefix = dm_uuid_prefix();
default_uuid_prefix_len = strlen(default_uuid_prefix);
if (suffix_list && (suffix_position = rindex(uuid, '-'))) {
if (suffix_list && (suffix_position = strrchr(uuid, '-'))) {
while ((suffix = suffix_list[i++])) {
if (strcmp(suffix_position + 1, suffix))
continue;
@@ -1579,8 +1578,37 @@ static int _thin_pool_node_message(struct dm_tree_node *dnode, struct thin_messa
}
if (!_node_message(dnode->info.major, dnode->info.minor,
tm->expected_errno, buf))
return_0;
tm->expected_errno, buf)) {
switch (m->type) {
case DM_THIN_MESSAGE_CREATE_SNAP:
case DM_THIN_MESSAGE_CREATE_THIN:
if (errno == EEXIST) {
/*
* ATM errno from ioctl() is preserved through code error path chain
* If this would ever change, another way need to be used to
* obtain result from failed DM message
*/
log_error("Thin pool %s already contain thin device with device_id %u.",
_node_name(dnode), m->u.m_create_snap.device_id);
/*
* TODO:
*
* Give some useful advice how to solve this problem,
* until lvconvert --repair can handle this automatically
*/
log_error("Manual intervention may be required to remove device dev_id=%u in thin pool metadata.",
m->u.m_create_snap.device_id);
log_error("Optionally new thin volume with device_id=%u can be manually added into a volume group.",
m->u.m_create_snap.device_id);
log_warn("WARNING: When uncertain how to do this, contact support!");
return 0;
}
/* fall through */
default:
return_0;
}
}
return 1;
}
@@ -1627,6 +1655,15 @@ static int _thin_pool_node_send_messages(struct dm_tree_node *dnode,
if (!have_messages || !send)
return 1; /* transaction_id is matching */
if (stp.fail || stp.read_only || stp.needs_check) {
log_error("Cannot send messages to thin pool %s%s%s%s.",
_node_name(dnode),
stp.fail ? " in failed state" : "",
stp.read_only ? " with read only metadata" : "",
stp.needs_check ? " which needs check first" : "");
return 0;
}
dm_list_iterate_items(tmsg, &seg->thin_messages) {
if (!(_thin_pool_node_message(dnode, tmsg)))
return_0;
@@ -2088,7 +2125,7 @@ int dm_tree_activate_children(struct dm_tree_node *dnode,
return r;
}
static int _create_node(struct dm_tree_node *dnode)
static int _create_node(struct dm_tree_node *dnode, struct dm_tree_node *parent)
{
int r = 0;
struct dm_task *dmt;
@@ -2137,38 +2174,15 @@ static int _create_node(struct dm_tree_node *dnode)
"Unable to get DM task info for %s.",
dnode->name);
}
if (r)
dnode->activated = 1;
out:
dm_task_destroy(dmt);
return r;
}
/*
* _remove_node
*
* This function is only used to remove a DM device that has failed
* to load any table.
*/
static int _remove_node(struct dm_tree_node *dnode)
{
if (!dnode->info.exists)
return 1;
if (dnode->info.live_table || dnode->info.inactive_table) {
log_error(INTERNAL_ERROR
"_remove_node called on device with loaded table(s).");
return 0;
}
if (!_deactivate_node(dnode->name, dnode->info.major, dnode->info.minor,
&dnode->dtree->cookie, dnode->udev_flags, 0)) {
log_error("Failed to clean-up device with no table: %s.",
_node_name(dnode));
return 0;
}
return 1;
}
static int _build_dev_string(char *devbuf, size_t bufsize, struct dm_tree_node *node)
{
if (!dm_format_dev(devbuf, bufsize, node->info.major, node->info.minor)) {
@@ -2357,7 +2371,7 @@ static int _mirror_emit_segment_line(struct dm_task *dmt, struct load_segment *s
EMIT_PARAMS(pos, " %u ", seg->mirror_area_count);
if (_emit_areas_line(dmt, seg, params, paramsize, &pos) <= 0)
if (!_emit_areas_line(dmt, seg, params, paramsize, &pos))
return_0;
if (handle_errors)
@@ -2559,7 +2573,7 @@ static int _raid_emit_segment_line(struct dm_task *dmt, uint32_t major,
/* Print number of metadata/data device pairs */
EMIT_PARAMS(pos, " %u", area_count);
if (_emit_areas_line(dmt, seg, params, paramsize, &pos) <= 0)
if (!_emit_areas_line(dmt, seg, params, paramsize, &pos))
return_0;
return 1;
@@ -2619,7 +2633,7 @@ static int _cache_emit_segment_line(struct dm_task *dmt,
EMIT_PARAMS(pos, " %s", name);
/* Do not pass migration_threshold 2048 which is default */
EMIT_PARAMS(pos, " %u", (seg->policy_argc + (seg->migration_threshold != 2048) ? 1 : 0) * 2);
EMIT_PARAMS(pos, " %u", (seg->policy_argc + ((seg->migration_threshold != 2048) ? 1 : 0)) * 2);
if (seg->migration_threshold != 2048)
EMIT_PARAMS(pos, " migration_threshold %u", seg->migration_threshold);
if (seg->policy_settings)
@@ -2660,6 +2674,10 @@ static int _writecache_emit_segment_line(struct dm_task *dmt,
count += 1;
if (seg->writecache_settings.nofua_set)
count += 1;
if (seg->writecache_settings.cleaner_set && seg->writecache_settings.cleaner)
count += 1;
if (seg->writecache_settings.max_age_set)
count += 2;
if (seg->writecache_settings.new_key)
count += 2;
@@ -2703,6 +2721,14 @@ static int _writecache_emit_segment_line(struct dm_task *dmt,
EMIT_PARAMS(pos, " nofua");
}
if (seg->writecache_settings.cleaner_set && seg->writecache_settings.cleaner) {
EMIT_PARAMS(pos, " cleaner");
}
if (seg->writecache_settings.max_age_set) {
EMIT_PARAMS(pos, " max_age %u", seg->writecache_settings.max_age);
}
if (seg->writecache_settings.new_key) {
EMIT_PARAMS(pos, " %s %s",
seg->writecache_settings.new_key,
@@ -2729,7 +2755,7 @@ static int _integrity_emit_segment_line(struct dm_task *dmt,
!_build_dev_string(meta_dev, sizeof(meta_dev), seg->integrity_meta_node))
return_0;
count = 1; /* for internal_hash which we always pass in */
count = 3; /* block_size, internal_hash, fix_padding options are always passed */
if (seg->integrity_meta_node)
count++;
@@ -2747,18 +2773,17 @@ static int _integrity_emit_segment_line(struct dm_task *dmt,
count++;
if (set->commit_time_set)
count++;
if (set->block_size_set)
count++;
if (set->bitmap_flush_interval_set)
count++;
if (set->sectors_per_bit_set)
count++;
EMIT_PARAMS(pos, "%s 0 %u %s %d internal_hash:%s",
EMIT_PARAMS(pos, "%s 0 %u %s %d fix_padding block_size:%u internal_hash:%s",
origin_dev,
set->tag_size,
set->mode,
count,
set->block_size,
set->internal_hash);
if (seg->integrity_meta_node)
@@ -2782,15 +2807,15 @@ static int _integrity_emit_segment_line(struct dm_task *dmt,
if (set->commit_time_set)
EMIT_PARAMS(pos, " commit_time:%u", set->commit_time);
if (set->block_size_set)
EMIT_PARAMS(pos, " block_size:%u", set->block_size);
if (set->bitmap_flush_interval_set)
EMIT_PARAMS(pos, " bitmap_flush_interval:%u", set->bitmap_flush_interval);
if (set->sectors_per_bit_set)
EMIT_PARAMS(pos, " sectors_per_bit:%llu", (unsigned long long)set->sectors_per_bit);
if (!dm_task_secure_data(dmt))
stack;
return 1;
}
@@ -2849,7 +2874,8 @@ static int _vdo_emit_segment_line(struct dm_task *dmt,
seg->vdo_params.block_map_era_length,
seg->vdo_params.use_metadata_hints ? "on" : "off" ,
(seg->vdo_params.write_policy == DM_VDO_WRITE_POLICY_SYNC) ? "sync" :
(seg->vdo_params.write_policy == DM_VDO_WRITE_POLICY_ASYNC) ? "async" : "auto", // policy
(seg->vdo_params.write_policy == DM_VDO_WRITE_POLICY_ASYNC) ? "async" :
(seg->vdo_params.write_policy == DM_VDO_WRITE_POLICY_ASYNC_UNSAFE) ? "async-unsafe" : "auto", // policy
seg->vdo_name,
seg->vdo_params.max_discard,
seg->vdo_params.ack_threads,
@@ -2894,7 +2920,6 @@ static int _emit_segment_line(struct dm_task *dmt, uint32_t major,
size_t paramsize)
{
int pos = 0;
int r;
int target_type_is_raid = 0;
char originbuf[DM_FORMAT_DEV_BUFSIZE], cowbuf[DM_FORMAT_DEV_BUFSIZE];
@@ -2905,8 +2930,7 @@ static int _emit_segment_line(struct dm_task *dmt, uint32_t major,
break;
case SEG_MIRRORED:
/* Mirrors are pretty complicated - now in separate function */
r = _mirror_emit_segment_line(dmt, seg, params, paramsize);
if (!r)
if (!_mirror_emit_segment_line(dmt, seg, params, paramsize))
return_0;
break;
case SEG_SNAPSHOT:
@@ -2927,7 +2951,7 @@ static int _emit_segment_line(struct dm_task *dmt, uint32_t major,
EMIT_PARAMS(pos, "%u %u ", seg->area_count, seg->stripe_size);
break;
case SEG_VDO:
if (!(r = _vdo_emit_segment_line(dmt, seg, params, paramsize)))
if (!_vdo_emit_segment_line(dmt, seg, params, paramsize))
return_0;
break;
case SEG_CRYPT:
@@ -2956,9 +2980,8 @@ static int _emit_segment_line(struct dm_task *dmt, uint32_t major,
case SEG_RAID6_LA_6:
case SEG_RAID6_RA_6:
target_type_is_raid = 1;
r = _raid_emit_segment_line(dmt, major, minor, seg, seg_start,
params, paramsize);
if (!r)
if (!_raid_emit_segment_line(dmt, major, minor, seg, seg_start,
params, paramsize))
return_0;
break;
@@ -2999,10 +3022,9 @@ static int _emit_segment_line(struct dm_task *dmt, uint32_t major,
case SEG_CRYPT:
case SEG_LINEAR:
case SEG_STRIPED:
if ((r = _emit_areas_line(dmt, seg, params, paramsize, &pos)) <= 0) {
stack;
return r;
}
if (!_emit_areas_line(dmt, seg, params, paramsize, &pos))
return_0;
if (!params[0]) {
log_error("No parameters supplied for %s target "
"%u:%u.", _dm_segtypes[seg->type].target,
@@ -3099,6 +3121,9 @@ static int _load_node(struct dm_tree_node *dnode)
if (!dm_task_suppress_identical_reload(dmt))
log_warn("WARNING: Failed to suppress reload of identical tables.");
if (dnode->props.skip_reload_params_compare)
dm_task_skip_reload_params_compare(dmt);
if ((r = dm_task_run(dmt))) {
r = dm_task_get_info(dmt, &dnode->info);
if (r && !dnode->info.inactive_table)
@@ -3117,8 +3142,8 @@ static int _load_node(struct dm_tree_node *dnode)
if (!existing_table_size && dnode->props.delay_resume_if_new)
dnode->props.size_changed = 0;
log_debug_activation("Table size changed from %" PRIu64 " to %"
PRIu64 " for %s.%s", existing_table_size,
log_debug_activation("Table size changed from %" PRIu64 " to %" PRIu64 " for %s.%s",
existing_table_size,
seg_start, _node_name(dnode),
dnode->props.size_changed ? "" : " (Ignoring.)");
@@ -3144,32 +3169,45 @@ out:
return r;
}
/*
* Currently try to deactivate only nodes created during preload.
* New node is always attached to the front of activated_list
*/
static int _dm_tree_revert_activated(struct dm_tree_node *parent)
/* Try to deactivate only nodes created during preload. */
static int _dm_tree_revert_activated(struct dm_tree_node *dnode)
{
void *handle = NULL;
struct dm_tree_node *child;
dm_list_iterate_items_gen(child, &parent->activated, activated_list) {
log_debug_activation("Reverting %s.", _node_name(child));
if (child->callback) {
log_debug_activation("Dropping callback for %s.", _node_name(child));
child->callback = NULL;
while ((child = dm_tree_next_child(&handle, dnode, 0))) {
if (child->activated) {
if (child->callback) {
log_debug_activation("Dropping callback for %s.", _node_name(child));
child->callback = NULL;
}
log_debug_activation("Reverting %s.", _node_name(child));
if (!_deactivate_node(child->name, child->info.major, child->info.minor,
&child->dtree->cookie, child->udev_flags, 0)) {
log_debug_activation("Unable to deactivate %s.", _node_name(child));
return 0;
}
}
if (!_deactivate_node(child->name, child->info.major, child->info.minor,
&child->dtree->cookie, child->udev_flags, 0)) {
log_error("Unable to deactivate %s.", _node_name(child));
return 0;
}
if (!_dm_tree_revert_activated(child))
if (dm_tree_node_num_children(child, 0) &&
!_dm_tree_revert_activated(child))
return_0;
}
return 1;
}
static int _dm_tree_wait_and_revert_activated(struct dm_tree_node *dnode)
{
if (!dm_udev_wait(dm_tree_get_cookie(dnode)))
stack;
dm_tree_set_cookie(dnode, 0);
return _dm_tree_revert_activated(dnode);
}
int dm_tree_preload_children(struct dm_tree_node *dnode,
const char *uuid_prefix,
size_t uuid_prefix_len)
@@ -3199,7 +3237,7 @@ int dm_tree_preload_children(struct dm_tree_node *dnode,
return_0;
/* FIXME Cope if name exists with no uuid? */
if (!child->info.exists && !(node_created = _create_node(child)))
if (!child->info.exists && !(node_created = _create_node(child, dnode)))
return_0;
/* Propagate delayed resume from exteded child node */
@@ -3209,28 +3247,22 @@ int dm_tree_preload_children(struct dm_tree_node *dnode,
if (!child->info.inactive_table &&
child->props.segment_count &&
!_load_node(child)) {
stack;
/*
* If the table load does not succeed, we remove the
* device in the kernel that would otherwise have an
* empty table. This makes the create + load of the
* device atomic. However, if other dependencies have
* already been created and loaded; this code is
* insufficient to remove those - only the node
* encountering the table load failure is removed.
* If the table load fails, try to device in the kernel
* together with other created and preloaded devices.
*/
if (node_created) {
if (!_remove_node(child))
return_0;
if (!dm_udev_wait(dm_tree_get_cookie(dnode)))
stack;
dm_tree_set_cookie(dnode, 0);
(void) _dm_tree_revert_activated(child);
}
return_0;
if (!_dm_tree_wait_and_revert_activated(dnode))
stack;
r = 0;
continue;
}
/* No resume for a device without parents or with unchanged or smaller size */
if (!dm_tree_node_num_children(child, 1) || (child->props.size_changed <= 0))
if (!dm_tree_node_num_children(child, 1))
continue;
if (child->props.size_changed <= 0)
continue;
if (!child->info.inactive_table && !child->info.suspended)
@@ -3241,28 +3273,19 @@ int dm_tree_preload_children(struct dm_tree_node *dnode,
&child->info, &child->dtree->cookie, child->udev_flags,
child->info.suspended)) {
log_error("Unable to resume %s.", _node_name(child));
/* If the device was not previously active, we might as well remove this node. */
if (!child->info.live_table &&
!_deactivate_node(child->name, child->info.major, child->info.minor,
&child->dtree->cookie, child->udev_flags, 0))
log_error("Unable to deactivate %s.", _node_name(child));
if (!_dm_tree_wait_and_revert_activated(dnode))
stack;
r = 0;
/* Each child is handled independently */
continue;
}
if (node_created) {
/* Collect newly introduced devices for revert */
dm_list_add_h(&dnode->activated, &child->activated_list);
/* When creating new node also check transaction_id. */
if (child->props.send_messages &&
!_node_send_messages(child, uuid_prefix, uuid_prefix_len, 0)) {
stack;
if (!dm_udev_wait(dm_tree_get_cookie(dnode)))
if (!_dm_tree_wait_and_revert_activated(dnode))
stack;
dm_tree_set_cookie(dnode, 0);
(void) _dm_tree_revert_activated(dnode);
r = 0;
continue;
}
@@ -3844,20 +3867,24 @@ int dm_tree_node_add_integrity_target(struct dm_tree_node *node,
if (!(seg = _add_segment(node, SEG_INTEGRITY, size)))
return_0;
if (meta_uuid) {
if (!(seg->integrity_meta_node = dm_tree_find_node_by_uuid(node->dtree, meta_uuid))) {
log_error("Missing integrity's meta uuid %s.", meta_uuid);
return 0;
}
if (!_link_tree_nodes(node, seg->integrity_meta_node))
return_0;
if (!meta_uuid) {
log_error("No integrity meta uuid.");
return 0;
}
if (!(seg->integrity_meta_node = dm_tree_find_node_by_uuid(node->dtree, meta_uuid))) {
log_error("Missing integrity's meta uuid %s.", meta_uuid);
return 0;
}
if (!_link_tree_nodes(node, seg->integrity_meta_node))
return_0;
if (!(seg->origin = dm_tree_find_node_by_uuid(node->dtree, origin_uuid))) {
log_error("Missing integrity's origin uuid %s.", origin_uuid);
return 0;
}
if (!_link_tree_nodes(node, seg->origin))
return_0;
@@ -3865,6 +3892,8 @@ int dm_tree_node_add_integrity_target(struct dm_tree_node *node,
seg->integrity_recalculate = recalculate;
node->props.skip_reload_params_compare = 1;
return 1;
}
@@ -3941,6 +3970,24 @@ int dm_tree_node_add_thin_pool_target(struct dm_tree_node *node,
uint32_t data_block_size,
uint64_t low_water_mark,
unsigned skip_block_zeroing)
{
return dm_tree_node_add_thin_pool_target_v1(node, size, transaction_id,
metadata_uuid, pool_uuid,
data_block_size,
low_water_mark,
skip_block_zeroing,
1);
}
int dm_tree_node_add_thin_pool_target_v1(struct dm_tree_node *node,
uint64_t size,
uint64_t transaction_id,
const char *metadata_uuid,
const char *pool_uuid,
uint32_t data_block_size,
uint64_t low_water_mark,
unsigned skip_block_zeroing,
unsigned crop_metadata)
{
struct load_segment *seg, *mseg;
uint64_t devsize = 0;
@@ -3968,17 +4015,18 @@ int dm_tree_node_add_thin_pool_target(struct dm_tree_node *node,
if (!_link_tree_nodes(node, seg->metadata))
return_0;
/* FIXME: more complex target may need more tweaks */
dm_list_iterate_items(mseg, &seg->metadata->props.segs) {
devsize += mseg->size;
if (devsize > DM_THIN_MAX_METADATA_SIZE) {
log_debug_activation("Ignoring %" PRIu64 " of device.",
devsize - DM_THIN_MAX_METADATA_SIZE);
mseg->size -= (devsize - DM_THIN_MAX_METADATA_SIZE);
devsize = DM_THIN_MAX_METADATA_SIZE;
/* FIXME: drop remaining segs */
if (crop_metadata)
/* FIXME: more complex target may need more tweaks */
dm_list_iterate_items(mseg, &seg->metadata->props.segs) {
devsize += mseg->size;
if (devsize > DM_THIN_MAX_METADATA_SIZE) {
log_debug_activation("Ignoring %" PRIu64 " of device.",
devsize - DM_THIN_MAX_METADATA_SIZE);
mseg->size -= (devsize - DM_THIN_MAX_METADATA_SIZE);
devsize = DM_THIN_MAX_METADATA_SIZE;
/* FIXME: drop remaining segs */
}
}
}
if (!(seg->pool = dm_tree_find_node_by_uuid(node->dtree, pool_uuid))) {
log_error("Missing pool uuid %s.", pool_uuid);
@@ -4273,63 +4321,9 @@ void dm_tree_node_set_callback(struct dm_tree_node *dnode,
dnode->callback_data = data;
}
#if defined(__GNUC__)
/*
* Backward compatible implementations.
*
* Keep these at the end of the file to make sure that
* no code in this file accidentally calls it.
*/
/* Backward compatible dm_tree_node_size_changed() implementations. */
int dm_tree_node_size_changed_base(const struct dm_tree_node *dnode);
int dm_tree_node_size_changed_base(const struct dm_tree_node *dnode)
{
/* Base does not make difference between smaller and bigger */
return dm_tree_node_size_changed(dnode) ? 1 : 0;
}
/*
* Retain ABI compatibility after adding the DM_CACHE_FEATURE_METADATA2
* in version 1.02.138.
*
* Binaries compiled against version 1.02.138 onwards will use
* the new function dm_tree_node_add_cache_target which detects unknown
* feature flags and returns error for them.
*/
int dm_tree_node_add_cache_target_base(struct dm_tree_node *node,
uint64_t size,
uint64_t feature_flags, /* DM_CACHE_FEATURE_* */
const char *metadata_uuid,
const char *data_uuid,
const char *origin_uuid,
const char *policy_name,
const struct dm_config_node *policy_settings,
uint32_t data_block_size);
int dm_tree_node_add_cache_target_base(struct dm_tree_node *node,
uint64_t size,
uint64_t feature_flags,
const char *metadata_uuid,
const char *data_uuid,
const char *origin_uuid,
const char *policy_name,
const struct dm_config_node *policy_settings,
uint32_t data_block_size)
{
/* Old version supported only these FEATURE bits, others were ignored so masked them */
static const uint64_t _mask =
DM_CACHE_FEATURE_WRITEBACK |
DM_CACHE_FEATURE_WRITETHROUGH |
DM_CACHE_FEATURE_PASSTHROUGH;
return dm_tree_node_add_cache_target(node, size, feature_flags & _mask,
metadata_uuid, data_uuid, origin_uuid,
policy_name, policy_settings, 0, 0, 0, 0, data_block_size);
}
#endif
int dm_tree_node_add_vdo_target(struct dm_tree_node *node,
uint64_t size,
const char *vdo_pool_name,
const char *data_uuid,
uint64_t data_size,
const struct dm_vdo_target_params *vtp)
@@ -4351,7 +4345,7 @@ int dm_tree_node_add_vdo_target(struct dm_tree_node *node,
return_0;
seg->vdo_params = *vtp;
seg->vdo_name = node->name;
seg->vdo_name = vdo_pool_name;
seg->vdo_data_size = data_size;
node->props.send_messages = 2;

View File

@@ -110,7 +110,7 @@ int dm_is_empty_dir(const char *dir)
DIR *d;
if (!(d = opendir(dir))) {
log_sys_error("opendir", dir);
log_sys_debug("opendir", dir);
return 0;
}
@@ -119,7 +119,7 @@ int dm_is_empty_dir(const char *dir)
break;
if (closedir(d))
log_sys_error("closedir", dir);
log_sys_debug("closedir", dir);
return dirent ? 0 : 1;
}

View File

@@ -492,7 +492,7 @@ static int _report_field_string_list(struct dm_report *rh,
delimiter = ",";
delimiter_len = strlen(delimiter);
i = pos = len = 0;
i = pos = 0;
dm_list_iterate_items(sl, data) {
arr[i].str = sl->str;
if (!sort) {
@@ -749,10 +749,11 @@ static void _display_fields_more(struct dm_report *rh,
id_len = strlen(type->prefix) + 3;
for (f = 0; fields[f].report_fn; f++) {
if ((type = _find_type(rh, fields[f].type)) && type->desc)
desc = type->desc;
else
desc = " ";
if (!(type = _find_type(rh, fields[f].type))) {
log_debug(INTERNAL_ERROR "Field type undefined.");
continue;
}
desc = (type->desc) ? : " ";
if (desc != last_desc) {
if (*last_desc)
log_warn(" ");
@@ -2331,7 +2332,7 @@ static const char *_reserved_name(struct dm_report *rh,
uint32_t field_num, const char *s, size_t len)
{
dm_report_reserved_handler handler;
const char *canonical_name;
const char *canonical_name = NULL;
const char **name;
char *tmp_s;
char c;
@@ -2473,7 +2474,7 @@ dm_percent_t dm_make_percent(uint64_t numerator, uint64_t denominator)
int dm_report_value_cache_set(struct dm_report *rh, const char *name, const void *data)
{
if (!rh->value_cache && (!(rh->value_cache = dm_hash_create(64)))) {
if (!rh->value_cache && (!(rh->value_cache = dm_hash_create(63)))) {
log_error("Failed to create cache for values used during reporting.");
return 0;
}
@@ -3773,7 +3774,7 @@ static struct selection_node *_parse_selection(struct dm_report *rh,
struct field_selection *fs;
struct selection_node *sn;
const char *ws, *we; /* field name */
const char *vs, *ve; /* value */
const char *vs = NULL, *ve = NULL; /* value */
const char *last;
uint32_t flags, field_num;
int implicit;
@@ -3909,7 +3910,7 @@ static struct selection_node *_parse_ex(struct dm_report *rh,
static const char _pe_expected_msg[] = "Syntax error: right parenthesis expected at \'%s\'";
struct selection_node *sn = NULL;
uint32_t t;
const char *tmp;
const char *tmp = NULL;
t = _tok_op_log(s, next, SEL_MODIFIER_NOT | SEL_PRECEDENCE_PS);
if (t == SEL_MODIFIER_NOT) {
@@ -3955,7 +3956,7 @@ static struct selection_node *_parse_and_ex(struct dm_report *rh,
struct selection_node *and_sn)
{
struct selection_node *n;
const char *tmp;
const char *tmp = NULL;
n = _parse_ex(rh, s, next);
if (!n)
@@ -3987,7 +3988,7 @@ static struct selection_node *_parse_or_ex(struct dm_report *rh,
struct selection_node *or_sn)
{
struct selection_node *n;
const char *tmp;
const char *tmp = NULL;
n = _parse_and_ex(rh, s, next, NULL);
if (!n)

View File

@@ -384,7 +384,7 @@ int dm_get_status_integrity(struct dm_pool *mem, const char *params,
struct dm_status_integrity **status)
{
struct dm_status_integrity *s;
char recalc_str[8] = "\0";
char recalc_str[16] = "\0";
if (!(s = dm_pool_zalloc(mem, sizeof(*s))))
return_0;

View File

@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.0+ WITH Linux-syscall-note */
/*
* Copyright (C) 2001 - 2003 Sistina Software (UK) Limited.
* Copyright (C) 2004 - 2017 Red Hat, Inc. All rights reserved.
* Copyright (C) 2004 - 2021 Red Hat, Inc. All rights reserved.
*
* This file is released under the LGPL.
*/
@@ -194,8 +195,22 @@ struct dm_name_list {
uint32_t next; /* offset to the next record from
the _start_ of this */
char name[0];
/*
* The following members can be accessed by taking a pointer that
* points immediately after the terminating zero character in "name"
* and aligning this pointer to next 8-byte boundary.
* Uuid is present if the flag DM_NAME_LIST_FLAG_HAS_UUID is set.
*
* uint32_t event_nr;
* uint32_t flags;
* char uuid[0];
*/
};
#define DM_NAME_LIST_FLAG_HAS_UUID 1
#define DM_NAME_LIST_FLAG_DOESNT_HAVE_UUID 2
/*
* Used to retrieve the target versions
*/
@@ -274,9 +289,9 @@ enum {
#define DM_GET_TARGET_VERSION _IOWR(DM_IOCTL, DM_GET_TARGET_VERSION_CMD, struct dm_ioctl)
#define DM_VERSION_MAJOR 4
#define DM_VERSION_MINOR 36
#define DM_VERSION_MINOR 45
#define DM_VERSION_PATCHLEVEL 0
#define DM_VERSION_EXTRA "-ioctl (2017-06-09)"
#define DM_VERSION_EXTRA "-ioctl (2021-03-22)"
/* Status bits */
#define DM_READONLY_FLAG (1 << 0) /* In/Out */
@@ -364,4 +379,10 @@ enum {
*/
#define DM_INTERNAL_SUSPEND_FLAG (1 << 18) /* Out */
/*
* If set, returns in the in buffer passed by UM, the raw table information
* that would be measured by IMA subsystem on device state change.
*/
#define DM_IMA_MEASUREMENT_FLAG (1 << 19) /* In */
#endif /* _LINUX_DM_IOCTL_H */

View File

@@ -98,7 +98,7 @@ void dm_pools_check_leaks(void)
p->orig_pool,
p->name, p->stats.bytes);
#else
log_error(" [%p] %s", p, p->name);
log_error(" [%p] %s", (void *)p, p->name);
#endif
}
pthread_mutex_unlock(&_dm_pools_mutex);

View File

@@ -69,7 +69,8 @@ bool dm_vdo_status_parse(struct dm_pool *mem, const char *input,
enum dm_vdo_write_policy {
DM_VDO_WRITE_POLICY_AUTO = 0,
DM_VDO_WRITE_POLICY_SYNC,
DM_VDO_WRITE_POLICY_ASYNC
DM_VDO_WRITE_POLICY_ASYNC,
DM_VDO_WRITE_POLICY_ASYNC_UNSAFE
};
// FIXME: review whether we should use the createParams from the userlib

View File

@@ -100,6 +100,7 @@ bool dm_vdo_validate_target_params(const struct dm_vdo_target_params *vtp,
switch (vtp->write_policy) {
case DM_VDO_WRITE_POLICY_SYNC:
case DM_VDO_WRITE_POLICY_ASYNC:
case DM_VDO_WRITE_POLICY_ASYNC_UNSAFE:
case DM_VDO_WRITE_POLICY_AUTO:
break;
default:

View File

@@ -94,7 +94,7 @@ journal_watermark:number
commit_time:number
Commit time in milliseconds. When this time passes, the journal is
written. The journal is also written immediatelly if the FLUSH
written. The journal is also written immediately if the FLUSH
request is received.
internal_hash:algorithm(:key) (the key is optional)

2
include/.gitignore vendored
View File

@@ -1 +1,3 @@
*.h
.symlinks
.symlinks_created

View File

@@ -1,5 +1,8 @@
/* include/configure.h.in. Generated from configure.ac by autoheader. */
/* Define to 1 to include code that uses libsystemd machine-id apis. */
#undef APP_MACHINEID_SUPPORT
/* Define to 1 to use libblkid detection of signatures when wiping. */
#undef BLKID_WIPING_SUPPORT
@@ -87,6 +90,9 @@
/* Use blkid wiping by default. */
#undef DEFAULT_USE_BLKID_WIPING
/* Default for lvm.conf use_devicefile. */
#undef DEFAULT_USE_DEVICES_FILE
/* Use lvmlockd by default. */
#undef DEFAULT_USE_LVMLOCKD
@@ -108,9 +114,6 @@
/* Define to 1 to enable the device-mapper filemap daemon. */
#undef DMFILEMAPD
/* Define to enable compat protocol */
#undef DM_COMPAT
/* Define default group for device node */
#undef DM_DEVICE_GID
@@ -126,9 +129,15 @@
/* Library version */
#undef DM_LIB_VERSION
/* Define to 1 to include the LVM editline shell. */
#undef EDITLINE_SUPPORT
/* Path to fsadm binary. */
#undef FSADM_PATH
/* Define to use GNU versioning in the shared library. */
#undef GNU_SYMVER
/* Define to 1 if you have the `alarm' function. */
#undef HAVE_ALARM
@@ -151,6 +160,9 @@
/* Define to 1 if you have the `atexit' function. */
#undef HAVE_ATEXIT
/* Define if ioctl BLKZEROOUT can be used for device zeroing. */
#undef HAVE_BLKZEROOUT
/* Define to 1 if canonicalize_file_name is available. */
#undef HAVE_CANONICALIZE_FILE_NAME
@@ -176,12 +188,18 @@
/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
#undef HAVE_DOPRNT
/* Define to 1 if you have the <editline/readline.h> header file. */
#undef HAVE_EDITLINE_READLINE_H
/* Define to 1 if you have the <errno.h> header file. */
#undef HAVE_ERRNO_H
/* Define to 1 if you have the <fcntl.h> header file. */
#undef HAVE_FCNTL_H
/* Define to 1 if you have the `ffs' function. */
#undef HAVE_FFS
/* Define to 1 if you have the <float.h> header file. */
#undef HAVE_FLOAT_H
@@ -507,6 +525,9 @@
/* valgrind.h found */
#undef HAVE_VALGRIND
/* Define to 1 if you have the `versionsort' function. */
#undef HAVE_VERSIONSORT
/* Define to 1 if you have the `vfork' function. */
#undef HAVE_VFORK
@@ -531,6 +552,12 @@
/* Define to 1 if the system has the `__builtin_clzll' built-in function */
#undef HAVE___BUILTIN_CLZLL
/* Define to 1 if the system has the `__builtin_ffs' built-in function */
#undef HAVE___BUILTIN_FFS
/* Define to 1 to include built-in support for integrity. */
#undef INTEGRITY_INTERNAL
/* Internalization package */
#undef INTL_PACKAGE
@@ -543,6 +570,9 @@
/* Define to 1 to include code that uses lvmlockd dlm option. */
#undef LOCKDDLM_SUPPORT
/* Define to 1 to include code that uses lvmlockd IDM option. */
#undef LOCKDIDM_SUPPORT
/* Define to 1 to include code that uses lvmlockd sanlock option. */
#undef LOCKDSANLOCK_SUPPORT
@@ -553,6 +583,9 @@
/* Path to lvmconfig binary. */
#undef LVMCONFIG_PATH
/* Path to lvm_import_vdo script. */
#undef LVMIMPORTVDO_PATH
/* Path to lvmlockd pidfile. */
#undef LVMLOCKD_PIDFILE
@@ -635,6 +668,9 @@
/* Define to 1 if strerror_r returns char *. */
#undef STRERROR_R_CHAR_P
/* Define to 1 to include code that uses systemd journal. */
#undef SYSTEMD_JOURNAL_SUPPORT
/* Path to testsuite data */
#undef TESTSUITE_DATA
@@ -678,9 +714,6 @@
/* Define to 1 to include built-in support for writecache. */
#undef WRITECACHE_INTERNAL
/* Define to 1 to include built-in support for integrity. */
#undef INTEGRITY_INTERNAL
/* Define to get access to GNU/Linux extension */
#undef _GNU_SOURCE

View File

@@ -15,6 +15,7 @@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
top_builddir = @top_builddir@
abs_srcdir = @abs_srcdir@
SOURCES =\
activate/activate.c \
@@ -29,14 +30,17 @@ SOURCES =\
device/bcache.c \
device/bcache-utils.c \
device/dev-cache.c \
device/device_id.c \
device/dev-ext.c \
device/dev-io.c \
device/dev-md.c \
device/dev-mpath.c \
device/dev-swap.c \
device/dev-type.c \
device/dev-luks.c \
device/dev-dasd.c \
device/dev-lvm1-pool.c \
device/online.c \
display/display.c \
error/errseg.c \
unknown/unknown.c \
@@ -52,6 +56,7 @@ SOURCES =\
filters/filter-usable.c \
filters/filter-internal.c \
filters/filter-signature.c \
filters/filter-deviceid.c \
format_text/archive.c \
format_text/archiver.c \
format_text/export.c \

View File

@@ -29,6 +29,7 @@
#include "lib/metadata/segtype.h"
#include "lib/misc/sharedlib.h"
#include "lib/metadata/metadata.h"
#include "lib/misc/lvm-signal.h"
#include <limits.h>
#include <fcntl.h>
@@ -177,6 +178,22 @@ int lv_passes_auto_activation_filter(struct cmd_context *cmd, struct logical_vol
return _lv_passes_volumes_filter(cmd, lv, cn, activation_auto_activation_volume_list_CFG);
}
static int _passes_readonly_filter(struct cmd_context *cmd,
const struct logical_volume *lv)
{
const struct dm_config_node *cn;
if (!(cn = find_config_tree_array(cmd, activation_read_only_volume_list_CFG, NULL)))
return 0;
return _lv_passes_volumes_filter(cmd, lv, cn, activation_read_only_volume_list_CFG);
}
int lv_passes_readonly_filter(const struct logical_volume *lv)
{
return _passes_readonly_filter(lv->vg->cmd, lv);
}
#ifndef DEVMAPPER_SUPPORT
void set_activation(int act, int silent)
{
@@ -185,8 +202,8 @@ void set_activation(int act, int silent)
if (warned || !act)
return;
log_error("Compiled without libdevmapper support. "
"Can't enable activation.");
log_warn("WARNING: Compiled without libdevmapper support. "
"Can't enable activation.");
warned = 1;
}
@@ -221,23 +238,13 @@ int lv_info(struct cmd_context *cmd, const struct logical_volume *lv, int use_la
{
return 0;
}
int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s, int use_layer,
struct lvinfo *info, int with_open_count, int with_read_ahead)
{
return 0;
}
int lv_info_with_seg_status(struct cmd_context *cmd, const struct logical_volume *lv,
const struct lv_segment *lv_seg, int use_layer,
int lv_info_with_seg_status(struct cmd_context *cmd,
const struct lv_segment *lv_seg,
struct lv_with_info_and_seg_status *status,
int with_open_count, int with_read_ahead)
{
return 0;
}
int lv_status(struct cmd_context *cmd, const struct lv_segment *lv_seg,
int use_layer, struct lv_seg_status *lv_seg_status)
{
return 0;
}
int lv_cache_status(const struct logical_volume *cache_lv,
struct lv_status_cache **status)
{
@@ -284,18 +291,21 @@ int lv_raid_message(const struct logical_volume *lv, const char *msg)
{
return 0;
}
int lv_thin_pool_percent(const struct logical_volume *lv, int metadata,
dm_percent_t *percent)
int lv_raid_status(const struct logical_volume *lv, struct lv_status_raid **status)
{
return 0;
}
int lv_thin_percent(const struct logical_volume *lv, int mapped,
dm_percent_t *percent)
int lv_writecache_message(const struct logical_volume *lv, const char *msg)
{
return 0;
}
int lv_thin_pool_transaction_id(const struct logical_volume *lv,
uint64_t *transaction_id)
int lv_thin_pool_status(const struct logical_volume *lv, int flush,
struct lv_status_thin_pool **thin_pool_status)
{
return 0;
}
int lv_thin_status(const struct logical_volume *lv, int flush,
struct lv_status_thin **thin_status)
{
return 0;
}
@@ -303,6 +313,15 @@ int lv_thin_device_id(const struct logical_volume *lv, uint32_t *device_id)
{
return 0;
}
int lv_vdo_pool_status(const struct logical_volume *lv, int flush,
struct lv_status_vdo **vdo_status)
{
return 0;
}
int lv_vdo_pool_percent(const struct logical_volume *lv, dm_percent_t *percent)
{
return 0;
}
int lvs_in_vg_activated(const struct volume_group *vg)
{
return 0;
@@ -394,7 +413,7 @@ int add_areas_line(struct dev_manager *dm, struct lv_segment *seg,
{
return 0;
}
int device_is_usable(struct device *dev, struct dev_usable_check_params check)
int device_is_usable(struct cmd_context *cmd, struct device *dev, struct dev_usable_check_params check, int *is_lv)
{
return 0;
}
@@ -457,17 +476,6 @@ static int _passes_activation_filter(struct cmd_context *cmd,
return _lv_passes_volumes_filter(cmd, lv, cn, activation_volume_list_CFG);
}
static int _passes_readonly_filter(struct cmd_context *cmd,
const struct logical_volume *lv)
{
const struct dm_config_node *cn;
if (!(cn = find_config_tree_array(cmd, activation_read_only_volume_list_CFG, NULL)))
return 0;
return _lv_passes_volumes_filter(cmd, lv, cn, activation_read_only_volume_list_CFG);
}
int library_version(char *version, size_t size)
{
if (!activation())
@@ -478,12 +486,20 @@ int library_version(char *version, size_t size)
int driver_version(char *version, size_t size)
{
static char _vsn[80] = { 0 };
if (!activation())
return 0;
log_very_verbose("Getting driver version");
return dm_driver_version(version, size);
if (!_vsn[0] &&
!dm_driver_version(_vsn, sizeof(_vsn)))
return_0;
(void) dm_strncpy(version, _vsn, size);
return 1;
}
int target_version(const char *target_name, uint32_t *maj,
@@ -555,7 +571,7 @@ int module_present(struct cmd_context *cmd, const char *target_name)
dm_sysfs_dir(), target_name);
if (i > 0) {
while (path[--i] != '/') /* stop on dm_ */
while ((i > 0) && path[--i] != '/') /* stop on dm_ */
if (path[i] == '-')
path[i] = '_'; /* replace '-' with '_' */
@@ -566,13 +582,9 @@ int module_present(struct cmd_context *cmd, const char *target_name)
}
#ifdef MODPROBE_CMD
if (strcmp(target_name, MODULE_NAME_VDO) == 0) {
argv[1] = target_name; /* ATM kvdo is without dm- prefix */
if ((ret = exec_cmd(cmd, argv, NULL, 0)))
return ret;
}
if (dm_snprintf(module, sizeof(module), "dm-%s", target_name) < 0) {
if (strcmp(target_name, TARGET_NAME_VDO) == 0)
argv[1] = MODULE_NAME_VDO; /* ATM kvdo is without dm- prefix */
else if (dm_snprintf(module, sizeof(module), "dm-%s", target_name) < 0) {
log_error("module_present module name too long: %s",
target_name);
return 0;
@@ -612,6 +624,15 @@ int target_present(struct cmd_context *cmd, const char *target_name,
&maj, &min, &patchlevel);
}
int get_device_list(const struct volume_group *vg, struct dm_list **devs,
unsigned *devs_features)
{
if (!activation())
return 0;
return dev_manager_get_device_list(NULL, devs, devs_features);
}
/*
* When '*info' is NULL, returns 1 only when LV is active.
* When '*info' != NULL, returns 1 when info structure is populated.
@@ -825,12 +846,15 @@ int lv_info_with_seg_status(struct cmd_context *cmd,
#define OPEN_COUNT_CHECK_USLEEP_DELAY 200000
/* Only report error if error_if_used is set */
/* Returns 0 if in use, 1 if it is unused, 2 when it is not present in table */
int lv_check_not_in_use(const struct logical_volume *lv, int error_if_used)
{
struct lvinfo info;
unsigned int open_count_check_retries;
if (!lv_info(lv->vg->cmd, lv, 0, &info, 1, 0) || !info.exists || !info.open_count)
if (!lv_info(lv->vg->cmd, lv, 0, &info, 1, 0) || !info.exists)
return 2;
else if (!info.open_count)
return 1;
/* If sysfs is not used, use open_count information only. */
@@ -857,25 +881,24 @@ int lv_check_not_in_use(const struct logical_volume *lv, int error_if_used)
}
open_count_check_retries = retry_deactivation() ? OPEN_COUNT_CHECK_RETRIES : 1;
while (info.open_count > 0 && open_count_check_retries--) {
if (!open_count_check_retries) {
if (error_if_used)
log_error("Logical volume %s in use.", display_lvname(lv));
else
log_debug_activation("Logical volume %s in use.", display_lvname(lv));
return 0;
}
while (open_count_check_retries--) {
if (interruptible_usleep(OPEN_COUNT_CHECK_USLEEP_DELAY))
break; /* interrupted */
usleep(OPEN_COUNT_CHECK_USLEEP_DELAY);
log_debug_activation("Retrying open_count check for %s.",
display_lvname(lv));
if (!lv_info(lv->vg->cmd, lv, 0, &info, 1, 0)) {
if (!lv_info(lv->vg->cmd, lv, 0, &info, 1, 0) || !info.exists) {
stack; /* device dissappeared? */
break;
}
return 1;
} else if (!info.open_count)
return 1;
}
return 1;
if (error_if_used)
log_error("Logical volume %s in use.", display_lvname(lv));
else
log_debug_activation("Logical volume %s in use.", display_lvname(lv));
return 0;
}
/*
@@ -966,35 +989,28 @@ int lv_raid_percent(const struct logical_volume *lv, dm_percent_t *percent)
int lv_raid_data_offset(const struct logical_volume *lv, uint64_t *data_offset)
{
int r;
struct dev_manager *dm;
struct dm_status_raid *status;
struct lv_status_raid *raid_status;
if (!lv_info(lv->vg->cmd, lv, 0, NULL, 0, 0))
return 0;
log_debug_activation("Checking raid data offset and dev sectors for LV %s/%s",
lv->vg->name, lv->name);
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1)))
return_0;
if (!(r = dev_manager_raid_status(dm, lv, &status))) {
dev_manager_destroy(dm);
return_0;
}
if (!lv_raid_status(lv, &raid_status))
return_0;
*data_offset = status->data_offset;
*data_offset = raid_status->raid->data_offset;
dev_manager_destroy(dm);
dm_pool_destroy(raid_status->mem);
return r;
return 1;
}
int lv_raid_dev_health(const struct logical_volume *lv, char **dev_health)
{
int r;
struct dev_manager *dm;
struct dm_status_raid *status;
int r = 1;
struct lv_status_raid *raid_status;
*dev_health = NULL;
@@ -1004,25 +1020,23 @@ int lv_raid_dev_health(const struct logical_volume *lv, char **dev_health)
log_debug_activation("Checking raid device health for LV %s.",
display_lvname(lv));
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1)))
return_0;
if (!lv_raid_status(lv, &raid_status))
return_0;
if (!(r = dev_manager_raid_status(dm, lv, &status)) ||
!(*dev_health = dm_pool_strdup(lv->vg->cmd->mem,
status->dev_health))) {
dev_manager_destroy(dm);
return_0;
if (!(*dev_health = dm_pool_strdup(lv->vg->cmd->mem,
raid_status->raid->dev_health))) {
stack;
r = 0;
}
dev_manager_destroy(dm);
dm_pool_destroy(raid_status->mem);
return r;
}
int lv_raid_dev_count(const struct logical_volume *lv, uint32_t *dev_cnt)
{
struct dev_manager *dm;
struct dm_status_raid *status;
struct lv_status_raid *raid_status;
*dev_cnt = 0;
@@ -1031,24 +1045,20 @@ int lv_raid_dev_count(const struct logical_volume *lv, uint32_t *dev_cnt)
log_debug_activation("Checking raid device count for LV %s/%s",
lv->vg->name, lv->name);
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1)))
if (!lv_raid_status(lv, &raid_status))
return_0;
if (!dev_manager_raid_status(dm, lv, &status)) {
dev_manager_destroy(dm);
return_0;
}
*dev_cnt = status->dev_count;
*dev_cnt = raid_status->raid->dev_count;
dev_manager_destroy(dm);
dm_pool_destroy(raid_status->mem);
return 1;
}
int lv_raid_mismatch_count(const struct logical_volume *lv, uint64_t *cnt)
{
struct dev_manager *dm;
struct dm_status_raid *status;
struct lv_status_raid *raid_status;
*cnt = 0;
@@ -1058,25 +1068,20 @@ int lv_raid_mismatch_count(const struct logical_volume *lv, uint64_t *cnt)
log_debug_activation("Checking raid mismatch count for LV %s.",
display_lvname(lv));
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1)))
if (!lv_raid_status(lv, &raid_status))
return_0;
if (!dev_manager_raid_status(dm, lv, &status)) {
dev_manager_destroy(dm);
return_0;
}
*cnt = status->mismatch_count;
*cnt = raid_status->raid->mismatch_count;
dev_manager_destroy(dm);
dm_pool_destroy(raid_status->mem);
return 1;
}
int lv_raid_sync_action(const struct logical_volume *lv, char **sync_action)
{
struct dev_manager *dm;
struct dm_status_raid *status;
char *action;
struct lv_status_raid *raid_status;
int r = 1;
*sync_action = NULL;
@@ -1086,30 +1091,27 @@ int lv_raid_sync_action(const struct logical_volume *lv, char **sync_action)
log_debug_activation("Checking raid sync_action for LV %s.",
display_lvname(lv));
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1)))
if (!lv_raid_status(lv, &raid_status))
return_0;
/* status->sync_action can be NULL if dm-raid version < 1.5.0 */
if (!dev_manager_raid_status(dm, lv, &status) ||
!status->sync_action ||
!(action = dm_pool_strdup(lv->vg->cmd->mem,
status->sync_action))) {
dev_manager_destroy(dm);
return_0;
if (!raid_status->raid->sync_action ||
!(*sync_action = dm_pool_strdup(lv->vg->cmd->mem,
raid_status->raid->sync_action))) {
stack;
r = 0;
}
*sync_action = action;
dm_pool_destroy(raid_status->mem);
dev_manager_destroy(dm);
return 1;
return r;
}
int lv_raid_message(const struct logical_volume *lv, const char *msg)
{
struct lv_status_raid *raid_status;
struct dev_manager *dm = NULL;
int r = 0;
struct dev_manager *dm;
struct dm_status_raid *status;
if (!seg_is_raid(first_seg(lv))) {
/*
@@ -1134,16 +1136,10 @@ int lv_raid_message(const struct logical_volume *lv, const char *msg)
return 0;
}
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1)))
if (!lv_raid_status(lv, &raid_status))
return_0;
if (!(r = dev_manager_raid_status(dm, lv, &status))) {
log_error("Failed to retrieve status of %s.",
display_lvname(lv));
goto out;
}
if (!status->sync_action) {
if (!raid_status->raid->sync_action) {
log_error("Kernel driver does not support this action: %s", msg);
goto out;
}
@@ -1165,19 +1161,43 @@ int lv_raid_message(const struct logical_volume *lv, const char *msg)
log_error("\"%s\" is not a supported sync operation.", msg);
goto out;
}
if (strcmp(status->sync_action, "idle")) {
if (strcmp(raid_status->raid->sync_action, "idle")) {
log_error("%s state is currently \"%s\". Unable to switch to \"%s\".",
display_lvname(lv), status->sync_action, msg);
display_lvname(lv), raid_status->raid->sync_action, msg);
goto out;
}
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1)))
return_0;
r = dev_manager_raid_message(dm, lv, msg);
out:
dev_manager_destroy(dm);
if (dm)
dev_manager_destroy(dm);
dm_pool_destroy(raid_status->mem);
return r;
}
int lv_raid_status(const struct logical_volume *lv, struct lv_status_raid **status)
{
struct dev_manager *dm;
int exists;
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1)))
return_0;
if (!dev_manager_raid_status(dm, lv, status, &exists)) {
dev_manager_destroy(dm);
if (exists)
stack;
return 0;
}
/* User has to call dm_pool_destroy(status->mem)! */
return 1;
}
int lv_writecache_message(const struct logical_volume *lv, const char *msg)
{
int r = 0;
@@ -1210,6 +1230,7 @@ int lv_cache_status(const struct logical_volume *cache_lv,
{
struct dev_manager *dm;
struct lv_segment *cache_seg;
int exists;
if (lv_is_cache_pool(cache_lv)) {
if (dm_list_empty(&cache_lv->segs_using_this_lv) ||
@@ -1227,125 +1248,74 @@ int lv_cache_status(const struct logical_volume *cache_lv,
return 0;
}
if (!lv_info(cache_lv->vg->cmd, cache_lv, 1, NULL, 0, 0)) {
log_error("Cannot check status for locally inactive cache volume %s.",
display_lvname(cache_lv));
return 0;
}
log_debug_activation("Checking status for cache volume %s.",
display_lvname(cache_lv));
if (!(dm = dev_manager_create(cache_lv->vg->cmd, cache_lv->vg->name, 1)))
return_0;
if (!dev_manager_cache_status(dm, cache_lv, status)) {
if (!dev_manager_cache_status(dm, cache_lv, status, &exists)) {
dev_manager_destroy(dm);
return_0;
if (exists)
stack;
return 0;
}
/* User has to call dm_pool_destroy(status->mem)! */
return 1;
}
/*
* Returns data or metadata percent usage, depends on metadata 0/1.
* Returns 1 if percent set, else 0 on failure.
*/
int lv_thin_pool_percent(const struct logical_volume *lv, int metadata,
dm_percent_t *percent)
int lv_thin_pool_status(const struct logical_volume *lv, int flush,
struct lv_status_thin_pool **thin_pool_status)
{
int r;
struct dev_manager *dm;
if (!lv_info(lv->vg->cmd, lv, 1, NULL, 0, 0))
return 0;
log_debug_activation("Checking thin %sdata percent for LV %s.",
(metadata) ? "meta" : "", display_lvname(lv));
int exists;
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1)))
return_0;
if (!(r = dev_manager_thin_pool_percent(dm, lv, metadata, percent)))
stack;
if (!dev_manager_thin_pool_status(dm, lv, flush, thin_pool_status, &exists)) {
dev_manager_destroy(dm);
if (exists)
stack;
return 0;
}
dev_manager_destroy(dm);
/* User has to call dm_pool_destroy(thin_pool_status->mem)! */
return r;
return 1;
}
/*
* Returns 1 if percent set, else 0 on failure.
*/
int lv_thin_percent(const struct logical_volume *lv,
int mapped, dm_percent_t *percent)
int lv_thin_status(const struct logical_volume *lv, int flush,
struct lv_status_thin **thin_status)
{
int r;
struct dev_manager *dm;
if (!lv_info(lv->vg->cmd, lv, 0, NULL, 0, 0))
return 0;
log_debug_activation("Checking thin percent for LV %s.",
display_lvname(lv));
int exists;
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1)))
return_0;
if (!(r = dev_manager_thin_percent(dm, lv, mapped, percent)))
stack;
dev_manager_destroy(dm);
return r;
}
/*
* Returns 1 if transaction_id set, else 0 on failure.
*/
int lv_thin_pool_transaction_id(const struct logical_volume *lv,
uint64_t *transaction_id)
{
int r;
struct dev_manager *dm;
struct dm_status_thin_pool *status;
if (!lv_info(lv->vg->cmd, lv, 1, NULL, 0, 0))
if (!dev_manager_thin_status(dm, lv, flush, thin_status, &exists)) {
dev_manager_destroy(dm);
if (exists)
stack;
return 0;
}
log_debug_activation("Checking thin-pool transaction id for LV %s.",
display_lvname(lv));
/* User has to call dm_pool_destroy(thin_status->mem)! */
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1)))
return_0;
if (!(r = dev_manager_thin_pool_status(dm, lv, &status, 0)))
stack;
else
*transaction_id = status->transaction_id;
dev_manager_destroy(dm);
return r;
return 1;
}
int lv_thin_device_id(const struct logical_volume *lv, uint32_t *device_id)
{
int r;
struct dev_manager *dm;
if (!lv_info(lv->vg->cmd, lv, 0, NULL, 0, 0))
return 0;
log_debug_activation("Checking device id for LV %s.",
display_lvname(lv));
int exists;
int r;
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1)))
return_0;
if (!(r = dev_manager_thin_device_id(dm, lv, device_id)))
stack;
if (!(r = dev_manager_thin_device_id(dm, lv, device_id, &exists)))
if (exists)
stack;
dev_manager_destroy(dm);
@@ -1362,28 +1332,22 @@ int lv_thin_device_id(const struct logical_volume *lv, uint32_t *device_id)
int lv_vdo_pool_status(const struct logical_volume *lv, int flush,
struct lv_status_vdo **vdo_status)
{
int r = 0;
struct dev_manager *dm;
if (!lv_info(lv->vg->cmd, lv, 1, NULL, 0, 0))
return 0;
log_debug_activation("Checking VDO pool status for LV %s.",
display_lvname(lv));
int exists;
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, !lv_is_pvmove(lv))))
return_0;
if (!dev_manager_vdo_pool_status(dm, lv, vdo_status, flush))
goto_out;
if (!dev_manager_vdo_pool_status(dm, lv, flush, vdo_status, &exists)) {
dev_manager_destroy(dm);
if (exists)
stack;
return 0;
}
/* User has to call dm_pool_destroy(vdo_status->mem) */
r = 1;
out:
if (!r)
dev_manager_destroy(dm);
return r;
return 1;
}
int lv_vdo_pool_percent(const struct logical_volume *lv, dm_percent_t *percent)
@@ -1544,7 +1508,7 @@ int lvs_in_vg_opened(const struct volume_group *vg)
*/
int raid4_is_supported(struct cmd_context *cmd, const struct segment_type *segtype)
{
unsigned attrs;
unsigned attrs = 0;
if (segtype_is_raid4(segtype) &&
(!segtype->ops->target_present ||
@@ -2079,12 +2043,6 @@ static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
if (!activation())
return 1;
/* Ignore origin_only unless LV is origin in both old and new metadata */
/* or LV is thin or thin pool volume */
if (!lv_is_thin_volume(lv) && !lv_is_thin_pool(lv) &&
!(lv_is_origin(lv) && lv_is_origin(lv_pre)))
laopts->origin_only = 0;
if (test_mode()) {
_skip("Suspending %s%s.", display_lvname(lv),
laopts->origin_only ? " origin without snapshots" : "");
@@ -2106,6 +2064,12 @@ static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
lv_calculate_readahead(lv, NULL);
/* Ignore origin_only unless LV is origin in both old and new metadata */
/* or LV is thin or thin pool volume */
if (!lv_is_thin_volume(lv) && !lv_is_thin_pool(lv) &&
!(lv_is_origin(lv) && lv_is_origin(lv_pre)))
laopts->origin_only = 0;
/*
* Preload devices for the LV.
* If the PVMOVE LV is being removed, it's only present in the old
@@ -2197,8 +2161,6 @@ static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
if (laopts->origin_only && lv_is_thin_volume(lv) && lv_is_thin_volume(lv_pre))
lockfs = 1;
critical_section_inc(cmd, "suspending");
if (!lv_is_locked(lv) && lv_is_locked(lv_pre) &&
(pvmove_lv = find_pvmove_lv_in_lv(lv_pre))) {
/*
@@ -2240,16 +2202,23 @@ static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
}
dm_list_add(&suspend_lvs, &lvl->list);
}
critical_section_inc(cmd, "suspending");
dm_list_iterate_items(lvl, &suspend_lvs)
if (!_lv_suspend_lv(lvl->lv, laopts, lockfs, 1)) {
critical_section_dec(cmd, "failed suspend");
goto_out; /* FIXME: resume on recovery path? */
}
} else /* Standard suspend */
} else { /* Standard suspend */
critical_section_inc(cmd, "suspending");
if (!_lv_suspend_lv(lv, laopts, lockfs, flush_required)) {
critical_section_dec(cmd, "failed suspend");
goto_out;
}
}
r = 1;
out:
@@ -2269,8 +2238,8 @@ int lv_suspend_if_active(struct cmd_context *cmd, const char *lvid_s, unsigned o
const struct logical_volume *lv, const struct logical_volume *lv_pre)
{
struct lv_activate_opts laopts = {
.origin_only = origin_only,
.exclusive = exclusive
.exclusive = exclusive,
.origin_only = origin_only
};
return _lv_suspend(cmd, lvid_s, &laopts, 0, lv, lv_pre);
@@ -2322,6 +2291,9 @@ static int _lv_resume(struct cmd_context *cmd, const char *lvid_s,
lv_is_thin_volume(lv) ? " thin only" : " without snapshots") : "",
laopts->revert ? " (reverting)" : "");
if (laopts->revert)
goto needs_resume;
if (!lv_info(cmd, lv, laopts->origin_only, &info, 0, 0))
goto_out;
@@ -2381,8 +2353,8 @@ int lv_resume_if_active(struct cmd_context *cmd, const char *lvid_s,
unsigned revert, const struct logical_volume *lv)
{
struct lv_activate_opts laopts = {
.origin_only = origin_only,
.exclusive = exclusive,
.origin_only = origin_only,
.revert = revert
};
@@ -2419,6 +2391,7 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s, const struct logi
static const struct lv_activate_opts laopts = { .skip_in_use = 1 };
struct dm_list *snh;
int r = 0;
unsigned tmp_state;
if (!activation())
return 1;
@@ -2431,44 +2404,47 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s, const struct logi
log_debug_activation("Deactivating %s.", display_lvname(lv));
if (!lv_info(cmd, lv, 0, &info, 0, 0))
goto_out;
if (!info.exists) {
r = 1;
/* Check attached snapshot segments are also inactive */
dm_list_iterate(snh, &lv->snapshot_segs) {
if (!lv_info(cmd, dm_list_struct_base(snh, struct lv_segment, origin_list)->cow,
0, &info, 0, 0))
goto_out;
if (info.exists) {
r = 0; /* Snapshot left in table? */
break;
}
}
if (lv_is_vdo_pool(lv)) {
/* If someone has remove 'linear' mapping over VDO device
* we may still be able to deactivate the rest of the tree
* i.e. in test-suite we simulate this via 'dmsetup remove' */
if (!lv_info(cmd, lv, 1, &info, 1, 0))
goto_out;
if (info.exists && !info.open_count)
r = 0; /* Unused VDO device left in table? */
}
if (r)
goto out;
}
if (lv_is_visible(lv) || lv_is_virtual_origin(lv) ||
lv_is_merging_thin_snapshot(lv)) {
if (!lv_check_not_in_use(lv, 1))
goto_out;
switch (lv_check_not_in_use(lv, 1)) {
case 0: goto_out;
case 2: goto no_exists;
}
if (lv_is_origin(lv) && _lv_has_open_snapshots(lv))
goto_out;
} else {
if (!lv_info(cmd, lv, 0, &info, 0, 0))
goto_out;
if (!info.exists) {
no_exists:
r = 1;
/* Check attached snapshot segments are also inactive */
dm_list_iterate(snh, &lv->snapshot_segs) {
if (!lv_info(cmd, dm_list_struct_base(snh, struct lv_segment, origin_list)->cow,
0, &info, 0, 0))
goto_out;
if (info.exists) {
r = 0; /* Snapshot left in table? */
break;
}
}
if (lv_is_vdo_pool(lv)) {
/* If someone has remove 'linear' mapping over VDO device
* we may still be able to deactivate the rest of the tree
* i.e. in test-suite we simulate this via 'dmsetup remove' */
if (!lv_info(cmd, lv, 1, &info, 1, 0))
goto_out;
if (info.exists && !info.open_count)
r = 0; /* Unused VDO device left in table? */
}
if (r)
goto out;
}
}
if (!monitor_dev_for_events(cmd, lv, &laopts, 0))
@@ -2488,12 +2464,17 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s, const struct logi
}
critical_section_dec(cmd, "deactivated");
tmp_state = cmd->disable_dm_devs;
cmd->disable_dm_devs = 1;
if (!lv_info(cmd, lv, 0, &info, 0, 0) || info.exists) {
/* Turn into log_error, but we do not log error */
log_debug_activation("Deactivated volume is still %s present.",
display_lvname(lv));
r = 0;
}
cmd->disable_dm_devs = tmp_state;
out:
return r;
@@ -2535,6 +2516,13 @@ static int _lv_activate(struct cmd_context *cmd, const char *lvid_s,
goto out;
}
if ((cmd->partial_activation || cmd->degraded_activation) &&
lv_is_partial(lv) && lv_is_raid(lv) && lv_raid_has_integrity((struct logical_volume *)lv)) {
cmd->partial_activation = 0;
cmd->degraded_activation = 0;
log_print("No degraded or partial activation for raid with integrity.");
}
if ((!lv->vg->cmd->partial_activation) && lv_is_partial(lv)) {
if (!lv_is_raid_type(lv) || !partial_raid_lv_supports_degraded_activation(lv)) {
log_error("Refusing activation of partial LV %s. "
@@ -2551,6 +2539,14 @@ static int _lv_activate(struct cmd_context *cmd, const char *lvid_s,
}
}
if ((cmd->partial_activation || cmd->degraded_activation) && lv_is_writecache(lv)) {
struct logical_volume *lv_fast = first_seg(lv)->writecache;
if (lv_is_partial(lv) || (lv_fast && lv_is_partial(lv_fast))) {
log_error("Cannot use partial or degraded activation with writecache.");
goto out;
}
}
if (lv_has_unknown_segments(lv)) {
log_error("Refusing activation of LV %s containing "
"an unrecognised segment.", display_lvname(lv));
@@ -2767,7 +2763,10 @@ static int _component_cb(struct logical_volume *lv, void *data)
(lv_is_thin_pool(lv) && pool_is_active(lv)))
return -1;
if (lv_is_active(lv)) {
/* External origin is activated through thinLV and uses -real suffix.
* Note: for old clustered logic we would need to check for all thins */
if ((lv_is_external_origin(lv) && lv_info(lv->vg->cmd, lv, 1, NULL, 0, 0)) ||
lv_is_active(lv)) {
if (!lv_is_component(lv) || lv_is_visible(lv))
return -1; /* skip whole subtree */
@@ -2850,7 +2849,7 @@ static int _deactivate_sub_lv_cb(struct logical_volume *lv, void *data)
*/
int deactivate_lv_with_sub_lv(const struct logical_volume *lv)
{
struct logical_volume *flv;
struct logical_volume *flv = NULL;
if (!deactivate_lv(lv->vg->cmd, lv)) {
log_error("Cannot deactivate logical volume %s.",
@@ -2860,7 +2859,7 @@ int deactivate_lv_with_sub_lv(const struct logical_volume *lv)
if (!for_each_sub_lv((struct logical_volume *)lv, _deactivate_sub_lv_cb, &flv)) {
log_error("Cannot deactivate subvolume %s of logical volume %s.",
display_lvname(flv), display_lvname(lv));
(flv) ? display_lvname(flv) : "", display_lvname(lv));
return 0;
}
@@ -2955,8 +2954,7 @@ int revert_lv(struct cmd_context *cmd, const struct logical_volume *lv)
ret = lv_resume_if_active(cmd, NULL, 0, 0, 1, lv_committed(lv));
critical_section_dec(cmd, "unlocking on resume");
critical_section_dec(cmd, "unlocking on revert");
return ret;
}

View File

@@ -106,6 +106,10 @@ int target_present(struct cmd_context *cmd, const char *target_name,
int use_modprobe);
int target_version(const char *target_name, uint32_t *maj,
uint32_t *min, uint32_t *patchlevel);
int get_device_list(const struct volume_group *vg, struct dm_list **devs,
unsigned *devs_features);
int raid4_is_supported(struct cmd_context *cmd, const struct segment_type *segtype);
int lvm_dm_prefix_check(int major, int minor, const char *prefix);
int list_segment_modules(struct dm_pool *mem, const struct lv_segment *seg,
@@ -188,16 +192,15 @@ int lv_raid_dev_health(const struct logical_volume *lv, char **dev_health);
int lv_raid_mismatch_count(const struct logical_volume *lv, uint64_t *cnt);
int lv_raid_sync_action(const struct logical_volume *lv, char **sync_action);
int lv_raid_message(const struct logical_volume *lv, const char *msg);
int lv_raid_status(const struct logical_volume *lv, struct lv_status_raid **status);
int lv_writecache_message(const struct logical_volume *lv, const char *msg);
int lv_cache_status(const struct logical_volume *cache_lv,
struct lv_status_cache **status);
int lv_thin_pool_percent(const struct logical_volume *lv, int metadata,
dm_percent_t *percent);
int lv_thin_percent(const struct logical_volume *lv, int mapped,
dm_percent_t *percent);
int lv_thin_pool_transaction_id(const struct logical_volume *lv,
uint64_t *transaction_id);
int lv_thin_device_id(const struct logical_volume *lv, uint32_t *device_id);
int lv_thin_status(const struct logical_volume *lv, int flush,
struct lv_status_thin **status);
int lv_thin_pool_status(const struct logical_volume *lv, int flush,
struct lv_status_thin_pool **status);
int lv_vdo_pool_status(const struct logical_volume *lv, int flush,
struct lv_status_vdo **status);
int lv_vdo_pool_percent(const struct logical_volume *lv, dm_percent_t *percent);
@@ -210,6 +213,8 @@ int lvs_in_vg_opened(const struct volume_group *vg);
int lv_is_active(const struct logical_volume *lv);
int lv_passes_readonly_filter(const struct logical_volume *lv);
/* Check is any component LV is active */
const struct logical_volume *lv_component_is_active(const struct logical_volume *lv);
const struct logical_volume *lv_holder_is_active(const struct logical_volume *lv);
@@ -253,7 +258,7 @@ struct dev_usable_check_params {
* Returns 1 if mapped device is not suspended, blocked or
* is using a reserved name.
*/
int device_is_usable(struct device *dev, struct dev_usable_check_params check);
int device_is_usable(struct cmd_context *cmd, struct device *dev, struct dev_usable_check_params check, int *is_lv);
/*
* Declaration moved here from fs.h to keep header fs.h hidden

View File

@@ -26,6 +26,7 @@
#include "lib/activate/activate.h"
#include "lib/misc/lvm-exec.h"
#include "lib/datastruct/str_list.h"
#include "lib/misc/lvm-signal.h"
#include <limits.h>
#include <dirent.h>
@@ -86,7 +87,7 @@ int read_only_lv(const struct logical_volume *lv, const struct lv_activate_opts
return 0; /* Keep RAID SubLvs writable */
if (!layer) {
if (lv_is_thin_pool(lv))
if (lv_is_thin_pool(lv) || lv_is_vdo_pool(lv))
return 1;
}
@@ -106,6 +107,8 @@ static struct dm_task *_setup_task_run(int task, struct dm_info *info,
int with_flush,
int query_inactive)
{
char vsn[80];
unsigned maj, min;
struct dm_task *dmt;
if (!(dmt = dm_task_create(task)))
@@ -137,8 +140,20 @@ static struct dm_task *_setup_task_run(int task, struct dm_info *info,
if (!with_flush && !dm_task_no_flush(dmt))
log_warn("WARNING: Failed to set no_flush.");
if (task == DM_DEVICE_TARGET_MSG)
switch (task) {
case DM_DEVICE_TARGET_MSG:
return dmt; /* TARGET_MSG needs more local tweaking before task_run() */
case DM_DEVICE_LIST:
/* Use 'newuuid' only with DM version that supports it */
if (driver_version(vsn, sizeof(vsn)) &&
(sscanf(vsn, "%u.%u", &maj, &min) == 2) &&
(maj == 4 ? min >= 19 : maj > 4) &&
!dm_task_set_newuuid(dmt, " ")) // new uuid has no meaning here
log_warn("WARNING: Failed to query uuid with LIST.");
break;
default:
break;
}
if (!dm_task_run(dmt))
goto_out;
@@ -156,6 +171,7 @@ out:
static int _get_segment_status_from_target_params(const char *target_name,
const char *params,
const struct dm_info *dminfo,
struct lv_seg_status *seg_status)
{
const struct lv_segment *seg = seg_status->seg;
@@ -188,7 +204,7 @@ static int _get_segment_status_from_target_params(const char *target_name,
/* If kernel's type isn't an exact match is it compatible? */
(!segtype->ops->target_status_compatible ||
!segtype->ops->target_status_compatible(target_name))) {
log_warn(INTERNAL_ERROR "WARNING: Segment type %s found does not match expected type %s for %s.",
log_warn("WARNING: Detected %s segment type does not match expected type %s for %s.",
target_name, segtype->name, display_lvname(seg_status->seg->lv));
return 0;
}
@@ -215,7 +231,7 @@ static int _get_segment_status_from_target_params(const char *target_name,
return_0;
seg_status->type = SEG_STATUS_SNAPSHOT;
} else if (segtype_is_vdo_pool(segtype)) {
if (!parse_vdo_pool_status(seg_status->mem, seg->lv, params, &seg_status->vdo_pool))
if (!parse_vdo_pool_status(seg_status->mem, seg->lv, params, dminfo, &seg_status->vdo_pool))
return_0;
seg_status->type = SEG_STATUS_VDO_POOL;
} else if (segtype_is_writecache(segtype)) {
@@ -261,7 +277,7 @@ static int _info_run(const char *dlid, struct dm_info *dminfo,
int dmtask;
int with_flush; /* TODO: arg for _info_run */
void *target = NULL;
uint64_t target_start, target_length, start, length;
uint64_t target_start, target_length, start, length, length_crop = 0;
char *target_name, *target_params;
const char *devname;
@@ -297,7 +313,7 @@ static int _info_run(const char *dlid, struct dm_info *dminfo,
/* Uses max DM_THIN_MAX_METADATA_SIZE sectors for metadata device */
if (lv_is_thin_pool_metadata(seg_status->seg->lv) &&
(length > DM_THIN_MAX_METADATA_SIZE))
length = DM_THIN_MAX_METADATA_SIZE;
length_crop = DM_THIN_MAX_METADATA_SIZE;
/* Uses virtual size with headers for VDO pool device */
if (lv_is_vdo_pool(seg_status->seg->lv))
@@ -310,14 +326,16 @@ static int _info_run(const char *dlid, struct dm_info *dminfo,
target = dm_get_next_target(dmt, target, &target_start,
&target_length, &target_name, &target_params);
if ((start == target_start) && (length == target_length))
if ((start == target_start) &&
((length == target_length) ||
(length_crop && (length_crop == target_length))))
break; /* Keep target_params when matching segment is found */
target_params = NULL; /* Marking this target_params unusable */
} while (target);
if (!target_name ||
!_get_segment_status_from_target_params(target_name, target_params, seg_status))
!_get_segment_status_from_target_params(target_name, target_params, dminfo, seg_status))
stack;
}
@@ -355,7 +373,8 @@ static int _info_run(const char *dlid, struct dm_info *dminfo,
*
* Returns: 1 if mirror should be ignored, 0 if safe to use
*/
static int _ignore_blocked_mirror_devices(struct device *dev,
static int _ignore_blocked_mirror_devices(struct cmd_context *cmd,
struct device *dev,
uint64_t start, uint64_t length,
char *mirror_status_str)
{
@@ -398,12 +417,12 @@ static int _ignore_blocked_mirror_devices(struct device *dev,
goto_out;
tmp_dev->dev = MKDEV(sm->logs[0].major, sm->logs[0].minor);
if (device_is_usable(tmp_dev, (struct dev_usable_check_params)
if (device_is_usable(cmd, tmp_dev, (struct dev_usable_check_params)
{ .check_empty = 1,
.check_blocked = 1,
.check_suspended = ignore_suspended_devices(),
.check_error_target = 1,
.check_reserved = 0 }))
.check_reserved = 0 }, NULL))
goto out; /* safe to use */
stack;
}
@@ -602,6 +621,60 @@ static int _ignore_frozen_raid(struct device *dev, const char *params)
return r;
}
static int _is_usable_uuid(const struct device *dev, const char *name, const char *uuid, int check_reserved, int check_lv, int *is_lv)
{
char *vgname, *lvname, *layer;
char vg_name[NAME_LEN];
if (!check_reserved && !check_lv)
return 1;
if (!strncmp(uuid, UUID_PREFIX, sizeof(UUID_PREFIX) - 1)) { /* with LVM- prefix */
if (check_reserved) {
/* Check internal lvm devices */
if (strlen(uuid) > (sizeof(UUID_PREFIX) + 2 * ID_LEN)) { /* 68 with suffix */
log_debug_activation("%s: Reserved uuid %s on internal LV device %s not usable.",
dev_name(dev), uuid, name);
return 0;
}
/* Recognize some older reserved LVs just from the LV name (snapshot, pvmove...) */
vgname = vg_name;
if (!dm_strncpy(vg_name, name, sizeof(vg_name)) ||
!dm_split_lvm_name(NULL, NULL, &vgname, &lvname, &layer))
return_0;
/* FIXME: fails to handle dev aliases i.e. /dev/dm-5, replace with UUID suffix */
if (lvname && (is_reserved_lvname(lvname) || *layer)) {
log_debug_activation("%s: Reserved internal LV device %s/%s%s%s not usable.",
dev_name(dev), vgname, lvname, *layer ? "-" : "", layer);
return 0;
}
}
if (check_lv) {
/* Skip LVs */
if (is_lv)
*is_lv = 1;
return 0;
}
}
if (check_reserved &&
(!strncmp(uuid, CRYPT_TEMP, sizeof(CRYPT_TEMP) - 1) ||
!strncmp(uuid, CRYPT_SUBDEV, sizeof(CRYPT_SUBDEV) - 1) ||
!strncmp(uuid, STRATIS, sizeof(STRATIS) - 1))) {
/* Skip private crypto devices */
log_debug_activation("%s: Reserved uuid %s on %s device %s not usable.",
dev_name(dev), uuid,
uuid[0] == 'C' ? "crypto" : "stratis",
name);
return 0;
}
return 1;
}
/*
* device_is_usable
* @dev
@@ -618,16 +691,16 @@ static int _ignore_frozen_raid(struct device *dev, const char *params)
*
* Returns: 1 if usable, 0 otherwise
*/
int device_is_usable(struct device *dev, struct dev_usable_check_params check)
int device_is_usable(struct cmd_context *cmd, struct device *dev, struct dev_usable_check_params check, int *is_lv)
{
struct dm_task *dmt;
struct dm_info info;
const char *name, *uuid;
uint64_t start, length;
char *target_type = NULL;
char *params, *vgname = NULL, *lvname, *layer;
char *params;
void *next = NULL;
int only_error_target = 1;
int only_error_or_zero_target = 1;
int r = 0;
if (!(dmt = _setup_task_run(DM_DEVICE_STATUS, &info, NULL, NULL, NULL,
@@ -650,43 +723,9 @@ int device_is_usable(struct device *dev, struct dev_usable_check_params check)
goto out;
}
/* Check internal lvm devices */
if (check.check_reserved &&
uuid && !strncmp(uuid, UUID_PREFIX, sizeof(UUID_PREFIX) - 1)) {
if (strlen(uuid) > (sizeof(UUID_PREFIX) + 2 * ID_LEN)) { /* 68 */
log_debug_activation("%s: Reserved uuid %s on internal LV device %s not usable.",
dev_name(dev), uuid, name);
goto out;
}
if (!(vgname = strdup(name)) ||
!dm_split_lvm_name(NULL, NULL, &vgname, &lvname, &layer))
goto_out;
/* FIXME: fails to handle dev aliases i.e. /dev/dm-5, replace with UUID suffix */
if (lvname && (is_reserved_lvname(lvname) || *layer)) {
log_debug_activation("%s: Reserved internal LV device %s/%s%s%s not usable.",
dev_name(dev), vgname, lvname, *layer ? "-" : "", layer);
goto out;
}
}
if (check.check_lv && uuid && !strncmp(uuid, "LVM-", 4)) {
/* Skip LVs */
if (uuid &&
!_is_usable_uuid(dev, name, uuid, check.check_reserved, check.check_lv, is_lv))
goto out;
}
if (check.check_reserved && uuid &&
(!strncmp(uuid, CRYPT_TEMP, sizeof(CRYPT_TEMP) - 1) ||
!strncmp(uuid, CRYPT_SUBDEV, sizeof(CRYPT_SUBDEV) - 1) ||
!strncmp(uuid, STRATIS, sizeof(STRATIS) - 1))) {
/* Skip private crypto devices */
log_debug_activation("%s: Reserved uuid %s on %s device %s not usable.",
dev_name(dev), uuid,
uuid[0] == 'C' ? "crypto" : "stratis",
name);
goto out;
}
/* FIXME Also check for mpath no paths */
do {
@@ -701,7 +740,7 @@ int device_is_usable(struct device *dev, struct dev_usable_check_params check)
log_debug_activation("%s: Scanning mirror devices is disabled.", dev_name(dev));
goto out;
}
if (!_ignore_blocked_mirror_devices(dev, start,
if (!_ignore_blocked_mirror_devices(cmd, dev, start,
length, params)) {
log_debug_activation("%s: Mirror device %s not usable.",
dev_name(dev), name);
@@ -756,13 +795,15 @@ int device_is_usable(struct device *dev, struct dev_usable_check_params check)
goto out;
}
if (strcmp(target_type, TARGET_NAME_ERROR))
only_error_target = 0;
if (only_error_or_zero_target &&
strcmp(target_type, TARGET_NAME_ERROR) &&
strcmp(target_type, TARGET_NAME_ZERO))
only_error_or_zero_target = 0;
} while (next);
/* Skip devices consisting entirely of error targets. */
/* Skip devices consisting entirely of error or zero targets. */
/* FIXME Deal with device stacked above error targets? */
if (check.check_error_target && only_error_target) {
if (check.check_error_target && only_error_or_zero_target) {
log_debug_activation("%s: Error device %s not usable.",
dev_name(dev), name);
goto out;
@@ -773,7 +814,6 @@ int device_is_usable(struct device *dev, struct dev_usable_check_params check)
r = 1;
out:
free(vgname);
dm_task_destroy(dmt);
return r;
}
@@ -825,13 +865,12 @@ static int _info(struct cmd_context *cmd,
return 1;
/* Check for original version of dlid before the suffixes got added in 2.02.106 */
if ((suffix_position = rindex(dlid, '-'))) {
if ((suffix_position = strrchr(dlid, '-'))) {
while ((suffix = uuid_suffix_list[i++])) {
if (strcmp(suffix_position + 1, suffix))
continue;
(void) strncpy(old_style_dlid, dlid, sizeof(old_style_dlid));
old_style_dlid[sizeof(old_style_dlid) - 1] = '\0';
(void) dm_strncpy(old_style_dlid, dlid, sizeof(old_style_dlid));
if (!_info_run(old_style_dlid, dminfo, read_ahead, seg_status,
name_check, with_open_count, with_read_ahead,
0, 0))
@@ -897,6 +936,25 @@ int dev_manager_check_prefix_dm_major_minor(uint32_t major, uint32_t minor, cons
return r;
}
int dev_manager_get_device_list(const char *prefix, struct dm_list **devs, unsigned *devs_features)
{
struct dm_task *dmt;
int r = 1;
if (!(dmt = _setup_task_run(DM_DEVICE_LIST, NULL, NULL, NULL, 0, 0, 0, 0, 0, 0)))
return_0;
if (!dm_task_get_device_list(dmt, devs, devs_features)) {
r = 0;
goto_out;
}
out:
dm_task_destroy(dmt);
return r;
}
int dev_manager_info(struct cmd_context *cmd,
const struct logical_volume *lv, const char *layer,
int with_open_count, int with_read_ahead, int with_name_check,
@@ -912,6 +970,16 @@ int dev_manager_info(struct cmd_context *cmd,
if (!(dlid = build_dm_uuid(cmd->mem, lv, layer)))
goto_out;
if (!cmd->disable_dm_devs &&
cmd->cache_dm_devs &&
!dm_device_list_find_by_uuid(cmd->cache_dm_devs, dlid, NULL)) {
log_debug("Cached as inactive %s.", name);
if (dminfo)
memset(dminfo, 0, sizeof(*dminfo));
r = 1;
goto out;
}
if (!(r = _info(cmd, name, dlid,
with_open_count, with_read_ahead, with_name_check,
dminfo, read_ahead, seg_status)))
@@ -1113,7 +1181,8 @@ static int _percent_run(struct dev_manager *dm, const char *name,
const char *dlid,
const char *target_type, int wait,
const struct logical_volume *lv, dm_percent_t *overall_percent,
uint32_t *event_nr, int fail_if_percent_unsupported)
uint32_t *event_nr, int fail_if_percent_unsupported,
int *interrupted)
{
int r = 0;
struct dm_task *dmt;
@@ -1134,9 +1203,12 @@ static int _percent_run(struct dev_manager *dm, const char *name,
if (!(segtype = get_segtype_from_string(dm->cmd, target_type)))
return_0;
if (wait)
sigint_allow();
if (!(dmt = _setup_task_run(wait ? DM_DEVICE_WAITEVENT : DM_DEVICE_STATUS, &info,
name, dlid, event_nr, 0, 0, 0, 0, 0)))
return_0;
goto_bad;
if (!info.exists)
goto_out;
@@ -1204,8 +1276,19 @@ static int _percent_run(struct dev_manager *dm, const char *name,
display_percent(dm->cmd, *overall_percent));
r = 1;
out:
out:
dm_task_destroy(dmt);
bad:
if (wait) {
sigint_restore();
if (sigint_caught()) {
*interrupted = 1;
return_0;
}
}
return r;
}
@@ -1214,20 +1297,24 @@ static int _percent(struct dev_manager *dm, const char *name, const char *dlid,
const struct logical_volume *lv, dm_percent_t *percent,
uint32_t *event_nr, int fail_if_percent_unsupported)
{
int interrupted = 0;
if (dlid && *dlid) {
if (_percent_run(dm, NULL, dlid, target_type, wait, lv, percent,
event_nr, fail_if_percent_unsupported))
event_nr, fail_if_percent_unsupported, &interrupted))
return 1;
if (_original_uuid_format_check_required(dm->cmd) &&
if (!interrupted &&
_original_uuid_format_check_required(dm->cmd) &&
_percent_run(dm, NULL, dlid + sizeof(UUID_PREFIX) - 1,
target_type, wait, lv, percent,
event_nr, fail_if_percent_unsupported))
event_nr, fail_if_percent_unsupported, &interrupted))
return 1;
}
if (name && _percent_run(dm, name, NULL, target_type, wait, lv, percent,
event_nr, fail_if_percent_unsupported))
if (!interrupted && name &&
_percent_run(dm, name, NULL, target_type, wait, lv, percent,
event_nr, fail_if_percent_unsupported, &interrupted))
return 1;
return_0;
@@ -1429,7 +1516,7 @@ int dev_manager_mirror_percent(struct dev_manager *dm,
int dev_manager_raid_status(struct dev_manager *dm,
const struct logical_volume *lv,
struct dm_status_raid **status)
struct lv_status_raid **status, int *exists)
{
int r = 0;
const char *dlid;
@@ -1439,6 +1526,11 @@ int dev_manager_raid_status(struct dev_manager *dm,
char *type = NULL;
char *params = NULL;
const char *layer = lv_layer(lv);
struct dm_status_raid *sr;
*exists = -1;
if (!(*status = dm_pool_zalloc(dm->mem, sizeof(struct lv_status_cache))))
return_0;
if (!(dlid = build_dm_uuid(dm->mem, lv, layer)))
return_0;
@@ -1446,8 +1538,11 @@ int dev_manager_raid_status(struct dev_manager *dm,
if (!(dmt = _setup_task_run(DM_DEVICE_STATUS, &info, NULL, dlid, 0, 0, 0, 0, 0, 0)))
return_0;
if (!info.exists)
goto_out;
if (!(*exists = info.exists))
goto out;
log_debug_activation("Checking raid status for volume %s.",
display_lvname(lv));
dm_get_next_target(dmt, NULL, &start, &length, &type, &params);
@@ -1459,9 +1554,13 @@ int dev_manager_raid_status(struct dev_manager *dm,
/* FIXME Check there's only one target */
if (!dm_get_status_raid(dm->mem, params, status))
if (!dm_get_status_raid(dm->mem, params, &sr))
goto_out;
(*status)->mem = dm->mem; /* User has to destroy this mem pool later */
(*status)->raid = sr;
(*status)->in_sync = dm_make_percent(sr->insync_regions, sr->total_regions);
r = 1;
out:
dm_task_destroy(dmt);
@@ -1550,7 +1649,7 @@ out:
int dev_manager_cache_status(struct dev_manager *dm,
const struct logical_volume *lv,
struct lv_status_cache **status)
struct lv_status_cache **status, int *exists)
{
int r = 0;
const char *dlid;
@@ -1561,17 +1660,18 @@ int dev_manager_cache_status(struct dev_manager *dm,
char *params = NULL;
struct dm_status_cache *c;
*exists = -1;
if (!(dlid = build_dm_uuid(dm->mem, lv, lv_layer(lv))))
return_0;
if (!(*status = dm_pool_zalloc(dm->mem, sizeof(struct lv_status_cache))))
return_0;
if (!(dmt = _setup_task_run(DM_DEVICE_STATUS, &info, NULL, dlid, 0, 0, 0, 0, 0, 0)))
return_0;
if (!info.exists)
goto_out;
if (!(*exists = info.exists))
goto out;
log_debug_activation("Checking status for cache volume %s.",
display_lvname(lv));
dm_get_next_target(dmt, NULL, &start, &length, &type, &params);
@@ -1589,8 +1689,11 @@ int dev_manager_cache_status(struct dev_manager *dm,
if (!dm_get_status_cache(dm->mem, params, &c))
goto_out;
(*status)->cache = c;
if (!(*status = dm_pool_zalloc(dm->mem, sizeof(struct lv_status_cache))))
goto_out;
(*status)->mem = dm->mem; /* User has to destroy this mem pool later */
(*status)->cache = c;
if (c->fail || c->error) {
(*status)->data_usage =
(*status)->metadata_usage =
@@ -1612,10 +1715,10 @@ out:
}
int dev_manager_thin_pool_status(struct dev_manager *dm,
const struct logical_volume *lv,
struct dm_status_thin_pool **status,
int flush)
const struct logical_volume *lv, int flush,
struct lv_status_thin_pool **status, int *exists)
{
struct dm_status_thin_pool *dm_status;
const char *dlid;
struct dm_task *dmt;
struct dm_info info;
@@ -1624,6 +1727,10 @@ int dev_manager_thin_pool_status(struct dev_manager *dm,
char *params = NULL;
int r = 0;
*exists = -1;
if (!(*status = dm_pool_zalloc(dm->mem, sizeof(struct lv_status_thin_pool))))
return_0;
/* Build dlid for the thin pool layer */
if (!(dlid = build_dm_uuid(dm->mem, lv, lv_layer(lv))))
return_0;
@@ -1631,16 +1738,36 @@ int dev_manager_thin_pool_status(struct dev_manager *dm,
if (!(dmt = _setup_task_run(DM_DEVICE_STATUS, &info, NULL, dlid, 0, 0, 0, 0, flush, 0)))
return_0;
if (!info.exists)
goto_out;
if (!(*exists = info.exists))
goto out;
log_debug_activation("Checking thin pool status for LV %s.",
display_lvname(lv));
dm_get_next_target(dmt, NULL, &start, &length, &type, &params);
/* FIXME Check for thin and check there's exactly one target */
if (!type || strcmp(type, TARGET_NAME_THIN_POOL)) {
log_error("Expected %s segment type but got %s instead.",
TARGET_NAME_THIN_POOL, type ? type : "NULL");
goto out;
}
if (!dm_get_status_thin_pool(dm->mem, params, status))
if (!dm_get_status_thin_pool(dm->mem, params, &dm_status))
goto_out;
(*status)->mem = dm->mem;
(*status)->thin_pool = dm_status;
if (dm_status->fail || dm_status->error) {
(*status)->data_usage =
(*status)->metadata_usage = DM_PERCENT_INVALID;
} else {
(*status)->data_usage = dm_make_percent(dm_status->used_data_blocks,
dm_status->total_data_blocks);
(*status)->metadata_usage = dm_make_percent(dm_status->used_metadata_blocks,
dm_status->total_metadata_blocks);
}
r = 1;
out:
dm_task_destroy(dmt);
@@ -1648,52 +1775,72 @@ out:
return r;
}
int dev_manager_thin_pool_percent(struct dev_manager *dm,
const struct logical_volume *lv,
int metadata, dm_percent_t *percent)
int dev_manager_thin_status(struct dev_manager *dm,
const struct logical_volume *lv, int flush,
struct lv_status_thin **status, int *exists)
{
char *name;
struct dm_status_thin *dm_status;
const char *dlid;
const char *layer = lv_layer(lv);
struct dm_task *dmt;
struct dm_info info;
uint64_t start, length;
char *type = NULL;
char *params = NULL;
uint64_t csize;
int r = 0;
/* Build a name for the top layer */
if (!(name = dm_build_dm_name(dm->mem, lv->vg->name, lv->name, layer)))
*exists = -1;
if (!(*status = dm_pool_zalloc(dm->mem, sizeof(struct lv_status_thin))))
return_0;
if (!(dlid = build_dm_uuid(dm->mem, lv, layer)))
if (!(dlid = build_dm_uuid(dm->mem, lv, lv_layer(lv))))
return_0;
log_debug_activation("Getting device status percentage for %s.", name);
if (!(_percent(dm, name, dlid, TARGET_NAME_THIN_POOL, 0,
(metadata) ? lv : NULL, percent, NULL, 1)))
if (!(dmt = _setup_task_run(DM_DEVICE_STATUS, &info, NULL, dlid, 0, 0, 0, 0, flush, 0)))
return_0;
return 1;
}
if (!(*exists = info.exists))
goto out;
int dev_manager_thin_percent(struct dev_manager *dm,
const struct logical_volume *lv,
int mapped, dm_percent_t *percent)
{
char *name;
const char *dlid;
const char *layer = lv_layer(lv);
log_debug_activation("Checking thin status for LV %s.",
display_lvname(lv));
/* Build a name for the top layer */
if (!(name = dm_build_dm_name(dm->mem, lv->vg->name, lv->name, layer)))
return_0;
dm_get_next_target(dmt, NULL, &start, &length, &type, &params);
if (!(dlid = build_dm_uuid(dm->mem, lv, layer)))
return_0;
if (!type || strcmp(type, TARGET_NAME_THIN)) {
log_error("Expected %s segment type but got %s instead.",
TARGET_NAME_THIN, type ? type : "NULL");
goto out;
}
log_debug_activation("Getting device status percentage for %s", name);
if (!dm_get_status_thin(dm->mem, params, &dm_status))
goto_out;
if (!(_percent(dm, name, dlid, TARGET_NAME_THIN, 0,
(mapped) ? NULL : lv, percent, NULL, 1)))
return_0;
(*status)->mem = dm->mem;
(*status)->thin = dm_status;
return 1;
if (dm_status->fail)
(*status)->usage = DM_PERCENT_INVALID;
else {
/* Pool allocates whole chunk so round-up to nearest one */
csize = first_seg(first_seg(lv)->pool_lv)->chunk_size;
csize = ((lv->size + csize - 1) / csize) * csize;
if (dm_status->mapped_sectors > csize) {
log_warn("WARNING: LV %s maps %s while the size is only %s.",
display_lvname(lv),
display_size(dm->cmd, dm_status->mapped_sectors),
display_size(dm->cmd, csize));
/* Don't show nonsense numbers like i.e. 1000% full */
dm_status->mapped_sectors = csize;
}
(*status)->usage = dm_make_percent(dm_status->mapped_sectors, csize);
}
r = 1;
out:
dm_task_destroy(dmt);
return r;
}
/*
@@ -1701,7 +1848,7 @@ int dev_manager_thin_percent(struct dev_manager *dm,
*/
int dev_manager_thin_device_id(struct dev_manager *dm,
const struct logical_volume *lv,
uint32_t *device_id)
uint32_t *device_id, int *exists)
{
const char *dlid;
struct dm_task *dmt;
@@ -1711,6 +1858,7 @@ int dev_manager_thin_device_id(struct dev_manager *dm,
const char *layer = lv_layer(lv);
int r = 0;
*exists = -1;
if (lv_is_merging_origin(lv) && !lv_info(lv->vg->cmd, lv, 1, NULL, 0, 0))
/* If the merge has already happened, that table
* can already be using correct LV without -real layer */
@@ -1723,8 +1871,11 @@ int dev_manager_thin_device_id(struct dev_manager *dm,
if (!(dmt = _setup_task_run(DM_DEVICE_TABLE, &info, NULL, dlid, 0, 0, 0, 0, 1, 0)))
return_0;
if (!info.exists)
goto_out;
if (!(*exists = info.exists))
goto out;
log_debug_activation("Checking device id for LV %s.",
display_lvname(lv));
if (dm_get_next_target(dmt, NULL, &start, &length,
&target_type, &params)) {
@@ -1753,11 +1904,9 @@ out:
}
int dev_manager_vdo_pool_status(struct dev_manager *dm,
const struct logical_volume *lv,
struct lv_status_vdo **vdo_status,
int flush)
const struct logical_volume *lv, int flush,
struct lv_status_vdo **status, int *exists)
{
struct lv_status_vdo *status;
const char *dlid;
struct dm_info info;
uint64_t start, length;
@@ -1766,12 +1915,9 @@ int dev_manager_vdo_pool_status(struct dev_manager *dm,
char *params = NULL;
int r = 0;
*vdo_status = NULL;
if (!(status = dm_pool_zalloc(dm->mem, sizeof(struct lv_status_vdo)))) {
log_error("Cannot allocate VDO status structure.");
return 0;
}
*exists = -1;
if (!(*status = dm_pool_zalloc(dm->mem, sizeof(struct lv_status_vdo))))
return_0;
if (!(dlid = build_dm_uuid(dm->mem, lv, lv_layer(lv))))
return_0;
@@ -1779,8 +1925,11 @@ int dev_manager_vdo_pool_status(struct dev_manager *dm,
if (!(dmt = _setup_task_run(DM_DEVICE_STATUS, &info, NULL, dlid, 0, 0, 0, 0, flush, 0)))
return_0;
if (!info.exists)
goto_out;
if (!(*exists = info.exists))
goto out;
log_debug_activation("Checking VDO pool status for LV %s.",
display_lvname(lv));
if (dm_get_next_target(dmt, NULL, &start, &length, &type, &params)) {
log_error("More then one table line found for %s.",
@@ -1794,11 +1943,10 @@ int dev_manager_vdo_pool_status(struct dev_manager *dm,
goto out;
}
if (!parse_vdo_pool_status(dm->mem, lv, params, status))
if (!parse_vdo_pool_status(dm->mem, lv, params, &info, *status))
goto_out;
status->mem = dm->mem;
*vdo_status = status;
(*status)->mem = dm->mem;
r = 1;
out:
@@ -2027,7 +2175,7 @@ static int _check_holder(struct dev_manager *dm, struct dm_tree *dtree,
if (!strncmp(default_uuid_prefix, uuid, default_uuid_prefix_len))
uuid += default_uuid_prefix_len;
if (!strncmp(uuid, (char*)&lv->vg->id, sizeof(lv->vg->id)) &&
if (!memcmp(uuid, &lv->vg->id, ID_LEN) &&
!dm_tree_find_node_by_uuid(dtree, uuid)) {
/* trims any UUID suffix (i.e. -cow) */
(void) dm_strncpy((char*)&id, uuid, 2 * sizeof(struct id) + 1);
@@ -2106,6 +2254,7 @@ static int _add_dev_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
{
char *dlid, *name;
struct dm_info info, info2;
const struct dm_active_device *dev;
if (!(name = dm_build_dm_name(dm->mem, lv->vg->name, lv->name, layer)))
return_0;
@@ -2113,9 +2262,21 @@ static int _add_dev_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
if (!(dlid = build_dm_uuid(dm->track_pending_delete ? dm->cmd->pending_delete_mem : dm->mem, lv, layer)))
return_0;
if (!_info(dm->cmd, name, dlid, 1, 0, 0, &info, NULL, NULL))
if (!dm->cmd->disable_dm_devs &&
dm->cmd->cache_dm_devs) {
if (!dm_device_list_find_by_uuid(dm->cmd->cache_dm_devs, dlid, &dev)) {
log_debug("Cached as not present %s.", name);
return 1;
}
info = (struct dm_info) {
.exists = 1,
.major = dev->major,
.minor = dev->minor,
};
log_debug("Cached as present %s %s (%d:%d).",
name, dlid, info.major, info.minor);
} else if (!_info(dm->cmd, name, dlid, 0, 0, 0, &info, NULL, NULL))
return_0;
/*
* For top level volumes verify that existing device match
* requested major/minor and that major/minor pair is available for use
@@ -2234,22 +2395,35 @@ static int _pool_callback(struct dm_tree_node *node,
const struct pool_cb_data *data = cb_data;
const struct logical_volume *pool_lv = data->pool_lv;
const struct logical_volume *mlv = first_seg(pool_lv)->metadata_lv;
struct cmd_context *cmd = pool_lv->vg->cmd;
long buf[64 / sizeof(long)]; /* buffer for short disk header (64B) */
int args = 0;
char *mpath;
const char *argv[19] = { /* Max supported 15 args */
find_config_tree_str_allow_empty(pool_lv->vg->cmd, data->exec, NULL)
find_config_tree_str_allow_empty(cmd, data->exec, NULL)
};
if (!*argv[0]) /* *_check tool is unconfigured/disabled with "" setting */
return 1;
if (!(mpath = lv_dmpath_dup(data->dm->mem, mlv))) {
log_error("Failed to build device path for checking pool metadata %s.",
display_lvname(mlv));
return 0;
if (lv_is_cache_vol(pool_lv)) {
if (!(mpath = lv_dmpath_suffix_dup(data->dm->mem, pool_lv, "-cmeta"))) {
log_error("Failed to build device path for checking cachevol metadata %s.",
display_lvname(pool_lv));
return 0;
}
} else {
if (!(mpath = lv_dmpath_dup(data->dm->mem, mlv))) {
log_error("Failed to build device path for checking pool metadata %s.",
display_lvname(mlv));
return 0;
}
}
dm_device_list_destroy(&cmd->cache_dm_devs); /* Cache no longer valid */
log_debug("Running check command on %s", mpath);
if (data->skip_zero) {
if ((fd = open(mpath, O_RDONLY)) < 0) {
log_sys_error("open", mpath);
@@ -2276,7 +2450,7 @@ static int _pool_callback(struct dm_tree_node *node,
}
}
if (!(cn = find_config_tree_array(mlv->vg->cmd, data->opts, NULL))) {
if (!(cn = find_config_tree_array(cmd, data->opts, NULL))) {
log_error(INTERNAL_ERROR "Unable to find configuration for pool check options.");
return 0;
}
@@ -2298,7 +2472,7 @@ static int _pool_callback(struct dm_tree_node *node,
argv[++args] = mpath;
if (!(ret = exec_cmd(pool_lv->vg->cmd, (const char * const *)argv,
if (!(ret = exec_cmd(cmd, (const char * const *)argv,
&status, 0))) {
if (status == ENOENT) {
log_warn("WARNING: Check is skipped, please install recommended missing binary %s!",
@@ -2307,7 +2481,7 @@ static int _pool_callback(struct dm_tree_node *node,
}
if ((data->version.maj || data->version.min || data->version.patch) &&
!_check_tool_version(pool_lv->vg->cmd, argv[0],
!_check_tool_version(cmd, argv[0],
data->version.maj, data->version.min, data->version.patch)) {
log_warn("WARNING: Check is skipped, please upgrade installed version of %s!",
argv[0]);
@@ -2351,10 +2525,6 @@ static int _pool_register_callback(struct dev_manager *dm,
return 1;
#endif
/* Skip for single-device cache pool */
if (lv_is_cache(lv) && lv_is_cache_vol(first_seg(lv)->pool_lv))
return 1;
if (!(data = dm_pool_zalloc(dm->mem, sizeof(*data)))) {
log_error("Failed to allocated path for callback.");
return 0;
@@ -2777,6 +2947,10 @@ int add_areas_line(struct dev_manager *dm, struct lv_segment *seg,
/* FIXME Avoid repeating identical stat in dm_tree_node_add_target_area */
for (s = start_area; s < areas; s++) {
/* FIXME: dev_name() does not return NULL! It needs to check if dm_list_empty(&dev->aliases)
but this knot of logic is too complex to pull apart without careful deconstruction. */
if ((seg_type(seg, s) == AREA_PV &&
(!seg_pvseg(seg, s) || !seg_pv(seg, s) || !seg_dev(seg, s) ||
!(name = dev_name(seg_dev(seg, s))) || !*name ||
@@ -2795,7 +2969,10 @@ int add_areas_line(struct dev_manager *dm, struct lv_segment *seg,
return_0;
num_error_areas++;
} else if (seg_type(seg, s) == AREA_PV) {
if (!dm_tree_node_add_target_area(node, dev_name(seg_dev(seg, s)), NULL,
struct device *dev = seg_dev(seg, s);
name = dm_list_empty(&dev->aliases) ? NULL : dev_name(dev);
if (!dm_tree_node_add_target_area(node, name, NULL,
(seg_pv(seg, s)->pe_start + (extent_size * seg_pe(seg, s)))))
return_0;
num_existing_areas++;
@@ -3332,6 +3509,10 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
if (!layer && lv_is_new_thin_pool(lv))
layer = lv_layer(lv);
/* Adds -real to the dm uuid of wcorig LV. */
if (!layer && lv_is_writecache_origin(lv))
layer = lv_layer(lv); /* "real" */
if (!(dlid = build_dm_uuid(dm->mem, lv, layer)))
return_0;
@@ -3443,6 +3624,12 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
!_pool_register_callback(dm, dnode, lv))
return_0;
if (lv_is_cache(lv) && lv_is_cache_vol(first_seg(lv)->pool_lv) &&
/* Register callback only for layer activation or non-layered cache LV */
(layer || !lv_layer(lv)) &&
!_pool_register_callback(dm, dnode, lv))
return_0;
/*
* Update tables for ANY PVMOVE holders for active LV where the name starts with 'pvmove',
* but it's not anymore PVMOVE LV and also it's not a PVMOVE _mimage LV.
@@ -3629,6 +3816,7 @@ static int _tree_action(struct dev_manager *dm, const struct logical_volume *lv,
struct dm_tree_node *root;
char *dlid;
int r = 0;
unsigned tmp_state;
if (action < DM_ARRAY_SIZE(_action_names))
log_debug_activation("Creating %s%s tree for %s.",
@@ -3648,9 +3836,17 @@ static int _tree_action(struct dev_manager *dm, const struct logical_volume *lv,
dm->suspend = (action == SUSPEND_WITH_LOCKFS) || (action == SUSPEND);
dm->track_external_lv_deps = 1;
/* ATM do not use caching for anything else then striped target.
* And also skip for CLEAN action */
tmp_state = dm->cmd->disable_dm_devs;
if (!seg_is_striped_target(first_seg(lv)) || (action == CLEAN))
dm->cmd->disable_dm_devs = 1;
if (!(dtree = _create_partial_dtree(dm, lv, laopts->origin_only)))
return_0;
dm->cmd->disable_dm_devs = tmp_state;
if (!(root = dm_tree_find_node(dtree, 0, 0))) {
log_error("Lost dependency tree root node.");
goto out_no_root;

View File

@@ -59,7 +59,7 @@ int dev_manager_mirror_percent(struct dev_manager *dm,
dm_percent_t *percent, uint32_t *event_nr);
int dev_manager_raid_status(struct dev_manager *dm,
const struct logical_volume *lv,
struct dm_status_raid **status);
struct lv_status_raid **status, int *exists);
int dev_manager_raid_message(struct dev_manager *dm,
const struct logical_volume *lv,
const char *msg);
@@ -68,24 +68,19 @@ int dev_manager_writecache_message(struct dev_manager *dm,
const char *msg);
int dev_manager_cache_status(struct dev_manager *dm,
const struct logical_volume *lv,
struct lv_status_cache **status);
int dev_manager_thin_pool_status(struct dev_manager *dm,
const struct logical_volume *lv,
struct dm_status_thin_pool **status,
int flush);
int dev_manager_thin_pool_percent(struct dev_manager *dm,
const struct logical_volume *lv,
int metadata, dm_percent_t *percent);
int dev_manager_thin_percent(struct dev_manager *dm,
const struct logical_volume *lv,
int mapped, dm_percent_t *percent);
struct lv_status_cache **status, int *exists);
int dev_manager_thin_status(struct dev_manager *dm,
const struct logical_volume *lv, int flush,
struct lv_status_thin **status, int *exists);
int dev_manager_thin_device_id(struct dev_manager *dm,
const struct logical_volume *lv,
uint32_t *device_id);
uint32_t *device_id, int *exist);
int dev_manager_thin_pool_status(struct dev_manager *dm,
const struct logical_volume *lv, int flush,
struct lv_status_thin_pool **status, int *exists);
int dev_manager_vdo_pool_status(struct dev_manager *dm,
const struct logical_volume *lv,
struct lv_status_vdo **vdo_status,
int flush);
const struct logical_volume *lv, int flush,
struct lv_status_vdo **status, int *exists);
int dev_manager_suspend(struct dev_manager *dm, const struct logical_volume *lv,
struct lv_activate_opts *laopts, int lockfs, int flush_required);
int dev_manager_activate(struct dev_manager *dm, const struct logical_volume *lv,
@@ -108,5 +103,7 @@ int dev_manager_device_uses_vg(struct device *dev,
int dev_manager_remove_dm_major_minor(uint32_t major, uint32_t minor);
int dev_manager_check_prefix_dm_major_minor(uint32_t major, uint32_t minor, const char *prefix);
int dev_manager_get_device_list(const char *prefix, struct dm_list **devs,
unsigned *devs_features);
#endif

View File

@@ -76,7 +76,7 @@ static int _rm_dir(const char *dev_dir, const char *vg_name)
return 0;
}
if (dir_exists(vg_path) && is_empty_dir(vg_path)) {
if (dir_exists(vg_path) && dm_is_empty_dir(vg_path)) {
log_very_verbose("Removing directory %s", vg_path);
rmdir(vg_path);
}
@@ -93,7 +93,7 @@ static void _rm_blks(const char *dir)
DIR *d;
if (!(d = opendir(dir))) {
log_sys_error("opendir", dir);
log_sys_debug("opendir", dir);
return;
}
@@ -104,7 +104,7 @@ static void _rm_blks(const char *dir)
continue;
if (dm_snprintf(path, sizeof(path), "%s/%s", dir, name) == -1) {
log_error("Couldn't create path for %s", name);
log_debug("Couldn't create path for %s.", name);
continue;
}
@@ -113,12 +113,12 @@ static void _rm_blks(const char *dir)
continue;
log_very_verbose("Removing %s", path);
if (unlink(path) < 0)
log_sys_error("unlink", path);
log_sys_debug("unlink", path);
}
}
if (closedir(d))
log_sys_error("closedir", dir);
log_sys_debug("closedir", dir);
}
static int _mk_link(const char *dev_dir, const char *vg_name,
@@ -169,7 +169,7 @@ static int _mk_link(const char *dev_dir, const char *vg_name,
log_very_verbose("Removing %s", lvm1_group_path);
if (unlink(lvm1_group_path) < 0)
log_sys_error("unlink", lvm1_group_path);
log_sys_debug("unlink", lvm1_group_path);
}
}

1483
lib/cache/lvmcache.c vendored

File diff suppressed because it is too large Load Diff

34
lib/cache/lvmcache.h vendored
View File

@@ -47,7 +47,7 @@ struct lvmcache_vginfo;
*/
struct lvmcache_vgsummary {
const char *vgname;
struct id vgid;
char vgid[ID_LEN + 1];
uint64_t vgstatus;
char *creation_host;
const char *system_id;
@@ -69,21 +69,21 @@ void lvmcache_destroy(struct cmd_context *cmd, int retain_orphans, int reset);
int lvmcache_label_scan(struct cmd_context *cmd);
int lvmcache_label_rescan_vg(struct cmd_context *cmd, const char *vgname, const char *vgid);
int lvmcache_label_rescan_vg_rw(struct cmd_context *cmd, const char *vgname, const char *vgid);
int lvmcache_label_reopen_vg_rw(struct cmd_context *cmd, const char *vgname, const char *vgid);
/* Add/delete a device */
struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
struct lvmcache_info *lvmcache_add(struct cmd_context *cmd, struct labeller *labeller, const char *pvid,
struct device *dev, uint64_t label_sector,
const char *vgname, const char *vgid,
uint32_t vgstatus, int *is_duplicate);
int lvmcache_add_orphan_vginfo(const char *vgname, struct format_type *fmt);
int lvmcache_add_orphan_vginfo(struct cmd_context *cmd, const char *vgname, struct format_type *fmt);
void lvmcache_del(struct lvmcache_info *info);
void lvmcache_del_dev(struct device *dev);
/* Update things */
int lvmcache_update_vgname_and_id(struct lvmcache_info *info,
int lvmcache_update_vgname_and_id(struct cmd_context *cmd, struct lvmcache_info *info,
struct lvmcache_vgsummary *vgsummary);
int lvmcache_update_vg_from_read(struct volume_group *vg, unsigned precommitted);
int lvmcache_update_vg_from_write(struct volume_group *vg);
void lvmcache_lock_vgname(const char *vgname, int read_only);
void lvmcache_unlock_vgname(const char *vgname);
@@ -95,9 +95,10 @@ struct lvmcache_vginfo *lvmcache_vginfo_from_vgname(const char *vgname,
const char *vgid);
struct lvmcache_vginfo *lvmcache_vginfo_from_vgid(const char *vgid);
struct lvmcache_info *lvmcache_info_from_pvid(const char *pvid, struct device *dev, int valid_only);
struct lvmcache_info *lvmcache_info_from_pv_id(const struct id *pv_id, struct device *dev, int valid_only);
const char *lvmcache_vgname_from_vgid(struct dm_pool *mem, const char *vgid);
const char *lvmcache_vgid_from_vgname(struct cmd_context *cmd, const char *vgname);
struct device *lvmcache_device_from_pvid(struct cmd_context *cmd, const struct id *pvid, uint64_t *label_sector);
struct device *lvmcache_device_from_pv_id(struct cmd_context *cmd, const struct id *pv_id, uint64_t *label_sector);
const char *lvmcache_vgname_from_info(struct lvmcache_info *info);
const struct format_type *lvmcache_fmt_from_info(struct lvmcache_info *info);
@@ -161,11 +162,6 @@ struct device *lvmcache_device(struct lvmcache_info *info);
unsigned lvmcache_mda_count(struct lvmcache_info *info);
uint64_t lvmcache_smallest_mda_size(struct lvmcache_info *info);
struct metadata_area *lvmcache_get_mda(struct cmd_context *cmd,
const char *vgname,
struct device *dev,
int use_mda_num);
bool lvmcache_has_duplicate_devs(void);
void lvmcache_del_dev_from_duplicates(struct device *dev);
bool lvmcache_dev_is_unused_duplicate(struct device *dev);
@@ -174,6 +170,7 @@ int lvmcache_get_unused_duplicates(struct cmd_context *cmd, struct dm_list *head
int vg_has_duplicate_pvs(struct volume_group *vg);
int lvmcache_found_duplicate_vgnames(void);
bool lvmcache_has_duplicate_local_vgname(const char *vgid, const char *vgname);
int lvmcache_contains_lock_type_sanlock(struct cmd_context *cmd);
@@ -184,7 +181,7 @@ int lvmcache_vg_is_foreign(struct cmd_context *cmd, const char *vgname, const ch
bool lvmcache_scan_mismatch(struct cmd_context *cmd, const char *vgname, const char *vgid);
int lvmcache_vginfo_has_pvid(struct lvmcache_vginfo *vginfo, char *pvid);
int lvmcache_vginfo_has_pvid(struct lvmcache_vginfo *vginfo, const char *pvid_arg);
uint64_t lvmcache_max_metadata_size(void);
void lvmcache_save_metadata_size(uint64_t val);
@@ -212,6 +209,8 @@ void lvmcache_del_outdated_devs(struct cmd_context *cmd,
void lvmcache_save_bad_mda(struct lvmcache_info *info, struct metadata_area *mda);
void lvmcache_del_save_bad_mda(struct lvmcache_info *info, int mda_num, int bad_mda_flag);
void lvmcache_get_bad_mdas(struct cmd_context *cmd,
const char *vgname, const char *vgid,
struct dm_list *bad_mda_list);
@@ -220,4 +219,15 @@ void lvmcache_get_mdas(struct cmd_context *cmd,
const char *vgname, const char *vgid,
struct dm_list *mda_list);
const char *dev_filtered_reason(struct device *dev);
const char *devname_error_reason(const char *devname);
struct metadata_area *lvmcache_get_dev_mda(struct device *dev, int mda_num);
void lvmcache_extra_md_component_checks(struct cmd_context *cmd);
unsigned int lvmcache_vg_info_count(void);
int lvmcache_pvsummary_count(const char *vgname);
#endif

View File

@@ -335,7 +335,7 @@ static int _lookup_kallsyms(const char *symbol)
static int _target_present(struct cmd_context *cmd,
const struct lv_segment *seg __attribute__((unused)),
unsigned *attributes __attribute__((unused)))
unsigned *attributes)
{
/* List of features with their kernel target version */
static const struct feature {
@@ -618,6 +618,9 @@ static int _cache_add_target_line(struct dev_manager *dm,
{
struct lv_segment *cache_pool_seg;
struct lv_segment *setting_seg;
struct dm_config_node *policy_settings;
struct dm_config_node *cn;
unsigned i, j;
union lvid metadata_lvid;
union lvid data_lvid;
char *metadata_uuid, *data_uuid, *origin_uuid;
@@ -718,6 +721,61 @@ static int _cache_add_target_line(struct dev_manager *dm,
return_0;
}
policy_settings = seg->cleaner_policy ? NULL : setting_seg->policy_settings;
if (policy_settings && cache_pool_seg->policy_name) {
static const struct act {
const char *name;
const char *settings[20];
} _accepted[] = {
{
"MQ", {
"migration_threshold", "sequential_threshold", "random_threshold",
"read_promote_adjustment", "write_promote_adjustment",
"discard_promote_adjustment", NULL
},
}, {
"SMQ", {
"migration_threshold", NULL
}
}
};
/* Check if cache settings are acceptable to knownm policies */
for (i = 0; i < DM_ARRAY_SIZE(_accepted); i++) {
if (strcasecmp(cache_pool_seg->policy_name, _accepted[i].name))
continue;
for (cn = policy_settings->child; cn; cn = cn->sib) {
for (j = 0; _accepted[i].settings[j]; j++)
if (strcmp(cn->key, _accepted[i].settings[j]) == 0)
break; /* -> Valid setting */
/* Have we found 'unsupported' cache setting? */
if (!_accepted[i].settings[j]) {
/* Make a copy of policy settings a remove unsupported settings and Warn */
if (!(policy_settings = dm_config_clone_node_with_mem(mem, policy_settings, 0)))
return_0;
restart:
for (cn = policy_settings->child; cn; cn = cn->sib) {
for (j = 0; _accepted[i].settings[j]; j++) {
if (strcmp(cn->key, _accepted[i].settings[j]) == 0)
break; /* need to be dropped */
}
if (!_accepted[i].settings[j]) {
log_warn("WARNING: %s cache policy does not support \"%s=" FMTu64 "\" setting, "
"remove with 'lvchange --cachesettings \"%s=default\" ...'.",
_accepted[i].name, cn->key, cn->v->v.i, cn->key);
dm_config_remove_node(policy_settings, cn);
goto restart;
}
}
break;
}
}
break;
}
}
if (!dm_tree_node_add_cache_target(node, len,
feature_flags,
metadata_uuid,
@@ -726,7 +784,7 @@ static int _cache_add_target_line(struct dev_manager *dm,
seg->cleaner_policy ? "cleaner" :
/* undefined policy name -> likely an old "mq" */
cache_pool_seg->policy_name ? : "mq",
seg->cleaner_policy ? NULL : setting_seg->policy_settings,
policy_settings,
seg->metadata_start,
seg->metadata_len,
seg->data_start,

View File

@@ -32,6 +32,7 @@
#include "lib/cache/lvmcache.h"
#include "lib/format_text/archiver.h"
#include "lib/lvmpolld/lvmpolld-client.h"
#include "lib/device/device_id.h"
#include <locale.h>
#include <sys/stat.h>
@@ -40,6 +41,10 @@
#include <syslog.h>
#include <time.h>
#ifdef APP_MACHINEID_SUPPORT
#include <systemd/sd-id128.h>
#endif
#ifdef __linux__
# include <malloc.h>
#endif
@@ -128,9 +133,12 @@ static const char *_read_system_id_from_file(struct cmd_context *cmd, const char
return system_id;
}
/* systemd-id128 new produced: f64406832c2140e8ac5422d1089aae03 */
#define LVM_APPLICATION_ID SD_ID128_MAKE(f6,44,06,83,2c,21,40,e8,ac,54,22,d1,08,9a,ae,03)
static const char *_system_id_from_source(struct cmd_context *cmd, const char *source)
{
char filebuf[PATH_MAX];
char buf[PATH_MAX];
const char *file;
const char *etc_str;
const char *str;
@@ -149,10 +157,25 @@ static const char *_system_id_from_source(struct cmd_context *cmd, const char *s
goto out;
}
#ifdef APP_MACHINEID_SUPPORT
if (!strcasecmp(source, "appmachineid")) {
sd_id128_t id = { 0 };
if (sd_id128_get_machine_app_specific(LVM_APPLICATION_ID, &id) != 0)
log_warn("WARNING: sd_id128_get_machine_app_specific() failed %s (%d).",
strerror(errno), errno);
if (dm_snprintf(buf, PATH_MAX, SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(id)) < 0)
stack;
system_id = system_id_from_string(cmd, buf);
goto out;
}
#endif
if (!strcasecmp(source, "machineid") || !strcasecmp(source, "machine-id")) {
etc_str = find_config_tree_str(cmd, global_etc_CFG, NULL);
if (dm_snprintf(filebuf, sizeof(filebuf), "%s/machine-id", etc_str) != -1)
system_id = _read_system_id_from_file(cmd, filebuf);
if (dm_snprintf(buf, sizeof(buf), "%s/machine-id", etc_str) != -1)
system_id = _read_system_id_from_file(cmd, buf);
goto out;
}
@@ -229,7 +252,7 @@ static void _get_sysfs_dir(struct cmd_context *cmd, char *buf, size_t buf_size)
return;
}
strncpy(buf, sys_mnt, buf_size);
(void) dm_strncpy(buf, sys_mnt, buf_size);
}
static uint32_t _parse_debug_fields(struct cmd_context *cmd, int cfg, const char *cfgname)
@@ -319,6 +342,33 @@ static int _parse_debug_classes(struct cmd_context *cmd)
return debug_classes;
}
static uint32_t _parse_log_journal(struct cmd_context *cmd, int cfg, const char *cfgname)
{
const struct dm_config_node *cn;
const struct dm_config_value *cv;
uint32_t fields = 0;
uint32_t val;
if (!(cn = find_config_tree_array(cmd, cfg, NULL))) {
log_debug("Unable to find configuration for log/%s.", cfgname);
return 0;
}
for (cv = cn->v; cv; cv = cv->next) {
if (cv->type != DM_CFG_STRING) {
log_verbose("log/%s contains a value which is not a string. Ignoring.", cfgname);
continue;
}
if ((val = log_journal_str_to_val(cv->v.str)))
fields |= val;
else
log_verbose("Unrecognised value for log/%s: %s", cfgname, cv->v.str);
}
return fields;
}
static void _init_logging(struct cmd_context *cmd)
{
int append = 1;
@@ -329,12 +379,11 @@ static void _init_logging(struct cmd_context *cmd)
/* Syslog */
cmd->default_settings.syslog = find_config_tree_bool(cmd, log_syslog_CFG, NULL);
if (cmd->default_settings.syslog != 1)
if (cmd->default_settings.syslog)
init_syslog(1, DEFAULT_LOG_FACILITY);
else
fin_syslog();
if (cmd->default_settings.syslog > 1)
init_syslog(cmd->default_settings.syslog);
/* Debug level for log file output */
cmd->default_settings.debug = find_config_tree_int(cmd, log_level_CFG, NULL);
init_debug(cmd->default_settings.debug);
@@ -387,6 +436,9 @@ static void _init_logging(struct cmd_context *cmd)
init_debug_file_fields(_parse_debug_fields(cmd, log_debug_file_fields_CFG, "debug_file_fields"));
init_debug_output_fields(_parse_debug_fields(cmd, log_debug_output_fields_CFG, "debug_output_fields"));
cmd->default_settings.journal = _parse_log_journal(cmd, log_journal_CFG, "journal");
init_log_journal(cmd->default_settings.journal);
t = time(NULL);
ctime_r(&t, &timebuf[0]);
timebuf[24] = '\0';
@@ -401,15 +453,12 @@ static void _init_logging(struct cmd_context *cmd)
reset_lvm_errno(1);
}
static int _check_disable_udev(const char *msg) {
static int _check_disable_udev(const char *msg)
{
if (getenv("DM_DISABLE_UDEV")) {
log_very_verbose("DM_DISABLE_UDEV environment variable set. "
"Overriding configuration to use "
"udev_rules=0, udev_sync=0, verify_udev_operations=1.");
if (udev_is_running())
log_warn("Udev is running and DM_DISABLE_UDEV environment variable is set. "
"Bypassing udev, LVM will %s.", msg);
log_very_verbose("DM_DISABLE_UDEV environment variable set.");
log_very_verbose("Overriding configuration to use udev_rules=0, udev_sync=0, verify_udev_operations=1.");
log_very_verbose("LVM will %s.", msg);
return 1;
}
@@ -562,7 +611,7 @@ static int _init_system_id(struct cmd_context *cmd)
static int _process_config(struct cmd_context *cmd)
{
mode_t old_umask;
const char *dev_ext_info_src;
const char *dev_ext_info_src = NULL;
const char *read_ahead;
struct stat st;
const struct dm_config_node *cn;
@@ -596,15 +645,26 @@ static int _process_config(struct cmd_context *cmd)
#endif
dev_ext_info_src = find_config_tree_str(cmd, devices_external_device_info_source_CFG, NULL);
if (dev_ext_info_src && !strcmp(dev_ext_info_src, "none"))
init_external_device_info_source(DEV_EXT_NONE);
else if (dev_ext_info_src && !strcmp(dev_ext_info_src, "udev"))
init_external_device_info_source(DEV_EXT_UDEV);
else {
log_error("Invalid external device info source specification.");
return 0;
if (dev_ext_info_src &&
strcmp(dev_ext_info_src, "none") &&
strcmp(dev_ext_info_src, "udev")) {
log_warn("WARNING: unknown external device info source, using none.");
dev_ext_info_src = NULL;
}
if (dev_ext_info_src && !strcmp(dev_ext_info_src, "udev")) {
if (udev_init_library_context()) {
init_external_device_info_source(DEV_EXT_UDEV);
} else {
log_warn("WARNING: failed to init udev for external device info, using none.");
dev_ext_info_src = NULL;
}
}
if (!dev_ext_info_src || !strcmp(dev_ext_info_src, "none"))
init_external_device_info_source(DEV_EXT_NONE);
/* proc dir */
if (dm_snprintf(cmd->proc_dir, sizeof(cmd->proc_dir), "%s",
find_config_tree_str(cmd, global_proc_CFG, NULL)) < 0) {
@@ -660,6 +720,8 @@ static int _process_config(struct cmd_context *cmd)
*/
cmd->default_settings.udev_fallback = udev_disabled ? 1 : -1;
cmd->default_settings.issue_discards = find_config_tree_bool(cmd, devices_issue_discards_CFG, NULL);
init_retry_deactivation(find_config_tree_bool(cmd, activation_retry_deactivation_CFG, NULL));
init_activation_checks(find_config_tree_bool(cmd, activation_checks_CFG, NULL));
@@ -705,6 +767,7 @@ static int _process_config(struct cmd_context *cmd)
init_pv_min_size((uint64_t)pv_min_kb * (1024 >> SECTOR_SHIFT));
cmd->check_pv_dev_sizes = find_config_tree_bool(cmd, metadata_check_pv_device_sizes_CFG, NULL);
cmd->event_activation = find_config_tree_bool(cmd, global_event_activation_CFG, NULL);
if (!process_profilable_config(cmd))
return_0;
@@ -963,8 +1026,13 @@ static void _destroy_config(struct cmd_context *cmd)
/* CONFIG_FILE/CONFIG_MERGED_FILES */
if ((cft = remove_config_tree_by_source(cmd, CONFIG_MERGED_FILES)))
config_destroy(cft);
else
remove_config_tree_by_source(cmd, CONFIG_FILE);
else if ((cft = remove_config_tree_by_source(cmd, CONFIG_FILE))) {
dm_list_iterate_items(cfl, &cmd->config_files) {
if (cfl->cft == cft)
dm_list_del(&cfl->list);
}
config_destroy(cft);
}
dm_list_iterate_items(cfl, &cmd->config_files)
config_destroy(cfl->cft);
@@ -1010,16 +1078,10 @@ static int _init_dev_cache(struct cmd_context *cmd)
if (!dev_cache_init(cmd))
return_0;
/*
* Override existing config and hardcode device_list_from_udev = 0 if:
* - udev is not running
* - udev is disabled using DM_DISABLE_UDEV environment variable
*/
if (_check_disable_udev("obtain device list by scanning device directory"))
device_list_from_udev = 0;
else
device_list_from_udev = udev_is_running() ?
find_config_tree_bool(cmd, devices_obtain_device_list_from_udev_CFG, NULL) : 0;
if ((device_list_from_udev = find_config_tree_bool(cmd, devices_obtain_device_list_from_udev_CFG, NULL))) {
if (!udev_init_library_context())
device_list_from_udev = 0;
}
init_obtain_device_list_from_udev(device_list_from_udev);
@@ -1066,7 +1128,7 @@ static int _init_dev_cache(struct cmd_context *cmd)
return 1;
}
#define MAX_FILTERS 10
#define MAX_FILTERS 11
static struct dev_filter *_init_filter_chain(struct cmd_context *cmd)
{
@@ -1081,16 +1143,6 @@ static struct dev_filter *_init_filter_chain(struct cmd_context *cmd)
* Update MAX_FILTERS definition above when adding new filters.
*/
/*
* sysfs filter. Only available on 2.6 kernels. Non-critical.
* Listed first because it's very efficient at eliminating
* unavailable devices.
*/
if (find_config_tree_bool(cmd, devices_sysfs_scan_CFG, NULL)) {
if ((filters[nr_filt] = sysfs_filter_create()))
nr_filt++;
}
/* internal filter used by command processing. */
if (!(filters[nr_filt] = internal_filter_create())) {
log_error("Failed to create internal device filter");
@@ -1100,7 +1152,7 @@ static struct dev_filter *_init_filter_chain(struct cmd_context *cmd)
/* global regex filter. Optional. */
if ((cn = find_config_tree_node(cmd, devices_global_filter_CFG, NULL))) {
if (!(filters[nr_filt] = regex_filter_create(cn->v))) {
if (!(filters[nr_filt] = regex_filter_create(cn->v, 0, 1))) {
log_error("Failed to create global regex device filter");
goto bad;
}
@@ -1109,7 +1161,7 @@ static struct dev_filter *_init_filter_chain(struct cmd_context *cmd)
/* regex filter. Optional. */
if ((cn = find_config_tree_node(cmd, devices_filter_CFG, NULL))) {
if (!(filters[nr_filt] = regex_filter_create(cn->v))) {
if (!(filters[nr_filt] = regex_filter_create(cn->v, 1, 0))) {
log_error("Failed to create regex device filter");
goto bad;
}
@@ -1123,6 +1175,24 @@ static struct dev_filter *_init_filter_chain(struct cmd_context *cmd)
}
nr_filt++;
/* filter based on the device_ids saved in the devices file */
if (!(filters[nr_filt] = deviceid_filter_create(cmd))) {
log_error("Failed to create deviceid device filter");
goto bad;
}
nr_filt++;
/*
* sysfs filter. Only available on 2.6 kernels. Non-critical.
* Eliminates unavailable devices.
* TODO: this may be unnecessary now with device ids
* (currently not used for devs match to device id using syfs)
*/
if (find_config_tree_bool(cmd, devices_sysfs_scan_CFG, NULL)) {
if ((filters[nr_filt] = sysfs_filter_create()))
nr_filt++;
}
/* usable device filter. Required. */
if (!(filters[nr_filt] = usable_filter_create(cmd, cmd->dev_types, FILTER_MODE_NO_LVMETAD))) {
log_error("Failed to create usabled device filter");
@@ -1164,7 +1234,7 @@ static struct dev_filter *_init_filter_chain(struct cmd_context *cmd)
nr_filt++;
}
if (!(composite = composite_filter_create(nr_filt, 1, filters)))
if (!(composite = composite_filter_create(nr_filt, filters)))
goto_bad;
return composite;
@@ -1276,7 +1346,7 @@ int init_lvmcache_orphans(struct cmd_context *cmd)
struct format_type *fmt;
dm_list_iterate_items(fmt, &cmd->formats)
if (!lvmcache_add_orphan_vginfo(fmt->orphan_vg_name, fmt))
if (!lvmcache_add_orphan_vginfo(cmd, fmt->orphan_vg_name, fmt))
return_0;
return 1;
@@ -1485,6 +1555,7 @@ int init_run_by_dmeventd(struct cmd_context *cmd)
init_dmeventd_monitor(DMEVENTD_MONITOR_IGNORE);
init_ignore_suspended_devices(1);
init_disable_dmeventd_monitoring(1); /* Lock settings */
cmd->run_by_dmeventd = 1;
return 0;
}
@@ -1532,7 +1603,6 @@ struct cmd_context *create_config_context(void)
dm_list_init(&cmd->config_files);
dm_list_init(&cmd->tags);
dm_list_init(&cmd->hints);
if (!_init_lvm_conf(cmd))
goto_out;
@@ -1582,8 +1652,6 @@ struct cmd_context *create_toolcontext(unsigned is_clvmd,
bindtextdomain(INTL_PACKAGE, LOCALEDIR);
#endif
init_syslog(DEFAULT_LOG_FACILITY);
if (!(cmd = zalloc(sizeof(*cmd)))) {
log_error("Failed to allocate command context");
return NULL;
@@ -1594,6 +1662,7 @@ struct cmd_context *create_toolcontext(unsigned is_clvmd,
cmd->handles_missing_pvs = 0;
cmd->handles_unknown_segments = 0;
cmd->hosttags = 0;
cmd->check_devs_used = 1;
dm_list_init(&cmd->arg_value_groups);
dm_list_init(&cmd->formats);
dm_list_init(&cmd->segtypes);
@@ -1716,6 +1785,8 @@ struct cmd_context *create_toolcontext(unsigned is_clvmd,
if (!_init_dev_cache(cmd))
goto_out;
devices_file_init(cmd);
memlock_init(cmd);
if (!_init_formats(cmd))
@@ -1841,6 +1912,7 @@ int refresh_toolcontext(struct cmd_context *cmd)
_destroy_segtypes(&cmd->segtypes);
_destroy_formats(cmd, &cmd->formats);
devices_file_exit(cmd);
if (!dev_cache_exit())
stack;
_destroy_dev_types(cmd);
@@ -1920,6 +1992,8 @@ int refresh_toolcontext(struct cmd_context *cmd)
if (!_init_dev_cache(cmd))
return_0;
devices_file_init(cmd);
if (!_init_formats(cmd))
return_0;
@@ -1967,24 +2041,18 @@ void destroy_toolcontext(struct cmd_context *cmd)
_destroy_segtypes(&cmd->segtypes);
_destroy_formats(cmd, &cmd->formats);
_destroy_filters(cmd);
if (cmd->mem)
dm_pool_destroy(cmd->mem);
devices_file_exit(cmd);
dev_cache_exit();
_destroy_dev_types(cmd);
_destroy_tags(cmd);
if ((cft_cmdline = remove_config_tree_by_source(cmd, CONFIG_STRING)))
config_destroy(cft_cmdline);
_destroy_config(cmd);
if (cmd->cft_def_hash)
dm_hash_destroy(cmd->cft_def_hash);
if (cmd->libmem)
dm_pool_destroy(cmd->libmem);
if (cmd->pending_delete_mem)
dm_pool_destroy(cmd->pending_delete_mem);
dm_device_list_destroy(&cmd->cache_dm_devs);
#ifndef VALGRIND_POOL
if (cmd->linebuffer) {
/* Reset stream buffering to defaults */
@@ -2009,7 +2077,7 @@ void destroy_toolcontext(struct cmd_context *cmd)
free(cmd->linebuffer);
}
#endif
free(cmd);
destroy_config_context(cmd);
lvmpolld_disconnect();

View File

@@ -29,7 +29,9 @@ struct config_info {
int debug_classes;
int verbose;
int silent;
int suppress;
int test;
int yes;
int syslog;
int activation;
int suffix;
@@ -39,7 +41,8 @@ struct config_info {
int udev_rules;
int udev_sync;
int udev_fallback;
int cache_vgmetadata;
int issue_discards;
uint32_t journal;
const char *msg_prefix;
const char *fmt_name;
const char *dmeventd_executable;
@@ -171,7 +174,7 @@ struct cmd_context {
unsigned activate_component:1; /* command activates component LV */
unsigned process_component_lvs:1; /* command processes also component LVs */
unsigned mirror_warn_printed:1; /* command already printed warning about non-monitored mirrors */
unsigned pvscan_cache_single:1;
unsigned expect_missing_vg_device:1; /* when reading a vg it's expected that a dev for a pv isn't found */
unsigned can_use_one_scan:1;
unsigned is_clvmd:1;
unsigned md_component_detection:1;
@@ -182,13 +185,37 @@ struct cmd_context {
unsigned pvscan_recreate_hints:1; /* enable special case hint handling for pvscan --cache */
unsigned scan_lvs:1;
unsigned wipe_outdated_pvs:1;
unsigned enable_devices_list:1; /* command is using --devices option */
unsigned enable_devices_file:1; /* command is using devices file */
unsigned pending_devices_file:1; /* command may create and enable devices file */
unsigned create_edit_devices_file:1; /* command expects to create and/or edit devices file */
unsigned edit_devices_file:1; /* command expects to edit devices file */
unsigned filter_deviceid_skip:1; /* don't use filter-deviceid */
unsigned filter_regex_with_devices_file:1; /* use filter-regex even when devices file is enabled */
unsigned filter_nodata_only:1; /* only use filters that do not require data from the dev */
unsigned run_by_dmeventd:1; /* command is being run by dmeventd */
unsigned sysinit:1; /* --sysinit is used */
unsigned ignorelockingfailure:1; /* --ignorelockingfailure is used */
unsigned check_devs_used:1; /* check devs used by LVs */
unsigned print_device_id_not_found:1; /* print devices file entries not found */
unsigned ignore_device_name_mismatch:1; /* skip updating devices file names */
unsigned backup_disabled:1; /* skip repeated debug message */
unsigned event_activation:1; /* whether event_activation is set */
unsigned udevoutput:1;
unsigned online_vg_file_removed:1;
unsigned disable_dm_devs:1; /* temporarily disable use of dm devs cache */
/*
* Devices and filtering.
*/
struct dev_filter *filter;
struct dm_list hints;
struct dm_list use_devices; /* struct dev_use for each entry in devices file */
const char *md_component_checks;
const char *search_for_devnames; /* config file setting */
const char *devicesfile; /* from --devicesfile option */
struct dm_list deviceslist; /* from --devices option, struct dm_str_list */
struct dm_list *cache_dm_devs; /* cache with UUIDs from DM_DEVICE_LIST (when available) */
/*
* Configuration.
@@ -220,6 +247,7 @@ struct cmd_context {
char system_dir[PATH_MAX];
char dev_dir[PATH_MAX];
char proc_dir[PATH_MAX];
char devices_file_path[PATH_MAX];
/*
* Reporting.

View File

@@ -501,12 +501,15 @@ int config_file_read_fd(struct dm_config_tree *cft, struct device *dev, dev_io_r
checksum_fn_t checksum_fn, uint32_t checksum,
int checksum_only, int no_dup_node_check)
{
char namebuf[NAME_LEN + 1] __attribute__((aligned(8)));
int namelen = 0;
int bad_name = 0;
char *fb, *fe;
int r = 0;
int use_mmap = 1;
off_t mmap_offset = 0;
int sz, use_plain_read = 1;
char *buf = NULL;
struct config_source *cs = dm_config_get_custom(cft);
size_t rsize;
if (!_is_file_based_config_source(cs->type)) {
log_error(INTERNAL_ERROR "config_file_read_fd: expected file, special file "
@@ -515,26 +518,30 @@ int config_file_read_fd(struct dm_config_tree *cft, struct device *dev, dev_io_r
return 0;
}
/* Only use mmap with regular files */
/* Only use plain read with regular files */
if (!(dev->flags & DEV_REGULAR) || size2)
use_mmap = 0;
use_plain_read = 0;
if (use_mmap) {
mmap_offset = offset % lvm_getpagesize();
/* memory map the file */
fb = mmap((caddr_t) 0, size + mmap_offset, PROT_READ,
MAP_PRIVATE, dev_fd(dev), offset - mmap_offset);
if (fb == (caddr_t) (-1)) {
log_sys_error("mmap", dev_name(dev));
goto out;
/* Ensure there is extra '\0' after end of buffer since we pass
* buffer to funtions like strtoll() */
if (!(buf = zalloc(size + size2 + 1))) {
log_error("Failed to allocate circular buffer.");
return 0;
}
if (use_plain_read) {
/* Note: also used for lvm.conf to read all settings */
for (rsize = 0; rsize < size; rsize += sz) {
do {
sz = read(dev_fd(dev), buf + rsize, size - rsize);
} while ((sz < 0) && ((errno == EINTR) || (errno == EAGAIN)));
if (sz < 0) {
log_sys_error("read", dev_name(dev));
goto out;
}
}
fb = fb + mmap_offset;
} else {
if (!(buf = malloc(size + size2))) {
log_error("Failed to allocate circular buffer.");
return 0;
}
if (!dev_read_bytes(dev, offset, size, buf))
goto out;
@@ -542,8 +549,25 @@ int config_file_read_fd(struct dm_config_tree *cft, struct device *dev, dev_io_r
if (!dev_read_bytes(dev, offset2, size2, buf + size))
goto out;
}
}
fb = buf;
fb = buf;
if (!(dev->flags & DEV_REGULAR)) {
memcpy(namebuf, buf, NAME_LEN);
while (namebuf[namelen] && !isspace(namebuf[namelen]) && namebuf[namelen] != '{' && namelen < (NAME_LEN - 1))
namelen++;
namebuf[namelen] = '\0';
/*
* Check that the text metadata begins with a valid name.
*/
if (!validate_name(namebuf)) {
log_warn("WARNING: Metadata location on %s at offset %llu begins with invalid name.",
dev_name(dev), (unsigned long long)offset);
bad_name = 1;
}
}
/*
@@ -555,10 +579,13 @@ int config_file_read_fd(struct dm_config_tree *cft, struct device *dev, dev_io_r
if (checksum_fn && checksum !=
(checksum_fn(checksum_fn(INITIAL_CRC, (const uint8_t *)fb, size),
(const uint8_t *)(fb + size), size2))) {
log_error("%s: Checksum error at offset %" PRIu64, dev_name(dev), (uint64_t) offset);
log_warn("WARNING: Checksum error on %s at offset %llu.", dev_name(dev), (unsigned long long)offset);
goto out;
}
if (bad_name)
goto out;
if (!checksum_only) {
fe = fb + size + size2;
if (no_dup_node_check) {
@@ -573,15 +600,7 @@ int config_file_read_fd(struct dm_config_tree *cft, struct device *dev, dev_io_r
r = 1;
out:
if (!use_mmap)
free(buf);
else {
/* unmap the file */
if (munmap(fb - mmap_offset, size + mmap_offset)) {
log_sys_error("munmap", dev_name(dev));
r = 0;
}
}
free(buf);
return r;
}
@@ -716,7 +735,7 @@ static struct dm_config_value *_get_def_array_values(struct cmd_context *cmd,
return array;
}
if (!(p = token = enc_value = strdup(def_enc_value))) {
if (!(token = enc_value = strdup(def_enc_value))) {
log_error("_get_def_array_values: strdup failed");
return NULL;
}
@@ -915,7 +934,7 @@ static int _check_value_differs_from_default(struct cft_check_handle *handle,
} else {
str = v_def ? v_def->v.str
: cfg_def_get_default_value(handle->cmd, def, CFG_TYPE_STRING, NULL);
diff = strcmp(str, v->v.str);
diff = str ? strcmp(str, v->v.str) : 0;
}
break;
case DM_CFG_EMPTY_ARRAY:
@@ -1147,8 +1166,10 @@ int config_def_check(struct cft_check_handle *handle)
* sections and settings with full path as a key.
* If section name is variable, use '#' as a substitute.
*/
*vp = 0;
*rp = 0;
if (!handle->cmd->cft_def_hash) {
if (!(handle->cmd->cft_def_hash = dm_hash_create(64))) {
if (!(handle->cmd->cft_def_hash = dm_hash_create(500))) {
log_error("Failed to create configuration definition hash.");
r = 0; goto out;
}
@@ -1714,6 +1735,7 @@ static int _out_prefix_fn(const struct dm_config_node *cn, const char *line, voi
const char *node_type_name = cn->v ? "option" : "section";
char path[CFG_PATH_MAX_LEN];
char commentline[MAX_COMMENT_LINE+1];
int is_deprecated = 0;
if (cn->id <= 0)
return 1;
@@ -1727,13 +1749,14 @@ static int _out_prefix_fn(const struct dm_config_node *cn, const char *line, voi
cfg_def = cfg_def_get_item_p(cn->id);
is_deprecated = _def_node_is_deprecated(cfg_def, out->tree_spec);
if (out->tree_spec->withsummary || out->tree_spec->withcomments) {
_cfg_def_make_path(path, sizeof(path), cfg_def->id, cfg_def, 1);
fprintf(out->fp, "\n");
fprintf(out->fp, "%s# Configuration %s %s.\n", line, node_type_name, path);
if (out->tree_spec->withcomments &&
_def_node_is_deprecated(cfg_def, out->tree_spec))
if (out->tree_spec->withcomments && is_deprecated && cfg_def->deprecation_comment)
fprintf(out->fp, "%s# %s", line, cfg_def->deprecation_comment);
if (cfg_def->comment) {
@@ -1744,14 +1767,14 @@ static int _out_prefix_fn(const struct dm_config_node *cn, const char *line, voi
continue;
commentline[0] = '\0';
}
fprintf(out->fp, "%s# %s\n", line, commentline);
fprintf(out->fp, "%s#%s%s\n", line, commentline[0] ? " " : "", commentline);
/* withsummary prints only the first comment line. */
if (!out->tree_spec->withcomments)
break;
}
}
if (_def_node_is_deprecated(cfg_def, out->tree_spec))
if (is_deprecated)
fprintf(out->fp, "%s# This configuration %s is deprecated.\n", line, node_type_name);
if (cfg_def->flags & CFG_ADVANCED)
@@ -1779,7 +1802,7 @@ static int _out_prefix_fn(const struct dm_config_node *cn, const char *line, voi
return_0;
fprintf(out->fp, "%s# Available since version %s.\n", line, version);
if (_def_node_is_deprecated(cfg_def, out->tree_spec)) {
if (is_deprecated) {
if (!_get_config_node_version(cfg_def->deprecated_since_version, version))
return_0;
fprintf(out->fp, "%s# Deprecated since version %s.\n", line, version);

View File

@@ -205,7 +205,7 @@ cfg_section(local_CFG_SECTION, "local", root_CFG_SECTION, 0, vsn(2, 2, 117), 0,
"# Please take care that each setting only appears once if uncommenting\n" \
"# example settings in this file and never copy this file between hosts.\n\n"
cfg(config_checks_CFG, "checks", config_CFG_SECTION, 0, CFG_TYPE_BOOL, 1, vsn(2, 2, 99), NULL, 0, NULL,
cfg(config_checks_CFG, "checks", config_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, 1, vsn(2, 2, 99), NULL, 0, NULL,
"If enabled, any LVM configuration mismatch is reported.\n"
"This implies checking that the configuration key is understood by\n"
"LVM and that the value of the key is the proper type. If disabled,\n"
@@ -213,22 +213,22 @@ cfg(config_checks_CFG, "checks", config_CFG_SECTION, 0, CFG_TYPE_BOOL, 1, vsn(2,
"without any warning (a message about the configuration key not being\n"
"found is issued in verbose mode only).\n")
cfg(config_abort_on_errors_CFG, "abort_on_errors", config_CFG_SECTION, 0, CFG_TYPE_BOOL, 0, vsn(2,2,99), NULL, 0, NULL,
cfg(config_abort_on_errors_CFG, "abort_on_errors", config_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, 0, vsn(2,2,99), NULL, 0, NULL,
"Abort the LVM process if a configuration mismatch is found.\n")
cfg_runtime(config_profile_dir_CFG, "profile_dir", config_CFG_SECTION, CFG_DISALLOW_INTERACTIVE, CFG_TYPE_STRING, vsn(2, 2, 99), 0, NULL,
cfg_runtime(config_profile_dir_CFG, "profile_dir", config_CFG_SECTION, CFG_DEFAULT_COMMENTED | CFG_DISALLOW_INTERACTIVE, CFG_TYPE_STRING, vsn(2, 2, 99), 0, NULL,
"Directory where LVM looks for configuration profiles.\n")
cfg(devices_dir_CFG, "dir", devices_CFG_SECTION, CFG_ADVANCED, CFG_TYPE_STRING, DEFAULT_DEV_DIR, vsn(1, 0, 0), NULL, 0, NULL,
cfg(devices_dir_CFG, "dir", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED | CFG_ADVANCED, CFG_TYPE_STRING, DEFAULT_DEV_DIR, vsn(1, 0, 0), NULL, 0, NULL,
"Directory in which to create volume group device nodes.\n"
"Commands also accept this as a prefix on volume group names.\n")
cfg_array(devices_scan_CFG, "scan", devices_CFG_SECTION, CFG_ADVANCED, CFG_TYPE_STRING, "#S/dev", vsn(1, 0, 0), NULL, 0, NULL,
cfg_array(devices_scan_CFG, "scan", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED | CFG_ADVANCED, CFG_TYPE_STRING, "#S/dev", vsn(1, 0, 0), NULL, 0, NULL,
"Directories containing device nodes to use with LVM.\n")
cfg_array(devices_loopfiles_CFG, "loopfiles", devices_CFG_SECTION, CFG_DEFAULT_UNDEFINED | CFG_UNSUPPORTED, CFG_TYPE_STRING, NULL, vsn(1, 2, 0), NULL, vsn(2, 3, 0), NULL, NULL)
cfg(devices_obtain_device_list_from_udev_CFG, "obtain_device_list_from_udev", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_OBTAIN_DEVICE_LIST_FROM_UDEV, vsn(2, 2, 85), NULL, 0, NULL,
cfg(devices_obtain_device_list_from_udev_CFG, "obtain_device_list_from_udev", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_OBTAIN_DEVICE_LIST_FROM_UDEV, vsn(2, 2, 85), NULL, 0, NULL,
"Obtain the list of available devices from udev.\n"
"This avoids opening or using any inapplicable non-block devices or\n"
"subdirectories found in the udev directory. Any device node or\n"
@@ -237,23 +237,11 @@ cfg(devices_obtain_device_list_from_udev_CFG, "obtain_device_list_from_udev", de
"directories will be scanned fully. LVM needs to be compiled with\n"
"udev support for this setting to apply.\n")
cfg(devices_external_device_info_source_CFG, "external_device_info_source", devices_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_EXTERNAL_DEVICE_INFO_SOURCE, vsn(2, 2, 116), NULL, 0, NULL,
"Select an external device information source.\n"
"Some information may already be available in the system and LVM can\n"
"use this information to determine the exact type or use of devices it\n"
"processes. Using an existing external device information source can\n"
"speed up device processing as LVM does not need to run its own native\n"
"routines to acquire this information. For example, this information\n"
"is used to drive LVM filtering like MD component detection, multipath\n"
"component detection, partition detection and others.\n"
"#\n"
"Accepted values:\n"
" none\n"
" No external device information source is used.\n"
" udev\n"
" Reuse existing udev database records. Applicable only if LVM is\n"
" compiled with udev support.\n"
"#\n")
cfg(devices_external_device_info_source_CFG, "external_device_info_source", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_EXTERNAL_DEVICE_INFO_SOURCE, vsn(2, 2, 116), NULL, 0, NULL,
"Enable device information from udev.\n"
"If set to \"udev\", lvm will supplement its own native device information\n"
"with information from libudev. This can potentially improve the detection\n"
"of MD component devices and multipath component devices.\n")
cfg(devices_hints_CFG, "hints", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_HINTS, vsn(2, 3, 2), NULL, 0, NULL,
"Use a local file to remember which devices have PVs on them.\n"
@@ -288,6 +276,32 @@ cfg_array(devices_preferred_names_CFG, "preferred_names", devices_CFG_SECTION, C
"preferred_names = [ \"^/dev/mpath/\", \"^/dev/mapper/mpath\", \"^/dev/[hs]d\" ]\n"
"#\n")
cfg(devices_use_devicesfile_CFG, "use_devicesfile", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_USE_DEVICES_FILE, vsn(2, 3, 12), NULL, 0, NULL,
"Enable or disable the use of a devices file.\n"
"When enabled, lvm will only use devices that\n"
"are lised in the devices file. A devices file will\n"
"be used, regardless of this setting, when the --devicesfile\n"
"option is set to a specific file name.\n")
cfg(devices_devicesfile_CFG, "devicesfile", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_DEVICES_FILE, vsn(2, 3, 12), NULL, 0, NULL,
"The name of the system devices file, listing devices that LVM should use.\n"
"This should not be used to select a non-system devices file.\n"
"The --devicesfile option is intended for alternative devices files.\n")
cfg(devices_search_for_devnames_CFG, "search_for_devnames", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_SEARCH_FOR_DEVNAMES, vsn(2, 3, 12), NULL, 0, NULL,
"Look outside of the devices file for missing devname entries.\n"
"A devname entry is used for a device that does not have a stable\n"
"device id, e.g. wwid, so the unstable device name is used as\n"
"the device id. After reboot, or if the device is reattached,\n"
"the device name may change, in which case lvm will not find\n"
"the expected PV on the device listed in the devices file.\n"
"This setting controls whether lvm will search other devices,\n"
"outside the devices file, to look for the missing PV on a\n"
"renamed device. If \"none\", lvm will not look at other devices,\n"
"and the PV may appear to be missing. If \"auto\", lvm will look\n"
"at other devices, but only those that are likely to have the PV.\n"
"If \"all\", lvm will look at all devices on the system.\n")
cfg_array(devices_filter_CFG, "filter", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, "#Sa|.*|", vsn(1, 0, 0), NULL, 0, NULL,
"Limit the block devices that are used by LVM commands.\n"
"This is a list of regular expressions used to accept or reject block\n"
@@ -326,16 +340,16 @@ cfg_array(devices_global_filter_CFG, "global_filter", devices_CFG_SECTION, CFG_D
"global_filter are not opened by LVM.\n")
cfg_runtime(devices_cache_CFG, "cache", devices_CFG_SECTION, 0, CFG_TYPE_STRING, vsn(1, 0, 0), vsn(1, 2, 19), NULL,
"This setting is no longer used.\n")
NULL)
cfg_runtime(devices_cache_dir_CFG, "cache_dir", devices_CFG_SECTION, 0, CFG_TYPE_STRING, vsn(1, 2, 19), vsn(2, 3, 0), NULL,
"This setting is no longer used.\n")
NULL)
cfg(devices_cache_file_prefix_CFG, "cache_file_prefix", devices_CFG_SECTION, CFG_ALLOW_EMPTY, CFG_TYPE_STRING, DEFAULT_CACHE_FILE_PREFIX, vsn(1, 2, 19), NULL, vsn(2, 3, 0), NULL,
"This setting is no longer used.\n")
NULL)
cfg(devices_write_cache_state_CFG, "write_cache_state", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, 1, vsn(1, 0, 0), NULL, vsn(2, 3, 0), NULL,
"This setting is no longer used.\n")
NULL)
cfg_array(devices_types_CFG, "types", devices_CFG_SECTION, CFG_DEFAULT_UNDEFINED | CFG_ADVANCED, CFG_TYPE_INT | CFG_TYPE_STRING, NULL, vsn(1, 0, 0), NULL, 0, NULL,
"List of additional acceptable block device types.\n"
@@ -346,12 +360,12 @@ cfg_array(devices_types_CFG, "types", devices_CFG_SECTION, CFG_DEFAULT_UNDEFINED
"types = [ \"fd\", 16 ]\n"
"#\n")
cfg(devices_sysfs_scan_CFG, "sysfs_scan", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_SYSFS_SCAN, vsn(1, 0, 8), NULL, 0, NULL,
cfg(devices_sysfs_scan_CFG, "sysfs_scan", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_SYSFS_SCAN, vsn(1, 0, 8), NULL, 0, NULL,
"Restrict device scanning to block devices appearing in sysfs.\n"
"This is a quick way of filtering out block devices that are not\n"
"present on the system. sysfs must be part of the kernel and mounted.)\n")
cfg(devices_scan_lvs_CFG, "scan_lvs", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_SCAN_LVS, vsn(2, 2, 182), NULL, 0, NULL,
cfg(devices_scan_lvs_CFG, "scan_lvs", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_SCAN_LVS, vsn(2, 2, 182), NULL, 0, NULL,
"Scan LVM LVs for layered PVs, allowing LVs to be used as PVs.\n"
"When 1, LVM will detect PVs layered on LVs, and caution must be\n"
"taken to avoid a host accessing a layered VG that may not belong\n"
@@ -364,10 +378,14 @@ cfg(devices_scan_lvs_CFG, "scan_lvs", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEF
"an LV. The LVs are ignored using a built in device filter that\n"
"identifies and excludes LVs.\n")
cfg(devices_multipath_component_detection_CFG, "multipath_component_detection", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_MULTIPATH_COMPONENT_DETECTION, vsn(2, 2, 89), NULL, 0, NULL,
cfg(devices_multipath_component_detection_CFG, "multipath_component_detection", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_MULTIPATH_COMPONENT_DETECTION, vsn(2, 2, 89), NULL, 0, NULL,
"Ignore devices that are components of DM multipath devices.\n")
cfg(devices_md_component_detection_CFG, "md_component_detection", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_MD_COMPONENT_DETECTION, vsn(1, 0, 18), NULL, 0, NULL,
cfg(devices_multipath_wwids_file_CFG, "multipath_wwids_file", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED | CFG_ALLOW_EMPTY, CFG_TYPE_STRING, DEFAULT_WWIDS_FILE, vsn(2, 3, 13), NULL, 0, NULL,
"The path to the multipath wwids file used for multipath component detection.\n"
"Set this to an empty string to disable the use of the multipath wwids file.\n")
cfg(devices_md_component_detection_CFG, "md_component_detection", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_MD_COMPONENT_DETECTION, vsn(1, 0, 18), NULL, 0, NULL,
"Enable detection and exclusion of MD component devices.\n"
"An MD component device is a block device that MD uses as part\n"
"of a software RAID virtual device. When an LVM PV is created\n"
@@ -393,26 +411,26 @@ cfg(devices_md_component_checks_CFG, "md_component_checks", devices_CFG_SECTION,
" This requires an extra read at the end of devices.\n"
"#\n")
cfg(devices_fw_raid_component_detection_CFG, "fw_raid_component_detection", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_FW_RAID_COMPONENT_DETECTION, vsn(2, 2, 112), NULL, 0, NULL,
cfg(devices_fw_raid_component_detection_CFG, "fw_raid_component_detection", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_FW_RAID_COMPONENT_DETECTION, vsn(2, 2, 112), NULL, 0, NULL,
"Ignore devices that are components of firmware RAID devices.\n"
"LVM must use an external_device_info_source other than none for this\n"
"detection to execute.\n")
cfg(devices_md_chunk_alignment_CFG, "md_chunk_alignment", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_MD_CHUNK_ALIGNMENT, vsn(2, 2, 48), NULL, 0, NULL,
cfg(devices_md_chunk_alignment_CFG, "md_chunk_alignment", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_MD_CHUNK_ALIGNMENT, vsn(2, 2, 48), NULL, 0, NULL,
"Align the start of a PV data area with md device's stripe-width.\n"
"This applies if a PV is placed directly on an md device.\n"
"default_data_alignment will be overriden if it is not aligned\n"
"default_data_alignment will be overridden if it is not aligned\n"
"with the value detected for this setting.\n"
"This setting is overriden by data_alignment_detection,\n"
"This setting is overridden by data_alignment_detection,\n"
"data_alignment, and the --dataalignment option.\n")
cfg(devices_default_data_alignment_CFG, "default_data_alignment", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, FIRST_PE_AT_ONE_MB_IN_MB, vsn(2, 2, 75), NULL, 0, NULL,
"Align the start of a PV data area with this number of MiB.\n"
"Set to 1 for 1MiB, 2 for 2MiB, etc. Set to 0 to disable.\n"
"This setting is overriden by data_alignment and the --dataalignment\n"
"This setting is overridden by data_alignment and the --dataalignment\n"
"option.\n")
cfg(devices_data_alignment_detection_CFG, "data_alignment_detection", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_DATA_ALIGNMENT_DETECTION, vsn(2, 2, 51), NULL, 0, NULL,
cfg(devices_data_alignment_detection_CFG, "data_alignment_detection", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_DATA_ALIGNMENT_DETECTION, vsn(2, 2, 51), NULL, 0, NULL,
"Align the start of a PV data area with sysfs io properties.\n"
"The start of a PV data area will be a multiple of minimum_io_size or\n"
"optimal_io_size exposed in sysfs. minimum_io_size is the smallest\n"
@@ -421,19 +439,19 @@ cfg(devices_data_alignment_detection_CFG, "data_alignment_detection", devices_CF
"preferred unit of receiving I/O, e.g. MD stripe width.\n"
"minimum_io_size is used if optimal_io_size is undefined (0).\n"
"If md_chunk_alignment is enabled, that detects the optimal_io_size.\n"
"default_data_alignment and md_chunk_alignment will be overriden\n"
"default_data_alignment and md_chunk_alignment will be overridden\n"
"if they are not aligned with the value detected for this setting.\n"
"This setting is overriden by data_alignment and the --dataalignment\n"
"This setting is overridden by data_alignment and the --dataalignment\n"
"option.\n")
cfg(devices_data_alignment_CFG, "data_alignment", devices_CFG_SECTION, 0, CFG_TYPE_INT, 0, vsn(2, 2, 45), NULL, 0, NULL,
cfg(devices_data_alignment_CFG, "data_alignment", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, 0, vsn(2, 2, 45), NULL, 0, NULL,
"Align the start of a PV data area with this number of KiB.\n"
"When non-zero, this setting overrides default_data_alignment.\n"
"Set to 0 to disable, in which case default_data_alignment\n"
"is used to align the first PE in units of MiB.\n"
"This setting is overriden by the --dataalignment option.\n")
"This setting is overridden by the --dataalignment option.\n")
cfg(devices_data_alignment_offset_detection_CFG, "data_alignment_offset_detection", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_DATA_ALIGNMENT_OFFSET_DETECTION, vsn(2, 2, 50), NULL, 0, NULL,
cfg(devices_data_alignment_offset_detection_CFG, "data_alignment_offset_detection", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_DATA_ALIGNMENT_OFFSET_DETECTION, vsn(2, 2, 50), NULL, 0, NULL,
"Shift the start of an aligned PV data area based on sysfs information.\n"
"After a PV data area is aligned, it will be shifted by the\n"
"alignment_offset exposed in sysfs. This offset is often 0, but may\n"
@@ -441,14 +459,14 @@ cfg(devices_data_alignment_offset_detection_CFG, "data_alignment_offset_detectio
"partitioning will have an alignment_offset of 3584 bytes (sector 7\n"
"is the lowest aligned logical block, the 4KiB sectors start at\n"
"LBA -1, and consequently sector 63 is aligned on a 4KiB boundary).\n"
"This setting is overriden by the --dataalignmentoffset option.\n")
"This setting is overridden by the --dataalignmentoffset option.\n")
cfg(devices_ignore_suspended_devices_CFG, "ignore_suspended_devices", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_IGNORE_SUSPENDED_DEVICES, vsn(1, 2, 19), NULL, 0, NULL,
cfg(devices_ignore_suspended_devices_CFG, "ignore_suspended_devices", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_IGNORE_SUSPENDED_DEVICES, vsn(1, 2, 19), NULL, 0, NULL,
"Ignore DM devices that have I/O suspended while scanning devices.\n"
"Otherwise, LVM waits for a suspended device to become accessible.\n"
"This should only be needed in recovery situations.\n")
cfg(devices_ignore_lvm_mirrors_CFG, "ignore_lvm_mirrors", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_IGNORE_LVM_MIRRORS, vsn(2, 2, 104), NULL, 0, NULL,
cfg(devices_ignore_lvm_mirrors_CFG, "ignore_lvm_mirrors", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_IGNORE_LVM_MIRRORS, vsn(2, 2, 104), NULL, 0, NULL,
"Do not scan 'mirror' LVs to avoid possible deadlocks.\n"
"This avoids possible deadlocks when using the 'mirror' segment type.\n"
"This setting determines whether LVs using the 'mirror' segment type\n"
@@ -466,19 +484,19 @@ cfg(devices_ignore_lvm_mirrors_CFG, "ignore_lvm_mirrors", devices_CFG_SECTION, 0
"apply to LVM RAID types like 'raid1' which handle failures in a\n"
"different way, making them a better choice for VG stacking.\n")
cfg(devices_disable_after_error_count_CFG, "disable_after_error_count", devices_CFG_SECTION, 0, CFG_TYPE_INT, 0, vsn(2, 2, 75), NULL, vsn(2, 3, 0), NULL,
"This setting is no longer used.\n")
cfg(devices_disable_after_error_count_CFG, "disable_after_error_count", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, 0, vsn(2, 2, 75), NULL, vsn(2, 3, 0), NULL,
NULL)
cfg(devices_require_restorefile_with_uuid_CFG, "require_restorefile_with_uuid", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_REQUIRE_RESTOREFILE_WITH_UUID, vsn(2, 2, 73), NULL, 0, NULL,
cfg(devices_require_restorefile_with_uuid_CFG, "require_restorefile_with_uuid", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_REQUIRE_RESTOREFILE_WITH_UUID, vsn(2, 2, 73), NULL, 0, NULL,
"Allow use of pvcreate --uuid without requiring --restorefile.\n")
cfg(devices_pv_min_size_CFG, "pv_min_size", devices_CFG_SECTION, 0, CFG_TYPE_INT, DEFAULT_PV_MIN_SIZE_KB, vsn(2, 2, 85), NULL, 0, NULL,
cfg(devices_pv_min_size_CFG, "pv_min_size", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_PV_MIN_SIZE_KB, vsn(2, 2, 85), NULL, 0, NULL,
"Minimum size in KiB of block devices which can be used as PVs.\n"
"In a clustered environment all nodes must use the same value.\n"
"Any value smaller than 512KiB is ignored. The previous built-in\n"
"value was 512.\n")
cfg(devices_issue_discards_CFG, "issue_discards", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_ISSUE_DISCARDS, vsn(2, 2, 85), NULL, 0, NULL,
cfg(devices_issue_discards_CFG, "issue_discards", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_ISSUE_DISCARDS, vsn(2, 2, 85), NULL, 0, NULL,
"Issue discards to PVs that are no longer used by an LV.\n"
"Discards are sent to an LV's underlying physical volumes when the LV\n"
"is no longer using the physical volumes' space, e.g. lvremove,\n"
@@ -490,7 +508,7 @@ cfg(devices_issue_discards_CFG, "issue_discards", devices_CFG_SECTION, 0, CFG_TY
"generally do. If enabled, discards will only be issued if both the\n"
"storage and kernel provide support.\n")
cfg(devices_allow_changes_with_duplicate_pvs_CFG, "allow_changes_with_duplicate_pvs", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_ALLOW_CHANGES_WITH_DUPLICATE_PVS, vsn(2, 2, 153), NULL, 0, NULL,
cfg(devices_allow_changes_with_duplicate_pvs_CFG, "allow_changes_with_duplicate_pvs", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_ALLOW_CHANGES_WITH_DUPLICATE_PVS, vsn(2, 2, 153), NULL, 0, NULL,
"Allow VG modification while a PV appears on multiple devices.\n"
"When a PV appears on multiple devices, LVM attempts to choose the\n"
"best device to use for the PV. If the devices represent the same\n"
@@ -502,7 +520,7 @@ cfg(devices_allow_changes_with_duplicate_pvs_CFG, "allow_changes_with_duplicate_
"Enabling this setting allows the VG to be used as usual even with\n"
"uncertain devices.\n")
cfg(devices_allow_mixed_block_sizes_CFG, "allow_mixed_block_sizes", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, 0, vsn(2, 3, 6), NULL, 0, NULL,
cfg(devices_allow_mixed_block_sizes_CFG, "allow_mixed_block_sizes", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, 0, vsn(2, 3, 6), NULL, 0, NULL,
"Allow PVs in the same VG with different logical block sizes.\n"
"When allowed, the user is responsible to ensure that an LV is\n"
"using PVs with matching block sizes when necessary.\n")
@@ -525,14 +543,14 @@ cfg_array(allocation_cling_tag_list_CFG, "cling_tag_list", allocation_CFG_SECTIO
"cling_tag_list = [ \"@site1\", \"@site2\" ]\n"
"#\n")
cfg(allocation_maximise_cling_CFG, "maximise_cling", allocation_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_MAXIMISE_CLING, vsn(2, 2, 85), NULL, 0, NULL,
cfg(allocation_maximise_cling_CFG, "maximise_cling", allocation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_MAXIMISE_CLING, vsn(2, 2, 85), NULL, 0, NULL,
"Use a previous allocation algorithm.\n"
"Changes made in version 2.02.85 extended the reach of the 'cling'\n"
"policies to detect more situations where data can be grouped onto\n"
"the same disks. This setting can be used to disable the changes\n"
"and revert to the previous algorithm.\n")
cfg(allocation_use_blkid_wiping_CFG, "use_blkid_wiping", allocation_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_USE_BLKID_WIPING, vsn(2, 2, 105), "@DEFAULT_USE_BLKID_WIPING@", 0, NULL,
cfg(allocation_use_blkid_wiping_CFG, "use_blkid_wiping", allocation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_USE_BLKID_WIPING, vsn(2, 2, 105), "@DEFAULT_USE_BLKID_WIPING@", 0, NULL,
"Use blkid to detect and erase existing signatures on new PVs and LVs.\n"
"The blkid library can detect more signatures than the native LVM\n"
"detection code, but may take longer. LVM needs to be compiled with\n"
@@ -541,7 +559,7 @@ cfg(allocation_use_blkid_wiping_CFG, "use_blkid_wiping", allocation_CFG_SECTION,
"swap signature, and LUKS signatures. To see the list of signatures\n"
"recognized by blkid, check the output of the 'blkid -k' command.\n")
cfg(allocation_wipe_signatures_when_zeroing_new_lvs_CFG, "wipe_signatures_when_zeroing_new_lvs", allocation_CFG_SECTION, 0, CFG_TYPE_BOOL, 1, vsn(2, 2, 105), NULL, 0, NULL,
cfg(allocation_wipe_signatures_when_zeroing_new_lvs_CFG, "wipe_signatures_when_zeroing_new_lvs", allocation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, 1, vsn(2, 2, 105), NULL, 0, NULL,
"Look for and erase any signatures while zeroing a new LV.\n"
"The --wipesignatures option overrides this setting.\n"
"Zeroing is controlled by the -Z/--zero option, and if not specified,\n"
@@ -557,7 +575,7 @@ cfg(allocation_wipe_signatures_when_zeroing_new_lvs_CFG, "wipe_signatures_when_z
"When this setting is disabled, signatures on new LVs are not detected\n"
"or erased unless the --wipesignatures option is used directly.\n")
cfg(allocation_mirror_logs_require_separate_pvs_CFG, "mirror_logs_require_separate_pvs", allocation_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_MIRROR_LOGS_REQUIRE_SEPARATE_PVS, vsn(2, 2, 85), NULL, 0, NULL,
cfg(allocation_mirror_logs_require_separate_pvs_CFG, "mirror_logs_require_separate_pvs", allocation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_MIRROR_LOGS_REQUIRE_SEPARATE_PVS, vsn(2, 2, 85), NULL, 0, NULL,
"Mirror logs and images will always use different PVs.\n"
"The default setting changed in version 2.02.85.\n")
@@ -568,7 +586,7 @@ cfg(allocation_raid_stripe_all_devices_CFG, "raid_stripe_all_devices", allocatio
"stripes to use.\n"
"This was the default behaviour until release 2.02.162.\n")
cfg(allocation_cache_pool_metadata_require_separate_pvs_CFG, "cache_pool_metadata_require_separate_pvs", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA, CFG_TYPE_BOOL, DEFAULT_CACHE_POOL_METADATA_REQUIRE_SEPARATE_PVS, vsn(2, 2, 106), NULL, 0, NULL,
cfg(allocation_cache_pool_metadata_require_separate_pvs_CFG, "cache_pool_metadata_require_separate_pvs", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_CACHE_POOL_METADATA_REQUIRE_SEPARATE_PVS, vsn(2, 2, 106), NULL, 0, NULL,
"Cache pool metadata and data will always use different PVs.\n")
cfg(allocation_cache_pool_cachemode_CFG, "cache_pool_cachemode", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_CACHE_MODE, vsn(2, 2, 113), NULL, vsn(2, 2, 128),
@@ -625,8 +643,13 @@ cfg(allocation_cache_pool_max_chunks_CFG, "cache_pool_max_chunks", allocation_CF
"For cache target v1.9 the recommended maximumm is 1000000 chunks.\n"
"Using cache pool with more chunks may degrade cache performance.\n")
cfg(allocation_thin_pool_metadata_require_separate_pvs_CFG, "thin_pool_metadata_require_separate_pvs", allocation_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_THIN_POOL_METADATA_REQUIRE_SEPARATE_PVS, vsn(2, 2, 89), NULL, 0, NULL,
"Thin pool metdata and data will always use different PVs.\n")
cfg(allocation_thin_pool_metadata_require_separate_pvs_CFG, "thin_pool_metadata_require_separate_pvs", allocation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_THIN_POOL_METADATA_REQUIRE_SEPARATE_PVS, vsn(2, 2, 89), NULL, 0, NULL,
"Thin pool metadata and data will always use different PVs.\n")
cfg(allocation_thin_pool_crop_metadata_CFG, "thin_pool_crop_metadata", allocation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_THIN_POOL_CROP_METADATA, vsn(2, 3, 12), NULL, 0, NULL,
"Older version of lvm2 cropped pool's metadata size to 15.81 GiB.\n"
"This is slightly less then the actual maximum 15.88 GiB.\n"
"For compatibility with older version and use of cropped size set to 1.\n")
cfg(allocation_thin_pool_zero_CFG, "thin_pool_zero", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_THIN_POOL_ZERO, vsn(2, 2, 99), NULL, 0, NULL,
"Thin pool data chunks are zeroed before they are first used.\n"
@@ -657,6 +680,9 @@ cfg(allocation_thin_pool_chunk_size_policy_CFG, "thin_pool_chunk_size_policy", a
" 512KiB.\n"
"#\n")
cfg(allocation_zero_metadata_CFG, "zero_metadata", allocation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_ZERO_METADATA, vsn(2, 3, 10), NULL, 0, NULL,
"Zero whole metadata area before use with thin or cache pool.\n")
cfg_runtime(allocation_thin_pool_chunk_size_CFG, "thin_pool_chunk_size", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_UNDEFINED, CFG_TYPE_INT, vsn(2, 2, 99), 0, NULL,
"The minimal chunk size in KiB for thin pool volumes.\n"
"Larger chunk sizes may improve performance for plain thin volumes,\n"
@@ -770,10 +796,12 @@ cfg(allocation_vdo_write_policy_CFG, "vdo_write_policy", allocation_CFG_SECTION,
"sync - Writes are acknowledged only after data is stably written.\n"
" This policy is not supported if the underlying storage is not also synchronous.\n"
"async - Writes are acknowledged after data has been cached for writing to stable storage.\n"
" Data which has not been flushed is not guaranteed to persist in this mode.\n")
" Data which has not been flushed is not guaranteed to persist in this mode.\n"
"async-unsafe - Writes are handled like 'async' but there is no guarantee of the atomicity async provides.\n"
" This mode should only be used for better performance when atomicity is not required.\n")
cfg(allocation_vdo_max_discard_CFG, "vdo_max_discard", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_VDO_MAX_DISCARD, VDO_1ST_VSN, NULL, 0, NULL,
"Specified te maximum size of discard bio accepted, in 4096 byte blocks.\n"
"Specified the maximum size of discard bio accepted, in 4096 byte blocks.\n"
"I/O requests to a VDO volume are normally split into 4096-byte blocks,\n"
"and processed up to 2048 at a time. However, discard requests to a VDO volume\n"
"can be automatically split to a larger size, up to <max discard> 4096-byte blocks\n"
@@ -782,6 +810,9 @@ cfg(allocation_vdo_max_discard_CFG, "vdo_max_discard", allocation_CFG_SECTION, C
"increased latency for the individual discard requests.\n"
"The default and minimum is 1. The maximum is UINT_MAX / 4096.\n")
cfg(allocation_vdo_pool_header_size_CFG, "vdo_pool_header_size", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_VDO_POOL_HEADER_SIZE_KB, vsn(2, 3, 12), NULL, 0, NULL,
"Specified the emptry header size in KiB at the front and end of vdo pool device.\n")
cfg(log_report_command_log_CFG, "report_command_log", log_CFG_SECTION, CFG_PROFILABLE | CFG_DEFAULT_COMMENTED | CFG_DISALLOW_INTERACTIVE, CFG_TYPE_BOOL, DEFAULT_COMMAND_LOG_REPORT, vsn(2, 2, 158), NULL, 0, NULL,
"Enable or disable LVM log reporting.\n"
"If enabled, LVM will collect a log of operations, messages,\n"
@@ -823,10 +854,10 @@ cfg(log_command_log_selection_CFG, "command_log_selection", log_CFG_SECTION, CFG
"For more information about selection criteria in general, see\n"
"lvm(8) man page.\n")
cfg(log_verbose_CFG, "verbose", log_CFG_SECTION, 0, CFG_TYPE_INT, DEFAULT_VERBOSE, vsn(1, 0, 0), NULL, 0, NULL,
cfg(log_verbose_CFG, "verbose", log_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_VERBOSE, vsn(1, 0, 0), NULL, 0, NULL,
"Controls the messages sent to stdout or stderr.\n")
cfg(log_silent_CFG, "silent", log_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_SILENT, vsn(2, 2, 98), NULL, 0, NULL,
cfg(log_silent_CFG, "silent", log_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_SILENT, vsn(2, 2, 98), NULL, 0, NULL,
"Suppress all non-essential messages from stdout.\n"
"This has the same effect as -qq. When enabled, the following commands\n"
"still produce output: dumpconfig, lvdisplay, lvmdiskscan, lvs, pvck,\n"
@@ -836,16 +867,22 @@ cfg(log_silent_CFG, "silent", log_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_SILENT,
"Any 'yes' or 'no' questions not overridden by other arguments are\n"
"suppressed and default to 'no'.\n")
cfg(log_syslog_CFG, "syslog", log_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_SYSLOG, vsn(1, 0, 0), NULL, 0, NULL,
cfg(log_syslog_CFG, "syslog", log_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_SYSLOG, vsn(1, 0, 0), NULL, 0, NULL,
"Send log messages through syslog.\n")
cfg(log_file_CFG, "file", log_CFG_SECTION, CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(1, 0, 0), NULL, 0, NULL,
"Write error and debug log messages to a file specified here.\n")
cfg(log_overwrite_CFG, "overwrite", log_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_OVERWRITE, vsn(1, 0, 0), NULL, 0, NULL,
cfg_array(log_journal_CFG, "journal", log_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, NULL, vsn(2, 3, 12), NULL, 0, NULL,
"Record lvm information in the systemd journal.\n"
"command: record commands that are run.\n"
"output: record default output from commands.\n"
"debug: record debug messages from commands.\n")
cfg(log_overwrite_CFG, "overwrite", log_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_OVERWRITE, vsn(1, 0, 0), NULL, 0, NULL,
"Overwrite the log file each time the program is run.\n")
cfg(log_level_CFG, "level", log_CFG_SECTION, 0, CFG_TYPE_INT, DEFAULT_LOGLEVEL, vsn(1, 0, 0), NULL, 0, NULL,
cfg(log_level_CFG, "level", log_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_LOGLEVEL, vsn(1, 0, 0), NULL, 0, NULL,
"The level of log messages that are sent to the log file or syslog.\n"
"There are 6 syslog-like log levels currently in use: 2 to 7 inclusive.\n"
"7 is the most verbose (LOG_DEBUG).\n")
@@ -853,23 +890,23 @@ cfg(log_level_CFG, "level", log_CFG_SECTION, 0, CFG_TYPE_INT, DEFAULT_LOGLEVEL,
cfg(log_indent_CFG, "indent", log_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_INDENT, vsn(1, 0, 0), NULL, 0, NULL,
"Indent messages according to their severity.\n")
cfg(log_command_names_CFG, "command_names", log_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_CMD_NAME, vsn(1, 0, 0), NULL, 0, NULL,
cfg(log_command_names_CFG, "command_names", log_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_CMD_NAME, vsn(1, 0, 0), NULL, 0, NULL,
"Display the command name on each line of output.\n")
cfg(log_prefix_CFG, "prefix", log_CFG_SECTION, CFG_ALLOW_EMPTY, CFG_TYPE_STRING, DEFAULT_MSG_PREFIX, vsn(1, 0, 0), NULL, 0, NULL,
cfg(log_prefix_CFG, "prefix", log_CFG_SECTION, CFG_DEFAULT_COMMENTED | CFG_ALLOW_EMPTY, CFG_TYPE_STRING, DEFAULT_MSG_PREFIX, vsn(1, 0, 0), NULL, 0, NULL,
"A prefix to use before the log message text.\n"
"(After the command name, if selected).\n"
"Two spaces allows you to see/grep the severity of each message.\n"
"To make the messages look similar to the original LVM tools use:\n"
"indent = 0, command_names = 1, prefix = \" -- \"\n")
cfg(log_activation_CFG, "activation", log_CFG_SECTION, 0, CFG_TYPE_BOOL, 0, vsn(1, 0, 0), NULL, 0, NULL,
cfg(log_activation_CFG, "activation", log_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, 0, vsn(1, 0, 0), NULL, 0, NULL,
"Log messages during activation.\n"
"Don't use this in low memory situations (can deadlock).\n")
cfg(log_activate_file_CFG, "activate_file", log_CFG_SECTION, CFG_DEFAULT_UNDEFINED | CFG_UNSUPPORTED, CFG_TYPE_STRING, NULL, vsn(1, 0, 0), NULL, 0, NULL, NULL)
cfg_array(log_debug_classes_CFG, "debug_classes", log_CFG_SECTION, CFG_ALLOW_EMPTY, CFG_TYPE_STRING, "#Smemory#Sdevices#Sio#Sactivation#Sallocation#Smetadata#Scache#Slocking#Slvmpolld#Sdbus", vsn(2, 2, 99), NULL, 0, NULL,
cfg_array(log_debug_classes_CFG, "debug_classes", log_CFG_SECTION, CFG_DEFAULT_COMMENTED | CFG_ALLOW_EMPTY, CFG_TYPE_STRING, "#Smemory#Sdevices#Sio#Sactivation#Sallocation#Smetadata#Scache#Slocking#Slvmpolld#Sdbus", vsn(2, 2, 99), NULL, 0, NULL,
"Select log messages by class.\n"
"Some debugging messages are assigned to a class and only appear in\n"
"debug output if the class is listed here. Classes currently\n"
@@ -884,55 +921,55 @@ cfg_array(log_debug_output_fields_CFG, "debug_output_fields", log_CFG_SECTION, C
"The fields included in debug output written to stderr.\n"
"Use \"all\" to include everything (the default).\n")
cfg(backup_backup_CFG, "backup", backup_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_BACKUP_ENABLED, vsn(1, 0, 0), NULL, 0, NULL,
cfg(backup_backup_CFG, "backup", backup_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_BACKUP_ENABLED, vsn(1, 0, 0), NULL, 0, NULL,
"Maintain a backup of the current metadata configuration.\n"
"Think very hard before turning this off!\n")
cfg_runtime(backup_backup_dir_CFG, "backup_dir", backup_CFG_SECTION, 0, CFG_TYPE_STRING, vsn(1, 0, 0), 0, NULL,
cfg_runtime(backup_backup_dir_CFG, "backup_dir", backup_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, vsn(1, 0, 0), 0, NULL,
"Location of the metadata backup files.\n"
"Remember to back up this directory regularly!\n")
cfg(backup_archive_CFG, "archive", backup_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_ARCHIVE_ENABLED, vsn(1, 0, 0), NULL, 0, NULL,
cfg(backup_archive_CFG, "archive", backup_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_ARCHIVE_ENABLED, vsn(1, 0, 0), NULL, 0, NULL,
"Maintain an archive of old metadata configurations.\n"
"Think very hard before turning this off.\n")
cfg_runtime(backup_archive_dir_CFG, "archive_dir", backup_CFG_SECTION, 0, CFG_TYPE_STRING, vsn(1, 0, 0), 0, NULL,
cfg_runtime(backup_archive_dir_CFG, "archive_dir", backup_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, vsn(1, 0, 0), 0, NULL,
"Location of the metdata archive files.\n"
"Remember to back up this directory regularly!\n")
cfg(backup_retain_min_CFG, "retain_min", backup_CFG_SECTION, 0, CFG_TYPE_INT, DEFAULT_ARCHIVE_NUMBER, vsn(1, 0, 0), NULL, 0, NULL,
cfg(backup_retain_min_CFG, "retain_min", backup_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_ARCHIVE_NUMBER, vsn(1, 0, 0), NULL, 0, NULL,
"Minimum number of archives to keep.\n")
cfg(backup_retain_days_CFG, "retain_days", backup_CFG_SECTION, 0, CFG_TYPE_INT, DEFAULT_ARCHIVE_DAYS, vsn(1, 0, 0), NULL, 0, NULL,
cfg(backup_retain_days_CFG, "retain_days", backup_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_ARCHIVE_DAYS, vsn(1, 0, 0), NULL, 0, NULL,
"Minimum number of days to keep archive files.\n")
cfg(shell_history_size_CFG, "history_size", shell_CFG_SECTION, 0, CFG_TYPE_INT, DEFAULT_MAX_HISTORY, vsn(1, 0, 0), NULL, 0, NULL,
cfg(shell_history_size_CFG, "history_size", shell_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_MAX_HISTORY, vsn(1, 0, 0), NULL, 0, NULL,
"Number of lines of history to store in ~/.lvm_history.\n")
cfg(global_umask_CFG, "umask", global_CFG_SECTION, CFG_FORMAT_INT_OCTAL, CFG_TYPE_INT, DEFAULT_UMASK, vsn(1, 0, 0), NULL, 0, NULL,
cfg(global_umask_CFG, "umask", global_CFG_SECTION, CFG_DEFAULT_COMMENTED | CFG_FORMAT_INT_OCTAL, CFG_TYPE_INT, DEFAULT_UMASK, vsn(1, 0, 0), NULL, 0, NULL,
"The file creation mask for any files and directories created.\n"
"Interpreted as octal if the first digit is zero.\n")
cfg(global_test_CFG, "test", global_CFG_SECTION, 0, CFG_TYPE_BOOL, 0, vsn(1, 0, 0), NULL, 0, NULL,
cfg(global_test_CFG, "test", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, 0, vsn(1, 0, 0), NULL, 0, NULL,
"No on-disk metadata changes will be made in test mode.\n"
"Equivalent to having the -t option on every command.\n")
cfg(global_units_CFG, "units", global_CFG_SECTION, CFG_PROFILABLE, CFG_TYPE_STRING, DEFAULT_UNITS, vsn(1, 0, 0), NULL, 0, NULL,
cfg(global_units_CFG, "units", global_CFG_SECTION, CFG_DEFAULT_COMMENTED | CFG_PROFILABLE, CFG_TYPE_STRING, DEFAULT_UNITS, vsn(1, 0, 0), NULL, 0, NULL,
"Default value for --units argument.\n")
cfg(global_si_unit_consistency_CFG, "si_unit_consistency", global_CFG_SECTION, CFG_PROFILABLE, CFG_TYPE_BOOL, DEFAULT_SI_UNIT_CONSISTENCY, vsn(2, 2, 54), NULL, 0, NULL,
cfg(global_si_unit_consistency_CFG, "si_unit_consistency", global_CFG_SECTION, CFG_DEFAULT_COMMENTED | CFG_PROFILABLE, CFG_TYPE_BOOL, DEFAULT_SI_UNIT_CONSISTENCY, vsn(2, 2, 54), NULL, 0, NULL,
"Distinguish between powers of 1024 and 1000 bytes.\n"
"The LVM commands distinguish between powers of 1024 bytes,\n"
"e.g. KiB, MiB, GiB, and powers of 1000 bytes, e.g. KB, MB, GB.\n"
"If scripts depend on the old behaviour, disable this setting\n"
"temporarily until they are updated.\n")
cfg(global_suffix_CFG, "suffix", global_CFG_SECTION, CFG_PROFILABLE, CFG_TYPE_BOOL, DEFAULT_SUFFIX, vsn(1, 0, 0), NULL, 0, NULL,
cfg(global_suffix_CFG, "suffix", global_CFG_SECTION, CFG_DEFAULT_COMMENTED | CFG_PROFILABLE, CFG_TYPE_BOOL, DEFAULT_SUFFIX, vsn(1, 0, 0), NULL, 0, NULL,
"Display unit suffix for sizes.\n"
"This setting has no effect if the units are in human-readable form\n"
"(global/units = \"h\") in which case the suffix is always displayed.\n")
cfg(global_activation_CFG, "activation", global_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_ACTIVATION, vsn(1, 0, 0), NULL, 0, NULL,
cfg(global_activation_CFG, "activation", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_ACTIVATION, vsn(1, 0, 0), NULL, 0, NULL,
"Enable/disable communication with the kernel device-mapper.\n"
"Disable to use the tools to manipulate LVM metadata without\n"
"activating any logical volumes. If the device-mapper driver\n"
@@ -940,70 +977,69 @@ 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, vsn(2, 3, 0), NULL,
"This setting is no longer used.\n")
NULL)
cfg(global_format_CFG, "format", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_FORMAT, vsn(1, 0, 0), NULL, vsn(2, 3, 0), NULL,
"This setting is no longer used.\n")
NULL)
cfg_array(global_format_libraries_CFG, "format_libraries", global_CFG_SECTION, CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(1, 0, 0), NULL, vsn(2, 3, 0), NULL,
"This setting is no longer used.")
NULL)
cfg_array(global_segment_libraries_CFG, "segment_libraries", global_CFG_SECTION, CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(1, 0, 18), NULL, vsn(2, 3, 3), NULL, NULL)
cfg(global_proc_CFG, "proc", global_CFG_SECTION, CFG_ADVANCED, CFG_TYPE_STRING, DEFAULT_PROC_DIR, vsn(1, 0, 0), NULL, 0, NULL,
cfg(global_proc_CFG, "proc", global_CFG_SECTION, CFG_DEFAULT_COMMENTED | CFG_ADVANCED, CFG_TYPE_STRING, DEFAULT_PROC_DIR, vsn(1, 0, 0), NULL, 0, NULL,
"Location of proc filesystem.\n")
cfg(global_etc_CFG, "etc", global_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_ETC_DIR, vsn(2, 2, 117), "@CONFDIR@", 0, NULL,
cfg(global_etc_CFG, "etc", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_ETC_DIR, vsn(2, 2, 117), "@CONFDIR@", 0, NULL,
"Location of /etc system configuration directory.\n")
cfg(global_locking_type_CFG, "locking_type", global_CFG_SECTION, 0, CFG_TYPE_INT, 1, vsn(1, 0, 0), NULL, vsn(2, 3, 0), NULL,
"This setting is no longer used.")
cfg(global_locking_type_CFG, "locking_type", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, 1, vsn(1, 0, 0), NULL, vsn(2, 3, 0), NULL,
NULL)
cfg(global_wait_for_locks_CFG, "wait_for_locks", global_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_WAIT_FOR_LOCKS, vsn(2, 2, 50), NULL, 0, NULL,
cfg(global_wait_for_locks_CFG, "wait_for_locks", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_WAIT_FOR_LOCKS, vsn(2, 2, 50), NULL, 0, NULL,
"When disabled, fail if a lock request would block.\n")
cfg(global_fallback_to_clustered_locking_CFG, "fallback_to_clustered_locking", global_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_FALLBACK_TO_CLUSTERED_LOCKING, vsn(2, 2, 42), NULL, vsn(2, 3, 0), NULL,
"This setting is no longer used.\n")
cfg(global_fallback_to_clustered_locking_CFG, "fallback_to_clustered_locking", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_FALLBACK_TO_CLUSTERED_LOCKING, vsn(2, 2, 42), NULL, vsn(2, 3, 0), NULL,
NULL)
cfg(global_fallback_to_local_locking_CFG, "fallback_to_local_locking", global_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_FALLBACK_TO_LOCAL_LOCKING, vsn(2, 2, 42), NULL, vsn(2, 3, 0), NULL,
"This setting is no longer used.\n")
cfg(global_fallback_to_local_locking_CFG, "fallback_to_local_locking", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_FALLBACK_TO_LOCAL_LOCKING, vsn(2, 2, 42), NULL, vsn(2, 3, 0), NULL,
NULL)
cfg(global_locking_dir_CFG, "locking_dir", global_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_LOCK_DIR, vsn(1, 0, 0), "@DEFAULT_LOCK_DIR@", 0, NULL,
cfg(global_locking_dir_CFG, "locking_dir", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_LOCK_DIR, vsn(1, 0, 0), "@DEFAULT_LOCK_DIR@", 0, NULL,
"Directory to use for LVM command file locks.\n"
"Local non-LV directory that holds file-based locks while commands are\n"
"in progress. A directory like /tmp that may get wiped on reboot is OK.\n")
cfg(global_prioritise_write_locks_CFG, "prioritise_write_locks", global_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_PRIORITISE_WRITE_LOCKS, vsn(2, 2, 52), NULL, 0, NULL,
cfg(global_prioritise_write_locks_CFG, "prioritise_write_locks", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_PRIORITISE_WRITE_LOCKS, vsn(2, 2, 52), NULL, 0, NULL,
"Allow quicker VG write access during high volume read access.\n"
"When there are competing read-only and read-write access requests for\n"
"a volume group's metadata, instead of always granting the read-only\n"
"requests immediately, delay them to allow the read-write requests to\n"
"be serviced. Without this setting, write access may be stalled by a\n"
"high volume of read-only requests. This option only affects\n"
"locking_type 1 viz. local file-based locking.\n")
"high volume of read-only requests. This option only affects file locks.\n")
cfg(global_library_dir_CFG, "library_dir", global_CFG_SECTION, CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(1, 0, 0), NULL, 0, NULL,
"Search this directory first for shared libraries.\n")
cfg(global_locking_library_CFG, "locking_library", global_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_LOCKING_LIB, vsn(1, 0, 0), NULL, vsn(2, 3, 0), NULL,
"This setting is no longer used.\n")
NULL)
cfg(global_abort_on_internal_errors_CFG, "abort_on_internal_errors", global_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_ABORT_ON_INTERNAL_ERRORS, vsn(2, 2, 57), NULL, 0, NULL,
cfg(global_abort_on_internal_errors_CFG, "abort_on_internal_errors", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_ABORT_ON_INTERNAL_ERRORS, vsn(2, 2, 57), NULL, 0, NULL,
"Abort a command that encounters an internal error.\n"
"Treat any internal errors as fatal errors, aborting the process that\n"
"encountered the internal error. Please only enable for debugging.\n")
cfg(global_detect_internal_vg_cache_corruption_CFG, "detect_internal_vg_cache_corruption", global_CFG_SECTION, 0, CFG_TYPE_BOOL, 0, vsn(2, 2, 96), NULL, vsn(2, 2, 174), NULL,
"No longer used.\n")
cfg(global_detect_internal_vg_cache_corruption_CFG, "detect_internal_vg_cache_corruption", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, 0, vsn(2, 2, 96), NULL, vsn(2, 2, 174), NULL,
NULL)
cfg(global_metadata_read_only_CFG, "metadata_read_only", global_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_METADATA_READ_ONLY, vsn(2, 2, 75), NULL, 0, NULL,
cfg(global_metadata_read_only_CFG, "metadata_read_only", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_METADATA_READ_ONLY, vsn(2, 2, 75), NULL, 0, NULL,
"No operations that change on-disk metadata are permitted.\n"
"Additionally, read-only commands that encounter metadata in need of\n"
"repair will still be allowed to proceed exactly as if the repair had\n"
"been performed (except for the unchanged vg_seqno). Inappropriate\n"
"use could mess up your system, so seek advice first!\n")
cfg(global_mirror_segtype_default_CFG, "mirror_segtype_default", global_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_MIRROR_SEGTYPE, vsn(2, 2, 87), "@DEFAULT_MIRROR_SEGTYPE@", 0, NULL,
cfg(global_mirror_segtype_default_CFG, "mirror_segtype_default", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_MIRROR_SEGTYPE, vsn(2, 2, 87), "@DEFAULT_MIRROR_SEGTYPE@", 0, NULL,
"The segment type used by the short mirroring option -m.\n"
"The --type mirror|raid1 option overrides this setting.\n"
"#\n"
@@ -1028,7 +1064,7 @@ cfg(global_mirror_segtype_default_CFG, "mirror_segtype_default", global_CFG_SECT
" fashion in a cluster.\n"
"#\n")
cfg(global_support_mirrored_mirror_log_CFG, "support_mirrored_mirror_log", global_CFG_SECTION, 0, CFG_TYPE_BOOL, 0, vsn(2, 3, 2), NULL, 0, NULL,
cfg(global_support_mirrored_mirror_log_CFG, "support_mirrored_mirror_log", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, 0, vsn(2, 3, 2), NULL, 0, NULL,
"Enable mirrored 'mirror' log type for testing.\n"
"#\n"
"This type is deprecated to create or convert to but can\n"
@@ -1038,7 +1074,7 @@ cfg(global_support_mirrored_mirror_log_CFG, "support_mirrored_mirror_log", globa
"Not supported for regular operation!\n"
"\n")
cfg(global_raid10_segtype_default_CFG, "raid10_segtype_default", global_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_RAID10_SEGTYPE, vsn(2, 2, 99), "@DEFAULT_RAID10_SEGTYPE@", 0, NULL,
cfg(global_raid10_segtype_default_CFG, "raid10_segtype_default", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_RAID10_SEGTYPE, vsn(2, 2, 99), "@DEFAULT_RAID10_SEGTYPE@", 0, NULL,
"The segment type used by the -i -m combination.\n"
"The --type raid10|mirror option overrides this setting.\n"
"The --stripes/-i and --mirrors/-m options can both be specified\n"
@@ -1056,7 +1092,7 @@ cfg(global_raid10_segtype_default_CFG, "raid10_segtype_default", global_CFG_SECT
" in terms of providing redundancy and performance.\n"
"#\n")
cfg(global_sparse_segtype_default_CFG, "sparse_segtype_default", global_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_SPARSE_SEGTYPE, vsn(2, 2, 112), "@DEFAULT_SPARSE_SEGTYPE@", 0, NULL,
cfg(global_sparse_segtype_default_CFG, "sparse_segtype_default", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_SPARSE_SEGTYPE, vsn(2, 2, 112), "@DEFAULT_SPARSE_SEGTYPE@", 0, NULL,
"The segment type used by the -V -L combination.\n"
"The --type snapshot|thin option overrides this setting.\n"
"The combination of -V and -L options creates a sparse LV. There are\n"
@@ -1082,25 +1118,23 @@ cfg(global_lvdisplay_shows_full_device_path_CFG, "lvdisplay_shows_full_device_pa
"Previously this was always shown as /dev/vgname/lvname even when that\n"
"was never a valid path in the /dev filesystem.\n")
cfg(global_event_activation_CFG, "event_activation", global_CFG_SECTION, 0, CFG_TYPE_BOOL, 1, vsn(2, 3, 1), 0, 0, NULL,
"Activate LVs based on system-generated device events.\n"
"When a device appears on the system, a system-generated event runs\n"
"the pvscan command to activate LVs if the new PV completes the VG.\n"
"Use auto_activation_volume_list to select which LVs should be\n"
"activated from these events (the default is all.)\n"
"When event_activation is disabled, the system will generally run\n"
"a direct activation command to activate LVs in complete VGs.\n")
cfg(global_event_activation_CFG, "event_activation", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, 1, vsn(2, 3, 1), 0, 0, NULL,
"Disable event based autoactivation commands.\n"
"WARNING: setting this to zero may cause machine startup to fail.\n"
"Previously, setting this to zero would enable static autoactivation\n"
"services (via the lvm2-activation-generator), but the autoactivation\n"
"services and generator have been removed.\n")
cfg(global_use_lvmetad_CFG, "use_lvmetad", global_CFG_SECTION, 0, CFG_TYPE_BOOL, 0, vsn(2, 2, 93), 0, vsn(2, 3, 0), NULL,
"This setting is no longer used.\n")
cfg(global_use_lvmetad_CFG, "use_lvmetad", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, 0, vsn(2, 2, 93), 0, vsn(2, 3, 0), NULL,
NULL)
cfg(global_lvmetad_update_wait_time_CFG, "lvmetad_update_wait_time", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, 0, vsn(2, 2, 151), NULL, vsn(2, 3, 0), NULL,
"This setting is no longer used.\n")
NULL)
cfg(global_use_aio_CFG, "use_aio", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_USE_AIO, vsn(2, 2, 183), NULL, 0, NULL,
"Use async I/O when reading and writing devices.\n")
cfg(global_use_lvmlockd_CFG, "use_lvmlockd", global_CFG_SECTION, 0, CFG_TYPE_BOOL, 0, vsn(2, 2, 124), NULL, 0, NULL,
cfg(global_use_lvmlockd_CFG, "use_lvmlockd", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, 0, vsn(2, 2, 124), NULL, 0, NULL,
"Use lvmlockd for locking among hosts using LVM on shared storage.\n"
"Applicable only if LVM is compiled with lockd support in which\n"
"case there is also lvmlockd(8) man page available for more\n"
@@ -1119,6 +1153,15 @@ cfg(global_sanlock_lv_extend_CFG, "sanlock_lv_extend", global_CFG_SECTION, CFG_D
"and can cause lvcreate to fail. Applicable only if LVM is compiled\n"
"with lockd support\n")
cfg(global_lvmlockctl_kill_command_CFG, "lvmlockctl_kill_command", global_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, "", vsn(2, 3, 12), NULL, 0, NULL,
"The command that lvmlockctl --kill should use to force LVs offline.\n"
"The lvmlockctl --kill command is run when a shared VG has lost\n"
"access to locks (e.g. when sanlock has lost access to storage.)\n"
"An empty string means that there will be no automatic attempt by\n"
"lvmlockctl --kill to forcibly shut down LVs in the VG, and the user\n"
"can manually intervene as described in lvmlockd(8).\n"
"The VG name will be appended to the command specified here.\n")
cfg(global_thin_check_executable_CFG, "thin_check_executable", global_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, THIN_CHECK_CMD, vsn(2, 2, 94), "@THIN_CHECK_CMD@", 0, NULL,
"The full path to the thin_check command.\n"
"LVM uses this command to check that a thin metadata device is in a\n"
@@ -1204,11 +1247,20 @@ cfg(global_vdo_format_executable_CFG, "vdo_format_executable", global_CFG_SECTIO
cfg_array(global_vdo_format_options_CFG, "vdo_format_options", global_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_VDO_FORMAT_OPTIONS_CONFIG, VDO_1ST_VSN, NULL, 0, NULL,
"List of options passed added to standard vdoformat command.\n")
cfg_array(global_vdo_disabled_features_CFG, "vdo_disabled_features", global_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(2, 3, 11), NULL, 0, NULL,
"Features to not use in the vdo driver.\n"
"This can be helpful for testing, or to avoid using a feature that is\n"
"causing problems. Features include: online_rename\n"
"#\n"
"Example\n"
"vdo_disabled_features = [ \"online_rename\" ]\n"
"#\n")
cfg(global_fsadm_executable_CFG, "fsadm_executable", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_FSADM_PATH, vsn(2, 2, 170), "@FSADM_PATH@", 0, NULL,
"The full path to the fsadm command.\n"
"LVM uses this command to help with lvresize -r operations.\n")
cfg(global_system_id_source_CFG, "system_id_source", global_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_SYSTEM_ID_SOURCE, vsn(2, 2, 117), NULL, 0, NULL,
cfg(global_system_id_source_CFG, "system_id_source", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_SYSTEM_ID_SOURCE, vsn(2, 2, 117), NULL, 0, NULL,
"The method LVM uses to set the local system ID.\n"
"Volume Groups can also be given a system ID (by vgcreate, vgchange,\n"
"or vgimport.) A VG on shared storage devices is accessible only to\n"
@@ -1224,10 +1276,12 @@ cfg(global_system_id_source_CFG, "system_id_source", global_CFG_SECTION, 0, CFG_
" uname\n"
" Set the system ID from the hostname (uname) of the system.\n"
" System IDs beginning localhost are not permitted.\n"
" appmachineid\n"
" Use an LVM-specific derivation of the local machine-id as the\n"
" system ID. See 'man machine-id'.\n"
" machineid\n"
" Use the contents of the machine-id file to set the system ID.\n"
" Some systems create this file at installation time.\n"
" See 'man machine-id' and global/etc.\n"
" Use the contents of the machine-id file to set the system ID\n"
" (appmachineid is recommended.)\n"
" file\n"
" Use the contents of another file (system_id_file) to set the\n"
" system ID.\n"
@@ -1238,13 +1292,13 @@ cfg(global_system_id_file_CFG, "system_id_file", global_CFG_SECTION, CFG_DEFAULT
"This is used when system_id_source is set to 'file'.\n"
"Comments starting with the character # are ignored.\n")
cfg(activation_checks_CFG, "checks", activation_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_ACTIVATION_CHECKS, vsn(2, 2, 86), NULL, 0, NULL,
cfg(activation_checks_CFG, "checks", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_ACTIVATION_CHECKS, vsn(2, 2, 86), NULL, 0, NULL,
"Perform internal checks of libdevmapper operations.\n"
"Useful for debugging problems with activation. Some of the checks may\n"
"be expensive, so it's best to use this only when there seems to be a\n"
"problem.\n")
cfg(global_use_lvmpolld_CFG, "use_lvmpolld", global_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_USE_LVMPOLLD, vsn(2, 2, 120), "@DEFAULT_USE_LVMPOLLD@", 0, NULL,
cfg(global_use_lvmpolld_CFG, "use_lvmpolld", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_USE_LVMPOLLD, vsn(2, 2, 120), "@DEFAULT_USE_LVMPOLLD@", 0, NULL,
"Use lvmpolld to supervise long running LVM commands.\n"
"When enabled, control of long running LVM commands is transferred\n"
"from the original LVM command to the lvmpolld daemon. This allows\n"
@@ -1257,7 +1311,7 @@ cfg(global_use_lvmpolld_CFG, "use_lvmpolld", global_CFG_SECTION, 0, CFG_TYPE_BOO
"commands will supervise long running operations by forking themselves.\n"
"Applicable only if LVM is compiled with lvmpolld support.\n")
cfg(global_notify_dbus_CFG, "notify_dbus", global_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_NOTIFY_DBUS, vsn(2, 2, 145), NULL, 0, NULL,
cfg(global_notify_dbus_CFG, "notify_dbus", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_NOTIFY_DBUS, vsn(2, 2, 145), NULL, 0, NULL,
"Enable D-Bus notification from LVM commands.\n"
"When enabled, an LVM command that changes PVs, changes VG metadata,\n"
"or changes the activation state of an LV will send a notification.\n")
@@ -1270,9 +1324,9 @@ cfg(global_io_memory_size_CFG, "io_memory_size", global_CFG_SECTION, CFG_DEFAULT
"This value should usually not be decreased from the default; setting\n"
"it too low can result in lvm failing to read VGs.\n")
cfg(activation_udev_sync_CFG, "udev_sync", activation_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_UDEV_SYNC, vsn(2, 2, 51), NULL, 0, NULL,
cfg(activation_udev_sync_CFG, "udev_sync", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_UDEV_SYNC, vsn(2, 2, 51), NULL, 0, NULL,
"Use udev notifications to synchronize udev and LVM.\n"
"The --nodevsync option overrides this setting.\n"
"The --noudevsync option overrides this setting.\n"
"When disabled, LVM commands will not wait for notifications from\n"
"udev, but continue irrespective of any possible udev processing in\n"
"the background. Only use this if udev is not running or has rules\n"
@@ -1280,25 +1334,25 @@ cfg(activation_udev_sync_CFG, "udev_sync", activation_CFG_SECTION, 0, CFG_TYPE_B
"running, and LVM processes are waiting for udev, run the command\n"
"'dmsetup udevcomplete_all' to wake them up.\n")
cfg(activation_udev_rules_CFG, "udev_rules", activation_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_UDEV_RULES, vsn(2, 2, 57), NULL, 0, NULL,
cfg(activation_udev_rules_CFG, "udev_rules", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_UDEV_RULES, vsn(2, 2, 57), NULL, 0, NULL,
"Use udev rules to manage LV device nodes and symlinks.\n"
"When disabled, LVM will manage the device nodes and symlinks for\n"
"active LVs itself. Manual intervention may be required if this\n"
"setting is changed while LVs are active.\n")
cfg(activation_verify_udev_operations_CFG, "verify_udev_operations", activation_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_VERIFY_UDEV_OPERATIONS, vsn(2, 2, 86), NULL, 0, NULL,
cfg(activation_verify_udev_operations_CFG, "verify_udev_operations", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_VERIFY_UDEV_OPERATIONS, vsn(2, 2, 86), NULL, 0, NULL,
"Use extra checks in LVM to verify udev operations.\n"
"This enables additional checks (and if necessary, repairs) on entries\n"
"in the device directory after udev has completed processing its\n"
"events. Useful for diagnosing problems with LVM/udev interactions.\n")
cfg(activation_retry_deactivation_CFG, "retry_deactivation", activation_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_RETRY_DEACTIVATION, vsn(2, 2, 89), NULL, 0, NULL,
cfg(activation_retry_deactivation_CFG, "retry_deactivation", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_RETRY_DEACTIVATION, vsn(2, 2, 89), NULL, 0, NULL,
"Retry failed LV deactivation.\n"
"If LV deactivation fails, LVM will retry for a few seconds before\n"
"failing. This may happen because a process run from a quick udev rule\n"
"temporarily opened the device.\n")
cfg(activation_missing_stripe_filler_CFG, "missing_stripe_filler", activation_CFG_SECTION, CFG_ADVANCED, CFG_TYPE_STRING, DEFAULT_STRIPE_FILLER, vsn(1, 0, 0), NULL, 0, NULL,
cfg(activation_missing_stripe_filler_CFG, "missing_stripe_filler", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED | CFG_ADVANCED, CFG_TYPE_STRING, DEFAULT_STRIPE_FILLER, vsn(1, 0, 0), NULL, 0, NULL,
"Method to fill missing stripes when activating an incomplete LV.\n"
"Using 'error' will make inaccessible parts of the device return I/O\n"
"errors on access. Using 'zero' will return success (and zero) on I/O\n"
@@ -1307,21 +1361,21 @@ cfg(activation_missing_stripe_filler_CFG, "missing_stripe_filler", activation_CF
"other than 'error' with mirrored or snapshotted volumes is likely to\n"
"result in data corruption.\n")
cfg(activation_use_linear_target_CFG, "use_linear_target", activation_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_USE_LINEAR_TARGET, vsn(2, 2, 89), NULL, 0, NULL,
cfg(activation_use_linear_target_CFG, "use_linear_target", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_USE_LINEAR_TARGET, vsn(2, 2, 89), NULL, 0, NULL,
"Use the linear target to optimize single stripe LVs.\n"
"When disabled, the striped target is used. The linear target is an\n"
"optimised version of the striped target that only handles a single\n"
"stripe.\n")
cfg(activation_reserved_stack_CFG, "reserved_stack", activation_CFG_SECTION, 0, CFG_TYPE_INT, DEFAULT_RESERVED_STACK, vsn(1, 0, 0), NULL, 0, NULL,
cfg(activation_reserved_stack_CFG, "reserved_stack", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_RESERVED_STACK, vsn(1, 0, 0), NULL, 0, NULL,
"Stack size in KiB to reserve for use while devices are suspended.\n"
"Insufficent reserve risks I/O deadlock during device suspension.\n")
cfg(activation_reserved_memory_CFG, "reserved_memory", activation_CFG_SECTION, 0, CFG_TYPE_INT, DEFAULT_RESERVED_MEMORY, vsn(1, 0, 0), NULL, 0, NULL,
cfg(activation_reserved_memory_CFG, "reserved_memory", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_RESERVED_MEMORY, vsn(1, 0, 0), NULL, 0, NULL,
"Memory size in KiB to reserve for use while devices are suspended.\n"
"Insufficent reserve risks I/O deadlock during device suspension.\n")
cfg(activation_process_priority_CFG, "process_priority", activation_CFG_SECTION, 0, CFG_TYPE_INT, DEFAULT_PROCESS_PRIORITY, vsn(1, 0, 0), NULL, 0, NULL,
cfg(activation_process_priority_CFG, "process_priority", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_PROCESS_PRIORITY, vsn(1, 0, 0), NULL, 0, NULL,
"Nice value used while devices are suspended.\n"
"Use a high priority so that LVs are suspended\n"
"for the shortest possible time.\n")
@@ -1351,22 +1405,22 @@ cfg_array(activation_volume_list_CFG, "volume_list", activation_CFG_SECTION, CFG
"#\n")
cfg_array(activation_auto_activation_volume_list_CFG, "auto_activation_volume_list", activation_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(2, 2, 97), NULL, 0, NULL,
"Only LVs selected by this list are auto-activated.\n"
"This list works like volume_list, but it is used only by\n"
"auto-activation commands. It does not apply to direct activation\n"
"commands. If this list is defined, an LV is only auto-activated\n"
"if it matches an entry in this list. If this list is undefined, it\n"
"imposes no limits on LV auto-activation (all are allowed.) If this\n"
"list is defined and empty, i.e. \"[]\", then no LVs are selected for\n"
"auto-activation. An LV that is selected by this list for\n"
"auto-activation, must also be selected by volume_list (if defined)\n"
"before it is activated. Auto-activation is an activation command that\n"
"includes the 'a' argument: --activate ay or -a ay. The 'a' (auto)\n"
"argument for auto-activation is meant to be used by activation\n"
"commands that are run automatically by the system, as opposed to LVM\n"
"commands run directly by a user. A user may also use the 'a' flag\n"
"directly to perform auto-activation. Also see pvscan(8) for more\n"
"information about auto-activation.\n"
"A list of VGs or LVs that should be autoactivated.\n"
"Autoactivation is an activation command run with -aay,\n"
"i.e. vgchange -aay, lvchange -aay, or pvscan --cache -aay.\n"
"When this list is defined, an autoactivation command will only\n"
"activate LVs included in the list. If this list is undefined,\n"
"it has no effect. If this list is defined but empty, then no\n"
"LVs will be autoactivated. LVs can be included in the list by\n"
"LV name, VG name (applies to all LVs in the VG), or tag name.\n"
"VGs and LVs can also have an autoactivation property set in\n"
"metadata, see --setautoactivation. LVs included in this list\n"
"will not be autoactivated if the VG or LV autoactivation\n"
"property is disabled (see vgs or lvs \"-o autoactivation\").\n"
"The volume_list setting and the \"activation skip\" property\n"
"also apply to autoactivation.\n"
"The -aay option is meant to be used by activation commands that\n"
"are run automatically by the system, e.g. from systemd services.\n"
"#\n"
"Accepted values:\n"
" vgname\n"
@@ -1411,11 +1465,11 @@ cfg_array(activation_read_only_volume_list_CFG, "read_only_volume_list", activat
"read_only_volume_list = [ \"vg1\", \"vg2/lvol1\", \"@tag1\", \"@*\" ]\n"
"#\n")
cfg(activation_mirror_region_size_CFG, "mirror_region_size", activation_CFG_SECTION, 0, CFG_TYPE_INT, DEFAULT_RAID_REGION_SIZE, vsn(1, 0, 0), NULL, vsn(2, 2, 99),
cfg(activation_mirror_region_size_CFG, "mirror_region_size", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_RAID_REGION_SIZE, vsn(1, 0, 0), NULL, vsn(2, 2, 99),
"This has been replaced by the activation/raid_region_size setting.\n",
"Size in KiB of each raid or mirror synchronization region.\n")
cfg(activation_raid_region_size_CFG, "raid_region_size", activation_CFG_SECTION, 0, CFG_TYPE_INT, DEFAULT_RAID_REGION_SIZE, vsn(2, 2, 99), NULL, 0, NULL,
cfg(activation_raid_region_size_CFG, "raid_region_size", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_RAID_REGION_SIZE, vsn(2, 2, 99), NULL, 0, NULL,
"Size in KiB of each raid or mirror synchronization region.\n"
"The clean/dirty state of data is tracked for each region.\n"
"The value is rounded down to a power of two if necessary, and\n"
@@ -1430,7 +1484,7 @@ cfg(activation_error_when_full_CFG, "error_when_full", activation_CFG_SECTION, C
"thin pool data space is extended. New thin pools are assigned the\n"
"behavior defined here.\n")
cfg(activation_readahead_CFG, "readahead", activation_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_READ_AHEAD, vsn(1, 0, 23), NULL, 0, NULL,
cfg(activation_readahead_CFG, "readahead", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_READ_AHEAD, vsn(1, 0, 23), NULL, 0, NULL,
"Setting to use when there is no readahead setting in metadata.\n"
"#\n"
"Accepted values:\n"
@@ -1440,7 +1494,7 @@ cfg(activation_readahead_CFG, "readahead", activation_CFG_SECTION, 0, CFG_TYPE_S
" Use default value chosen by kernel.\n"
"#\n")
cfg(activation_raid_fault_policy_CFG, "raid_fault_policy", activation_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_RAID_FAULT_POLICY, vsn(2, 2, 89), NULL, 0, NULL,
cfg(activation_raid_fault_policy_CFG, "raid_fault_policy", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_RAID_FAULT_POLICY, vsn(2, 2, 89), NULL, 0, NULL,
"Defines how a device failure in a RAID LV is handled.\n"
"This includes LVs that have the following segment types:\n"
"raid1, raid4, raid5*, and raid6*.\n"
@@ -1461,7 +1515,7 @@ cfg(activation_raid_fault_policy_CFG, "raid_fault_policy", activation_CFG_SECTIO
" replace faulty devices.\n"
"#\n")
cfg_runtime(activation_mirror_image_fault_policy_CFG, "mirror_image_fault_policy", activation_CFG_SECTION, 0, CFG_TYPE_STRING, vsn(2, 2, 57), 0, NULL,
cfg_runtime(activation_mirror_image_fault_policy_CFG, "mirror_image_fault_policy", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, vsn(2, 2, 57), 0, NULL,
"Defines how a device failure in a 'mirror' LV is handled.\n"
"An LV with the 'mirror' segment type is composed of mirror images\n"
"(copies) and a mirror log. A disk log ensures that a mirror LV does\n"
@@ -1497,16 +1551,16 @@ cfg_runtime(activation_mirror_image_fault_policy_CFG, "mirror_image_fault_policy
" replacement.\n"
"#\n")
cfg(activation_mirror_log_fault_policy_CFG, "mirror_log_fault_policy", activation_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_MIRROR_LOG_FAULT_POLICY, vsn(1, 2, 18), NULL, 0, NULL,
cfg(activation_mirror_log_fault_policy_CFG, "mirror_log_fault_policy", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_MIRROR_LOG_FAULT_POLICY, vsn(1, 2, 18), NULL, 0, NULL,
"Defines how a device failure in a 'mirror' log LV is handled.\n"
"The mirror_image_fault_policy description for mirrored LVs also\n"
"applies to mirrored log LVs.\n")
cfg(activation_mirror_device_fault_policy_CFG, "mirror_device_fault_policy", activation_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_MIRROR_DEVICE_FAULT_POLICY, vsn(1, 2, 10), NULL, vsn(2, 2, 57),
cfg(activation_mirror_device_fault_policy_CFG, "mirror_device_fault_policy", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_MIRROR_DEVICE_FAULT_POLICY, vsn(1, 2, 10), NULL, vsn(2, 2, 57),
"This has been replaced by the activation/mirror_image_fault_policy setting.\n",
"Define how a device failure affecting a mirror is handled.\n")
cfg(activation_snapshot_autoextend_threshold_CFG, "snapshot_autoextend_threshold", activation_CFG_SECTION, 0, CFG_TYPE_INT, DEFAULT_SNAPSHOT_AUTOEXTEND_THRESHOLD, vsn(2, 2, 75), NULL, 0, NULL,
cfg(activation_snapshot_autoextend_threshold_CFG, "snapshot_autoextend_threshold", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_SNAPSHOT_AUTOEXTEND_THRESHOLD, vsn(2, 2, 75), NULL, 0, NULL,
"Auto-extend a snapshot when its usage exceeds this percent.\n"
"Setting this to 100 disables automatic extension.\n"
"The minimum value is 50 (a smaller value is treated as 50.)\n"
@@ -1520,7 +1574,7 @@ cfg(activation_snapshot_autoextend_threshold_CFG, "snapshot_autoextend_threshold
"snapshot_autoextend_threshold = 70\n"
"#\n")
cfg(activation_snapshot_autoextend_percent_CFG, "snapshot_autoextend_percent", activation_CFG_SECTION, 0, CFG_TYPE_INT, DEFAULT_SNAPSHOT_AUTOEXTEND_PERCENT, vsn(2, 2, 75), NULL, 0, NULL,
cfg(activation_snapshot_autoextend_percent_CFG, "snapshot_autoextend_percent", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_SNAPSHOT_AUTOEXTEND_PERCENT, vsn(2, 2, 75), NULL, 0, NULL,
"Auto-extending a snapshot adds this percent extra space.\n"
"The amount of additional space added to a snapshot is this\n"
"percent of its current size.\n"
@@ -1532,7 +1586,7 @@ cfg(activation_snapshot_autoextend_percent_CFG, "snapshot_autoextend_percent", a
"snapshot_autoextend_percent = 20\n"
"#\n")
cfg(activation_thin_pool_autoextend_threshold_CFG, "thin_pool_autoextend_threshold", activation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA, CFG_TYPE_INT, DEFAULT_THIN_POOL_AUTOEXTEND_THRESHOLD, vsn(2, 2, 89), NULL, 0, NULL,
cfg(activation_thin_pool_autoextend_threshold_CFG, "thin_pool_autoextend_threshold", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED | CFG_PROFILABLE | CFG_PROFILABLE_METADATA, CFG_TYPE_INT, DEFAULT_THIN_POOL_AUTOEXTEND_THRESHOLD, vsn(2, 2, 89), NULL, 0, NULL,
"Auto-extend a thin pool when its usage exceeds this percent.\n"
"Setting this to 100 disables automatic extension.\n"
"The minimum value is 50 (a smaller value is treated as 50.)\n"
@@ -1546,7 +1600,7 @@ cfg(activation_thin_pool_autoextend_threshold_CFG, "thin_pool_autoextend_thresho
"thin_pool_autoextend_threshold = 70\n"
"#\n")
cfg(activation_thin_pool_autoextend_percent_CFG, "thin_pool_autoextend_percent", activation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA, CFG_TYPE_INT, DEFAULT_THIN_POOL_AUTOEXTEND_PERCENT, vsn(2, 2, 89), NULL, 0, NULL,
cfg(activation_thin_pool_autoextend_percent_CFG, "thin_pool_autoextend_percent", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED | CFG_PROFILABLE | CFG_PROFILABLE_METADATA, CFG_TYPE_INT, DEFAULT_THIN_POOL_AUTOEXTEND_PERCENT, vsn(2, 2, 89), NULL, 0, NULL,
"Auto-extending a thin pool adds this percent extra space.\n"
"The amount of additional space added to a thin pool is this\n"
"percent of its current size.\n"
@@ -1558,7 +1612,7 @@ cfg(activation_thin_pool_autoextend_percent_CFG, "thin_pool_autoextend_percent",
"thin_pool_autoextend_percent = 20\n"
"#\n")
cfg(activation_vdo_pool_autoextend_threshold_CFG, "vdo_pool_autoextend_threshold", activation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA, CFG_TYPE_INT, DEFAULT_VDO_POOL_AUTOEXTEND_THRESHOLD, VDO_1ST_VSN, NULL, 0, NULL,
cfg(activation_vdo_pool_autoextend_threshold_CFG, "vdo_pool_autoextend_threshold", activation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_VDO_POOL_AUTOEXTEND_THRESHOLD, VDO_1ST_VSN, NULL, 0, NULL,
"Auto-extend a VDO pool when its usage exceeds this percent.\n"
"Setting this to 100 disables automatic extension.\n"
"The minimum value is 50 (a smaller value is treated as 50.)\n"
@@ -1598,17 +1652,17 @@ cfg_array(activation_mlock_filter_CFG, "mlock_filter", activation_CFG_SECTION, C
"mlock_filter = [ \"locale/locale-archive\", \"gconv/gconv-modules.cache\" ]\n"
"#\n")
cfg(activation_use_mlockall_CFG, "use_mlockall", activation_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_USE_MLOCKALL, vsn(2, 2, 62), NULL, 0, NULL,
cfg(activation_use_mlockall_CFG, "use_mlockall", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_USE_MLOCKALL, vsn(2, 2, 62), NULL, 0, NULL,
"Use the old behavior of mlockall to pin all memory.\n"
"Prior to version 2.02.62, LVM used mlockall() to pin the whole\n"
"process's memory while activating devices.\n")
cfg(activation_monitoring_CFG, "monitoring", activation_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_DMEVENTD_MONITOR, vsn(2, 2, 63), NULL, 0, NULL,
cfg(activation_monitoring_CFG, "monitoring", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_DMEVENTD_MONITOR, vsn(2, 2, 63), NULL, 0, NULL,
"Monitor LVs that are activated.\n"
"The --ignoremonitoring option overrides this setting.\n"
"When enabled, LVM will ask dmeventd to monitor activated LVs.\n")
cfg(activation_polling_interval_CFG, "polling_interval", activation_CFG_SECTION, 0, CFG_TYPE_INT, DEFAULT_INTERVAL, vsn(2, 2, 63), NULL, 0, NULL,
cfg(activation_polling_interval_CFG, "polling_interval", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_INTERVAL, vsn(2, 2, 63), NULL, 0, NULL,
"Check pvmove or lvconvert progress at this interval (seconds).\n"
"When pvmove or lvconvert must wait for the kernel to finish\n"
"synchronising or merging data, they check and report progress at\n"
@@ -1625,7 +1679,7 @@ cfg(activation_auto_set_activation_skip_CFG, "auto_set_activation_skip", activat
"flag set. When this setting is enabled, the activation skip flag is\n"
"set on new thin snapshot LVs.\n")
cfg(activation_mode_CFG, "activation_mode", activation_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_ACTIVATION_MODE, vsn(2,2,108), NULL, 0, NULL,
cfg(activation_mode_CFG, "activation_mode", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_ACTIVATION_MODE, vsn(2,2,108), NULL, 0, NULL,
"How LVs with missing devices are activated.\n"
"The --activationmode option overrides this setting.\n"
"#\n"
@@ -1722,7 +1776,7 @@ cfg(metadata_pvmetadataignore_CFG, "pvmetadataignore", metadata_CFG_SECTION, CFG
cfg(metadata_stripesize_CFG, "stripesize", metadata_CFG_SECTION, CFG_ADVANCED | CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_STRIPESIZE, vsn(1, 0, 0), NULL, 0, NULL, NULL)
cfg_array(metadata_dirs_CFG, "dirs", metadata_CFG_SECTION, CFG_ADVANCED | CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(1, 0, 0), NULL, vsn(2, 3, 0), NULL,
"This setting is no longer used.\n")
NULL)
cfg_section(metadata_disk_areas_CFG_SUBSECTION, "disk_areas", metadata_CFG_SECTION, CFG_UNSUPPORTED | CFG_DEFAULT_COMMENTED, vsn(1, 0, 0), vsn(2, 3, 0), NULL, NULL)
cfg_section(disk_area_CFG_SUBSECTION, "disk_area", metadata_disk_areas_CFG_SUBSECTION, CFG_NAME_VARIABLE | CFG_UNSUPPORTED | CFG_DEFAULT_COMMENTED, vsn(1, 0, 0), vsn(2, 3, 0), NULL, NULL)
@@ -2047,7 +2101,7 @@ cfg(report_two_word_unknown_device_CFG, "two_word_unknown_device", report_CFG_SE
"Use the two words 'unknown device' in place of '[unknown]'.\n"
"This is displayed when the device for a PV is not known.\n")
cfg(dmeventd_mirror_library_CFG, "mirror_library", dmeventd_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_DMEVENTD_MIRROR_LIB, vsn(1, 2, 3), NULL, 0, NULL,
cfg(dmeventd_mirror_library_CFG, "mirror_library", dmeventd_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_DMEVENTD_MIRROR_LIB, vsn(1, 2, 3), NULL, 0, NULL,
"The library dmeventd uses when monitoring a mirror device.\n"
"libdevmapper-event-lvm2mirror.so attempts to recover from\n"
"failures. It removes failed devices from a volume group and\n"
@@ -2056,13 +2110,13 @@ cfg(dmeventd_mirror_library_CFG, "mirror_library", dmeventd_CFG_SECTION, 0, CFG_
cfg(dmeventd_raid_library_CFG, "raid_library", dmeventd_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_DMEVENTD_RAID_LIB, vsn(2, 2, 87), NULL, 0, NULL, NULL)
cfg(dmeventd_snapshot_library_CFG, "snapshot_library", dmeventd_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_DMEVENTD_SNAPSHOT_LIB, vsn(1, 2, 26), NULL, 0, NULL,
cfg(dmeventd_snapshot_library_CFG, "snapshot_library", dmeventd_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_DMEVENTD_SNAPSHOT_LIB, vsn(1, 2, 26), NULL, 0, NULL,
"The library dmeventd uses when monitoring a snapshot device.\n"
"libdevmapper-event-lvm2snapshot.so monitors the filling of snapshots\n"
"and emits a warning through syslog when the usage exceeds 80%. The\n"
"warning is repeated when 85%, 90% and 95% of the snapshot is filled.\n")
cfg(dmeventd_thin_library_CFG, "thin_library", dmeventd_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_DMEVENTD_THIN_LIB, vsn(2, 2, 89), NULL, 0, NULL,
cfg(dmeventd_thin_library_CFG, "thin_library", dmeventd_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_DMEVENTD_THIN_LIB, vsn(2, 2, 89), NULL, 0, NULL,
"The library dmeventd uses when monitoring a thin device.\n"
"libdevmapper-event-lvm2thin.so monitors the filling of a pool\n"
"and emits a warning through syslog when the usage exceeds 80%. The\n"
@@ -2148,4 +2202,4 @@ cfg(local_host_id_CFG, "host_id", local_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_
"This must be unique among all hosts, and must be between 1 and 2000.\n"
"Applicable only if LVM is compiled with lockd support\n")
cfg(CFG_COUNT, NULL, root_CFG_SECTION, 0, CFG_TYPE_INT, 0, vsn(0, 0, 0), NULL, 0, NULL, NULL)
cfg(CFG_COUNT, NULL, root_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, 0, vsn(0, 0, 0), NULL, 0, NULL, NULL)

View File

@@ -42,7 +42,7 @@
#define DEFAULT_DEV_DIR "/dev"
#define DEFAULT_PROC_DIR "/proc"
#define DEFAULT_SYSTEM_ID_SOURCE "none"
#define DEFAULT_OBTAIN_DEVICE_LIST_FROM_UDEV 1
#define DEFAULT_OBTAIN_DEVICE_LIST_FROM_UDEV 0
#define DEFAULT_EXTERNAL_DEVICE_INFO_SOURCE "none"
#define DEFAULT_SYSFS_SCAN 1
#define DEFAULT_MD_COMPONENT_DETECTION 1
@@ -118,6 +118,8 @@
#define DEFAULT_THIN_REPAIR_OPTION1 ""
#define DEFAULT_THIN_REPAIR_OPTIONS_CONFIG "#S" DEFAULT_THIN_REPAIR_OPTION1
#define DEFAULT_THIN_POOL_METADATA_REQUIRE_SEPARATE_PVS 0
#define DEFAULT_THIN_POOL_CROP_METADATA 0
#define DEFAULT_THIN_POOL_MAX_METADATA_SIZE_V1_KB (UINT64_C(255) * ((1 << 14) - 64) * 4) /* KB */ /* 0x3f8040 blocks */
#define DEFAULT_THIN_POOL_MAX_METADATA_SIZE (DM_THIN_MAX_METADATA_SIZE / 2) /* KB */
#define DEFAULT_THIN_POOL_MIN_METADATA_SIZE 2048 /* KB */
#define DEFAULT_THIN_POOL_OPTIMAL_METADATA_SIZE (128 * 1024) /* KB */
@@ -129,6 +131,7 @@
#define DEFAULT_THIN_POOL_DISCARDS "passdown"
#define DEFAULT_THIN_POOL_ZERO 1
#define DEFAULT_POOL_METADATA_SPARE 1 /* thin + cache */
#define DEFAULT_ZERO_METADATA 1 /* thin + cache */
#ifdef CACHE_CHECK_NEEDS_CHECK
# define DEFAULT_CACHE_CHECK_OPTION1 "-q"
@@ -178,8 +181,7 @@
* VDO pool will reverve some sectors in the front and the back of pool device to avoid
* seeing same device twice in the system.
*/
#define DEFAULT_VDO_POOL_HEADER_SIZE (1024) // 512KiB
#define DEFAULT_VDO_POOL_HEADER_SIZE_KB (512)
#define DEFAULT_FSADM_PATH FSADM_PATH
@@ -219,7 +221,7 @@
#endif
#define DEFAULT_COMMAND_LOG_REPORT 0
#define DEFAULT_SYSLOG 1
#define DEFAULT_SYSLOG 0
#define DEFAULT_VERBOSE 0
#define DEFAULT_SILENT 0
#define DEFAULT_LOGLEVEL 0
@@ -320,4 +322,14 @@
#define DEFAULT_MD_COMPONENT_CHECKS "auto"
#define DEFAULT_DEVICES_FILE "system.devices"
#define DEFAULT_SEARCH_FOR_DEVNAMES "auto"
#define DEFAULT_WWIDS_FILE "/etc/multipath/wwids"
#define PVS_ONLINE_DIR DEFAULT_RUN_DIR "/pvs_online"
#define VGS_ONLINE_DIR DEFAULT_RUN_DIR "/vgs_online"
#define PVS_LOOKUP_DIR DEFAULT_RUN_DIR "/pvs_lookup"
#endif /* _LVM_DEFAULTS_H */

View File

@@ -218,7 +218,7 @@ struct dm_list *str_to_str_list(struct dm_pool *mem, const char *str,
return NULL;
}
p1 = p2 = str;
p1 = str;
while (*p1) {
if (!(p2 = strstr(p1, delim)))
next = p2 = str + strlen(str);

View File

@@ -39,32 +39,32 @@ static uint64_t _min(uint64_t lhs, uint64_t rhs)
//----------------------------------------------------------------
void bcache_prefetch_bytes(struct bcache *cache, int fd, uint64_t start, size_t len)
void bcache_prefetch_bytes(struct bcache *cache, int di, uint64_t start, size_t len)
{
block_address bb, be;
byte_range_to_block_range(cache, start, len, &bb, &be);
while (bb < be) {
bcache_prefetch(cache, fd, bb);
bcache_prefetch(cache, di, bb);
bb++;
}
}
//----------------------------------------------------------------
bool bcache_read_bytes(struct bcache *cache, int fd, uint64_t start, size_t len, void *data)
bool bcache_read_bytes(struct bcache *cache, int di, uint64_t start, size_t len, void *data)
{
struct block *b;
block_address bb, be;
uint64_t block_size = bcache_block_sectors(cache) << SECTOR_SHIFT;
uint64_t block_offset = start % block_size;
bcache_prefetch_bytes(cache, fd, start, len);
bcache_prefetch_bytes(cache, di, start, len);
byte_range_to_block_range(cache, start, len, &bb, &be);
for (; bb != be; bb++) {
if (!bcache_get(cache, fd, bb, 0, &b))
if (!bcache_get(cache, di, bb, 0, &b))
return false;
size_t blen = _min(block_size - block_offset, len);
@@ -79,7 +79,7 @@ bool bcache_read_bytes(struct bcache *cache, int fd, uint64_t start, size_t len,
return true;
}
bool bcache_invalidate_bytes(struct bcache *cache, int fd, uint64_t start, size_t len)
bool bcache_invalidate_bytes(struct bcache *cache, int di, uint64_t start, size_t len)
{
block_address bb, be;
bool result = true;
@@ -87,7 +87,7 @@ bool bcache_invalidate_bytes(struct bcache *cache, int fd, uint64_t start, size_
byte_range_to_block_range(cache, start, len, &bb, &be);
for (; bb != be; bb++) {
if (!bcache_invalidate(cache, fd, bb))
if (!bcache_invalidate(cache, di, bb))
result = false;
}
@@ -101,8 +101,8 @@ bool bcache_invalidate_bytes(struct bcache *cache, int fd, uint64_t start, size_
struct updater;
typedef bool (*partial_update_fn)(struct updater *u, int fd, block_address bb, uint64_t offset, size_t len);
typedef bool (*whole_update_fn)(struct updater *u, int fd, block_address bb, block_address be);
typedef bool (*partial_update_fn)(struct updater *u, int di, block_address bb, uint64_t offset, size_t len);
typedef bool (*whole_update_fn)(struct updater *u, int di, block_address bb, block_address be);
struct updater {
struct bcache *cache;
@@ -111,7 +111,7 @@ struct updater {
void *data;
};
static bool _update_bytes(struct updater *u, int fd, uint64_t start, size_t len)
static bool _update_bytes(struct updater *u, int di, uint64_t start, size_t len)
{
struct bcache *cache = u->cache;
block_address bb, be;
@@ -124,12 +124,12 @@ static bool _update_bytes(struct updater *u, int fd, uint64_t start, size_t len)
// If the last block is partial, we will require a read, so let's
// prefetch it.
if ((start + len) % block_size)
bcache_prefetch(cache, fd, (start + len) / block_size);
bcache_prefetch(cache, di, (start + len) / block_size);
// First block may be partial
if (block_offset) {
size_t blen = _min(block_size - block_offset, len);
if (!u->partial_fn(u, fd, bb, block_offset, blen))
if (!u->partial_fn(u, di, bb, block_offset, blen))
return false;
len -= blen;
@@ -141,7 +141,7 @@ static bool _update_bytes(struct updater *u, int fd, uint64_t start, size_t len)
// Now we write out a set of whole blocks
nr_whole = len / block_size;
if (!u->whole_fn(u, fd, bb, bb + nr_whole))
if (!u->whole_fn(u, di, bb, bb + nr_whole))
return false;
bb += nr_whole;
@@ -151,27 +151,29 @@ static bool _update_bytes(struct updater *u, int fd, uint64_t start, size_t len)
return true;
// Finally we write a partial end block
return u->partial_fn(u, fd, bb, 0, len);
return u->partial_fn(u, di, bb, 0, len);
}
//----------------------------------------------------------------
static bool _write_partial(struct updater *u, int fd, block_address bb,
static bool _write_partial(struct updater *u, int di, block_address bb,
uint64_t offset, size_t len)
{
struct block *b;
if (!bcache_get(u->cache, fd, bb, GF_DIRTY, &b))
if (!bcache_get(u->cache, di, bb, GF_DIRTY, &b))
return false;
memcpy(((unsigned char *) b->data) + offset, u->data, len);
u->data = ((unsigned char *) u->data) + len;
if (u->data) {
memcpy(((unsigned char *) b->data) + offset, u->data, len);
u->data = ((unsigned char *) u->data) + len;
}
bcache_put(b);
return true;
}
static bool _write_whole(struct updater *u, int fd, block_address bb, block_address be)
static bool _write_whole(struct updater *u, int di, block_address bb, block_address be)
{
struct block *b;
uint64_t block_size = bcache_block_sectors(u->cache) << SECTOR_SHIFT;
@@ -179,7 +181,7 @@ static bool _write_whole(struct updater *u, int fd, block_address bb, block_addr
for (; bb != be; bb++) {
// We don't need to read the block since we are overwriting
// it completely.
if (!bcache_get(u->cache, fd, bb, GF_ZERO, &b))
if (!bcache_get(u->cache, di, bb, GF_ZERO, &b))
return false;
memcpy(b->data, u->data, block_size);
u->data = ((unsigned char *) u->data) + block_size;
@@ -189,7 +191,7 @@ static bool _write_whole(struct updater *u, int fd, block_address bb, block_addr
return true;
}
bool bcache_write_bytes(struct bcache *cache, int fd, uint64_t start, size_t len, void *data)
bool bcache_write_bytes(struct bcache *cache, int di, uint64_t start, size_t len, void *data)
{
struct updater u;
@@ -198,16 +200,16 @@ bool bcache_write_bytes(struct bcache *cache, int fd, uint64_t start, size_t len
u.whole_fn = _write_whole;
u.data = data;
return _update_bytes(&u, fd, start, len);
return _update_bytes(&u, di, start, len);
}
//----------------------------------------------------------------
static bool _zero_partial(struct updater *u, int fd, block_address bb, uint64_t offset, size_t len)
static bool _zero_partial(struct updater *u, int di, block_address bb, uint64_t offset, size_t len)
{
struct block *b;
if (!bcache_get(u->cache, fd, bb, GF_DIRTY, &b))
if (!bcache_get(u->cache, di, bb, GF_DIRTY, &b))
return false;
memset(((unsigned char *) b->data) + offset, 0, len);
@@ -216,12 +218,12 @@ static bool _zero_partial(struct updater *u, int fd, block_address bb, uint64_t
return true;
}
static bool _zero_whole(struct updater *u, int fd, block_address bb, block_address be)
static bool _zero_whole(struct updater *u, int di, block_address bb, block_address be)
{
struct block *b;
for (; bb != be; bb++) {
if (!bcache_get(u->cache, fd, bb, GF_ZERO, &b))
if (!bcache_get(u->cache, di, bb, GF_ZERO, &b))
return false;
bcache_put(b);
}
@@ -229,7 +231,7 @@ static bool _zero_whole(struct updater *u, int fd, block_address bb, block_addre
return true;
}
bool bcache_zero_bytes(struct bcache *cache, int fd, uint64_t start, size_t len)
bool bcache_zero_bytes(struct bcache *cache, int di, uint64_t start, size_t len)
{
struct updater u;
@@ -238,17 +240,17 @@ bool bcache_zero_bytes(struct bcache *cache, int fd, uint64_t start, size_t len)
u.whole_fn = _zero_whole;
u.data = NULL;
return _update_bytes(&u, fd, start, len);
return _update_bytes(&u, di, start, len);
}
//----------------------------------------------------------------
static bool _set_partial(struct updater *u, int fd, block_address bb, uint64_t offset, size_t len)
static bool _set_partial(struct updater *u, int di, block_address bb, uint64_t offset, size_t len)
{
struct block *b;
uint8_t val = *((uint8_t *) u->data);
uint8_t val = (u->data) ? *((uint8_t *) u->data) : 0;
if (!bcache_get(u->cache, fd, bb, GF_DIRTY, &b))
if (!bcache_get(u->cache, di, bb, GF_DIRTY, &b))
return false;
memset(((unsigned char *) b->data) + offset, val, len);
@@ -257,14 +259,14 @@ static bool _set_partial(struct updater *u, int fd, block_address bb, uint64_t o
return true;
}
static bool _set_whole(struct updater *u, int fd, block_address bb, block_address be)
static bool _set_whole(struct updater *u, int di, block_address bb, block_address be)
{
struct block *b;
uint8_t val = *((uint8_t *) u->data);
uint8_t val = (u->data) ? *((uint8_t *) u->data) : 0;
uint64_t len = bcache_block_sectors(u->cache) * 512;
for (; bb != be; bb++) {
if (!bcache_get(u->cache, fd, bb, GF_ZERO, &b))
if (!bcache_get(u->cache, di, bb, GF_ZERO, &b))
return false;
memset((unsigned char *) b->data, val, len);
bcache_put(b);
@@ -273,7 +275,7 @@ static bool _set_whole(struct updater *u, int fd, block_address bb, block_addres
return true;
}
bool bcache_set_bytes(struct bcache *cache, int fd, uint64_t start, size_t len, uint8_t val)
bool bcache_set_bytes(struct bcache *cache, int di, uint64_t start, size_t len, uint8_t val)
{
struct updater u;
@@ -282,6 +284,6 @@ bool bcache_set_bytes(struct bcache *cache, int fd, uint64_t start, size_t len,
u.whole_fn = _set_whole;
u.data = &val;
return _update_bytes(&u, fd, start, len);
return _update_bytes(&u, di, start, len);
}

View File

@@ -33,11 +33,16 @@
#define SECTOR_SHIFT 9L
#define FD_TABLE_INC 1024
static int _fd_table_size;
static int *_fd_table;
//----------------------------------------------------------------
static void log_sys_warn(const char *call)
{
log_warn("%s failed: %s", call, strerror(errno));
log_warn("WARNING: %s failed: %s.", call, strerror(errno));
}
// Assumes the list is not empty.
@@ -61,23 +66,17 @@ struct control_block {
struct cb_set {
struct dm_list free;
struct dm_list allocated;
struct control_block *vec;
struct control_block vec[];
} control_block_set;
static struct cb_set *_cb_set_create(unsigned nr)
{
int i;
struct cb_set *cbs = malloc(sizeof(*cbs));
unsigned i;
struct cb_set *cbs = malloc(sizeof(*cbs) + nr * sizeof(*cbs->vec));
if (!cbs)
return NULL;
cbs->vec = malloc(nr * sizeof(*cbs->vec));
if (!cbs->vec) {
free(cbs);
return NULL;
}
dm_list_init(&cbs->free);
dm_list_init(&cbs->allocated);
@@ -93,11 +92,10 @@ static void _cb_set_destroy(struct cb_set *cbs)
// never be in flight IO.
if (!dm_list_empty(&cbs->allocated)) {
// bail out
log_error("async io still in flight");
log_warn("WARNING: async io still in flight.");
return;
}
free(cbs->vec);
free(cbs);
}
@@ -155,11 +153,11 @@ static void _async_destroy(struct io_engine *ioe)
free(e);
}
static int _last_byte_fd;
static int _last_byte_di;
static uint64_t _last_byte_offset;
static int _last_byte_sector_size;
static bool _async_issue(struct io_engine *ioe, enum dir d, int fd,
static bool _async_issue(struct io_engine *ioe, enum dir d, int di,
sector_t sb, sector_t se, void *data, void *context)
{
int r;
@@ -183,7 +181,7 @@ static bool _async_issue(struct io_engine *ioe, enum dir d, int fd,
/*
* If bcache block goes past where lvm wants to write, then clamp it.
*/
if ((d == DIR_WRITE) && _last_byte_offset && (fd == _last_byte_fd)) {
if ((d == DIR_WRITE) && _last_byte_offset && (di == _last_byte_di)) {
if (offset > _last_byte_offset) {
log_error("Limit write at %llu len %llu beyond last byte %llu",
(unsigned long long)offset,
@@ -268,7 +266,7 @@ static bool _async_issue(struct io_engine *ioe, enum dir d, int fd,
memset(&cb->cb, 0, sizeof(cb->cb));
cb->cb.aio_fildes = (int) fd;
cb->cb.aio_fildes = (int) _fd_table[di];
cb->cb.u.c.buf = data;
cb->cb.u.c.offset = offset;
cb->cb.u.c.nbytes = nbytes;
@@ -276,13 +274,15 @@ static bool _async_issue(struct io_engine *ioe, enum dir d, int fd,
#if 0
if (d == DIR_READ) {
log_debug("io R off %llu bytes %llu",
log_debug("io R off %llu bytes %llu di %d fd %d",
(unsigned long long)cb->cb.u.c.offset,
(unsigned long long)cb->cb.u.c.nbytes);
(unsigned long long)cb->cb.u.c.nbytes,
di, _fd_table[di]);
} else {
log_debug("io W off %llu bytes %llu",
log_debug("io W off %llu bytes %llu di %d fd %d",
(unsigned long long)cb->cb.u.c.offset,
(unsigned long long)cb->cb.u.c.nbytes);
(unsigned long long)cb->cb.u.c.nbytes,
di, _fd_table[di]);
}
#endif
@@ -318,9 +318,7 @@ static bool _async_wait(struct io_engine *ioe, io_complete_fn fn)
struct async_engine *e = _to_async(ioe);
memset(&event, 0, sizeof(event));
do {
r = io_getevents(e->aio_context, 1, MAX_EVENT, event, NULL);
} while (r == -EINTR);
r = io_getevents(e->aio_context, 1, MAX_EVENT, event, NULL);
if (r < 0) {
log_sys_warn("io_getevents");
@@ -360,10 +358,16 @@ static unsigned _async_max_io(struct io_engine *e)
struct io_engine *create_async_io_engine(void)
{
static int _pagesize = 0;
int r;
struct async_engine *e = malloc(sizeof(*e));
struct async_engine *e;
if (!e)
if ((_pagesize <= 0) && (_pagesize = sysconf(_SC_PAGESIZE)) < 0) {
log_warn("_SC_PAGESIZE returns negative value.");
return NULL;
}
if (!(e = malloc(sizeof(*e))))
return NULL;
e->e.destroy = _async_destroy;
@@ -386,8 +390,9 @@ struct io_engine *create_async_io_engine(void)
return NULL;
}
e->page_mask = sysconf(_SC_PAGESIZE) - 1;
e->page_mask = (unsigned) _pagesize - 1;
/* coverity[leaked_storage] 'e' is not leaking */
return &e->e;
}
@@ -414,7 +419,7 @@ static void _sync_destroy(struct io_engine *ioe)
free(e);
}
static bool _sync_issue(struct io_engine *ioe, enum dir d, int fd,
static bool _sync_issue(struct io_engine *ioe, enum dir d, int di,
sector_t sb, sector_t se, void *data, void *context)
{
int rv;
@@ -430,7 +435,7 @@ static bool _sync_issue(struct io_engine *ioe, enum dir d, int fd,
}
where = sb * 512;
off = lseek(fd, where, SEEK_SET);
off = lseek(_fd_table[di], where, SEEK_SET);
if (off == (off_t) -1) {
log_warn("Device seek error %d for offset %llu", errno, (unsigned long long)where);
free(io);
@@ -445,7 +450,7 @@ static bool _sync_issue(struct io_engine *ioe, enum dir d, int fd,
/*
* If bcache block goes past where lvm wants to write, then clamp it.
*/
if ((d == DIR_WRITE) && _last_byte_offset && (fd == _last_byte_fd)) {
if ((d == DIR_WRITE) && _last_byte_offset && (di == _last_byte_di)) {
uint64_t offset = where;
uint64_t nbytes = len;
sector_t limit_nbytes = 0;
@@ -526,9 +531,9 @@ static bool _sync_issue(struct io_engine *ioe, enum dir d, int fd,
while (pos < len) {
if (d == DIR_READ)
rv = read(fd, (char *)data + pos, len - pos);
rv = read(_fd_table[di], (char *)data + pos, len - pos);
else
rv = write(fd, (char *)data + pos, len - pos);
rv = write(_fd_table[di], (char *)data + pos, len - pos);
if (rv == -1 && errno == EINTR)
continue;
@@ -602,7 +607,8 @@ struct io_engine *create_sync_io_engine(void)
e->e.wait = _sync_wait;
e->e.max_io = _sync_max_io;
dm_list_init(&e->complete);
dm_list_init(&e->complete);
/* coverity[leaked_storage] 'e' is not leaking */
return &e->e;
}
@@ -688,7 +694,7 @@ struct bcache {
//----------------------------------------------------------------
struct key_parts {
uint32_t fd;
uint32_t di;
uint64_t b;
} __attribute__ ((packed));
@@ -697,12 +703,12 @@ union key {
uint8_t bytes[12];
};
static struct block *_block_lookup(struct bcache *cache, int fd, uint64_t i)
static struct block *_block_lookup(struct bcache *cache, int di, uint64_t i)
{
union key k;
union radix_value v;
k.parts.fd = fd;
k.parts.di = di;
k.parts.b = i;
if (radix_tree_lookup(cache->rtree, k.bytes, k.bytes + sizeof(k.bytes), &v))
@@ -716,7 +722,7 @@ static bool _block_insert(struct block *b)
union key k;
union radix_value v;
k.parts.fd = b->fd;
k.parts.di = b->di;
k.parts.b = b->index;
v.ptr = b;
@@ -727,10 +733,10 @@ static void _block_remove(struct block *b)
{
union key k;
k.parts.fd = b->fd;
k.parts.di = b->di;
k.parts.b = b->index;
radix_tree_remove(b->cache->rtree, k.bytes, k.bytes + sizeof(k.bytes));
(void) radix_tree_remove(b->cache->rtree, k.bytes, k.bytes + sizeof(k.bytes));
}
//----------------------------------------------------------------
@@ -869,7 +875,7 @@ static void _issue_low_level(struct block *b, enum dir d)
dm_list_move(&cache->io_pending, &b->list);
if (!cache->engine->issue(cache->engine, d, b->fd, sb, se, b->data, b)) {
if (!cache->engine->issue(cache->engine, d, b->di, sb, se, b->data, b)) {
/* FIXME: if io_submit() set an errno, return that instead of EIO? */
_complete_io(b, -EIO);
return;
@@ -945,21 +951,26 @@ static struct block *_find_unused_clean_block(struct bcache *cache)
return NULL;
}
static struct block *_new_block(struct bcache *cache, int fd, block_address i, bool can_wait)
static struct block *_new_block(struct bcache *cache, int di, block_address i, bool can_wait)
{
struct block *b;
b = _alloc_block(cache);
while (!b && !dm_list_empty(&cache->clean)) {
while (!b) {
b = _find_unused_clean_block(cache);
if (!b) {
if (can_wait) {
if (dm_list_empty(&cache->io_pending))
_writeback(cache, 16); // FIXME: magic number
_wait_io(cache);
_wait_all(cache);
if (dm_list_size(&cache->errored) >= cache->max_io) {
log_debug("bcache no new blocks for di %d index %u with >%d errors.",
di, (uint32_t) i, cache->max_io);
return NULL;
}
} else {
log_debug("bcache no new blocks for fd %d index %u",
fd, (uint32_t) i);
log_debug("bcache no new blocks for di %d index %u",
di, (uint32_t) i);
return NULL;
}
}
@@ -968,7 +979,7 @@ static struct block *_new_block(struct bcache *cache, int fd, block_address i, b
if (b) {
dm_list_init(&b->list);
b->flags = 0;
b->fd = fd;
b->di = di;
b->index = i;
b->ref_count = 0;
b->error = 0;
@@ -1014,10 +1025,10 @@ static void _miss(struct bcache *cache, unsigned flags)
}
static struct block *_lookup_or_read_block(struct bcache *cache,
int fd, block_address i,
int di, block_address i,
unsigned flags)
{
struct block *b = _block_lookup(cache, fd, i);
struct block *b = _block_lookup(cache, di, i);
if (b) {
// FIXME: this is insufficient. We need to also catch a read
@@ -1042,7 +1053,7 @@ static struct block *_lookup_or_read_block(struct bcache *cache,
} else {
_miss(cache, flags);
b = _new_block(cache, fd, i, true);
b = _new_block(cache, di, i, true);
if (b) {
if (flags & GF_ZERO)
_zero_block(b);
@@ -1084,11 +1095,12 @@ static void _preemptive_writeback(struct bcache *cache)
struct bcache *bcache_create(sector_t block_sectors, unsigned nr_cache_blocks,
struct io_engine *engine)
{
static long _pagesize = 0;
struct bcache *cache;
unsigned max_io = engine->max_io(engine);
long pgsize = sysconf(_SC_PAGESIZE);
int i;
if (pgsize < 0) {
if ((_pagesize <= 0) && ((_pagesize = sysconf(_SC_PAGESIZE)) < 0)) {
log_warn("WARNING: _SC_PAGESIZE returns negative value.");
return NULL;
}
@@ -1103,7 +1115,7 @@ struct bcache *bcache_create(sector_t block_sectors, unsigned nr_cache_blocks,
return NULL;
}
if (block_sectors & ((pgsize >> SECTOR_SHIFT) - 1)) {
if (block_sectors & ((_pagesize >> SECTOR_SHIFT) - 1)) {
log_warn("bcache block size must be a multiple of page size");
return NULL;
}
@@ -1140,13 +1152,25 @@ struct bcache *bcache_create(sector_t block_sectors, unsigned nr_cache_blocks,
cache->write_misses = 0;
cache->prefetches = 0;
if (!_init_free_list(cache, nr_cache_blocks, pgsize)) {
if (!_init_free_list(cache, nr_cache_blocks, _pagesize)) {
cache->engine->destroy(cache->engine);
radix_tree_destroy(cache->rtree);
free(cache);
return NULL;
}
_fd_table_size = FD_TABLE_INC;
if (!(_fd_table = malloc(sizeof(int) * _fd_table_size))) {
cache->engine->destroy(cache->engine);
radix_tree_destroy(cache->rtree);
free(cache);
return NULL;
}
for (i = 0; i < _fd_table_size; i++)
_fd_table[i] = -1;
return cache;
}
@@ -1162,6 +1186,9 @@ void bcache_destroy(struct bcache *cache)
radix_tree_destroy(cache->rtree);
cache->engine->destroy(cache->engine);
free(cache);
free(_fd_table);
_fd_table = NULL;
_fd_table_size = 0;
}
sector_t bcache_block_sectors(struct bcache *cache)
@@ -1179,13 +1206,13 @@ unsigned bcache_max_prefetches(struct bcache *cache)
return cache->max_io;
}
void bcache_prefetch(struct bcache *cache, int fd, block_address i)
void bcache_prefetch(struct bcache *cache, int di, block_address i)
{
struct block *b = _block_lookup(cache, fd, i);
struct block *b = _block_lookup(cache, di, i);
if (!b) {
if (cache->nr_io_pending < cache->max_io) {
b = _new_block(cache, fd, i, false);
b = _new_block(cache, di, i, false);
if (b) {
cache->prefetches++;
_issue_read(b);
@@ -1203,12 +1230,15 @@ static void _recycle_block(struct bcache *cache, struct block *b)
_free_block(b);
}
bool bcache_get(struct bcache *cache, int fd, block_address i,
bool bcache_get(struct bcache *cache, int di, block_address i,
unsigned flags, struct block **result)
{
struct block *b;
b = _lookup_or_read_block(cache, fd, i, flags);
if (di >= _fd_table_size)
goto bad;
b = _lookup_or_read_block(cache, di, i, flags);
if (b) {
if (b->error) {
if (b->io_dir == DIR_READ) {
@@ -1227,10 +1257,10 @@ bool bcache_get(struct bcache *cache, int fd, block_address i,
*result = b;
return true;
}
bad:
*result = NULL;
log_error("bcache failed to get block %u fd %d", (uint32_t) i, fd);
log_error("bcache failed to get block %u di %d", (uint32_t) i, di);
return false;
}
@@ -1294,7 +1324,7 @@ static bool _invalidate_block(struct bcache *cache, struct block *b)
if (b->ref_count) {
log_warn("bcache_invalidate: block (%d, %llu) still held",
b->fd, (unsigned long long) b->index);
b->di, (unsigned long long) b->index);
return false;
}
@@ -1311,9 +1341,9 @@ static bool _invalidate_block(struct bcache *cache, struct block *b)
return true;
}
bool bcache_invalidate(struct bcache *cache, int fd, block_address i)
bool bcache_invalidate(struct bcache *cache, int di, block_address i)
{
return _invalidate_block(cache, _block_lookup(cache, fd, i));
return _invalidate_block(cache, _block_lookup(cache, di, i));
}
//----------------------------------------------------------------
@@ -1329,27 +1359,27 @@ static bool _writeback_v(struct radix_tree_iterator *it,
struct block *b = v.ptr;
if (_test_flags(b, BF_DIRTY))
_issue_write(b);
_issue_write(b);
return true;
return true;
}
static bool _invalidate_v(struct radix_tree_iterator *it,
uint8_t *kb, uint8_t *ke, union radix_value v)
{
struct block *b = v.ptr;
struct invalidate_iterator *iit = container_of(it, struct invalidate_iterator, it);
struct invalidate_iterator *iit = container_of(it, struct invalidate_iterator, it);
if (b->error || _test_flags(b, BF_DIRTY)) {
log_warn("bcache_invalidate: block (%d, %llu) still dirty",
b->fd, (unsigned long long) b->index);
iit->success = false;
return true;
log_warn("WARNING: bcache_invalidate: block (%d, %llu) still dirty.",
b->di, (unsigned long long) b->index);
iit->success = false;
return true;
}
if (b->ref_count) {
log_warn("bcache_invalidate: block (%d, %llu) still held",
b->fd, (unsigned long long) b->index);
log_warn("WARNING: bcache_invalidate: block (%d, %llu) still held.",
b->di, (unsigned long long) b->index);
iit->success = false;
return true;
}
@@ -1362,24 +1392,24 @@ static bool _invalidate_v(struct radix_tree_iterator *it,
return true;
}
bool bcache_invalidate_fd(struct bcache *cache, int fd)
bool bcache_invalidate_di(struct bcache *cache, int di)
{
union key k;
union key k;
struct invalidate_iterator it;
k.parts.fd = fd;
k.parts.di = di;
it.it.visit = _writeback_v;
radix_tree_iterate(cache->rtree, k.bytes, k.bytes + sizeof(k.parts.fd), &it.it);
radix_tree_iterate(cache->rtree, k.bytes, k.bytes + sizeof(k.parts.di), &it.it);
_wait_all(cache);
it.success = true;
it.it.visit = _invalidate_v;
radix_tree_iterate(cache->rtree, k.bytes, k.bytes + sizeof(k.parts.fd), &it.it);
radix_tree_iterate(cache->rtree, k.bytes, k.bytes + sizeof(k.parts.di), &it.it);
if (it.success)
radix_tree_remove_prefix(cache->rtree, k.bytes, k.bytes + sizeof(k.parts.fd));
(void) radix_tree_remove_prefix(cache->rtree, k.bytes, k.bytes + sizeof(k.parts.di));
return it.success;
}
@@ -1393,7 +1423,7 @@ static bool _abort_v(struct radix_tree_iterator *it,
if (b->ref_count) {
log_fatal("bcache_abort: block (%d, %llu) still held",
b->fd, (unsigned long long) b->index);
b->di, (unsigned long long) b->index);
return true;
}
@@ -1405,35 +1435,94 @@ static bool _abort_v(struct radix_tree_iterator *it,
return true;
}
void bcache_abort_fd(struct bcache *cache, int fd)
void bcache_abort_di(struct bcache *cache, int di)
{
union key k;
union key k;
struct radix_tree_iterator it;
k.parts.fd = fd;
k.parts.di = di;
it.visit = _abort_v;
radix_tree_iterate(cache->rtree, k.bytes, k.bytes + sizeof(k.parts.fd), &it);
radix_tree_remove_prefix(cache->rtree, k.bytes, k.bytes + sizeof(k.parts.fd));
radix_tree_iterate(cache->rtree, k.bytes, k.bytes + sizeof(k.parts.di), &it);
(void) radix_tree_remove_prefix(cache->rtree, k.bytes, k.bytes + sizeof(k.parts.di));
}
//----------------------------------------------------------------
void bcache_set_last_byte(struct bcache *cache, int fd, uint64_t offset, int sector_size)
void bcache_set_last_byte(struct bcache *cache, int di, uint64_t offset, int sector_size)
{
_last_byte_fd = fd;
_last_byte_di = di;
_last_byte_offset = offset;
_last_byte_sector_size = sector_size;
if (!sector_size)
_last_byte_sector_size = 512;
}
void bcache_unset_last_byte(struct bcache *cache, int fd)
void bcache_unset_last_byte(struct bcache *cache, int di)
{
if (_last_byte_fd == fd) {
_last_byte_fd = 0;
if (_last_byte_di == di) {
_last_byte_di = 0;
_last_byte_offset = 0;
_last_byte_sector_size = 0;
}
}
int bcache_set_fd(int fd)
{
int *new_table = NULL;
int new_size = 0;
int i;
retry:
for (i = 0; i < _fd_table_size; i++) {
if (_fd_table[i] == -1) {
_fd_table[i] = fd;
return i;
}
}
/* already tried once, shouldn't happen */
if (new_size)
return -1;
new_size = _fd_table_size + FD_TABLE_INC;
new_table = realloc(_fd_table, sizeof(int) * new_size);
if (!new_table) {
log_error("Cannot extend bcache fd table");
return -1;
}
for (i = _fd_table_size; i < new_size; i++)
new_table[i] = -1;
_fd_table = new_table;
_fd_table_size = new_size;
goto retry;
}
/*
* Should we check for unflushed or inprogress io on an fd
* prior to doing clear_fd or change_fd? (To catch mistakes;
* the caller should be smart enough to not do that.)
*/
void bcache_clear_fd(int di)
{
if (di >= _fd_table_size)
return;
_fd_table[di] = -1;
}
int bcache_change_fd(int di, int fd)
{
if (di >= _fd_table_size)
return 0;
if (di < 0) {
log_error(INTERNAL_ERROR "Cannot change not opened DI with FD:%d", fd);
return 0;
}
_fd_table[di] = fd;
return 1;
}

View File

@@ -16,19 +16,12 @@
#define BCACHE_H
#include "device_mapper/all.h"
#include "base/memory/container_of.h"
#include <linux/fs.h>
#include <stdint.h>
#include <stdbool.h>
/*----------------------------------------------------------------*/
// FIXME: move somewhere more sensible
#define container_of(v, t, head) \
((t *)((const char *)(v) - (const char *)&((t *) 0)->head))
/*----------------------------------------------------------------*/
enum dir {
DIR_READ,
DIR_WRITE
@@ -41,7 +34,7 @@ typedef void io_complete_fn(void *context, int io_error);
struct io_engine {
void (*destroy)(struct io_engine *e);
bool (*issue)(struct io_engine *e, enum dir d, int fd,
bool (*issue)(struct io_engine *e, enum dir d, int di,
sector_t sb, sector_t se, void *data, void *context);
bool (*wait)(struct io_engine *e, io_complete_fn fn);
unsigned (*max_io)(struct io_engine *e);
@@ -55,7 +48,7 @@ struct io_engine *create_sync_io_engine(void);
struct bcache;
struct block {
/* clients may only access these three fields */
int fd;
int di;
uint64_t index;
void *data;
@@ -113,12 +106,12 @@ unsigned bcache_max_prefetches(struct bcache *cache);
* they complete. But we're talking a very small difference, and it's worth it
* to keep callbacks out of this interface.
*/
void bcache_prefetch(struct bcache *cache, int fd, block_address index);
void bcache_prefetch(struct bcache *cache, int di, block_address index);
/*
* Returns true on success.
*/
bool bcache_get(struct bcache *cache, int fd, block_address index,
bool bcache_get(struct bcache *cache, int di, block_address index,
unsigned flags, struct block **result);
void bcache_put(struct block *b);
@@ -136,38 +129,42 @@ bool bcache_flush(struct bcache *cache);
*
* If the block is currently held false will be returned.
*/
bool bcache_invalidate(struct bcache *cache, int fd, block_address index);
bool bcache_invalidate(struct bcache *cache, int di, block_address index);
/*
* Invalidates all blocks on the given descriptor. Call this before closing
* the descriptor to make sure everything is written back.
*/
bool bcache_invalidate_fd(struct bcache *cache, int fd);
bool bcache_invalidate_di(struct bcache *cache, int di);
/*
* Call this function if flush, or invalidate fail and you do not
* wish to retry the writes. This will throw away any dirty data
* not written. If any blocks for fd are held, then it will call
* not written. If any blocks for di are held, then it will call
* abort().
*/
void bcache_abort_fd(struct bcache *cache, int fd);
void bcache_abort_di(struct bcache *cache, int di);
//----------------------------------------------------------------
// The next four functions are utilities written in terms of the above api.
// Prefetches the blocks neccessary to satisfy a byte range.
void bcache_prefetch_bytes(struct bcache *cache, int fd, uint64_t start, size_t len);
void bcache_prefetch_bytes(struct bcache *cache, int di, uint64_t start, size_t len);
// Reads, writes and zeroes bytes. Returns false if errors occur.
bool bcache_read_bytes(struct bcache *cache, int fd, uint64_t start, size_t len, void *data);
bool bcache_write_bytes(struct bcache *cache, int fd, uint64_t start, size_t len, void *data);
bool bcache_zero_bytes(struct bcache *cache, int fd, uint64_t start, size_t len);
bool bcache_set_bytes(struct bcache *cache, int fd, uint64_t start, size_t len, uint8_t val);
bool bcache_invalidate_bytes(struct bcache *cache, int fd, uint64_t start, size_t len);
bool bcache_read_bytes(struct bcache *cache, int di, uint64_t start, size_t len, void *data);
bool bcache_write_bytes(struct bcache *cache, int di, uint64_t start, size_t len, void *data);
bool bcache_zero_bytes(struct bcache *cache, int di, uint64_t start, size_t len);
bool bcache_set_bytes(struct bcache *cache, int di, uint64_t start, size_t len, uint8_t val);
bool bcache_invalidate_bytes(struct bcache *cache, int di, uint64_t start, size_t len);
void bcache_set_last_byte(struct bcache *cache, int fd, uint64_t offset, int sector_size);
void bcache_unset_last_byte(struct bcache *cache, int fd);
void bcache_set_last_byte(struct bcache *cache, int di, uint64_t offset, int sector_size);
void bcache_unset_last_byte(struct bcache *cache, int di);
//----------------------------------------------------------------
int bcache_set_fd(int fd); /* returns di */
void bcache_clear_fd(int di);
int bcache_change_fd(int di, int fd);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -28,13 +28,12 @@ struct cmd_context;
struct dev_filter {
int (*passes_filter) (struct cmd_context *cmd, struct dev_filter *f, struct device *dev, const char *use_filter_name);
void (*destroy) (struct dev_filter *f);
void (*wipe) (struct dev_filter *f);
void (*wipe) (struct cmd_context *cmd, struct dev_filter *f, struct device *dev, const char *use_filter_name);
void *private;
unsigned use_count;
const char *name;
};
int dev_cache_index_devs(void);
struct dm_list *dev_cache_get_dev_list_for_vgid(const char *vgid);
struct dm_list *dev_cache_get_dev_list_for_lvid(const char *lvid);
@@ -49,14 +48,15 @@ int dev_cache_exit(void);
*/
int dev_cache_check_for_open_devices(void);
void dev_cache_scan(void);
void dev_cache_scan(struct cmd_context *cmd);
int dev_cache_has_scanned(void);
int dev_cache_add_dir(const char *path);
struct device *dev_cache_get(struct cmd_context *cmd, const char *name, struct dev_filter *f);
const char *dev_cache_filtered_reason(const char *name);
struct device *dev_cache_get_existing(struct cmd_context *cmd, const char *name, struct dev_filter *f);
struct device *dev_cache_get_by_devt(struct cmd_context *cmd, dev_t devt);
struct device *dev_cache_get_by_devt(struct cmd_context *cmd, dev_t device, struct dev_filter *f, int *filtered);
struct device *dev_hash_get(const char *name);
void dev_set_preferred_name(struct dm_str_list *sl, struct device *dev);
@@ -68,10 +68,20 @@ struct dev_iter *dev_iter_create(struct dev_filter *f, int unused);
void dev_iter_destroy(struct dev_iter *iter);
struct device *dev_iter_get(struct cmd_context *cmd, struct dev_iter *iter);
void dev_reset_error_count(struct cmd_context *cmd);
void dev_cache_failed_path(struct device *dev, const char *path);
bool dev_cache_has_md_with_end_superblock(struct dev_types *dt);
int get_sysfs_value(const char *path, char *buf, size_t buf_size, int error_if_no_value);
int get_dm_uuid_from_sysfs(char *buf, size_t buf_size, int major, int minor);
int setup_devices_file(struct cmd_context *cmd);
int setup_devices(struct cmd_context *cmd);
int setup_device(struct cmd_context *cmd, const char *devname);
int setup_devices_for_online_autoactivation(struct cmd_context *cmd);
int setup_devname_in_dev_cache(struct cmd_context *cmd, const char *devname);
int setup_devno_in_dev_cache(struct cmd_context *cmd, dev_t devno);
struct device *setup_dev_in_dev_cache(struct cmd_context *cmd, dev_t devno, const char *devname);
#endif

View File

@@ -81,7 +81,7 @@ typedef struct dasd_information2_t {
int dasd_is_cdl_formatted(struct device *dev)
{
int ret = 0;
dasd_information2_t dasd_info2;
dasd_information2_t dasd_info2 = { 0 };
if (!dev_open_readonly(dev))
return_0;

View File

@@ -58,6 +58,9 @@ static int _dev_get_size_file(struct device *dev, uint64_t *size)
const char *name = dev_name(dev);
struct stat info;
if (dm_list_empty(&dev->aliases))
return_0;
if (dev->size_seqno == _dev_size_seqno) {
log_very_verbose("%s: using cached size %" PRIu64 " sectors",
name, dev->size);
@@ -86,6 +89,9 @@ static int _dev_get_size_dev(struct device *dev, uint64_t *size)
int fd = dev->bcache_fd;
int do_close = 0;
if (dm_list_empty(&dev->aliases))
return_0;
if (dev->size_seqno == _dev_size_seqno) {
log_very_verbose("%s: using cached size %" PRIu64 " sectors",
name, dev->size);
@@ -94,16 +100,16 @@ static int _dev_get_size_dev(struct device *dev, uint64_t *size)
}
if (fd <= 0) {
if (!dev_open_readonly(dev))
if (!dev_open_readonly_quiet(dev))
return_0;
fd = dev_fd(dev);
do_close = 1;
}
if (ioctl(fd, BLKGETSIZE64, size) < 0) {
log_sys_error("ioctl BLKGETSIZE64", name);
log_warn("WARNING: %s: ioctl BLKGETSIZE64 %s", name, strerror(errno));
if (do_close && !dev_close_immediate(dev))
log_sys_error("close", name);
stack;
return 0;
}
@@ -114,25 +120,28 @@ 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_immediate(dev))
log_sys_error("close", name);
stack;
return 1;
}
static int _dev_read_ahead_dev(struct device *dev, uint32_t *read_ahead)
{
long read_ahead_long;
long read_ahead_long = 0;
if (dev->read_ahead != -1) {
*read_ahead = (uint32_t) dev->read_ahead;
return 1;
}
if (!dev_open_readonly(dev))
return_0;
if (!dev_open_readonly_quiet(dev)) {
log_warn("WARNING: Failed to open %s to get readahead %s.",
dev_name(dev), strerror(errno));
return 0;
}
if (ioctl(dev->fd, BLKRAGET, &read_ahead_long) < 0) {
log_sys_error("ioctl BLKRAGET", dev_name(dev));
log_warn("WARNING: %s: ioctl BLKRAGET %s.", dev_name(dev), strerror(errno));
if (!dev_close_immediate(dev))
stack;
return 0;
@@ -165,7 +174,7 @@ static int _dev_discard_blocks(struct device *dev, uint64_t offset_bytes, uint64
test_mode() ? " (test mode - suppressed)" : "");
if (!test_mode() && ioctl(dev->fd, BLKDISCARD, &discard_range) < 0) {
log_error("%s: BLKDISCARD ioctl at offset %" PRIu64 " size %" PRIu64 " failed: %s.",
log_warn("WARNING: %s: ioctl BLKDISCARD at offset %" PRIu64 " size %" PRIu64 " failed: %s.",
dev_name(dev), offset_bytes, size_bytes, strerror(errno));
if (!dev_close_immediate(dev))
stack;
@@ -194,7 +203,7 @@ int dev_get_direct_block_sizes(struct device *dev, unsigned int *physical_block_
}
if (fd <= 0) {
if (!dev_open_readonly(dev))
if (!dev_open_readonly_quiet(dev))
return 0;
fd = dev_fd(dev);
do_close = 1;
@@ -299,6 +308,13 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet)
if ((flags & O_EXCL))
need_excl = 1;
if (dm_list_empty(&dev->aliases)) {
/* shouldn't happen */
log_print("Cannot open device %d:%d with no valid paths.", (int)MAJOR(dev->dev), (int)MINOR(dev->dev));
return 0;
}
name = dev_name(dev);
if (dev->fd >= 0) {
if (((dev->flags & DEV_OPENED_RW) || !need_rw) &&
((dev->flags & DEV_OPENED_EXCL) || !need_excl)) {
@@ -308,7 +324,7 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet)
if (dev->open_count && !need_excl)
log_debug_devs("%s: Already opened read-only. Upgrading "
"to read-write.", dev_name(dev));
"to read-write.", name);
/* dev_close_immediate will decrement this */
dev->open_count++;
@@ -321,11 +337,7 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet)
if (critical_section())
/* FIXME Make this log_error */
log_verbose("dev_open(%s) called while suspended",
dev_name(dev));
if (!(name = dev_name_confirmed(dev, quiet)))
return_0;
log_verbose("dev_open(%s) called while suspended", name);
#ifdef O_DIRECT_SUPPORT
if (direct) {
@@ -366,16 +378,18 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet)
}
#endif
if (quiet)
log_sys_debug("open", name);
log_debug("Failed to open device path %s (%d).", name, errno);
else
log_sys_error("open", name);
log_error("Failed to open device path %s (%d).", name, errno);
dev->flags |= DEV_OPEN_FAILURE;
return 0;
}
#ifdef O_DIRECT_SUPPORT
#if defined(O_NOATIME) || defined(O_DIRECT_SUPPORT)
opened:
#endif
#ifdef O_DIRECT_SUPPORT
if (direct)
dev->flags |= DEV_O_DIRECT_TESTED;
#endif
@@ -407,10 +421,12 @@ 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);
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" : "",
dev->flags & DEV_O_DIRECT ? " O_DIRECT" : "");
if (!quiet) {
log_debug_devs("Opened %s %s%s%s", name,
dev->flags & DEV_OPENED_RW ? "RW" : "RO",
dev->flags & DEV_OPENED_EXCL ? " O_EXCL" : "",
dev->flags & DEV_O_DIRECT ? " O_DIRECT" : "");
}
dev->flags &= ~DEV_OPEN_FAILURE;
return 1;
@@ -444,7 +460,7 @@ int dev_open_readonly_quiet(struct device *dev)
static void _close(struct device *dev)
{
if (close(dev->fd))
log_sys_error("close", dev_name(dev));
log_sys_debug("close", dev_name(dev));
dev->fd = -1;
log_debug_devs("Closed %s", dev_name(dev));

View File

@@ -18,7 +18,7 @@
#define LUKS_SIGNATURE "LUKS\xba\xbe"
#define LUKS_SIGNATURE_SIZE 6
int dev_is_luks(struct device *dev, uint64_t *offset_found, int full)
int dev_is_luks(struct cmd_context *cmd, struct device *dev, uint64_t *offset_found, int full)
{
char buf[LUKS_SIGNATURE_SIZE];
int ret = -1;

View File

@@ -16,6 +16,8 @@
#include "lib/misc/lib.h"
#include "lib/device/dev-type.h"
#include "lib/mm/xlate.h"
#include "lib/misc/crc.h"
#include "lib/commands/toolcontext.h"
#ifdef UDEV_SYNC_SUPPORT
#include <libudev.h> /* for MD detection using udev db records */
#include "lib/device/dev-ext-udev-constants.h"
@@ -48,79 +50,122 @@ static int _dev_has_md_magic(struct device *dev, uint64_t sb_offset)
return 0;
}
/*
* Calculate the position of the superblock.
* It is always aligned to a 4K boundary and
* depending on minor_version, it can be:
* 0: At least 8K, but less than 12K, from end of device
* 1: At start of device
* 2: 4K from start of device.
*/
typedef enum {
MD_MINOR_VERSION_MIN,
MD_MINOR_V0 = MD_MINOR_VERSION_MIN,
MD_MINOR_V1,
MD_MINOR_V2,
MD_MINOR_VERSION_MAX = MD_MINOR_V2
} md_minor_version_t;
#define IMSM_SIGNATURE "Intel Raid ISM Cfg Sig. "
#define IMSM_SIG_LEN (sizeof(IMSM_SIGNATURE) - 1)
static uint64_t _v1_sb_offset(uint64_t size, md_minor_version_t minor_version)
static int _dev_has_imsm_magic(struct device *dev, uint64_t devsize_sectors)
{
uint64_t sb_offset;
char imsm_signature[IMSM_SIG_LEN];
uint64_t off;
unsigned int physical_block_size = 0;
unsigned int logical_block_size = 0;
switch(minor_version) {
case MD_MINOR_V0:
sb_offset = (size - 8 * 2) & ~(4 * 2 - 1ULL);
break;
case MD_MINOR_V1:
sb_offset = 0;
break;
case MD_MINOR_V2:
sb_offset = 4 * 2;
break;
default:
log_warn(INTERNAL_ERROR "WARNING: Unknown minor version %d.",
minor_version);
return 0;
}
sb_offset <<= SECTOR_SHIFT;
if (!dev_get_direct_block_sizes(dev, &physical_block_size, &logical_block_size))
return_0;
return sb_offset;
if (logical_block_size == 4096)
off = (devsize_sectors * 512) - 8192;
else
off = (devsize_sectors * 512) - 1024;
if (!dev_read_bytes(dev, off, IMSM_SIG_LEN, imsm_signature))
return_0;
if (!memcmp(imsm_signature, IMSM_SIGNATURE, IMSM_SIG_LEN))
return 1;
return 0;
}
/*
* _udev_dev_is_md_component() only works if
* external_device_info_source="udev"
*
* but
*
* udev_dev_is_md_component() in dev-type.c only works if
* obtain_device_list_from_udev=1
*
* and neither of those config setting matches very well
* with what we're doing here.
*/
#define DDF_MAGIC 0xDE11DE11
struct ddf_header {
uint32_t magic;
uint32_t crc;
char guid[24];
char revision[8];
char padding[472];
};
static int _dev_has_ddf_magic(struct device *dev, uint64_t devsize_sectors, uint64_t *sb_offset)
{
struct ddf_header hdr;
uint32_t crc, our_crc;
uint64_t off;
uint64_t devsize_bytes = devsize_sectors * 512;
if (devsize_bytes < 0x30000)
return 0;
/* 512 bytes before the end of device (from libblkid) */
off = ((devsize_bytes / 0x200) - 1) * 0x200;
if (!dev_read_bytes(dev, off, 512, &hdr))
return_0;
if ((hdr.magic == cpu_to_be32(DDF_MAGIC)) ||
(hdr.magic == cpu_to_le32(DDF_MAGIC))) {
crc = hdr.crc;
hdr.crc = 0xffffffff;
our_crc = calc_crc(0, (const uint8_t *)&hdr, 512);
if ((cpu_to_be32(our_crc) == crc) ||
(cpu_to_le32(our_crc) == crc)) {
*sb_offset = off;
return 1;
} else {
log_debug_devs("Found md ddf magic at %llu wrong crc %x disk %x %s",
(unsigned long long)off, our_crc, crc, dev_name(dev));
return 0;
}
}
/* 128KB before the end of device (from libblkid) */
off = ((devsize_bytes / 0x200) - 257) * 0x200;
if (!dev_read_bytes(dev, off, 512, &hdr))
return_0;
if ((hdr.magic == cpu_to_be32(DDF_MAGIC)) ||
(hdr.magic == cpu_to_le32(DDF_MAGIC))) {
crc = hdr.crc;
hdr.crc = 0xffffffff;
our_crc = calc_crc(0, (const uint8_t *)&hdr, 512);
if ((cpu_to_be32(our_crc) == crc) ||
(cpu_to_le32(our_crc) == crc)) {
*sb_offset = off;
return 1;
} else {
log_debug_devs("Found md ddf magic at %llu wrong crc %x disk %x %s",
(unsigned long long)off, our_crc, crc, dev_name(dev));
return 0;
}
}
return 0;
}
#ifdef UDEV_SYNC_SUPPORT
static int _udev_dev_is_md_component(struct device *dev)
static int _dev_is_md_component_udev(struct device *dev)
{
const char *value;
struct dev_ext *ext;
/*
* external_device_info_source="udev" enables these udev checks.
* external_device_info_source="none" disables them.
*/
if (!(ext = dev_ext_get(dev)))
return_0;
if (!(value = udev_device_get_property_value((struct udev_device *)ext->handle, DEV_EXT_UDEV_BLKID_TYPE))) {
dev->flags |= DEV_UDEV_INFO_MISSING;
if (!(value = udev_device_get_property_value((struct udev_device *)ext->handle, DEV_EXT_UDEV_BLKID_TYPE)))
return 0;
}
return !strcmp(value, DEV_EXT_UDEV_BLKID_TYPE_SW_RAID);
}
#else
static int _udev_dev_is_md_component(struct device *dev)
static int _dev_is_md_component_udev(struct device *dev)
{
dev->flags |= DEV_UDEV_INFO_MISSING;
return 0;
}
#endif
@@ -128,14 +173,16 @@ static int _udev_dev_is_md_component(struct device *dev)
/*
* Returns -1 on error
*/
static int _native_dev_is_md_component(struct device *dev, uint64_t *offset_found, int full)
static int _dev_is_md_component_native(struct device *dev, uint64_t *offset_found, int full)
{
md_minor_version_t minor;
uint64_t size, sb_offset;
uint64_t size, sb_offset = 0;
int ret;
if (!scan_bcache)
return -EAGAIN;
/* i/o layer has not been set up */
if (!scan_bcache) {
log_error(INTERNAL_ERROR "dev_is_md_component_native requires io layer.");
return -1;
}
if (!dev_get_size(dev, &size)) {
stack;
@@ -146,9 +193,9 @@ static int _native_dev_is_md_component(struct device *dev, uint64_t *offset_foun
return 0;
/*
* Old md versions locate the magic number at the end of the device.
* 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
* Some md versions locate the magic number at the end of the device.
* Those checks can't be satisfied with the initial scan data, and
* 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.
*
@@ -159,42 +206,81 @@ static int _native_dev_is_md_component(struct device *dev, uint64_t *offset_foun
* and set it for commands that could possibly write to an md dev
* (pvcreate/vgcreate/vgextend).
*/
if (!full) {
sb_offset = 0;
if (_dev_has_md_magic(dev, sb_offset)) {
log_debug_devs("Found md magic number at offset 0 of %s.", dev_name(dev));
ret = 1;
goto out;
}
sb_offset = 8 << SECTOR_SHIFT;
if (_dev_has_md_magic(dev, sb_offset)) {
log_debug_devs("Found md magic number at offset %d of %s.", (int)sb_offset, dev_name(dev));
ret = 1;
goto out;
}
/*
* md superblock version 1.1 at offset 0 from start
*/
ret = 0;
goto out;
}
/* Check if it is an md component device. */
/* Version 0.90.0 */
sb_offset = MD_NEW_SIZE_SECTORS(size) << SECTOR_SHIFT;
if (_dev_has_md_magic(dev, sb_offset)) {
if (_dev_has_md_magic(dev, 0)) {
log_debug_devs("Found md magic number at offset 0 of %s.", dev_name(dev));
ret = 1;
goto out;
}
minor = MD_MINOR_VERSION_MIN;
/* Version 1, try v1.0 -> v1.2 */
do {
sb_offset = _v1_sb_offset(size, minor);
if (_dev_has_md_magic(dev, sb_offset)) {
ret = 1;
goto out;
}
} while (++minor <= MD_MINOR_VERSION_MAX);
/*
* md superblock version 1.2 at offset 4KB from start
*/
if (_dev_has_md_magic(dev, 4096)) {
log_debug_devs("Found md magic number at offset 4096 of %s.", dev_name(dev));
ret = 1;
goto out;
}
if (!full) {
ret = 0;
goto out;
}
/*
* Handle superblocks at the end of the device.
*/
/*
* md superblock version 0 at 64KB from end of device
* (after end is aligned to 64KB)
*/
sb_offset = MD_NEW_SIZE_SECTORS(size) << SECTOR_SHIFT;
if (_dev_has_md_magic(dev, sb_offset)) {
log_debug_devs("Found md magic number at offset %llu of %s.", (unsigned long long)sb_offset, dev_name(dev));
ret = 1;
goto out;
}
/*
* md superblock version 1.0 at 8KB from end of device
*/
sb_offset = ((size - 8 * 2) & ~(4 * 2 - 1ULL)) << SECTOR_SHIFT;
if (_dev_has_md_magic(dev, sb_offset)) {
log_debug_devs("Found md magic number at offset %llu of %s.", (unsigned long long)sb_offset, dev_name(dev));
ret = 1;
goto out;
}
/*
* md imsm superblock 1K from end of device
*/
if (_dev_has_imsm_magic(dev, size)) {
log_debug_devs("Found md imsm magic number at offset %llu of %s.", (unsigned long long)sb_offset, dev_name(dev));
sb_offset = 1024;
ret = 1;
goto out;
}
/*
* md ddf superblock 512 bytes from end, or 128KB from end
*/
if (_dev_has_ddf_magic(dev, size, &sb_offset)) {
log_debug_devs("Found md ddf magic number at offset %llu of %s.", (unsigned long long)sb_offset, dev_name(dev));
ret = 1;
goto out;
}
ret = 0;
out:
@@ -204,41 +290,20 @@ out:
return ret;
}
int dev_is_md_component(struct device *dev, uint64_t *offset_found, int full)
int dev_is_md_component(struct cmd_context *cmd, struct device *dev, uint64_t *offset_found, int full)
{
int ret;
if (_dev_is_md_component_native(dev, offset_found, full) == 1)
goto found;
/*
* If non-native device status source is selected, use it
* only if offset_found is not requested as this
* information is not in udev db.
*/
if ((dev->ext.src == DEV_EXT_NONE) || offset_found) {
ret = _native_dev_is_md_component(dev, offset_found, full);
if (!full) {
if (!ret || (ret == -EAGAIN)) {
if (udev_dev_is_md_component(dev))
ret = 1;
}
}
if (ret && (ret != -EAGAIN))
dev->flags |= DEV_IS_MD_COMPONENT;
return ret;
if (external_device_info_source() == DEV_EXT_UDEV) {
if (_dev_is_md_component_udev(dev) == 1)
goto found;
}
return 0;
if (dev->ext.src == DEV_EXT_UDEV) {
ret = _udev_dev_is_md_component(dev);
if (ret && (ret != -EAGAIN))
dev->flags |= DEV_IS_MD_COMPONENT;
return ret;
}
log_error(INTERNAL_ERROR "Missing hook for MD device recognition "
"using external device info source %s", dev_ext_name(dev));
return -1;
found:
dev->flags |= DEV_IS_MD_COMPONENT;
return 1;
}
static int _md_sysfs_attribute_snprintf(char *path, size_t size,
@@ -461,7 +526,8 @@ int dev_is_md_with_end_superblock(struct dev_types *dt, struct device *dev)
#else
int dev_is_md_component(struct device *dev __attribute__((unused)),
int dev_is_md_component(struct cmd_context *cmd __attribute__((unused)),
struct device *dev __attribute__((unused)),
uint64_t *sb __attribute__((unused)))
{
return 0;

555
lib/device/dev-mpath.c Normal file
View File

@@ -0,0 +1,555 @@
/*
* Copyright (C) 2011 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "base/memory/zalloc.h"
#include "lib/misc/lib.h"
#include "lib/activate/activate.h"
#include "lib/commands/toolcontext.h"
#include "lib/device/device_id.h"
#ifdef UDEV_SYNC_SUPPORT
#include <libudev.h>
#include "lib/device/dev-ext-udev-constants.h"
#endif
#include <dirent.h>
#define MPATH_PREFIX "mpath-"
/*
* This hash table keeps track of whether a given dm device
* is a mpath device or not.
*
* If dm-3 is an mpath device, then the constant "2" is stored in
* the hash table with the key of the dm minor number ("3" for dm-3).
* If dm-3 is not an mpath device, then the constant "1" is stored in
* the hash table with the key of the dm minor number.
*/
static struct dm_pool *_hash_mem;
static struct dm_hash_table *_minor_hash_tab;
static struct dm_hash_table *_wwid_hash_tab;
#define MAX_WWID_LINE 512
/*
* do we need to check the multipath.conf blacklist?
*/
static void _read_wwid_file(const char *config_wwids_file)
{
FILE *fp;
char line[MAX_WWID_LINE];
char *wwid, *p;
int count = 0;
if (config_wwids_file[0] != '/') {
log_print("Ignoring unknown multipath_wwids_file.");
return;
}
if (!(fp = fopen(config_wwids_file, "r"))) {
log_debug("multipath wwids file not found");
return;
}
while (fgets(line, sizeof(line), fp)) {
if (line[0] == '#')
continue;
wwid = line;
if (line[0] == '/')
wwid++;
/* skip the initial '3' */
wwid++;
if ((p = strchr(wwid, '/')))
*p = '\0';
(void) dm_hash_insert_binary(_wwid_hash_tab, wwid, strlen(wwid), (void*)1);
count++;
}
if (fclose(fp))
stack;
log_debug("multipath wwids read %d from %s", count, config_wwids_file);
}
int dev_mpath_init(const char *config_wwids_file)
{
struct dm_pool *mem;
struct dm_hash_table *minor_tab;
struct dm_hash_table *wwid_tab;
if (!(mem = dm_pool_create("mpath", 256))) {
log_error("mpath pool creation failed.");
return 0;
}
if (!(minor_tab = dm_hash_create(110))) {
log_error("mpath hash table creation failed.");
dm_pool_destroy(mem);
return 0;
}
_hash_mem = mem;
_minor_hash_tab = minor_tab;
/* multipath_wwids_file="" disables the use of the file */
if (config_wwids_file && !strlen(config_wwids_file)) {
log_debug("multipath wwids file disabled.");
return 1;
}
if (!(wwid_tab = dm_hash_create(110))) {
log_error("mpath hash table creation failed.");
dm_hash_destroy(_minor_hash_tab);
dm_pool_destroy(_hash_mem);
_minor_hash_tab = NULL;
_hash_mem = NULL;
return 0;
}
_wwid_hash_tab = wwid_tab;
if (config_wwids_file)
_read_wwid_file(config_wwids_file);
return 1;
}
void dev_mpath_exit(void)
{
if (_minor_hash_tab)
dm_hash_destroy(_minor_hash_tab);
if (_wwid_hash_tab)
dm_hash_destroy(_wwid_hash_tab);
if (_hash_mem)
dm_pool_destroy(_hash_mem);
_minor_hash_tab = NULL;
_wwid_hash_tab = NULL;
_hash_mem = NULL;
}
/*
* given "/dev/foo" return "foo"
*/
static const char *_get_sysfs_name(struct device *dev)
{
const char *name;
if (!(name = strrchr(dev_name(dev), '/'))) {
log_error("Cannot find '/' in device name.");
return NULL;
}
name++;
if (!*name) {
log_error("Device name is not valid.");
return NULL;
}
return name;
}
/*
* given major:minor
* readlink translates /sys/dev/block/major:minor to /sys/.../foo
* from /sys/.../foo return "foo"
*/
static const char *_get_sysfs_name_by_devt(const char *sysfs_dir, dev_t devno,
char *buf, size_t buf_size)
{
const char *name;
char path[PATH_MAX];
int size;
if (dm_snprintf(path, sizeof(path), "%sdev/block/%d:%d", sysfs_dir,
(int) MAJOR(devno), (int) MINOR(devno)) < 0) {
log_error("Sysfs path string is too long.");
return NULL;
}
if ((size = readlink(path, buf, buf_size - 1)) < 0) {
log_sys_error("readlink", path);
return NULL;
}
buf[size] = '\0';
if (!(name = strrchr(buf, '/'))) {
log_error("Cannot find device name in sysfs path.");
return NULL;
}
name++;
return name;
}
static int _get_sysfs_string(const char *path, char *buffer, int max_size)
{
FILE *fp;
int r = 0;
if (!(fp = fopen(path, "r"))) {
log_sys_error("fopen", path);
return 0;
}
if (!fgets(buffer, max_size, fp))
log_sys_error("fgets", path);
else
r = 1;
if (fclose(fp))
log_sys_error("fclose", path);
return r;
}
static int _get_sysfs_dm_mpath(struct dev_types *dt, const char *sysfs_dir, const char *holder_name)
{
char path[PATH_MAX];
char buffer[128];
if (dm_snprintf(path, sizeof(path), "%sblock/%s/dm/uuid", sysfs_dir, holder_name) < 0) {
log_error("Sysfs path string is too long.");
return 0;
}
buffer[0] = '\0';
if (!_get_sysfs_string(path, buffer, sizeof(buffer)))
return_0;
if (!strncmp(buffer, MPATH_PREFIX, 6))
return 1;
return 0;
}
#ifdef UDEV_SYNC_SUPPORT
static int _dev_is_mpath_component_udev(struct device *dev)
{
const char *value;
struct dev_ext *ext;
/*
* external_device_info_source="udev" enables these udev checks.
* external_device_info_source="none" disables them.
*/
if (!(ext = dev_ext_get(dev)))
return_0;
value = udev_device_get_property_value((struct udev_device *)ext->handle, DEV_EXT_UDEV_BLKID_TYPE);
if (value && !strcmp(value, DEV_EXT_UDEV_BLKID_TYPE_MPATH))
return 1;
value = udev_device_get_property_value((struct udev_device *)ext->handle, DEV_EXT_UDEV_MPATH_DEVICE_PATH);
if (value && !strcmp(value, "1"))
return 1;
return 0;
}
#else
static int _dev_is_mpath_component_udev(struct device *dev)
{
return 0;
}
#endif
static int _dev_is_mpath_component_sysfs(struct cmd_context *cmd, struct device *dev)
{
struct dev_types *dt = cmd->dev_types;
const char *part_name;
const char *name; /* e.g. "sda" for "/dev/sda" */
char link_path[PATH_MAX]; /* some obscure, unpredictable sysfs path */
char holders_path[PATH_MAX]; /* e.g. "/sys/block/sda/holders/" */
char dm_dev_path[PATH_MAX]; /* e.g. "/dev/dm-1" */
char *holder_name; /* e.g. "dm-1" */
const char *sysfs_dir = dm_sysfs_dir();
DIR *dr;
struct dirent *de;
int dev_major = MAJOR(dev->dev);
int dev_minor = MINOR(dev->dev);
int dm_dev_major;
int dm_dev_minor;
struct stat info;
dev_t primary_dev;
int is_mpath_component = 0;
/* multipathing is only known to exist for SCSI or NVME devices */
if (!major_is_scsi_device(dt, dev_major) && !dev_is_nvme(dt, dev))
return 0;
switch (dev_get_primary_dev(dt, dev, &primary_dev)) {
case 2: /* The dev is partition. */
part_name = dev_name(dev); /* name of original dev for log_debug msg */
/* gets "foo" for "/dev/foo" where "/dev/foo" comes from major:minor */
if (!(name = _get_sysfs_name_by_devt(sysfs_dir, primary_dev, link_path, sizeof(link_path))))
return_0;
log_debug_devs("%s: Device is a partition, using primary "
"device %s for mpath component detection",
part_name, name);
break;
case 1: /* The dev is already a primary dev. Just continue with the dev. */
/* gets "foo" for "/dev/foo" */
if (!(name = _get_sysfs_name(dev)))
return_0;
break;
default: /* 0, error. */
log_warn("Failed to get primary device for %d:%d.", dev_major, dev_minor);
return 0;
}
if (dm_snprintf(holders_path, sizeof(holders_path), "%sblock/%s/holders", sysfs_dir, name) < 0) {
log_warn("Sysfs path to check mpath is too long.");
return 0;
}
/* also will filter out partitions */
if (stat(holders_path, &info))
return 0;
if (!S_ISDIR(info.st_mode)) {
log_warn("Path %s is not a directory.", holders_path);
return 0;
}
/*
* If any holder is a dm mpath device, then return 1;
*/
if (!(dr = opendir(holders_path))) {
log_debug("Device %s has no holders dir", dev_name(dev));
return 0;
}
while ((de = readdir(dr))) {
if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, ".."))
continue;
/*
* holder_name is e.g. "dm-1"
* dm_dev_path is then e.g. "/dev/dm-1"
*/
holder_name = de->d_name;
if (dm_snprintf(dm_dev_path, sizeof(dm_dev_path), "%s/%s", cmd->dev_dir, holder_name) < 0) {
log_warn("dm device path to check mpath is too long.");
continue;
}
/*
* stat "/dev/dm-1" which is the holder of the dev we're checking
* dm_dev_major:dm_dev_minor come from stat("/dev/dm-1")
*/
if (stat(dm_dev_path, &info)) {
log_debug_devs("dev_is_mpath_component %s holder %s stat result %d",
dev_name(dev), dm_dev_path, errno);
continue;
}
dm_dev_major = (int)MAJOR(info.st_rdev);
dm_dev_minor = (int)MINOR(info.st_rdev);
if (dm_dev_major != dt->device_mapper_major) {
log_debug_devs("dev_is_mpath_component %s holder %s %d:%d does not have dm major",
dev_name(dev), dm_dev_path, dm_dev_major, dm_dev_minor);
continue;
}
/*
* A previous call may have checked if dm_dev_minor is mpath and saved
* the result in the hash table. If there's a saved result just use that.
*
* The minor number of "/dev/dm-1" is added to the hash table with
* const value 2 meaning that dm minor 1 (for /dev/dm-1) is a multipath dev
* and const value 1 meaning that dm minor 1 is not a multipath dev.
*/
if (_minor_hash_tab) {
long look = (long) dm_hash_lookup_binary(_minor_hash_tab, &dm_dev_minor, sizeof(dm_dev_minor));
if (look > 0) {
log_debug_devs("dev_is_mpath_component %s holder %s %u:%u already checked as %sbeing mpath.",
dev_name(dev), holder_name, dm_dev_major, dm_dev_minor, (look > 1) ? "" : "not ");
is_mpath_component = (look == 2);
goto out;
}
/* no saved result for dm_dev_minor, so check the uuid for it */
}
/*
* Returns 1 if /sys/block/<holder_name>/dm/uuid indicates that
* <holder_name> is a dm device with dm uuid prefix mpath-.
* When true, <holder_name> will be something like "dm-1".
*/
if (_get_sysfs_dm_mpath(dt, sysfs_dir, holder_name)) {
log_debug_devs("dev_is_mpath_component %s holder %s %u:%u ignore mpath component",
dev_name(dev), holder_name, dm_dev_major, dm_dev_minor);
/* For future checks, save that the dm minor refers to mpath ("2" == is mpath) */
if (_minor_hash_tab)
(void) dm_hash_insert_binary(_minor_hash_tab, &dm_dev_minor, sizeof(dm_dev_minor), (void*)2);
is_mpath_component = 1;
goto out;
}
/* For future checks, save that the dm minor does not refer to mpath ("1" == is not mpath) */
if (_minor_hash_tab)
(void) dm_hash_insert_binary(_minor_hash_tab, &dm_dev_minor, sizeof(dm_dev_minor), (void*)1);
}
out:
if (closedir(dr))
stack;
return is_mpath_component;
}
static int _dev_in_wwid_file(struct cmd_context *cmd, struct device *dev)
{
char sysbuf[PATH_MAX] = { 0 };
char *wwid;
long look;
if (!_wwid_hash_tab)
return 0;
if (!read_sys_block(cmd, dev, "device/wwid", sysbuf, sizeof(sysbuf)))
return 0;
if (!sysbuf[0])
return 0;
/*
* sysfs prints wwid as <typestr>.<value>
* multipath wwid uses '3'<value>
* does "<typestr>." always correspond to "3"?
*/
if (!(wwid = strchr(sysbuf, '.')))
return 0;
/* skip the type and dot, just as '3' was skipped from wwids entry */
wwid++;
look = (long) dm_hash_lookup_binary(_wwid_hash_tab, wwid, strlen(wwid));
if (look) {
log_debug_devs("dev_is_mpath_component %s multipath wwid %s", dev_name(dev), wwid);
return 1;
}
return 0;
}
int dev_is_mpath_component(struct cmd_context *cmd, struct device *dev)
{
if (_dev_is_mpath_component_sysfs(cmd, dev) == 1)
goto found;
if (_dev_in_wwid_file(cmd, dev))
goto found;
if (external_device_info_source() == DEV_EXT_UDEV) {
if (_dev_is_mpath_component_udev(dev) == 1)
goto found;
}
return 0;
found:
return 1;
}
const char *dev_mpath_component_wwid(struct cmd_context *cmd, struct device *dev)
{
char slaves_path[PATH_MAX];
char wwid_path[PATH_MAX];
char sysbuf[PATH_MAX] = { 0 };
char *slave_name;
const char *wwid = NULL;
struct stat info;
DIR *dr;
struct dirent *de;
/* /sys/dev/block/253:7/slaves/sda/device/wwid */
if (dm_snprintf(slaves_path, sizeof(slaves_path), "%s/dev/block/%d:%d/slaves",
dm_sysfs_dir(), (int)MAJOR(dev->dev), (int)MINOR(dev->dev)) < 0) {
log_warn("Sysfs path to check mpath components is too long.");
return NULL;
}
if (stat(slaves_path, &info))
return NULL;
if (!S_ISDIR(info.st_mode)) {
log_warn("Path %s is not a directory.", slaves_path);
return NULL;
}
/* Get wwid from first component */
if (!(dr = opendir(slaves_path))) {
log_debug("Device %s has no slaves dir", dev_name(dev));
return NULL;
}
while ((de = readdir(dr))) {
if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, ".."))
continue;
/* slave_name "sda" */
slave_name = de->d_name;
/* read /sys/block/sda/device/wwid */
if (dm_snprintf(wwid_path, sizeof(wwid_path), "%s/block/%s/device/wwid",
dm_sysfs_dir(), slave_name) < 0) {
log_warn("Failed to create sysfs wwid path for %s", slave_name);
continue;
}
get_sysfs_value(wwid_path, sysbuf, sizeof(sysbuf), 0);
if (!sysbuf[0])
continue;
if (strstr(sysbuf, "scsi_debug")) {
int i;
for (i = 0; i < strlen(sysbuf); i++) {
if (sysbuf[i] == ' ')
sysbuf[i] = '_';
}
}
if ((wwid = dm_pool_strdup(cmd->mem, sysbuf)))
break;
}
if (closedir(dr))
stack;
return wwid;
}

View File

@@ -35,7 +35,7 @@ static int _swap_detect_signature(const char *buf)
return 0;
}
int dev_is_swap(struct device *dev, uint64_t *offset_found, int full)
int dev_is_swap(struct cmd_context *cmd, struct device *dev, uint64_t *offset_found, int full)
{
char buf[10];
uint64_t size;

Some files were not shown because too many files have changed in this diff Show More