1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-08-20 21:49:28 +03:00

Compare commits

..

1671 Commits

Author SHA1 Message Date
ce9c5f2f7e WHATS_NEW: update 2024-10-10 08:53:07 -05:00
eea78613ef device_mapper: slight improvement of tok_match
Reduce amount of unnecessary instructions for some code paths.
2024-10-10 08:53:07 -05:00
00a8946e46 import_vsn1: increate hash size
With larger amount of LV hashing buckets within VG,
until better structures for dynamic handling of LV elements will be used.
2024-10-10 08:53:07 -05:00
53d5e2e602 device_mapper: slight reorder for _get_token
For most common part check for '#' when it's known it's not a space.
And also when we checked for '\n' we dont need to check again isspace().
2024-10-10 08:53:07 -05:00
ce970403d6 device_mapper: nodes and values with strings
Avoid double pool allocation call by placing string
directly after the node/value structure end.

It would be likely better to not copy the string at all
and derefence it from the original string however that
is much larger rework - and also for unescaping we would
need to allocate anyway.
2024-10-10 08:53:07 -05:00
4e623daf8e crc: add newer zlib code
This code is faster when calculating crc32 checksum for larger
block areas. There is also SIMD variant present in the code,
however ATM the influence on performance of lvm2 is not that big..
2024-10-10 08:53:07 -05:00
e03bdcfbc2 crc: move static table
Move static table upward in the code so it can be shared with
another 'crc' implementation.
2024-10-10 08:53:06 -05:00
fa12a2398e config: set vg_copy_internal to binary for testing 2024-10-10 08:50:52 -05:00
18babdc3ac vg: copy alternative to reimporting
One vg struct is copied to another vg struct, rather than
importing vg metadata text to create the new vg struct.

Enable with global/vg_copy_internal="binary"
2024-10-09 15:49:03 -05:00
317fae4024 dev-type: detect mixed dos partition with gpt's PMBR
Detect when we have mixed dos partition with gpt's PMBR partition.

This is not a sane configuration, but detect it anyway, just in case
someone configures such partition layout manually and forcefully and
incorrectly defines one of the partition types to be the GPT's PMBR.

For example:

  ❯  fdisk -l /dev/sdc

  Device     Boot Start    End Sectors Size Id Type
  /dev/sdc1        2048  67583   65536  32M 83 Linux
  /dev/sdc2       67584 262143  194560  95M ee GPT

Before:
(The partition filter passes even though there's real existing dos
partition - the empty GPT PMBR overrides it.)

  ❯  pvcreate /dev/sdc
  WARNING: PMBR signature detected on /dev/sdc at offset 510. Wipe it? [y/n]:
  Wiping PMBR signature on /dev/sdc.
  Physical volume "/dev/sdc" successfully created.

With this patch applied:
(The GPT PMBR does not override the existence of the dos partition.)

  ❯  pvcreate /dev/sdc
    Cannot use /dev/sdc: device is partitioned
2024-10-03 09:55:36 +02:00
e2e6b08518 post-release 2024-10-02 14:21:43 +02:00
207990a877 pre-release 2024-10-02 14:21:09 +02:00
ec965dde39 WHATS_NEW and release-notes update 2024-10-02 14:18:35 +02:00
b77f7acac8 WHATS_NEW: update 2024-10-02 13:49:45 +02:00
ca02546649 [WIP] Disable dlm for RHEL10 2024-10-02 13:48:11 +02:00
493d8908fb lvmdbusd: Fix Python script
The thread does not contain field "damon" but "daemon".

Actually found with codespell.

Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
2024-10-02 11:34:22 +00:00
9d6a3ee547 filesystem: add note about swap devices 2024-10-02 13:31:54 +02:00
bd5ca83c43 tests: also test swap devices in lvresize-fs.sh 2024-10-02 13:31:54 +02:00
5096335277 lv_manip: handle swap devices in fs-related checks for lvreduce/lvextend
This provides better hints when trying to resize the fs on top of an LV.
Also needs a3f6d2f593 for proper operation.

❯  lvs -o name,size vg/swap
  lv_name lv_size
  swap     60.00m

Before:

❯  lvextend -L72m vg/swap
  Size of logical volume vg/swap changed from 60.00 MiB (15 extents) to 72.00 MiB (18 extents).
  Logical volume vg/swap successfully resized.

❯  lvreduce -L60m vg/swap
  File system swap found on vg/swap.
  File system device usage is not available from libblkid.

❯  lvreduce -L50m vg/swap
  Rounding size to boundary between physical extents: 52.00 MiB.
  File system swap found on vg/swap.
  File system device usage is not available from libblkid.

After:

❯  lvextend -L72m vg/swap
  Size of logical volume vg/swap changed from 60.00 MiB (15 extents) to 72.00 MiB (18 extents).
  Logical volume vg/swap successfully resized.

❯  lvreduce -L60m vg/swap
  File system swap found on vg/swap.
  File system size (60.00 MiB) is equal to the requested size (60.00 MiB).
  File system reduce is not needed, skipping.
  Size of logical volume vg/swap changed from 72.00 MiB (18 extents) to 60.00 MiB (15 extents).
  Logical volume vg/swap successfully resized.

❯  lvreduce -L50m vg/swap
  Rounding size to boundary between physical extents: 52.00 MiB.
  File system swap found on vg/swap.
  File system size (60.00 MiB) is larger than the requested size (52.00 MiB).
  File system reduce is required and not supported (swap).
2024-10-02 13:31:54 +02:00
e009becd73 dev-type: get swap device size from blkid using FSSIZE
blkid does not report FSLASTBLOCK for a swap device. However, blkid
does report FSSIZE for swap devices, so use this field (and including
the header size which is of FSBLOCKSIZE for the swap) instead to
set the "filesystem last block" which is used subsequently for
further calculations and conditions.
2024-10-02 13:31:54 +02:00
4524778b23 tests: add pvcreate-partition.sh 2024-10-02 12:02:35 +02:00
d5d2c98980 dev-type: add prefix to differentiate msdos and gpt constants 2024-10-02 12:02:34 +02:00
84cabd068b filter: partitioned: also detect non-empty GPT partition table
We already detect msdos partition table. If it is empty, that is, there
is just the partition header and no actual partitions defined, then the
filter-partitioned passes, otherwise not.

Do the same for GPT partition table.
2024-10-02 11:54:01 +02:00
4708a354f6 make: generate 2024-09-30 15:00:03 +02:00
28e7be9f39 cov: annotate 2024-09-30 15:00:03 +02:00
0e1e220c3d cov: potentially overflowing expression
Use 64bit arithmentic.
2024-09-30 15:00:03 +02:00
7f29afdb06 lvmlockd: configurable sanlock lease sizes on 4K disks
New config setting sanlock_align_size can be used to configure
the sanlock lease size that lvmlockd will use on 4K disks.

By default, lvmlockd and sanlock use 8MiB align_size (lease size)
on 4K disks, which supports up to 2000 hosts (and max host_id.)

This can be reduced to 1, 2 or 4 (in MiB), to reduce lease i/o.
The reduced sizes correspond to smaller max hosts/host_id:

1 MiB = 250 hosts
2 MiB = 500 hosts
4 MiB = 1000 hosts
8 MiB = 2000 hosts (default)

(Disks with 512 byte sectors always use 1MiB leases and support
2000 hosts/host_id, and are not affected by this.)
2024-09-27 17:59:03 -05:00
6816366ff1 WHATS_NEW: update 2024-09-27 13:44:59 +02:00
7447634c26 cleanup: replace use of alloced with allocated 2024-09-27 13:42:45 +02:00
0862e2b150 cleanup: typos in libdm 2024-09-27 13:42:45 +02:00
74f607952d cleanup: more typos in WHATS_NEW 2024-09-27 13:42:45 +02:00
cb781b3e1d cleanup: fix typos
Typos found with codespell.

Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
2024-09-27 13:42:45 +02:00
964012fdb9 memlock: use value of 0 to disable memory locking
In cases user is sure he is not using his 'rootfs' or 'swap' on LVs
managed with his command - it possible to completely bypass pinning
process to RAM which may eventually slightly speedup command execution,
(however at the risk the process can be eventually delayed by swapping).
Basicaly use this only at your risk...

TODO: add some dmeventd support for this.
2024-09-27 13:42:45 +02:00
7e2bb2a35e vdo: depcreate unused settings 2024-09-26 16:25:12 +02:00
e9413fb211 lvmlockd: use lvmlock LV size
Previously, lvmlockd detected the end of the lvmlock LV
by doing i/o to it until an i/o error was returned.
This triggered sanlock warning messages, so use the LV
size to avoid accessing beyond the end of the device.

Previously, every lvcreate would refresh the lvmlock LV
in case another machine had extended it.  This involves
a lot of unnecessary work in most cases, so now compare
the LV size and device size to detect when a refresh is
needed.
2024-09-26 08:53:09 -05:00
9d7c19c2ce lvmlockd: fix previous thin locking fix
Restore the original lvremove locking for non-thin LVs
that were changed in the thin locking fix.
2024-09-23 17:15:42 -05:00
d7a028aaad vg: remove unused hostnames hash table
The hash table of lv creation hostnames was not used for anything,
so remove it.
2024-09-23 15:04:53 -05:00
1c3d7dfb07 lvmlockd: fix locking for thin
lvremove of a thin lv while the pool is inactive would
leave the pool locked but inactive.

lvcreate of a thin snapshot while the pool is inactive
would leave the pool locked but inactive.

lvcreate of a thin lv could activate the pool to check
a threshold before the pool lock was acquired in lvmlockd.
2024-09-23 14:57:07 -05:00
86a9db05cf tests: remove superfluous -a option for df used in lvresize-fs.sh 2024-09-19 15:12:44 +02:00
f42aef4706 metadata: use lv_hash in segment-specific metadata parsing
The lv_hash wasn't being passed to the seg-specific text import
functions, so they were doing many find_lv() calls which consumes
a lot of time when there are many LVs in the metadata.
2024-09-10 11:51:15 -05:00
1b68841605 args: readonly description update
Include reference to --permission r.
2024-09-06 08:44:06 -05:00
e8383073a9 WHATS_NEW_DM: update 2024-09-05 12:14:42 +02:00
1e48599193 libdm: do not fail if GETVAL semctl fails for udev sync inc and dec
While performing udev sync semaphore's inc/dec operation, we use the
result from GETVAL semctl just to print a debug message with current
value of that sempahore, nothing else.

If the GETVAL fails for whetever reason while the actual inc/dec
completes successfully, just log a warning message about the GETVAL
(and print the debug messages without the actual semaphore value)
and return success for the inc/dec operation as a whole.
2024-09-05 12:14:42 +02:00
f7f08ba881 libdm: clean up udev sync semaphore on fail path during its creation
Clean up udev sync semaphore on fail path during its creation, otherwise
the caller will have no handle returned to clean it up itself and the
semaphore will keep staying in the system. The only way to clean it up
would be to call `dmsetup udevcomplete_all` which would destroy all
udev sync semaphores, not just the failed one, which we don't want.
2024-09-05 12:14:42 +02:00
de196f4b60 libdm: add 'cookie create/inc/dec' log prefix if GETVAL fails for udev sync ops
The same message is printed while performing create/inc/dec operation and
the GETVAL semctl fails. Add a prefix so we know exactly in which of
these functions the issue actually happened.
2024-09-05 12:14:37 +02:00
80d7483322 scripts: Fix ConditionPathExists in unit files 2024-09-04 14:40:58 +02:00
b7fef5b133 WHATS_NEW: update 2024-08-30 16:51:15 +02:00
418fb5a3b4 configure: autoreconf 2024-08-30 16:51:15 +02:00
915689f566 make generate 2024-08-30 16:51:15 +02:00
a4fa14c73b cleanup: typos in configure.ac 2024-08-30 16:51:15 +02:00
460ff472f9 cleanup: typos in test comments 2024-08-30 16:51:15 +02:00
0e52e215a8 cleanup: typos in test logging 2024-08-30 16:51:15 +02:00
26a6c69a87 cleanup: typos in doc 2024-08-30 16:51:15 +02:00
e3a2f7b8ee cleanup: typos man pages 2024-08-30 16:51:15 +02:00
7d816c6a4a cleanup: typos in WHATS_NEW 2024-08-30 16:51:15 +02:00
39b7d1ba8f cleanup: typos in comments
Collection of typos in code comments.
Should have no runtime effect.
2024-08-30 16:51:15 +02:00
7da47cea35 cleanup: typos in logging
Fixes various typos in printed/logged messages.
2024-08-30 16:51:15 +02:00
643bc26595 cleanup: typo dirctory to directory
Rename internal lm_idm_scsi_find_block_directory() function.
2024-08-30 16:51:14 +02:00
6a8ba51d82 cleanup: typo premable to preamble
Correct preable, seems even unused.
2024-08-30 16:51:04 +02:00
1c9e619fef libdm: _DOESNT_ to _DOES_NOT_
Rename internal define DM_NAME_LIST_FLAG_DOESNT_HAVE_UUID
to DM_NAME_LIST_FLAG_DOES_NOT_HAVE_UUID
(currently unused)
2024-08-30 16:48:48 +02:00
bfd5464002 lvmlockd: retrive to retrieve
Replace retrive with retrieve for internal function.
2024-08-30 16:48:48 +02:00
625c55fd6c libdaemon: daemonise to daemonize
Replace daemonise() with daemonize().
2024-08-30 16:48:48 +02:00
b8a4fda0f7 lvconvert: use pvmove as part of renamed LV name
LV with pvmove_ prefix is not allowed to be created by user
so bigger chance our selected name will never exist.

TODO: probably add code to get generic unused LV name...
2024-08-30 16:48:48 +02:00
a8696ee72a libdm: check for queue name
Fix typo and check for queue string within sysfs kernel name.
2024-08-30 16:48:48 +02:00
f301f6acbc integrity: typo interleave_sectors
Correct emitted parameter name for interleave_sectors for DM table line.
2024-08-30 16:48:48 +02:00
7a20ac4f61 make: generate 2024-08-30 14:24:26 +02:00
4313e3896c man: lvmreport: add note about log/command_log_selection="all" 2024-08-30 14:24:26 +02:00
30e25d0db9 config: update description for log/command_log_selection 2024-08-30 14:20:03 +02:00
83ae675f8d lvresize: ignore given stripe and stripe size args for raid0 2024-08-29 14:01:27 +02:00
c65d379769 toollib: do not accept duplicate device name on pvcreate input 2024-08-28 10:35:18 +02:00
8e9d7ace7b post-release 2024-08-23 16:02:19 +02:00
6de3937ac5 pre-release 2024-08-23 16:02:19 +02:00
7825d914e3 lvmlockd: increase dump buffer size 2024-08-22 16:23:07 -05:00
e2f6af68c2 WHATS_NEW: update 2024-08-22 14:47:29 +02:00
efbea49971 make: generate 2024-08-22 14:47:29 +02:00
038760da4f gcc: single type initializers
Older gcc doesn't really like complex types (buffer, struct) to be
initialized without extra {} around such type.
So pick any other 'single type' var from a struct and set it to 0,
rest will do the compiler without emitting a warning.
2024-08-22 14:47:29 +02:00
ff2cadbf18 cleanup: drop extra space 2024-08-22 14:38:40 +02:00
7dbb362c0f tests: check pvmove on single PV 2024-08-22 14:36:28 +02:00
07b6174f7c validation: support empty lv segments
Revert 373372c8ab and instead update
our validation code to handle LVs with empty segment - currently
we should need this only for pvmove operation, thus such LV should
have name  'pvmove%u'.

This fixes a problem where user tried i.e. pvmove on a VG with single
PV - as reported: https://github.com/lvmteam/lvm2/issues/148

Reported-by: bob@redhat.com
2024-08-22 14:36:28 +02:00
9df8dd97c3 WHATS_NEW: update 2024-08-14 15:30:30 +02:00
b53a2ae2a4 tools: vgscan: accept --refresh option 2024-08-14 15:12:59 +02:00
1ced65b6b4 tools: vgscan: accept --refresh option 2024-08-14 15:09:50 +02:00
9472e9c5a0 tools: args: update description for --refresh 2024-08-14 14:59:07 +02:00
4efed9ee99 tools: vgmknodes: use display_lvname 2024-08-14 14:20:55 +02:00
845a65a755 tools: vgmknodes: handle /dev/mapper content without LV refresh only if udev not running 2024-08-14 13:53:17 +02:00
5c6120186d tools: vgmknodes: log error message if LV refresh fails 2024-08-14 13:50:22 +02:00
75f9b0c25a tools: vgmknodes: wait for udev first with --refresh, then check /dev 2024-08-14 13:07:25 +02:00
bec1860531 man: vgmknodes: add note about udev and --refresh 2024-08-14 11:51:34 +02:00
012854b3c2 gitignore: update
The .cache and compile_commands.json is used by popular source crawling and
indexing clang tools which in turn may be integrated with source code editors.

We may reuse the .cache directory for for other caches and temporary
files.

The /doc/.ikiwiki and /public are related to the ikiwiki.
2024-08-13 11:17:57 +02:00
90a845a708 make: generate 2024-08-09 16:34:22 +02:00
9036862357 Revert "tests: use put_time"
This reverts commit b4af2571db.
std::put_time is a relatively new feature so breaks builds on older
systems.
2024-08-09 15:37:59 +02:00
2dc6c3d236 tests: add some udev waits
Avoid possible udev race - since dmsetup create is
not using the same cookie logic as lvm2 commands,
try to avoid racing on some systems with udev scanning.
2024-08-09 15:10:24 +02:00
b4af2571db tests: use put_time 2024-08-09 15:10:24 +02:00
a06a49b549 tests: search for delimiter in bounded buffer 2024-08-09 15:10:24 +02:00
aa75e1f0bf cov: annotate known case 2024-08-09 15:10:24 +02:00
e150931fc4 cov: validate list emptiness
Emit internal error for empty list.
2024-08-09 15:10:18 +02:00
d1c6da2f66 cov: validate altdev list is not empty 2024-08-09 15:10:18 +02:00
22672be97d cov: check for dev_iter_create result
dev_iter_create() may fail in malloc so check
for its error code.
2024-08-09 15:10:18 +02:00
76936f2832 cov: drop unused header inclusion 2024-08-09 13:20:44 +02:00
426c3c7b88 cov: avoid expression overflow
Use 64bit math to multiply extent_size.
2024-08-09 13:20:44 +02:00
78d14a805c integrity: add --integritysettings for tuning
The option can be used in multiple ways (like --cachesettings):

--integritysettings key=val
--integritysettings 'key1=val1 key2=val2'
--integritysettings key1=val1 --integritysettings key2=val2

Use with lvcreate or lvconvert when integrity is first enabled
to configure:
journal_sectors
journal_watermark
commit_time
bitmap_flush_interval
allow_discards

Use with lvchange to configure (only while inactive):
journal_watermark
commit_time
bitmap_flush_interval
allow_discards

lvchange --integritysettings "" clears any previously configured
settings, so dm-integrity will use its own defaults.

lvs -a -o integritysettings displays configured settings.
2024-08-07 17:40:34 -05:00
07576f7e51 devices: fix dev_dm_uuid
If a non-dm device is passed, the dm code doesn't fail and returns
some dm uuid.
2024-08-01 11:32:56 -05:00
ae8d5113f4 WHATS_NEW: update 2024-07-30 10:32:25 +02:00
7fdba39b3f tests: add tests for autoswitching to JSON format for log messages 2024-07-24 09:50:26 +00:00
0e8c429e30 make: generate 2024-07-24 09:50:26 +00:00
14dbf6ca7b reporter: simplify checking output format setting in report_format_init 2024-07-24 09:50:26 +00:00
3eecdcbd64 config_settings: fix typo 2024-07-24 09:50:26 +00:00
8281f7c111 config: use default log/command_log_report=1 for json/json_std output format
log/command_log_report config setting defaults to 1 now if json or json_std
output format is used (either by setting report/output_format config
setting or using --reportformat cmd line arg).

This means that if we use json/json_std output format, the command log
messages are then part of the json output too, not interleaved as
unstructured text mixed with the json output.

If log/command_log_report is set explicitly in the config, then we still
respect that, no matter what output format is used currently. In this
case, users can still separate and redirect the output by using
LVM_OUT_FD, LVM_ERR_FD and LVM_REPORT_FD so that the different types
do not interleave with the json/json_std output.
2024-07-24 09:50:26 +00:00
be229b0cd1 WHATS_NEW 2024-07-19 13:28:30 +02:00
557b2850ce lv_manip: avoid unreleased memory pool(s) message on RAID extend
In case of different PV sizes in a VG, the lvm2 allocator falls short
to define extended segments resiliently asked for 100%FREE RaidLV extension
and a RAID distinct allocation check fails.  Fix is to release a memory pool
on the resulting error path.

Until the lvm2 allocator gets enhanced (WIP) to do such complex (and other)
allocations proper, a workaround is to extend a RaidLV to any free space on
its already allocated PVs by defining those PVs on the lvextend command line
then iteratively run further such lvextend commands to extend it to its
final intended size.  Mind, this may be a non-trivial extension interation.
2024-07-18 14:36:47 +02:00
c288ddd6c8 pages: Update release note tag and timestamp 2024-07-12 12:50:20 +02:00
60fbbd5f5f post-release 2024-07-12 12:42:39 +02:00
0eef5ab6e1 pre-release 2024-07-12 12:42:39 +02:00
f8aa073a8d Revert "dev-cache: move global variables into cmd struct"
This reverts commit 77be3250d9.
2024-07-08 15:32:41 -05:00
39e65c8f59 Revert "bcache: move from global variable to cmd struct"
This reverts commit 5bf4efbab5.
2024-07-08 15:32:35 -05:00
5bf4efbab5 bcache: move from global variable to cmd struct 2024-07-03 12:58:18 -05:00
77be3250d9 dev-cache: move global variables into cmd struct
The cmd struct is now required in many more functions, and
it's added as a function arg for most direct dev-cache function
calls.  The cmd struct is added to struct device (dev->cmd) so
that it can be accessed in many other cases where dev-cache
functions are being called from places where getting the cmd
struct is too difficult.
2024-07-03 11:52:32 -05:00
57e9083c90 config_file: remove unused code
config_file_read() is only used for regular files, not devices.
2024-07-02 16:24:12 -05:00
76bd678ce3 devices: isolate fake device setup for config file
Freeing dev-cache from dumb fake device usage.
2024-07-02 16:18:09 -05:00
92fd2cb498 devices: isolate fake dev use for mirror checks
Freeing dev-cache from dumb fake device usage.
2024-07-02 15:07:43 -05:00
82d145a372 lvmlockd: fix compilation with disabled lvmlockd
With updated functionality for lvmlockd some prototypes
needs to be updated for builds without lvmlockd.
2024-07-02 16:58:03 +02:00
ad1d688734 devices: simpler dm devs cache naming
The dm devs cache is separate from the ordinary dev cache,
so give the function names distinct prefixes, using
"dm_devs_cache" to prefix dm devs cache functions.
2024-07-01 11:50:59 -05:00
8b4701d7c4 devices: redo bcache invalidation of PVs on LV 2024-07-01 11:30:51 -05:00
5551e4a1e9 devices: update dm uuid cache naming
replace "dm uuid" with "dm devs" in case it begins
caching more than dm uuids.
2024-07-01 10:59:16 -05:00
5f26c05bf2 Revert "devices: simpler bcache invalidation of PVs on LVs"
This reverts commit 200b05cec0.

Doesn't work to depend on lv name.
2024-07-01 10:59:16 -05:00
2f8550a388 doc: release notes for 2.03.25 2024-07-01 15:33:37 +02:00
3ced86217c WHATS_NEW: update 2024-07-01 15:33:36 +02:00
200b05cec0 devices: simpler bcache invalidation of PVs on LVs
When a PV is stacked on an LV, the PV needs to be
dropped from bcache before the LV is processed.
The LV can be found in dev-cache using its name
rather than the devno.
2024-06-28 18:19:15 -05:00
b8869e2d4e dev-cache: unify dm uuid cache struct lifetimes
The list of dm devs was in the cmd struct and had a
different lifetime than the radix trees referencing
those dm devs.  Now the list and radix trees are
created and destroyed together.
2024-06-28 18:01:29 -05:00
24943fe9d3 devices: update function name to dm_device_is_usable 2024-06-28 14:05:57 -05:00
990f4f7c4f devices: dm uuid related function names
In the context of dm, 'device' refers to a dm device, but
in the context of lvm, 'device' refers to struct device.
Change some lvm function names to make that difference clearer.

dev_manager_get_device_list() -> dev_manager_get_dm_active_devices()
get_device_list() -> get_dm_active_devices()
device_get_uuid() -> dev_dm_uuid(), devno_dm_uuid()
2024-06-28 14:05:53 -05:00
680f7bd676 lvmlockd: vgchange systemid doen't need global lock
The comment explained that the ex global lock was just
used to trigger global cache invalidation, which is no
longer needed.  This extra locking can cause problems
with LVM-activate when local and shared VGs are mixed
(and the incorrect exit code for errors was causing
problems.)
2024-06-27 13:29:03 -05:00
54a8562804 lvmlockd: after restart use existing dlm global lockspace
If lvmlockd is killed and restarted, let it adopt the
existing global lockspace.
2024-06-27 13:29:03 -05:00
f1d88007b0 lvmlockd: skip LV unlocking with no lvmlockd or no lockspace
vgchange -an vg is permitted when the vg lockspace
is not available, because LVs could still be active
for some reason, and they should be inactive when not
properly locked.  In case lvmlockd was not running, or
the lockspace was not started, the command was
unnecessarily trying and failing to unlock every LV,
printing errors for every LV.  We can skip this when
the lockspace is known to not be available.
2024-06-27 13:29:03 -05:00
d85ceff9c5 lvmlockd: let vgchange lockstop fail with EBUSY for orphans
vgchange --lockstop will fail with EBUSY if orphan locks in the
lock manager prevent stopping the lockspace.  The orphan locks
can then be adopted and released, and the lockspace then stopped
cleanly.
2024-06-27 13:29:03 -05:00
f32fd1fcb9 lvmlockd: adopt options
Lock adoption is not part of standard command behavior, but can
be used for manual recovery or cleanup from unexpected failure
cases.  Like other lockopt values, they are hidden options for
--lockopt.  Different lock managers will behave differently.
Adopting locks with lvmlockd -A1 is more accurate and automatic.

--lockopt adoptls
. for vgchange --lockstart
. adopt existing ls, or fail if no existing lockspace is found

--lockopt adoptgl | adoptvg | adoptlv
. for commands using lvmlockd locks
. adopt orphan gl/vg/lv lock, or fail the lock request if
  no orphan lock is found
. will fail if orphan lock exists with a different lock mode
. command may still continue with a failed shared lock request

--lockopt adopt
. for lockstart or any command using lvmlockd locks
. adopt existing lockspace, or start lockspace if none exists
. adopt orphan gl/vg/lv lock, or acquire new lock if no orphan found
. will fail if orphan lock exists with a different lock mode
. command may still continue with a failed shared lock request
. with dlm this option only works for ls
2024-06-27 13:29:03 -05:00
943e979079 lvmlockd: parse lockopt string into flags 2024-06-27 13:29:03 -05:00
9ea5ff3db5 lvmlockd: remove unused paramater
start_init option has never been used
2024-06-27 13:29:03 -05:00
4d8fb10af2 vgchange: improve some lvmlockd lockstart messages
Stop printing "Skipping global lock: lockspace not found or started"
for vgchange --lockstart, since it's generally an inherent limitation
that the global lock isn't available until after locking is started.

Update the start delay warning to "a few seconds".
2024-06-27 13:29:03 -05:00
bada03cd48 man: lvmlockd updates 2024-06-27 13:29:03 -05:00
e777ef720c lvmlockd: allow service options
command line options can be set in /etc/sysconfig/lvmlockd, e.g.
OPTIONS='-A1 -o2'
2024-06-27 13:29:03 -05:00
5e1d64a991 lvmlockd: reduce adopt delays 2024-06-27 13:29:03 -05:00
039be7d5b9 lvmlockd: update debug messages
Reduce debug messages, and make less verbose.
2024-06-27 13:29:03 -05:00
55687b6656 lvmlockd: disable lvb for sanlock
The lvb is used to hold lock versions, but lock verions are
no longer used (since the removal of lvmetad), so the lvb
is not actually useful.  Disable their use for sanlock to
avoid the extra i/o required to maintain the lvb.
2024-06-27 13:29:03 -05:00
58e75f6178 lvmlockd: skip more vgremove steps with lockopt force
vgremove with --lockopt force should skip lvmlockd-related
steps and allow a forced vg cleanup, in addition to using
--nolocking to skip normal locking calls.
2024-06-27 13:29:03 -05:00
4dc009c872 lvmlockd: allow forced vgchange locktype from none
vgchange --locktype sanlock|dlm --lockopt force <vgname>
can be used to change the lock type without lvmlockd or
the lock manager involved.
2024-06-27 13:29:03 -05:00
bf60cb4da2 lvmlockd: avoid lockd_vg for local VGs
Previously, a command would call lockd_vg() for a local VG,
which would go to lvmlockd, which would send back ENOLS,
and the command would not care when it saw the VG was local.
The pointless back-and-forth to lvmlockd for local VGs can
be avoided by checking the VG lock_type in lvmcache (which
label_scan now saves there; this wasn't the case back when
the original lockd_vg logic was added.)  If the lock_type
saved during label_scan indicates a local VG, then the
lockd_vg step is skipped.
2024-06-27 13:29:03 -05:00
1b9bf5007b scripts: Install services for devices file init
Services introduced in commit c609dedc2f
need installing.
2024-06-27 15:16:26 +02:00
ab93e1c38d pages: Fix typos 2024-06-27 15:16:26 +02:00
82ea579ba2 pages: Fix macro 2024-06-27 15:16:26 +02:00
21b215ee63 udev: disable suffix handling
The idea in the patch 6e6d4c62b for handling -suffix as
indication of private device needs to be disabled.

Some problematic cases are currently not resolvable and some
more thinking is needed.

Once fixed, we can revert this patch.
2024-06-25 23:18:07 +02:00
336cb32884 device_mapper: empty string for missing uuid
Constify name & uuid within dm_active_device.
Set uuid to "" for case the DM device has no uuid.
Do not store "empty" device uuid in radix tree.
2024-06-21 14:51:25 +02:00
57e6e94a83 WHATS_NEW: update 2024-06-21 11:28:54 +02:00
88fb07b669 label: use dev iterator directly
Avoid preparing 'extra' dm_list with devices, and just
use the iterator result directly.
2024-06-21 11:28:54 +02:00
cc344c3e69 dev_cache: replace dm_hash with radix_tree
For large device sets our dm_hash can produce larger amounf of mapping
collision and we would need to further increase our has size.

So instead use the radix_tree code which is immune agains growing size
of devices and uses memory more effiecently to store all the paths.
2024-06-21 11:28:54 +02:00
e0537559c6 dev-cache: replace btree with radix_tree usage
Instead of less efficient 'btree' switch dev_cache to use
radix_tree, that is generating more efficient tree mapping.

Some direct use of btree iteration replace with our dev_iter code.
2024-06-21 11:28:54 +02:00
4b126fd953 filter-persistent: convert to use radix_tree
Convert the persisten filter to use more memory compact radix_tree as
dm_hash is bound to preallocated number of slots and stores whole
key together with value.
2024-06-21 11:28:54 +02:00
ed440367b9 dev_manager: check if uuid isn't already in cache
When DM uuid cache is available, we can possibly avoid unnecessary
status ioctl() when we check the device for 'usable' uuid.

If this test passes the existing code will got through the full check.
2024-06-21 11:28:54 +02:00
e30bc9b179 device_mapper: refactor code to lvm library
Move the code around caching active dm device devno, name and uuid
from device_mapper/libdm-iface to dev_cache file - as libdm layer
cares about 'decoding' ioctl data from kernel and caching for use by
lvm stays within lvm.

Introduce:
dev_cache_update_dm_devs
dev_cache_get_dm_dev_by_devno
dev_cache_get_dm_dev_by_uuid

Use radix_tree for searching.
2024-06-21 11:28:54 +02:00
14f782c5a7 dev_manager: no layer suffix for component
Do not attach layer suffix to the UUID when activating component LV.

In this case we want to see allow this LV to be public, thus
such LV should not be using -layer suffix in its UUID.

This also requires that our 'cached' access will check for
both UUID (with & without suffix) which was unnoticed issue before.

This change is now necesssary since our udev rule automatically expects
any LV with -layer suffix is private and will prevent generaring
any systemd unit even when there are no 'DM' flags bits passed via
cookie mechanism while creating such LV.
2024-06-21 11:25:33 +02:00
b1d80a0ffd gcc: pipe error path
Close opened descriptors on failed fork path.
2024-06-19 14:28:02 +02:00
64ccbc4b52 gcc: check cv pointer when needed
As 'cv' was already dereferenced, check for NULL with do {} while();
loop.
2024-06-19 14:28:02 +02:00
a98beb8ee3 gcc: ensure all fmt struct element are initialized 2024-06-19 14:28:02 +02:00
f8907b8f3c gcc: ensure reset of fd on error path 2024-06-19 14:28:02 +02:00
d01e5ec126 raid_manip: prevent reshape with freed component SubLVs
In order to free SubLVs after a stripe removing reshape, lvconvert has
to be run without layout changes.   Prevent a layout changing request
in case any such freed SubLVs exist and inform the user about the fact
requesting to release them first.
2024-06-18 14:14:24 +02:00
cc6ddf978a tests: adjust lvconvert-raid-reshape-size.sh delays/timeouts 2024-06-18 14:13:20 +02:00
2468b66b30 tests: add reshape size consistency tests script lvconvert-raid-reshape-size.sh
Calculates expected size before/after reshapes adding/removing stripes
to/from RaidLVs with levels 4/5/6/10 and compares it with the actual
one the block layer shows.  Stripes reshaped to are listed in the
tst_stripes variable.  mkfs/fsck/resize2fs the respective RaidLVs
to confirm ext4 can be resized accordingly without issues.
2024-06-11 15:44:36 +02:00
6e6d4c62b3 udev: ignore private LVM devs in udev and systemd
We automatically ignore these devs, when lvm2 create devs,
whoever when lvm2 database is dropped or someone just
created these devs with such formated UUID, there is no
other informantion then to check DM UUID.
2024-06-03 15:30:05 +02:00
fe68fb0525 tests: fix wrong pos with CONFIG_PRINTK_CALLER
SUSE kernels distribution enables CONFIG_PRINTK_CALLER by default.

One line of cat /dev/kmsg is like:

6,904,9506214456,-,caller=T24012;loop8: detected capacity change from 0
to 354304

If CONFIG_PRINTK_CALLER is off:

6,721,53563833,-;loop0: detected capacity change from 0 to 354304

',caller=T24012' is the redundant part needed to be handled.
Otherwise pos will be lager than buf size causing sz underflowed.
Then constructor of std::string will throw a exception to break
tests:
$ make  check_local  T=shell/000-basic.sh
VERBOSE=0 ./lib/runner \
        --testdir . --outdir results \
        --flavours ndev-vanilla --only shell/000-basic.sh --skip @

running 1 tests
running: [ndev-vanilla] shell/000-basic.sh
            0:00.000Exception: basic_string::_M_create
make[1]: *** [Makefile:148: check_local] Error 1
make[1]: Leaving directory '/root/lvm2/test'
make: *** [Makefile:89: check_local] Error 2

Fix it with strchr for ';' as delimiter to get pos.

Reported-by: Su Yue <glass.su@suse.com>
2024-06-03 15:30:05 +02:00
3a9689652d radix_tree: add radix_tree_values
To more easily adopt radix_tree over existing code base, add
abstraction over 'radix_tree_iterate' which basically builds
an array of all traversed values, and then it's just easy to
go over all array elements.

TODO: code should be converted to use  radix_tree_iterate()
directly as it's more efficient.

Note: it can be possibly to rewrite recursive _iterate() usage
to linear travesal, not sure whether it's worth the effort
as conversion to 'radix_itree_iterator' is relatively simple.
2024-06-03 15:30:05 +02:00
1813d0d186 radix_tree: add radix_tree_lookup/insert_ptr
Add simple 'wrapper' inline functions to insert or return ptr lookup value.
(So the user doesn't need to deal with 'union radix_value' locally and
also it makes easier to translage some lvm2 functions to use radix_tree).

Note: If the stored 'value' would NULL, it cannot be recognized
from a case of 'not found'. So usable only when 'values' stored with
tree are not NULL.
2024-06-03 15:30:05 +02:00
b77edc337a radix_tree: constify _iterate
Use nodes as const.
Swap order of arguments.
2024-06-03 15:30:05 +02:00
1e2a3445d9 radix_tree: debug updates
Some updates to _dump()  debugging function so the printed result
can be more easily examined by human.

Also print 'prefix' as string when all chars are printable.

Add 'simple' variant of _dump also to 'simple' version of radix tree
(which is however normally not compiled).
2024-06-03 15:30:05 +02:00
88681f05f1 radix_tree: api change
Instead of using 'key state & key end' uint8_t* switch to use
void* key, & size_t keylen.  This allows easier adaptation with
lvm code base with way too much casting with every use of function.

Also correctly mark const buffers to avoid compiled warnings and
casting.

Adapt the only bcache user ATM for API change.

Adapt unit test to match changed API.
2024-06-03 15:30:05 +02:00
5731d06bc5 radix_tree: indent
Some minor indent changes to more easily read code.
2024-06-03 15:30:05 +02:00
76ca20a9af gcc: drop const specifier from allocated string
Use nornal (char*) for pointers we should free().
2024-06-03 15:30:05 +02:00
524df486b3 cov: annotate already validated lv name 2024-06-03 15:30:05 +02:00
896410b393 cleanup: use _ for static var
Add missing '_' for some static vars.
2024-06-03 15:30:05 +02:00
cd0f5ee36c cleanup: remove unneded headers
As the common code was refactored to toollib, this header file
no longer needs to be included here.
2024-06-03 15:30:05 +02:00
13e0222ba2 device_id: more use of device_get_uuid
Use function that is caching UUID if kernel provides functionality
from a single ioctl() call.
2024-06-03 15:30:05 +02:00
fffff2c2a2 dev-mpath: check uuid with device_get_uuid 2024-06-03 15:30:05 +02:00
915dd18361 typo: fix typos
Typo and indent.
2024-06-03 15:30:05 +02:00
85e0636623 cleanup: some more MAJOR MINOR unsigned
Finish remaing missing cases where MAJOR/MINOR was casted to (int)
while we can now use it directly as 'unsigned'.
2024-06-03 15:30:05 +02:00
91502446ac lvremove: reuse existing dm_build_dm_uuid
Use existing dm_build_dm_uuid() to generate LV's DM UUID.
2024-06-03 15:30:05 +02:00
a8b8e1f074 vgimportdevices: skip global lockd locking
Fix commit b65a2c3f3a "vgimportdevices: skip lvmlockd locking"
which intended to disable lvmlockd locking, but the lockd_gl_disable
flag was mistakenly set after lock_global() so it wasn't effective.
This caused vgimportdevices to fail unless locking was started.
2024-05-30 14:53:46 -05:00
ace25d5eeb README: remove old branch names 2024-05-29 09:30:41 -05:00
9ee6a9b982 make: generate 2024-05-28 14:55:53 +02:00
c14e0282ec tests: accept new vdoformat output
There is slight change in the printed size number.
2024-05-28 14:55:53 +02:00
2c8ff67470 args: generate configurable path 2024-05-28 14:55:53 +02:00
f10de12ade tests: quoted DM_DEV_DIR 2024-05-27 21:34:25 +02:00
7e59c3aa58 tests: use single aux lvmconf
Reduce log size as lvmconf can process multiple settings at once.
2024-05-27 21:34:25 +02:00
9207bae33b device_id: use faster dm_strncpy 2024-05-27 21:34:25 +02:00
fbdd26a4a3 device_mapper: solve no devices path
Malloc needs to use sane value when names would be NULL.
Also for devices without 'uuid' return empty string instead of NULL.
2024-05-27 21:33:59 +02:00
533a87d0ea lvremove: initilize struct list 2024-05-27 18:23:26 +02:00
80fa3511be lvremove: check for handle
Get lvremove_params from non NULL handle.
Introduced in commit 47f8bda05.
TODO: any more thing needed ?
2024-05-27 17:03:37 +02:00
c496cfa99a WHATS_NEW: update 2024-05-27 16:35:23 +02:00
d825e8887c make: generate 2024-05-27 16:35:23 +02:00
9dfe5ce2bc cov: replace enum report_type_t with unsigned
Another enum used as bitfield mask.
2024-05-27 16:35:23 +02:00
90c6c421cd cov: convert some more enternal field masks
Some more 'internal' masks misusing enums for bitfields.
2024-05-27 16:35:23 +02:00
3b649c3076 cov: cleanup mask from enum to unsigned
Enums are single 'values' so not a proper type for bitfields.
(Probably better to use such values as defines).

Although here 'daemon_talk()' is part of library API, it's hidden
non-public API call - and moreover 'enum' and 'unsigned' are
using the same size, so linker shouldn't have any issue with
this symbol usage.

For this reason there are no 'versioning' tricks applied.
2024-05-27 16:35:23 +02:00
403ecb46fa cov: annotate known use of validated lv name 2024-05-27 16:35:23 +02:00
1b90865843 cleanup: remove blank spaces 2024-05-27 16:35:23 +02:00
88e0060aa8 cleanup: refactor common code
Refactor shared code from _get_rootvg_dev() between vgchange
and vgimportdevices to get_rootvg_dev_uuid() in toollib.c
2024-05-27 16:35:00 +02:00
2e6e752c3a tests: add some lvm shell testing
Check lvm shell for autocomplete functionality and error reporting.
2024-05-27 15:35:58 +02:00
cd56b04ef6 cleanup: print MAJOR and MINOR as unsigned
Print directly as %u instead of %d with (int) casting.
2024-05-27 15:35:58 +02:00
cdcd482fa4 libdm: use 'unsigned' for major minor
Although linux uses 'dev_t' as 'unsigned long int' on 64bit,
it's easier to print with just '%u' instead of '%lu'.
2024-05-27 15:35:58 +02:00
e1fd179dc5 cleanup: replace strlen with sizeof
Use the string size from compile time.
2024-05-27 15:35:58 +02:00
eaa4882924 cleanup: use const for sizeof values 2024-05-27 15:35:58 +02:00
ddf3b6e5e3 cleanup: simplier loop condition
Check char for != 0.
2024-05-27 15:35:58 +02:00
9ab2607c7f cleanup: use correct log_sys_debug 2024-05-27 15:35:58 +02:00
40cf4ce1e1 cleanup: struct reorder
Better alignments.
2024-05-27 15:35:58 +02:00
45c06025da cleanup: some typos
Collection of some typos or invalid uppercase or doublespace cases.
2024-05-27 15:35:57 +02:00
bbe1b93ed9 hash: increase some default hash table size
Size of these hashes was quite small, so raise the size of
hashed entries to reduce amount of hash collistion.
Select some unique/unused number for hash_create below 8192.
2024-05-27 15:35:57 +02:00
93115ef91d libdm: drop allocation
Use structure allocated on local stack.
2024-05-27 15:35:57 +02:00
fdfe80f024 mirror: drop unneeded call
Major,minor,patchlevel are already set from previous call.
2024-05-27 15:35:57 +02:00
01e014a246 device: use device_get_uuid
Replace call to get_dm_uuid_from_sysfs() with use of
device_get_uuid() which gets the same information,
but instead of several syscalls it need either 1 or even 0
when the information is cached with newer kernels.
2024-05-27 15:35:57 +02:00
b63e54d0ed dev_manager: remove disable_dm_dev flag
Lvm currenly drops cache before first table manipulation
there is no need for this flag ATM.
2024-05-27 15:35:57 +02:00
e211768d1c dev_manager: drop cache for dm tree manipulation
We've got cached DM list before grabbing lock, so there
is some chance, that DM table has changed and we would
need to refresh this info.

TODO: benchmark, whether it would even make sense to refresh cache
and keep it content instead of using individual ioctl() for tree build.
2024-05-27 15:35:57 +02:00
d192477ae6 label: cache dm dev list earlier
Cache (when possibly with newer kernel) earlier within label
scanning loop, so the cache information can be also used by
hints file.
2024-05-27 15:35:57 +02:00
dac2bfe6a4 device_manager: add device_get_uuid
Function that is working with DM target is located within
lib/activate directory.

This function is able to use cached  dm_device_list when possible
to quickly resolve checks for device's UUID.

Function can fully replace get_dm_uuid_from_sysfs() and instead
of syscalls for open/read/close get the UUID with single ioctl.

When there is cached dm devs list, we can get many UUID from
a single syscall.
2024-05-27 15:35:56 +02:00
5da282fa23 device: propagate struct cmd_context
For better use of cached data located within cmd_context,
pass this structure from the top level function.
Also add missing '_' for static _dev_cache_index_devs.
No other change here.
2024-05-27 15:35:17 +02:00
1712845ab5 device_mapper: use const for this API
Allow using constified version of devs_list.
Internal loop does not need to modify anythin in this stucture.
2024-05-27 15:35:17 +02:00
36691b9844 device_mapper: add dm_device_list_find_by_dev
Introduce function to find device's name and uuid for
a given major:minor.

This information is cached with dm_device_list which reads all the
info from single ioctl(DM_DEVICE_LIST).
Lvm keeps major:minor name & uuid for active devices in the system.
2024-05-27 15:34:16 +02:00
5c24d6d4db dev-type: use if..else if...
Compare strings till the first match.
2024-05-27 15:16:26 +02:00
aad1add77f command: reorder vals order
Keep most frequently used val names in front.
2024-05-27 15:16:26 +02:00
314c759a09 command: store val_name with its size
Compile length of val_name during compilation.
2024-05-27 15:16:26 +02:00
a198224666 dev-cache: skip scanning known blockless dirs
Skip scan and stat() for dirs and nodes within known /dev/ paths,
where no block devices are located.

Also strlen(_cache.dev_dir) just once.

TODO: add more dirs to _no_scan (configurable via lvm.conf ?)
2024-05-27 15:16:26 +02:00
d8e639ecba dev-cache: collapsing slashes counts string size
_collapse_slashes() already goes through the whole string,
so just return now already known string length.
2024-05-27 15:16:26 +02:00
caa0e08738 cleanup: use single array for idtype string
Share string array for de/coding idtype.
2024-05-27 15:16:26 +02:00
2e0ac97903 error: try with modprobe
If the error target would be built as module,
ask modprobe to load it if the target is not present.
2024-05-27 15:16:26 +02:00
9a371639fc cleanup: relocate section
Move _features[] structure from .data.rel.ro to .rodata.
2024-05-27 15:16:26 +02:00
83c0b19f61 cleanup: use ALTERNATIVE_EXTENTS
Instead of comparing string of command names,
introduce ALTERNATIVE_EXTENTS command flags.
2024-05-27 15:16:25 +02:00
93918a1990 cleanup: use ARG_LONG_OPT
Just like with _VAL strings, also _ARG strings do not need to
be present - as we can easily check for LONG opt version just
by adding attribute.

With attribute ARG_LONG_OPT string arg name[] becomes unused
and can be safely removed.

Also within _find_command_id_function() we do not need to handle
'command_enum == CMD_NONE' as separate case and just use single loop.
2024-05-27 15:16:25 +02:00
59345da03f cleanup: do not store _VAL name string
String enum_name[] is unused so remove is with
all generated strings.

Reoder struct members, so there are no holes.
2024-05-27 15:16:25 +02:00
dd78573073 libdm: parse only block section for proc_devices
Check for begining of 'B'lock section in /proc/devices file
before starting to sscanf() for major.
2024-05-27 15:16:25 +02:00
38d34dbe75 lvmcmdline: use known lvm_command_enum
lvm command is already decoded (when found),
so use lvm_command_enum directly and avoid
comparing all strings again...
2024-05-27 15:16:25 +02:00
5173b0c222 command: return proper unsigned value
Use better 'unsigned' value, so we don't have any 'casting' troubles.
2024-05-27 15:16:25 +02:00
73298635b9 lvm: fix shell completion
Previous commit 82617852a4
introduce bug in complession - as the rl_completion_matches()
needs to always advance to next element where the index
is held in static variable.

Add comment about this usage.
2024-05-27 15:16:25 +02:00
47f8bda051 lvremove: remove device_id for PVs on LVs
When PVs are created on LVs, remove the devices file entries
for the PVs when the LVs are removed.  In general, the devices
file entries should be removed with lvmdevices --deldev when
the LVs are removed (lvremove is the equivalent of detaching
a device from the system when layering PVs on LVs.)
This change is effectively an automatic lvmdevices --deldev
command that is built into lvremove when the LV has a PV on it.
2024-05-22 15:32:17 -05:00
c609dedc2f Allow system.devices to be automatically created on first boot
An OS installer can create system.devices for the system and
disks, but an OS image cannot create the system-specific
system.devices.  The OS image can instead configure the
image so that lvm will create system.devices on first boot.

Image preparation steps to enable auto creation of system.devices:
- create empty file /etc/lvm/devices/auto-import-rootvg
- remove any existing /etc/lvm/devices/system.devices
- enable lvm-devices-import.path
- enable lvm-devices-import.service

On first boot of the prepared image:
- udev triggers vgchange -aay --autoactivation event <rootvg>
- vgchange activates LVs in the root VG
- vgchange finds the file /etc/lvm/devices/auto-import-rootvg,
  and no /etc/lvm/devices/system.devices, so it creates
  /run/lvm/lvm-devices-import
- lvm-devices-import.path is run when /run/lvm/lvm-devices-import
  appears, and triggers lvm-devices-import.service
- lvm-devices-import.service runs vgimportdevices --rootvg --auto
- vgimportdevices finds /etc/lvm/devices/auto-import-rootvg,
  and no system.devices, so it creates system.devices containing
  PVs in the root VG, and removes /etc/lvm/devices/auto-import-rootvg
  and /run/lvm/lvm-devices-import

Run directly, vgimportdevices --rootvg (without --auto), will create
a new system.devices for the root VG, or will add devices for the
root VG to an existing system.devices.
2024-05-21 16:29:12 -05:00
6fdc8787eb post-release 2024-05-16 12:17:02 +02:00
90ec2cd92f pre-release 2024-05-16 12:12:06 +02:00
15413226a8 pages: Use gitlab pages and ikiwiki for doc 2024-05-16 12:00:26 +02:00
5906f44bee doc: Update TESTING file 2024-05-16 11:32:43 +02:00
32b2776afc makefiles: use properly defined varitable
Variable used for tracking dependencies is USE_TRACKING.
2024-05-14 17:59:26 +02:00
a0c5b2c9fd tests: add basics for dm_hash unit testing
Better code coverage.
2024-05-14 17:59:26 +02:00
e59c84ca3a gcc: clean cast with -Wbad-function-cast
Makes gcc happier.
2024-05-14 17:59:26 +02:00
e3dff2cba2 gcc: same signess 2024-05-14 17:59:26 +02:00
7d22be22d9 gcc: use proper commnent 2024-05-14 17:59:26 +02:00
e08e5a5a07 gcc: better initilizer for older gcc compilers
So use  { { } }.
2024-05-14 17:59:26 +02:00
915267c900 activation: log_debug_activation
Correcting debug class.
2024-05-14 17:59:16 +02:00
c2c028c680 tests: reduce number of created LVs
lvm2 for a while already optimizes 'vgremove' operation to
a single commit when possible if all LVs can be
easily deactivated.

So the number of LVs doesn't matter much - but the tested
case 'test_delete_non_complete_job' seems to be taking
some time anyway to capture the exception.

So just reducing the running time of the test significatanly
as we don't need to create 64LVs for 4 'execution mode' runs.
2024-05-13 18:04:34 +02:00
a86fb27607 cov: ensure pointer has defined value
Add initialization of 'fin' pointer.
2024-05-13 17:32:46 +02:00
c6b5eb5b50 dmfilemapd: assign 0 to integer
Avoid mixing enumeration assign with 0, so just pick some integer
from filemap_monitor,  stucture will be fully zeroed anyway....
2024-05-13 17:32:46 +02:00
d58a2644e6 libdevmapper-event: correct switch break
Replace 'continue' within 'switch' statement with correct break.
2024-05-13 17:32:46 +02:00
aafa22e643 man: lvmlockd: remove dash in option name
for consistency with other man pages
2024-05-13 09:16:20 -05:00
af983ad3d3 lvmcmdline: check for NULL
Althought this code likely never is hit with NULL, just add
check to be sure.
2024-05-13 14:49:54 +02:00
c0e7cdff9d cov: enusure _table doesn't leak
If someone would enter _table multiple times by mistatek,
there is 'teroretical' leak - although doesn't matter much
in this case...
2024-05-13 14:48:46 +02:00
a1a1e13dbe make: generate 2024-05-13 12:58:37 +02:00
60bad2f22d lv_types: sort order of types
Order is used for man page generation (although not completely).
So place  'zero & error' to the end of list.
Keep  linear,striped,snapshot in front.
For the rest use alphabetic order.
2024-05-13 12:58:37 +02:00
026344e8cc cleanup: local const arrays
No need for relocation entries for locally used arrays.
2024-05-13 12:58:37 +02:00
ee3be2807f cleanup: static missed _ 2024-05-13 12:58:37 +02:00
d25c43c8cd cleanup: remove unuable code path
Eliminate some ancient unreachable code
for historical version of libdm.
2024-05-13 12:58:37 +02:00
ffdceeb982 cleanup: some missed public symbols static 2024-05-13 12:58:19 +02:00
74e487f3a9 label: make scan_bcache local
Seems there are no users of scan_bcache, so make it local.
TODO: such variable should be ideally in cmd_context.
2024-05-13 02:21:37 +02:00
8da0ab6fc1 cleanup: drop unused declared struct 2024-05-13 02:21:37 +02:00
c7a9a1fb6c cleanup: use static vars
Drop global visibility.
2024-05-13 02:21:37 +02:00
46669fe9e8 cleanup: add static _ 2024-05-13 02:21:37 +02:00
5b7e30da76 lv_type: simplier macro usage
Use more simple macros - as there is likely not going to happen
any macro replacement - so use more effient structure layout.
2024-05-13 02:21:28 +02:00
429ab45a1c lv_prop: simplier macro usage
Use more simple macros - as there is likely not going to happen
any macro replacement - so use more effient structure layout.
2024-05-13 02:20:29 +02:00
f86bdcb6e9 command: validation code only for man-generator
Don't waste time with string order validation within command,
check within  'man-generator -c' is enough.
2024-05-13 02:18:19 +02:00
25236a963f command: refactor inner loop
Move part of the 'inner' loop which is would be otherwise
always production same results for all  'opt_enum' values
out of the loop, so it can be evaluated just once.
2024-05-13 02:18:18 +02:00
fd8ed7554e command: replace strcmp with enum
Here we already know 'enum' value, so compare
just those instead of calling strcmp().
2024-05-13 02:15:55 +02:00
1a219c69ee lvmcmdline: runtime function resolving
Instead of resolving and storing 'command_fn'
withing 'struct command' use just funtion enum
and resolve function pointer just in place,
where it is really needed - first try to resolve
'new style' and fallback to 'old style' named.
2024-05-13 02:15:55 +02:00
bebbb1e66a command: use command_id_to_enum
Instead of storing command_id as string, direcly
translate string to enum index and use 'command_enum()'
to get string when needed for printing.

This way we can easily detect error in the structure
while parsing it - and we can later avoid separate
'translation' loop.
2024-05-13 02:15:55 +02:00
5840f90e82 command: refactor code for simplier lookup
We can more efficiently use command_name struct to
lookup for  lvm_command_enum and avoid many repeated
command name searches since we already know
the enum index that is now stored in 'struct command'.
2024-05-13 02:15:55 +02:00
82617852a4 lvmcmdline: use strcut as const
Constity members in cmdline_context, would be nice, to replace
this static struct with couple function calls.

Also replace some 'while' loops with for loops, so code
is more readable.
2024-05-13 02:15:55 +02:00
f854e3a722 command: return if already factored
We can directly return here, when we spot already counted varitants.
2024-05-13 02:15:53 +02:00
abe1b49b47 command: refactor struct command_name
Split struct command_name to the constant part (keep the name)
and new 'struct command_name_args' which holds runtime computed
info.   To get to the _args part - we can easily use
lvm_command_enum as equivalent index.

Constified part 'struct command_name' is now fully stored
in .data.rel.ro segment, while command_name_args part goes
to .bss segment.

Code will be further reduced with next refactoring.
2024-05-12 23:53:19 +02:00
433154fc8a command: better const usage for struct cmd_name
No need to store _CMD string - as it's not used anywhere.
Use LVM_COMMAND_COUNT as end of array.
2024-05-12 23:53:19 +02:00
8ac1cc593e command: reduce struct size
Reduce memory usage for parser.
If the sizes would need to be bigger, man-generator warns.
For struct command_name  use just uint8_t to keep 1|0.
2024-05-12 23:49:09 +02:00
d85c9728fb command: no need to duplicate const mem
No need to duplicate const char* here as
we refer already constant string in .rodata segment.
2024-05-12 22:17:46 +02:00
1c396598ff command: futher move to single struct
Refactor code to not allocate memory for rule->opts,
instead use uint16_t array of MAX_RULE_OPTS within cmd_rule.

Also print more info if array would not be enough (>= 8).
2024-05-12 22:15:15 +02:00
d3c22aedc4 tests: check vg fields with one command 2024-05-10 22:04:06 +02:00
057b1bde75 tests: keep more LVs inactive 2024-05-10 21:42:00 +02:00
e54bfe2a83 tests: mask result from kill command 2024-05-10 21:41:13 +02:00
cd6e1d0475 tests: wait for running dmeventd
Add slight delay for waiting until 'started' dmeventd is
responsing to other 'dmeventd -i' command.

TODO: race observed here is somewhat unclear, might need some more
details
2024-05-10 17:53:44 +02:00
b678decfca tests: kill process in flock group
There is no reason to wait for 10sec when removing 'vg' at test
exit - we just need to kill 'sleep 10' process forked from flock.

(Not using 'flock -F' as this flag is not across all machines used
for testing)
2024-05-10 17:36:48 +02:00
87cd61c6bd tests: skip test on systems without delay_dev
On such systems this test only sleeps for 30sec.
2024-05-10 17:35:07 +02:00
00cfe3a24e libdm: reapply "fix condition"
This reverts commit d16a8f80e9.
So the correction was OK, however we missed to fix also
cut&paste bug here - as the second check should be
actually checking  field->type.
2024-05-10 14:24:17 +02:00
55a9fb98d1 WHATS_NEW: update 2024-05-10 01:15:55 +02:00
44d58f28f1 make: generate 2024-05-10 01:15:55 +02:00
d2c6866bdb tests: vdo conversion updates 2024-05-10 01:15:55 +02:00
868bd3b51e commands: move tabs to eol
Make the source code a bit easier to read.
2024-05-10 01:15:55 +02:00
5aff63c07b commands: enable more options for vdo conversion
Update definitions to add support for some more VDO options
when converting volumes to be used as thin-pool with vdo data volume.

Split some option in existing OO_LVCONVERT_VDO to OO_LVCONVERT_VDO_POOL
and reused then with OO_LVCONVERT_THINPOOL.
2024-05-10 01:15:55 +02:00
8a323082ef lvconvert: vdo support conversion options
When convert already existing vdopool to be used as
thin-pool backend and user is passinng option for VDO configuration
process them - as we know converted LV is offline, we can do such
change easily instead of telling user to run separate lvchange later.
2024-05-10 01:15:55 +02:00
04d9f13fa6 lvconvert: vdo control for signature wiping
When converting volumes to be used for thin-pool with VDO, allow
users to control wipesingature behaviour.
By default volumes should be checked against signature, and if
they are present, we promt user whether he wants to process with
conversion and lose i.e. filesystem present on such volume.

Users that want to bypass prompt in script can use either --yes
or they can disable wipe signature -Wn.
2024-05-10 01:15:55 +02:00
298bd24e53 man: lvmthin more extend options 2024-05-08 10:30:05 -05:00
7a74229a8e tests: runner updates line with last timestamp 2024-05-08 16:14:58 +02:00
a3dcdf5671 clean: use struct initializer 2024-05-08 16:14:58 +02:00
6db19f6b51 dmsetup: const string_args array
Convert _string_args to const char*.
Do not modify options read from getopt().
2024-05-08 16:13:11 +02:00
57143a216e dmsetup: use tab for indent
Use \t for help indention.
2024-05-08 16:12:41 +02:00
7c016506a2 dmsetup: more const strings
More strings into .rodata segment.
2024-05-08 16:12:07 +02:00
5561f2a530 dmsetup: reduce parser code
Switch set upfront.
Only add code, which is not common for every switch.
Use just 16bit for switch counting.
2024-05-08 16:10:52 +02:00
2f3fcbd245 libdm: fix invalid conversion
Previous commit missed to also add one to added 'len'.
2024-05-08 10:16:01 +02:00
4dda6d1555 libdm: stats uses overflowing counter
Here we need to annotate counter as it starts with UINT64_MAX
and overflows to 0 is expected.
2024-05-08 10:14:52 +02:00
8168b5e71d clenaup: update local static with _ 2024-05-08 01:55:21 +02:00
c48cc22b18 const: tests 2024-05-08 01:55:21 +02:00
edbc0ed447 man-generator: remove unused declarations 2024-05-08 01:55:21 +02:00
383d7c4413 cov: remove dead code 2024-05-08 01:55:21 +02:00
cfcbf89ed0 cov: eliminate dead code
Deduplicate code and also drop some warn about dead code.
2024-05-08 01:55:21 +02:00
09f70dbb87 cov: avoid TOCTOU
Use just opendir() call and produce error message from errno state.
2024-05-08 01:55:21 +02:00
5f1c799e6a cov: enum mapping cache format
Cleanly map cache metadata format enumeration.
2024-05-08 01:55:21 +02:00
f0d3d0482e cov: enum health status
Cleanly map health char status to enum.
2024-05-08 01:55:21 +02:00
5818fbfbcf cov: enum matching type 2024-05-08 01:55:21 +02:00
3e91823b3e cov: enum correct prototype
Cleanup enum usage.
2024-05-08 01:55:21 +02:00
59b4c97564 cov: cast to matching prototype
Match function prototype with casting.
2024-05-08 01:55:21 +02:00
3f41b4af55 cov: check for overlow math
Add some extre protection to avoid integer overflow type of problems.
2024-05-08 01:55:21 +02:00
5c7d6083a9 cov: annotate to silent some coverity warning 2024-05-08 01:55:21 +02:00
bbf352892d cov: use literal for printf
Use literal for printf and just empty string if needed.
2024-05-08 01:55:21 +02:00
d7c2fe9723 cov: use literal for printf format
Prepare suffix ahead and use literal for printf().
2024-05-08 01:55:21 +02:00
f6e0e7b9aa cov: sanitize input buffer
Make coverity aware the input line is legit.
Eventually add more sanitize functionality.
2024-05-08 01:55:21 +02:00
9f4dc4170b cov: sanitize string for file path 2024-05-08 01:55:21 +02:00
a07bf7b90b cov: wrap pvck call
Resolve reported leak by renaming existing pckk() to pvck_mf()
and wrapping pvck() over this. This function can easily
free allocated buffer within the subfunction.
2024-05-08 01:55:21 +02:00
dae792baad cov: strcpy mempcy 2024-05-08 01:55:21 +02:00
db40a2e33c cov: replace strcat with safe snprintf 2024-05-08 01:55:21 +02:00
4761753a6f cov: replace strcpy with memcpy 2024-05-08 01:55:21 +02:00
04b407674c cov: use sscanf buffer size limits
String parsing with buffer size limit.
2024-05-08 01:55:21 +02:00
61a11f25a3 cov: check for valid raid0 LV segment
Add internal error to quiet Coverity fear of NULL pointer deref.
2024-05-08 01:55:21 +02:00
099a4e2146 raid: easier prompt message
Use  printf capability of 'prompt()' funtions so use literal
when building this message.
2024-05-08 01:55:21 +02:00
91991e3cc1 lvmlockd-dlm: log_error message with literal
Use literals for printf() message construction.
2024-05-08 01:55:21 +02:00
e56e7ed533 libdm: unlink checks for ENOENT 2024-05-08 01:55:21 +02:00
a763420786 libdm: use literal for error message
Use literals for printf messages.
2024-05-08 01:55:20 +02:00
75a03c2c26 const: daemon server logging backend struct 2024-05-08 01:55:20 +02:00
495ea0f058 const: lvmpolld long_options
Rework usage of long_options so it can be constified,
and also correct use of 'enum action_index'.
2024-05-08 01:55:20 +02:00
c140601cf6 const: rework conversion to enum
Easier code with string and also avoids mixing enums.
2024-05-08 01:55:20 +02:00
5d573cc91d const: array of const values 2024-05-08 01:55:20 +02:00
7b872bc4cd const: libdm err_fmt as string 2024-05-08 01:55:20 +02:00
2a75dc7465 man: lvmthin update
major refresh of text and organization
2024-05-06 12:17:13 -05:00
09426b4663 dmsetup: fix invalid loop test
Last patcheds had incorrect merging bug - fix loop test.
2024-05-04 01:53:54 +02:00
d16a8f80e9 Revert "libdm: fix condition"
This reverts commit 2a1e200f7a.

Breaks some test - more analysis is needed.
2024-05-04 01:37:51 +02:00
f3d3d4a07d WHATS_NEW: update 2024-05-04 01:02:31 +02:00
2e38369ecf make: generate
Update for --wipesignatures for lvconvert.
2024-05-04 01:02:18 +02:00
011e0672c5 dmsetup: use getopt defines
Replace 0/1 with getopts defines no/required_argument
2024-05-04 01:01:57 +02:00
2b198cd874 const: dmsetup long_options 2024-05-04 01:01:57 +02:00
8daa702880 const: dmsetup string 2024-05-04 01:01:57 +02:00
781bb0ea37 const: cmirrord array 2024-05-04 01:01:57 +02:00
f65f5e1c22 const: lvmlockctl options 2024-05-04 01:01:57 +02:00
9a9db862a4 const: dmfilemapd strings 2024-05-04 01:01:57 +02:00
7f25e58f66 const: array for _vdo_split 2024-05-04 01:01:57 +02:00
0eb6a59299 const: report_name 2024-05-04 01:01:57 +02:00
e0bd66b73a const: use common error path
Instead of defining  _field_selection_value_alloc_failed_msg[],
use common error path code for printing field_id.
2024-05-04 01:01:57 +02:00
8bbd00162b const: log level string 2024-05-04 01:01:57 +02:00
c9f9744f50 const: libdm cmd_data_v4 2024-05-04 01:01:57 +02:00
9247e754fe const: libdm tok_op 2024-05-04 01:01:57 +02:00
eae0314b55 const: suffixes list
dm_tree_set_optional_uuid_suffixes() is safe to use with overcasted
array to (const char**)
2024-05-04 01:01:57 +02:00
9cf127b429 const: suffixes 2024-05-04 01:01:57 +02:00
0e5250c475 const: _reserved 2024-05-04 01:01:57 +02:00
e6f46fafe7 const: use arrays of strings 2
Next set of changes.
2024-05-04 01:01:57 +02:00
0bcf2c6514 const: use arrays of strings
Such string is stored directly in '.rodata' section.
2024-05-04 01:01:57 +02:00
efe2005022 const: drop static keyword
We don't need relocatable space to store 'const' number.
2024-05-04 01:01:57 +02:00
abf7c40185 const: static array
Such array can be stored  in   .rodata   section.
2024-05-04 01:01:57 +02:00
acabc995c0 const: config items 2024-05-04 01:01:57 +02:00
9f506eb89e const: raid takover arrays 2024-05-04 01:01:57 +02:00
6430a6ca63 const: _fns poll_function 2024-05-04 01:01:57 +02:00
ff699eab24 const: _ops text_vg_version 2024-05-04 01:01:57 +02:00
41ffa8c74d const: _ops labeler _text_ops 2024-05-04 01:01:57 +02:00
64cb8b5940 const: _ops segtype handler 2024-05-04 01:01:57 +02:00
effafa8fc8 const: _ops text handler
Making sure these structures ends in '.data.rel.ro' section.
(instead of plain '.data' section).
2024-05-04 01:01:42 +02:00
2a1e200f7a libdm: fix condition
When we switch supported_reserved_types_with_range to const
gcc repots this problem:

 warning: ‘and’ of mutually exclusive equal-tests is always 0
 !(iter->type & supported_reserved_types_with_range))) {

It's not clear from the history what was the actual intention of this
internal error test, let's assume the check wanted to make sure
that when DM_REPORT_FIELD_RESERVED_VALUE_RANGE is set,
some other fields from supported_reserved_types_with_range set
are also selected.
2024-05-04 00:58:44 +02:00
9b2f9d64c0 libdm: ensure suffixes list elements are const
This was rather API mistake - the internal of libdm
do handle suffixes list as const string, just the API
was only using  'const char **'.

So the user may pass safely casted 'const char * const`.
2024-05-04 00:57:52 +02:00
e02695cb45 lvonvert: support control over wipingsignature
When converting volume to a thin-pool allow control over
signature wiping.

TODO: likely should become more commonly supported option...
2024-05-04 00:57:52 +02:00
a6f4aed3c0 vdo: enhance error path
When the conversion to VDO fails, try to restore previous VG state
and also remove orphan DM node from table.
2024-05-04 00:57:14 +02:00
1f92fc2af7 lvcreate: --yes option for thin-pool vdo creation
Correct typo and accept proper --yes option instead
of misplaced --force option.
2024-05-04 00:56:32 +02:00
a98f908c23 command: correct lvresize
Code for supporting size reduction of pool metadata is not yet present
so don't pretend the option can work as pushed in previous commit.
2024-05-02 13:18:08 +02:00
54e2de82c0 WHATS_NEW: update 2024-05-02 12:07:47 +02:00
8f37c22df2 make: generate
Update lvresize options with +/-.
2024-05-02 12:04:07 +02:00
1ab66f37ae command-lines: improve spec for thin snapshot
man-generate --check actually noticed 2 same definitions
for snapshot create  with 'lvreate -T [--snapshot]'
and 'lvcreate --snapshot [-T]'.
So drop the '-T' from second alternative variant as
thin type is already implied here.
2024-05-02 12:04:07 +02:00
611975c51b use LVM_COMMAND_COUNT 2024-05-02 12:04:07 +02:00
eeffc1d52b man-generator: code reformating 2024-05-02 12:04:07 +02:00
b4670db008 command: refactor to use const command structure
Refactor code so the definitions may become 'static const'
and with configure_command_option_values() we update options
val_enum for actually running command option when used.

Also update _update_relative_opt() which is used for
generating man pages and command help.

Introduce enumeration for lvm2 commands - so we may
use enum cmd_COMMAND instead of string checking.

So running command now does not modified opt_names.
2024-05-02 12:01:06 +02:00
0b064aedb3 command: embedding strings to structs
Since we will make these struct const, we can also
embedding string content into them to avoid unnecessary
pointer relocations.
2024-05-02 11:59:42 +02:00
6f8abdc978 cleanup: tab indent and typo 2024-05-02 11:58:26 +02:00
db6bb6e90b cleanup: unlink passes with ENOENT 2024-05-01 10:55:17 +02:00
061fa7b690 cleanup: remove unused code 2024-05-01 10:55:17 +02:00
2a39ed7741 writecache: reuse some API
Tiny code updates, reuse dm_pool_strdup().
2024-05-01 10:55:17 +02:00
b8d5c4b41a memory: compile with VALGRIND_POOL
Function to _allocate_memory() was not compiled-in when lvm2 was
build with support for better tracking memory pool with valgrind.
Instead now correctly avoid this function only when running
withing valgrind environment.
2024-05-01 10:54:54 +02:00
d5da7604e5 memory: convert log_error
As the memory locking is not causing command's error - convert
error messages to warnings and debugs.
2024-05-01 10:54:54 +02:00
7ec0f69cd1 toolcontext: introduce var for run in valgrind 2024-05-01 10:54:34 +02:00
9162ae0a0a activation: interruptible sleep when talking to dmeventd 2024-05-01 10:54:34 +02:00
c35385a1cd cleanup: drop double _ 2024-04-29 00:13:43 +02:00
26cbd4057a lvmcmdline: code update 2024-04-29 00:13:43 +02:00
e654b9cba9 command: more arrays keep static 2024-04-29 00:13:43 +02:00
45d9b2c470 command: more static const declaration
Use static const for declared arrays.
Access to arrays through get_ functions().
2024-04-29 00:13:43 +02:00
d2f953c9db command: use const declaration for arrays 2024-04-29 00:13:43 +02:00
063910c54b command: refactor common code to command_enum.h
Move shared code to command_enum.h and avoid duplicating code.
2024-04-29 00:13:43 +02:00
f453665f92 lvchange: constify option array 2024-04-29 00:13:43 +02:00
cd69d58fcd command: using single printf call
Use single string for 1 printf() call with \t tabs.
2024-04-29 00:13:43 +02:00
0316dd7955 command: refactor loop test for end of string 2024-04-29 00:13:43 +02:00
e1211d38a4 command: refactor test for relative opt
Use _update_relative_opt to check for relative option and
update val_enum accordingly.
2024-04-29 00:13:43 +02:00
ee45cd8965 man-generator: some switch case refactoring 2024-04-29 00:13:43 +02:00
6ece8b74f0 command: split man-generator code
Move code for generating man pages to man-generator.c
which is no longer a symlink to command.c and just
includes this file for the common code.
2024-04-29 00:13:43 +02:00
063ade474c command: refactor if condition 2024-04-29 00:13:43 +02:00
ecabdf68cf lvconvert: use cmd_context variable
Do not modify flags field from 'strcut command_name' and
instead control this via cmd_context  get_vgname_from_options.

Flag GET_VGNAME_FROM_OPTIONS is currently used only by lvconvert.
2024-04-29 00:13:43 +02:00
1bb03cff66 lvmdbusd: its fine if dir already exists
With previous patch, we now need to handle the case
when dir already exists.
2024-04-29 00:13:43 +02:00
7c4be946cb dmeventd: use standard reopening mechanism
Apply same code for reopening /dev/null for 0,1,2 when daemonizing.
2024-04-27 00:36:24 +02:00
d194fb8513 daemon-stray: correct size limitation for filename
Correct the buffer size for filename printing.
2024-04-26 23:51:38 +02:00
b3189d9b15 lvmdbusd: create dirs for lock file
Create leading dirs for lvmdbusd lock file, otherwise it fails to start:

| systemd[1]: Starting LVM2 D-Bus service...
| lvmdbusd[1602]: [1602]: Error during creation of lock file(/var/lock/lvm/lvmdbusd): errno(2), exiting!

Signed-off-by: Kai Kang <kai.kang@windriver.com>
2024-04-26 23:17:56 +02:00
6e985f553b WHATS_NEW: update 2024-04-26 21:37:52 +02:00
e51c2376dd make: generate 2024-04-26 21:37:52 +02:00
38cc021d67 cmdlines: use OO_LVCREATE_RAID
Common options in one OO_
2024-04-26 21:37:52 +02:00
41e0a93a8f cmdlines: simplify OO_LVCONVER/LVCREATE_THINPOOL
OO_LVCONVERT_THINPOOL always constains OO_LVCONVERT_POOL
OO_LVCREATE_THINPOOL always contains OO_LVCREATE_POOL

More readable description.
2024-04-26 21:37:51 +02:00
ce97056a7a tests: resize thin-pool with vdo data 2024-04-26 21:37:51 +02:00
82c062be74 tests: correcting test for invalid commnad
Correting typo in specification of create --typo.
Also removing some unnecessary parts...
2024-04-26 21:37:51 +02:00
95fca3d1d5 makefile: avoid creating shared lib for static only build 2024-04-26 21:37:51 +02:00
3fc34ac7ee vdo: fix setting VDO size when stacked
When VDO is used as data LV for thin-pool, we need
to use correct function to propagate this through
the stack of volumes.
2024-04-26 21:37:51 +02:00
21b683614c lvmcache: stop saving duplicate pvs info between scans
In the past it was common for a single command to run
multiple lvmcache_label_scan, and this code was a way
to make each call select the same duplicate pvs.  Now
commands run a single lvmcache_label_scan, so this is
not needed.
2024-04-26 14:13:46 -05:00
db96e81f76 tests: wait for raid being in sync 2024-04-26 12:43:03 +02:00
d0cfe73326 cov: unused headers 2024-04-26 00:13:34 +02:00
57ab219d9b cov: validation
Add internal error for missing vg.
2024-04-26 00:13:34 +02:00
c6a37ddca4 toolcontext: check runtime valgrind
When reseting stream buffer - check for being run within valgrind
and only in this case skip this code.
Define VALGRIND_POOL was incorrectly used for this logic.
2024-04-25 21:26:01 +02:00
4c5eb2e713 daemon-stray: compile also with VALGRIND_POOL
We can run and build this code just fine with VALGRIND_POOL
and just rely on runtime detection - so we do not close
descriptors also within running valgrind session.
2024-04-25 21:07:36 +02:00
4557427a61 spec: require ncurses only for readline
Hopefully editline can go without ncurses dependency.
2024-04-25 17:08:19 +02:00
b0c0e8bd7a makefiles: change condition
Old system do not work well with -l% in findstring,
so use a different strategy to recognize whether -lreadline needs
another library (-ltinfo, -lncourses...)
(So we don't need to solve this via 'configure')

Also for now comment out -Wl,-z,pack-relative-relocs and leave it
for the package maintainer whether they want to use.
Possibly add some 'configure' autodetection for usable switch,
as it's relatively new feature..
2024-04-25 17:06:07 +02:00
68a8555d69 tests: avoid race check 2024-04-24 13:54:05 +02:00
baebd7ca29 tests: accept also closing status 2024-04-24 13:44:58 +02:00
b14f29ab5b makefiles: comman escape needs this trick 2024-04-24 13:42:05 +02:00
a8009f72bf makefiles: add as-needed only for newer systems
Add some -Wl flags separatly and avoid their duplication.
Also add --as-needed only when system is using 'newer' readline
library - on these older system the usage of '--as-needed'
seems to be causing some hard to solve problem - so avoid it.
2024-04-24 11:35:05 +02:00
ba13ac8704 tests: correct linking order for RT_LIBS 2024-04-24 11:34:35 +02:00
f569ac59a7 configure: autoreconf 2024-04-24 00:38:32 +02:00
078445658c configure.ac: update ldflags args
Attach -Wl,-z,relro,-z,now,-z,pack-relative-relocs,--as-needed
to LDFLAGS, but only if LDFLAGS already doesn't contain 'relro'
(so it's not given repeatedly).

Also start to use -z,now linkage also when building libraries
with default compilation - this avoid calling symbol resolver
while library function are using function needing resolving.

Note: Fedora or RHEL rpm building is using:
CFLAGS=$(rpm --eval %{build_cflags})
LDFLAGS=$(rpm --eval %{build_ldflags})

Also split -DUSE_SD_NOTIFY into DEFS from CFLAGS.
2024-04-24 00:31:26 +02:00
f022da9e5f configure.ac: leave LDFLAGS resolving on make time
Use LDFLAGS separately with every use of CLDFLAGS and leave
this flag only for handling versioning.

This will reflect any LDFLAGS setting use during make.
2024-04-24 00:30:05 +02:00
5d23054cb3 tests: update dmsecuretest
Look not only for whole 64byte sequence,
but seek also 32byte, 16byte and 8byte parts of the
key.

Currently to pass memcpy ZMM problems add possible
workaround in the form of GLIBC_TUNABLES setting.
2024-04-23 22:06:30 +02:00
0b3b40f056 make: generate 2024-04-20 00:03:18 +02:00
6caeffa4be tests: look also for 16byte sequences 2024-04-20 00:03:18 +02:00
22571fb36a tests: add explicit call to lvs
Avoid using 'lvs' from  'get' shell - as that would wait until
whole group of processes is finished.

TODO: rethink what would be the point of starting 'dmeventd' with lvs.
It seems to break some rules.
2024-04-19 23:56:16 +02:00
6ee731ba1a spec: define rhel_version_file for rhel only
Do not define rhel_minor_version on non-rhel systems.
2024-04-19 23:56:16 +02:00
79bb9e3172 libdevmapper: _do_event waits for working dmeventd
Refactor _start_daemon and add synchronization delay waiting
untill new forked dmeventd actually open fifos and is ready
to process messages.

This closes some race window in testing.
2024-04-19 23:56:16 +02:00
85b711caae lvmlockd: check for multiple lock managers running
When no lock manager for the global lock had been set yet,
and the first global lock request was received, and both
dlm and sanlock were running, lvmlockd would assume it
should use the dlm for the global lock, and would start
the "lvm_global" dlm lockspace automatically.  That's
not always correct, so don't assume the dlm should be used,
fail the lock request, and wait until a VG with a specific
lock type is started to determine the lock manager to use.
2024-04-19 10:53:37 -05:00
f4911177da lvcreate: allow raidintegrity option with implicit raid type
Allow "lvcreate -m1 --raidintegrity y" when raid1 is used, but
not explicit on the command line.
2024-04-17 13:40:33 -05:00
77ff83f784 spec: correct condition
Test needs to make sure that it's either <RHX or <FXX.
However they are set to 0 when on different system.
So use '&&'.
2024-04-16 21:17:42 +02:00
b885355e76 tests: add extra dmsetup table
Strange race seems to be occuring here from time to time...
2024-04-16 21:17:42 +02:00
2d01af8e56 tests: add another explicit barrier
Just to be sure compiler cannot optimize this out.
2024-04-16 21:17:42 +02:00
bb276bf250 tests: update aux for vdo checking
Detect also presence of  'vdoformat' tool.
Fallback to 'kvdo' modprobe only when dm-vdo fails
(removed ugly error message from log)

Also add extra check for scsi model being present
so the test can wait a bit if 'scsi_debug' takes longer time.

No need for 'aux' within aux.
2024-04-16 21:17:42 +02:00
93c47a2b94 tests: ensure sscan buffer is nul terminated
Avoid reading past the read buffer when sscanf is used.
2024-04-16 01:11:32 +02:00
4ca9d478d4 spec: sanlock 3.7 with version >fc27 and >rh7.4
Decode minor version for rhel.
2024-04-16 01:10:47 +02:00
485a1961e8 clang: implicit conversion from 'long' to 'double'
implicit conversion from 'long' to 'double' changes value
from 9223372036854775807 to 9223372036854775808.

So rather compare same integer types.
2024-04-16 01:10:03 +02:00
d3d06f8ca0 WHATS_NEW: update 2024-04-15 13:45:11 +02:00
569dd5d089 configure: autoreconf 2024-04-15 13:38:44 +02:00
3b9bb773fe configure.ac: 3.7.0 is new minimal sanlock versioh
Require this minimal version of sanlock for usage with lvmlockd.
2024-04-15 13:38:44 +02:00
716fc27fdd dmeventd: use daemon_close_stray_fds
Use common code for close stray descriptors.
2024-04-15 13:38:44 +02:00
79cdfc8ca6 libdaemon: implement daemon_close_stray_fds
Refactor existing code from tools/lvmcmdline.c to
libdaemon/server/daemon-stray.h daemon_close_stray_fds()
used to close stray descriptors above some specified Fd.

This is code parses content of /proc dir to minimize 'blind' closing
of all possible descriptors within rlimits range.

As we have the same code in few other places in it's more 'trivial'
version - these were actually sensitive to high amount of descriptors,
which might be configured on some system.

With this patch we effectively resolve this reported gitlab issue:
https://gitlab.com/lvmteam/lvm2/-/issues/5

TODO: Current placement might not be ideal - however considering
existing code base constrains it's not so simple.
ATM it uses lib/misc/lvm-file.h  for custom_fds declaration
and rest of functinality is included in daemon header file.
2024-04-15 13:38:44 +02:00
ecb8399005 lvm: use configure proc dir in lvm.conf
Update some code parts to use configurer /proc from lvm.conf
(so i.e. our testing can use some fake values)
2024-04-15 13:38:44 +02:00
84b084c9b6 configure.ac: define DEFAULT_PROC_DIR in one place
Let's move proc into include/configure.h so this define can
be easily used across the source base.

Configure defines it - but ATM we do not provide any configure
option to change it - there should be no need to ever change it.
2024-04-15 13:38:44 +02:00
2ea8afba93 dmeventd: typo fix
Fix typo and minor reorder of struct member for better alignment.
2024-04-15 12:58:27 +02:00
f59ec61fa7 lvmcache: fix memleaks on list removal
Free members released from the list.
2024-04-15 12:58:27 +02:00
0168de83de spec: disable LTO
Currently there is not much gain in using LTO when building
testing rpms
2024-04-12 01:27:26 +02:00
fcfbef26e4 spec: replace exists macro with plain shell test
seems this macro works only with recent rpm.
2024-04-12 01:27:26 +02:00
8ce8e33a44 tests: better handling for dmeventd restart
Handle the case, where we  'kill -9' running dmeventd,
and restarting 'dmeventd -R' manages to still contact this
'zombie' damone and manages to get list of monitored devices
out of this and eventually 'run' new and in this case
unexpected instance of dmeventd.
2024-04-12 00:21:46 +02:00
aae7c98aaa tests: fallback to normal hostname on older machines
hostname -I  is newer option, add some fallback
2024-04-12 00:21:45 +02:00
81dc0e72da tests: explicitely use event_activation=1
Some test do expect event_activation to be set.
So add explicit configuring of this setting in tests,
but also add new default which kind of does it globally
as it's expected default  (yet our testing rpms might
be create with disabled event_activation)
By adding this to each test individually - it's now easy
to locate such tests...
2024-04-12 00:21:45 +02:00
d6b15e755e dmeventd: reduce some static variable usage
Move static to main() local vars.

Initilize libdm logging also before starting _restart_dmeventd()
so function there can be also logged.

Move call of _info_dmevent() out of option processing - so some
options like -V are processed with higher priority.
2024-04-12 00:20:43 +02:00
5e3224c57d dmeventd: no log when after unlink file is gone
Check for errno ENOENT.

TODO: there should be global wrapper for this...
2024-04-12 00:14:03 +02:00
54840d867e devmapper-event: add unlock into init_fifo error path
Unlock server path if there is open failure for client_path
and whole init_fifos() function is returning failure.
2024-04-12 00:14:02 +02:00
3a433b14f2 dmeventd: rework _restart_dmeventd
Use _restart_dmeventd() with return values 0,1,2.
Also let's use already created fifos struct.

Make sure the _systemd_activation variable is properly initialized
from _systemd_handover before calling _restart_dmeventd() as
this variable is used there to decide where   1 or 2 should
be returned - aka either letting systemd to initilize
or restart dmeventd itself.
2024-04-12 00:14:01 +02:00
449af6c335 lvmlockd: use sanlock.h for defines 2024-04-11 10:50:06 -05:00
fd0517c82b spec: try with default dependency tracking
Check whether we have now all dependencies right.
2024-04-10 17:38:26 +02:00
543011fa86 spec: when building rpm on test machine disable event_activation
This is initial test how to disable event_activation on
machines, where lvm2-testsuite packages are installed
with its lvm.conf file.

TODO: find more elegant mechanism
2024-04-10 17:38:26 +02:00
ac3cee638b spec: update default values
Reverse condition and downgrade setting for older versions.
Also define proper version strings
2024-04-10 17:38:26 +02:00
8ba9574ed4 tests: aux extend lvmdbusd timeout for startup
Unclear yet what's going on here - so try waiting up 10second
to see if our service will get there.
Print task list if not...
2024-04-10 17:38:26 +02:00
faf4fe0714 tests: use lvname with space
Occasionally this test fails as soemtimes UUID actually
may constain LV[d] string causing it to grep mismatch
UUID and LV name and eventually fail test for wrong reason.

As a simple workaround print the LV name first and
check the name is followed by a space character.
2024-04-10 17:36:50 +02:00
a14cb2495b WHATS_NEW: update 2024-04-10 00:04:54 +02:00
8d1a946a9b tests: update unit-tests
Fix some memleaks.
Drop call of bcache_clear_fd() when bache was not initialized.
2024-04-10 00:04:54 +02:00
8a2839c867 tests: update for faster dmeventd
We can drop sleep 6, since dmeventd will quit immediatelly
when no running dmeventd can be restarted.

Also restart itself check more conditions.
2024-04-10 00:03:33 +02:00
6382d141fa tests: add missing vgck
This test missed being adjusted with this updated workflow
so it's been testing something different...
2024-04-10 00:03:09 +02:00
32c6dbb425 tests: aux fallback to sleep
When dbus-send tool is not present on system, fallback to sleep.
2024-04-10 00:03:09 +02:00
6a95c66f5b tests: drop test warning
These kernel are not going to be ever fixed, so drop warning
being displayed for these tests.
2024-04-10 00:03:09 +02:00
fa62397ff8 cov: mask false positive
This code is somewhat complex and involves recursion and pointer
shuffling which confuses coverity here.

Let's add masking comment for this warning as there is no double
free in this code.
2024-04-10 00:03:09 +02:00
2b9c3f8dc9 cov: pass buffer size 2024-04-10 00:03:09 +02:00
82f50dc800 gcc: remove warning about inlining failure
Persuade gcc we want this function to be inline and avoid:
  warning: inlining failed in call to ‘lvmlockd_open.constprop.0’:
2024-04-10 00:03:09 +02:00
2b802ab413 cov: use check of snprintf result
Do validation in one go with snprintf() result,
so there is no extra strlen() and uncheck possibly truncating snprintf()
visible to coverity.
2024-04-10 00:03:09 +02:00
c5b4574729 cov: use stream ptr in its original form
Let's stop Coverity thinking here we are using freed FILE*
for anything else then comparing numbers.
For this use the original source of old_stream pointer.
2024-04-10 00:03:09 +02:00
2a8c195360 cov: use dm_strncpy variant 2024-04-10 00:03:09 +02:00
cb16f5053f cov: make obvious how free of memory happens
When there is allocation, it needs also deallocator.
Remove no longer needed coverity warning masking.
2024-04-10 00:03:09 +02:00
e7a54c1a50 cov: use safer version with size limitation
Although there is likely not much risk of having chance of overwritting
given buffers use safer variant.
Use dm_strncpy() when just copying %s.
2024-04-10 00:03:09 +02:00
3ce83f923d cov: extra pointer validation
Add few more internal errors to enusure there is no use of NULL pointers
along the code path.
2024-04-10 00:03:09 +02:00
8545621d39 cov: replace strcpy with memcpy
When we know the size we can avoid using strcpy.
2024-04-10 00:03:09 +02:00
22a0cfdc05 cov: use memccpy
When we want to copy string which may not be null terminated,
replace strncpy with more correct memccpy.
2024-04-10 00:03:09 +02:00
f27273e1f0 dmeventd: restart checks for running daemon
Check whether the pid file is associated with running daemon.
If not there is not much point to wait many seconds in loop.
2024-04-10 00:03:09 +02:00
f27388b5d8 toolib: skip when there is no vg and error_vg
We must skip even if the skip would be suggesting otherwise
if there is no vg and no error_vg as there is nothing to process.
2024-04-09 17:47:55 +02:00
cd9b2b32aa configure: add --with-default-event-activaion=ON
Add new configurable option for building lvm2 with enable/disable
default autoactivation setting.

Might be useful for building i.e. rpms for systems where
this event_activation is not desired.
2024-04-09 17:47:03 +02:00
9dad6f202c reporter: correcting failure return value
This function do use ECMD_ return values,
so use ECMD_FAILED as initial value - used for internal error paths
2024-04-09 17:43:23 +02:00
f404d8ccb7 gitignore: add more ignored suffixes 2024-04-08 22:24:18 +02:00
5125629f2a makefiles: add libdm as deps for unit-test
When using just 'make check' ensure we make also dmsetup
so it's not needed to run explicit 'make' to get all the tools.
2024-04-08 22:24:18 +02:00
39d375ecd1 tests: include date and hostname IPs in test log
When our testing machines are going wild with NetworkManager,
this might be slightly helping.
2024-04-08 22:24:18 +02:00
b120b2932d tests: add timestamp to kernel line
Parse timestamps included in kernel kmsg line and add current system
time to the messsage as well - this makes it easier to look over,
when chasing some messages in journal after some time...
2024-04-08 22:24:18 +02:00
08888d57cb tests: check for supported dBus interface
Instead of blindly relying on sleeping, that dBus understands our
dBus interface, query the info with dbus-send.
2024-04-08 22:24:18 +02:00
f524dd80f4 tests: query dmeventd instead of sleep
Checking status of running instance of dmeventd should be a better 'sleep'.
2024-04-08 22:24:18 +02:00
092951f634 dmeventd: check for running dmeventd for status
Before initiation fifo communication, check whether there is
running dmeventd - in case there is no running instance, this
would be just blocked for 5 seconds trying to open fifo.
2024-04-08 22:24:18 +02:00
d8e52aed87 tests: use non inlined copy constructor
gcc would like to see code without trying to inline large
copy constructor used for std::vector
2024-04-08 14:52:28 +02:00
6ec84993bd makefiles: avoid using # with awk
Also awk got annoyed by this \# char sequence which is reported
as incorrect, however older rpm builder were failing without this.
So let's just try other variant.
2024-04-08 14:52:23 +02:00
88ad83e3d6 makefiles: use SHOW 2024-04-08 14:52:23 +02:00
d490572410 gcc: clear some complains
Use dm_strncpy() were possible to get rid of gcc compile warnings.
2024-04-08 14:52:23 +02:00
aae27f6be6 WHATS_NEW: update 2024-04-07 20:47:28 +02:00
04e8f8c93d tests: add sleep
mdadm may eventually be too slow...
2024-04-07 20:47:28 +02:00
d6df31fba1 pools: no checking for lv/vgremove deactivation
Thin-pool and cache-pool targets got already quite stable so let's try
to remove checking of pools when using lvremove or vgremove commands.

This skips checking pools when they are going to be removed, but it
also when removing thin volume that was the only user of a thin-pool.
In this case thin-pool will be still there and could be activated
again with another thin volume and thin_check will be executed
in this moment. In this case it can delay discovery of metadata damage.
2024-04-07 20:44:28 +02:00
2fdf3b137a thin-pool: avoid reactivation on new thin-pool
Shortens processing of 'lvcreate -L -V -T' command and
avoid deactivation and its activation with thin_check of the empty
created thin-pool that will be used for the new thin volume
made with a single lvcreate command.
2024-04-07 20:38:55 +02:00
dbc0105e1a vdo: modprobe dm-vdo for kernels >= 6.9
Modprobe "dm-vdo" with new kernels >= 6.9 and go for
'kvdo' with older Linux kernels.
2024-04-07 20:27:39 +02:00
a82b93b298 WHATS_NEW: update 2024-04-05 14:31:54 +02:00
7fbd3bac71 tests: skip convertions tests for usptream driver 2024-04-05 14:25:27 +02:00
6305db53c1 tests: add correct condition for skip of lvmpolld tests
Check when flavour want to test  lvmlockd & lvmpolld tests and
in for case ignore SKIP_WITH_LVMPOLLD from test script.
2024-04-05 14:14:50 +02:00
dda859027c vdo: use stats msg parser for also segment status
Shuffle code to parsing VDO message also for lvs segment status
so it can report correctly data usage for VDO LVs.

For this change move code and also change its API to use just mempool.

Fixes usage with upstream 6.9 vdo target driver.
2024-04-05 14:14:50 +02:00
203c8b3997 vdo: fix status message parsing
When using message API for parsing VDO stats info, 0 was wrongly
used for fallback for trying the old sysfs API.

Switch to use  ULLONG_MAX for values that could not have been obtained
through the message call.

Fixes lvdisplay info for freshly created VDO volume with 0 used data
blocks.
2024-04-05 13:09:10 +02:00
000f55a1a2 tests: updated check for dm-vdo module
With new kernels dm-vdo is now correct name,
so use standard loading and just try extra for kvdo.
2024-04-04 19:38:21 +02:00
ecacb2b544 tests: inittest fix skipping condition 2024-04-04 19:38:21 +02:00
50b188eebd dev_manager: improve readability
Make a seperate function to decode which ID should be user
for cvol meta or data volume - also avoids duplication of code.
As a result it's now also easier to see how the lvid is build.
2024-04-04 19:38:21 +02:00
41f13b2a3b device_id: add comment for trim 2024-04-04 19:38:21 +02:00
5dec664ccf lvmlocks: rework dm_strncpy
Fix cutting away 1 character via incorrect usage of dm_strncpy
introduced in last batch of commits and use sizeof(buffer) to
get proper sizes.

In case of use strcpy_name_len() the replacement was invalid,
so we need to restore this case since sanlock uses buffer without
nul ending, so we would strip one more character from the buffer.

Also start to use dm_strncpy() without (void) for unchecked usage.
2024-04-04 19:38:21 +02:00
f9fefaaabe refactor: update dm_strncpy to _dm_strncpy
For checked versions of dm_strncpy use inline wrapper _dm_strncpy.
2024-04-04 19:38:21 +02:00
995ff58903 refactor: remove (void) from dm_strncpy usage
Start to use dm_strncpy() as unchecked version within source tree.
2024-04-04 19:38:21 +02:00
295e632e81 util: add _dm_strncpy
Add internal inline function wrapper for dm_strncpy().
Use it for calls where we test the result.
Avoids emitting warnings in Coverity for unchecked usage.
2024-04-04 19:37:13 +02:00
5c0ade35e2 util: swap header file load order
Ensure libdevmapper is included before util.h since
we are going to add function that is using it.
TODO: maybe add include directly here...
2024-04-04 19:33:58 +02:00
fa81c7561f cov: missing initializer
Ensure there is no code path with uninitialized takes_arg.
2024-04-04 19:33:58 +02:00
c78970c0d0 lvmcache: free list of add_cache_devs 2024-04-03 15:59:25 -05:00
6d6e8d69eb lvmdevices: fix memleak of use_old du
missed in the the prev done_old commit
2024-04-03 15:29:17 -05:00
fb80ed3143 cleanup: remove lvmcache_has_bad_metadata 2024-03-30 00:17:39 +01:00
adfa16c899 cleanup: drop unused code 2024-03-30 00:17:39 +01:00
d39b47d665 filtes: remove lvmetad bits from usable filter
Eliminate some dead code from usable filter, that is no longer usable
after removal of lvmetad.
2024-03-30 00:17:39 +01:00
46ef562c50 device_id: simplier loop control 2024-03-30 00:17:39 +01:00
d65a428f2d device_id: use dm_strncpy
Simplify code.
2024-03-30 00:17:39 +01:00
b8d5744c6e deviced_id: use zalloc
While moving to dm_strncpy, in this case since pvid is also
passed to crc calc, make sure whole buffer is always initilized.
2024-03-30 00:17:39 +01:00
4151df32c1 filter: zero internal structure
Valgrind noticed access to unitialized warned_filter.
2024-03-30 00:17:39 +01:00
6172db5326 lvmdevices: fix memleak of done_old du
'done_old' list missed released.
2024-03-30 00:17:07 +01:00
eba277bca8 cov: cast to uint32 2024-03-29 01:36:48 +01:00
a98709aeae cov: validate count is bigger then 0
To avoid teoretical underflow...
2024-03-29 01:36:48 +01:00
466265eaa6 tests: better constructor 2024-03-29 01:36:48 +01:00
ee496f2846 cov: validate major and minor
Check  major and minor is >= 0.
2024-03-29 01:36:48 +01:00
93a633092a cov: store 64b flags
Alhtough no target is currently using that many bits for their flags,
preserve the size for loaded segment internally.
2024-03-29 01:36:48 +01:00
960df88621 cov: validate i before underflow
Although it can't happen in this code, ensure 'i' is not 0
before decrementing it.
2024-03-29 01:34:22 +01:00
fef49a0e86 cov: remove unnecessary sanity check
This sanity check actually confused in some way Coverity
giving it some assumption about array access.

Since these two checks basically validated compiler's capability
to add and then substract the number from char pointer we likely
don't really need them - as if this base math would not work,
compiler would be having far more troubles...

So drop them - and get rid of report:
Event overrun-call: Overrunning callee's array of size 513 by...
2024-03-29 01:34:22 +01:00
fe2294769c cov: use dm_strncpy
Use better variant.
2024-03-28 22:19:45 +01:00
2b7d0db7f1 cov: no overwrite of const qualified fields 2024-03-28 22:19:14 +01:00
7ec7d8cf54 cov: reset FILE on error path
Although fclose() fails - we should not be retrying with
already released stucture.
2024-03-28 21:15:38 +01:00
59b46fc8cd tests: lvmdbusest.py faster test_z_sigint
Reduce #lv and intervals.

We are trying to ensure that the daemon stops while it's busy processing
its internal queues.  Decrease the number of LVs and intervals to allow
this test to complete in less time.
2024-03-28 18:18:37 +01:00
f2edc96bb6 tests: lvmdbustest.py skip if g_tmo != 0
This test doesn't have any additional value when running when g_tmo != 0.
2024-03-28 18:18:37 +01:00
3430395c85 lvmdbusd: Exit faster
Add a global timeout value to be used for the threads to end waiting for
whatever it is they are blocked on.  The values varied from 2-5 seconds,
which is way longer than needed.  Value of 0.5 shows no CPU load when
service is running and is idle.
2024-03-28 18:18:37 +01:00
fc477192e5 cleanup: drop unused code
Code was related to long time obsoleted  vgconvert
for lvm1 to lvm2 conversion.
This code likely was missed to be removed.
2024-03-28 18:18:37 +01:00
4ba683bb18 debug: update some structure members
Makes pahole output look slightly better.
2024-03-28 18:18:37 +01:00
f1e80f3be0 commands: reduce command structure size more
Check for internal limits, if they would ever need to be raised report
error message and fail parsing.
2024-03-28 18:18:37 +01:00
8965fd18aa cov: ensure buffer always ends with nul
When we print anything out of buffer, ensure there is \0.
2024-03-28 18:18:37 +01:00
1d150d63c7 cov: ensure nul ends string 2024-03-28 18:18:37 +01:00
69f9fcfd20 tests: skip some mirror tests for polld and lockd
Leave just lvconvert-mirror-basic-1 test
for polld and lockd testing.
2024-03-27 01:26:57 +01:00
4a69bacc20 gcc: use uint16_t for counters 2024-03-27 01:11:00 +01:00
83b726e5dd gcc: move declaration into ifdef
Prevent unused warning when the ifdef code is not compiled.
2024-03-27 01:11:00 +01:00
0dbd90d74e gcc: match signed integers 2024-03-27 01:11:00 +01:00
2b864aeb14 configure: lcov needs -fprofile-update=atomic
To avoid negative counters.
See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68080
2024-03-27 01:11:00 +01:00
f98d2ffe87 device_id: use dm_basename
Avoid problems for other libc like muslc and use dm_basename.

Prototype for basename has been removed from string.h from latest musl [1]
compilers e.g. clang-18 flags the absense of prototype as error. therefore
include libgen.h for providing it.

[1] https://git.musl-libc.org/cgit/musl/commit/?id=725e17ed6dff4d0cd22487bb64470881e86a92e7

Reported-by: Khem Raj <raj.khem@gmail.com>
2024-03-27 00:30:58 +01:00
8c4b8c6e27 dmsetup: refactor getopt_long usage
Shuffle code to avoid using static variable to pass parsed option.
Code is now easier to follow and also number of coverity reports
will go away.
There should be no functional change.
2024-03-26 15:58:36 +01:00
1c2dff2655 tests: missed reduction of raid check 2024-03-25 17:17:40 +01:00
c4b1bfa5f0 cov: use proper enum value 2024-03-25 17:17:24 +01:00
421afd287a cov: ensure namelist is defined
Seems coverity doesn't have good model for scandir.
Let's ensure pointer is seen as defined.
2024-03-25 17:16:00 +01:00
4abdc5981a cov: validate return from display_lvname
Ensure strdup will not get NULL.
2024-03-25 16:59:27 +01:00
4f1d89d37f cov: validate origin pointer
Add internal error for NULL origin here.
2024-03-25 16:57:53 +01:00
ac90ab7736 cov: drop some unneeded continue 2024-03-25 16:54:11 +01:00
ae7b59f509 cov: check for syscall resuls 2024-03-25 16:38:52 +01:00
b84702349f cov: ensure buffer is nul ended
Use dm_strncpy() to ensure ending nul.
2024-03-25 16:37:04 +01:00
7e5e98e4f2 tests: fix improper merge within last update 2024-03-25 15:01:48 +01:00
05993fd432 makefiles: ignore negative errors for lcov 2024-03-25 14:46:23 +01:00
75e532417e tests: check for raid shrink support
Shrink of raid LVs supported from 1.9
2024-03-25 14:46:02 +01:00
8716d8c188 cov: check for to_dlm_mode return value
Avoid processing invalid to_dlm_mode in lm_convert_dlm.
2024-03-25 14:45:09 +01:00
46e013988f cov: check for strftime result 2024-03-25 14:45:09 +01:00
3b47ce0a37 devices_id: add some syscall checks
Add debug tracing for syscall failures.
Also switch some log_error to log_warn when command does not exit
with 'error' result and only warns user.
Easier error path handling.
Initialize some vars at declaration time.
2024-03-25 14:43:33 +01:00
1ba2d40473 gcc: ensure num has always initilized value 2024-03-25 11:44:36 +01:00
bca6f58848 cov: ensure string ends with \0
Use dm_strncpy() that ensures \0 termination.
2024-03-25 11:18:29 +01:00
835e8f9d7a cov: fix incorrect error check
Check for NULL pointer.
Fix missing release on error path.
Also dir_fd might be just != -1.
2024-03-25 11:18:29 +01:00
781bf867cc tests: update lvconvert-raid.sh
Handle case of removal of orig leg while it's being synchronized.
2024-03-25 11:18:29 +01:00
658c446f13 tests: update raid_leg_status check
Do not wait for progres (non zero processed amount of blocks),
when the raid status already reported 'resync' or 'recover'.
2024-03-25 11:18:29 +01:00
e8b7b53db1 tests: aux avoid discarding created loop devices
Usually it's not a big deal, but couple test creates
large devices and here discard operation just excersice
CPU and consumes time.
2024-03-25 11:18:29 +01:00
68939136c1 tests: reduction needs to ignore fs
Drop 'should' usage and use  --fs ignore when reducing raid LV.
2024-03-25 11:18:29 +01:00
d7f6d5b9da tests: update extend of raid
Here we actually need to slowdown only $dev2 - since repair operation
is only reading data from this device and compares it with origin $dev1,
and if they match there is no write...
2024-03-25 11:15:58 +01:00
e36c6a31e6 commands: refactor memset
Move memset() to the initialization function define_commands().

There is also not much point in clearing memory on command's exit
so drop zeroing of ~2M of RAM.
2024-03-25 11:05:05 +01:00
e450ad287e commands: reduce structure sizes
Reduce slightly RAM usage of running lvm2 and use smaller fields
to count small numbers.
2024-03-25 11:05:05 +01:00
b951f81db5 commands: use nul for EOL for compiled-in buffer
Use \0 as EOL in compiled-in syntax description to avoid
unnecessary line copy that just replaced \n with \0.
Also use already splitted lines when possible.
2024-03-25 11:05:05 +01:00
50ad27a4ab reporting: reuse existing _get_field
Use already existing _get_field() function that also
slightly optimizes 'strlen()' usage.
2024-03-25 11:05:05 +01:00
ab3c690077 dev-cache: change locales just once 2024-03-25 11:05:05 +01:00
2eff6e1974 raid: update dm_get_status_raid
Handle mismatch of reported 'dm raid' status, where the active
raid LV can be actually showing higher numebr of raid leg devices,
that the number of shown status characters.

This can happen if the raid leg is dropped during initial
resynchronization.
2024-03-25 11:05:05 +01:00
f09a992720 udev: create /dev/disk/by-label symlinks for DM devs that have crypto as next layer
We already create /dev/disk/by-uuid symlinks for DM devices which
contain crypto-type as next layer (as identified by blkid).

Also create /dev/disk/by-label symlinks as the labels can be
defined for crypto-type devices too.

Reported and fix suggested by: Patrick Plenefisch <simonpatp@gmail.com>
See also:
https://lore.kernel.org/lvm-devel/CAOCpoWfYjOVNJNt+cnOVXDHiDq2wRogTqBijcUoa7chqOLRa5Q@mail.gmail.com/
2024-03-25 10:30:25 +01:00
4203fdbfef WHATS_NEW: update
Commits 48188d7181 and eb4f744820
2024-03-25 09:14:57 +01:00
eb4f744820 Upstream db_persist udev rule from dracut
Setting db_persist is required for dm devices so that their properties
are carried over on switch-root from the initrd to the rootfs. This
logic has always lived in dracut
(https://github.com/dracutdevs/dracut/blob/master/modules.d/90dm/11-dm.rules).
However, this means that other initramfs generators each have to
implement and maintain the same rule which leads to unnecessary
duplication.

Instead, let's make the rule part of the upstream lvm rules, which
will ensure that generated initramfses will just work if they make
sure the lvm udev rules are installed, without having to figure out
that they have to add an extra rule themselves on top.

Identical rule in Arch Linux's lvm2 package: https://gitlab.archlinux.org/archlinux/packaging/packages/lvm2/-/blob/main/11-dm-initramfs.rules?ref_type=heads
2024-03-25 08:04:00 +00:00
48188d7181 udev: change action check from ACTION!="add|change" to ACTION=="remove"
For DM devices, the add/change/remove can appear as action for genuine
udev events.

However, there are more action types (bind, unbind, move, online, offline)
which never appear as actions for genuine DM udev events, but they can
still be synthesized (e.g. by writing "<action>" to "/sys/.../uevent" file
or by calling "udevadm trigger --action=<action>").

Let's also process these extra action types so that the udev-related content
is not lost completely, keeping all the symlinks and udev db entries just like
this was a synthetic udev event with "change" action.

Related to https://gitlab.com/lvmteam/lvm2/-/issues/4.
2024-03-25 07:57:33 +00:00
71bac6f45b WHATS_NEW: update
Commits 6f44e1093c .. 038f9254d9
2024-03-25 08:52:56 +01:00
038f9254d9 10-dm.rules: bump DM_UDEV_RULES_VSN to 3
Bump the rules version in order to indicate that upper level rules
should consume DM_UDEV_DISABLE_OTHER_RULES_FLAG rather than DM_NOSCAN
and DM_SUSPENDED.

Also update the comments at the top of the file that describe the
exported properties, and add a note about internal device-mapper
properties.

Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Peter Rajnoha <prajnoha@redhat.com>
2024-03-25 07:31:36 +00:00
a196752969 dm udev rules: don't export and save DM_NOSCAN
DM_NOSCAN is not an official API any more and doesn't have to be
restored from the udev db. Rename it to .DM_NOSCAN.

Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Peter Rajnoha <prajnoha@redhat.com>
2024-03-25 07:31:36 +00:00
21ca92c432 dm udev rules: don't export and save DM_SUSPENDED
DM_SUSPENDED is a device-mapper internal flag, which is not intended to be
used by other rules, and which is determined by 10-dm.rules from sysfs for
every uevent. Rename it to ".DM_SUSPENDED", so that it won't be saved in the
udev database.

Known consumers of DM_SUSPENDED are 66-kpartx.rules (from multipath-tools) and
99-systemd.rules (from systemd). These will have to be adapted.
11-dm-mpath.rules will be changed to use .DM_SUSPENDED.

Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Peter Rajnoha <prajnoha@redhat.com>
2024-03-25 07:31:36 +00:00
2b2f11a74c 11-dm-lvm.rules: don't restore DM_UDEV_DISABLE_OTHER_RULES_FLAG from db
DM_UDEV_DISABLE_OTHER_RULES_FLAG is used as the "output" flag of the
device-mapper rules, to be consumed by non-dm rules. It is a logical OR of
several conditions that might make dm devices inaccessible. 10-dm.rules
calculates it for every uevent, whether it's genuine or spurious.

DM_SUBSYSTEM_UDEV_FLAG0 is just another flag that needs to be or'd in. We
don't need to restore the previous state of DM_UDEV_DISABLE_OTHER_RULES_FLAG.
Actually, doing so is wrong if the flag has previously been set because the
device was suspended, and the device isn't suspended anymore.

Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Peter Rajnoha <prajnoha@redhat.com>
2024-03-25 07:31:36 +00:00
f98d020ead 10-dm-rules: don't restore DM_UDEV_DISABLE_OTHER_RULES_FLAG from db
We use DM_UDEV_DISABLE_OTHER_RULES_FLAG to tell upper non-DM layers
to keep their hands off the device in question, for any reason.
One possible reason is that the device is supended; another is that
the cookie carries the flag of the same name.

DM_SUSPENDED is not restored from the db, but evaluated anew for every
uevent. Therefore DM_UDEV_DISABLE_OTHER_RULES_FLAG shouldn't be
restored, either. Use a new variable DM_COOKIE_DISABLE_OTHER_RULES_FLAG
to save and restore the original value from the cookie.

Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Peter Rajnoha <prajnoha@redhat.com>
2024-03-25 07:31:36 +00:00
0fe2d778aa 10-dm.rules: test DISK_RO after importing properties
DISK_RO is set in the environment of a block-device uevent if and only if
the read-only (ro) attribute of the device just changed (the kernel
function set_disk_ro() was called). It is not synoymous with the "ro" sysfs
attribute; the device could very well be write-protected if DISK_RO is not
set. Device mapper-level probing is possible for DISK_RO events, but it makes
little sense, because the device propreties haven't changed as far as dm is
concerned. But we should import possible previously set device properties
to avoid confusing follow-up rules. We should do this for both DISK_RO=1
and DISK_RO=0 events.

Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Peter Rajnoha <prajnoha@redhat.com>
2024-03-25 07:31:36 +00:00
6f44e1093c 13-dm-disk.rules: import ID_FS_TYPE
ID_FS_TYPE is the most important udev property for most follow-up
rules. It must be imported from the udev db if blkid can't be run.

Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Peter Rajnoha <prajnoha@redhat.com>
2024-03-25 07:31:36 +00:00
e5dc11e26d WHATS_NEW: update 2024-03-21 22:35:47 +01:00
635df7486f configure: autoreconf with new version
Add  AC_PROG_GREP & AC_PROG_EGREP.
Rebuild with newer version of auto tools packages.
2024-03-21 22:35:47 +01:00
c5827b2013 tests: check cachevol makes one table line for -cmeta
When using cache with cachevol, make sure the subdevice -cmeta
creates just one line.
2024-03-21 22:35:47 +01:00
b47b66ebff dev_manager: pending traces only existing LV
Before adding LV to the dtree, check whether it's already
in dtree.
2024-03-21 22:35:47 +01:00
622884d67a dev_manager: open_count not needed
We do not need to check for open_count in these _info calls.
2024-03-21 22:35:47 +01:00
363e8888ae dev_manager: implement _cached_dm_tree_node 2024-03-21 22:35:47 +01:00
a985d5c63d dev_manager: fix table for cache with cachevol
When using cached LV with cachevols (so not with cachepool),
the loaded table could have been using more then one mapping line
for sub devices - resulting into data corruption in some cases
when i.e. taking snapshot of such cached LV with and instead of
single line - 2 lines were generated into DM table as the code
skipped protection again repeated addition.

vg-fast_cvol-cdata: 0 16384 linear 253:2 16384
vg-fast_cvol-cdata: 16384 16384 linear 253:2 16384

New code is also refactoring to use _add_new_cvol_subdev_to_dtree
(similar _add_cvol_subdev.. ) and also the addition of subdev has
been moved after check for already processed node.
Also the cachevol sub devices are now added with the insertion
of cachevol with cached LV.
2024-03-21 22:35:47 +01:00
ad582da3ca dev_manager: relocate code
Use better place to search for cvol subdev mappings.
Add them with cachevol that is used for cache LV.
2024-03-21 22:35:47 +01:00
abc1b44d8d dev_manager: refactor
Use struct initilizer to setup lvid.
2024-03-21 22:35:47 +01:00
9718fd2496 debug: print names of tracked LVs
Debug was printing passed in LV name, but it's more usable to see
names of LVs 'tracked' for removal.
2024-03-21 22:35:47 +01:00
1658776aaf man: lvm.conf mention missing array brackets 2024-03-21 09:16:41 -05:00
2fc66d2835 lvconvert: fix displayed lv name in convert to snapshot 2024-03-20 09:13:31 -05:00
4efe8e83cf tests: add more sleep time
Give some more waiting time to testing loop.
2024-03-20 11:19:26 +01:00
4b1664236b cmdline: some simple optimization
Some cheap parser init speedups cutting away some cpu cycles...
Use cheaper tests in if ( && )
Avoid unnecessary strchr calls.
2024-03-20 11:18:04 +01:00
f93446486e makefiles: add missing cleanup targer 2024-03-19 20:08:01 +01:00
d0c83d4680 WHATS_NEW: update 2024-03-17 13:31:57 +01:00
7084b17c95 make: generate 2024-03-17 13:31:57 +01:00
9c9c37aa11 tests: external origin chaining
Add tests for stacked usage of external origins.
2024-03-17 13:17:53 +01:00
901becc748 man: lvmthin update for external origin usage
Document usage of chaining external origins as it is now possibly to
create thinA LV in poolA which use thinB LV in poolB as it external
origin and user could create chain of such LV.
2024-03-17 13:17:53 +01:00
68fdae1184 debug: enhace device_mapper debug log for dm tree 2024-03-17 13:17:53 +01:00
8c7400121e debug: trace when ignoring origin_only suspend
Add log debug message when origin_only suspend would be ignored.
2024-03-17 13:17:53 +01:00
3b9787d4ee lvconvert: enhance external origin conversion 2024-03-17 13:17:53 +01:00
7ae9662b4e lv: swap more lv properties
When using swap_lv_identifiers() we were basiclly exchanging 'names'
and only according to the caller some more data were 'transfered'.

However in most cases we should swap properties like 'hostname' as
the creation information should be preserved.

So let's do the function more universal.
2024-03-17 13:17:53 +01:00
457bd1392a thin: support chaining of external origins
Improve support for building DM tree when there is a chain
of external origins used for LV.

For this we cannot use track_external_lv_deps as this works
only for LV with just one external origin in its device tree.

Instead add directly 'dev' to the instead of add whole LV.
This avoid possibly recurive endless loop, however we may eventally
have some problems with undiscovered/missing devices in DM tree.
2024-03-17 13:17:53 +01:00
a0776fe409 thin: remove stack external origins
Ensure external origin is deactivated during removal.
Only unused external origins can be deactivated.
2024-03-17 13:17:53 +01:00
3bd9f936da thin: delayed resume for LV conversion
When we have some existing LV and this LV is being converted to
external origin - during the DM table manipulation there is a short
moment when the LV is being 'resumed' as 'read-only' volume
while still being live as 'rw' volume i.e. we could have had
a single thin LV active twice.

To avoid such weird scenarios of dual access to a same volume, we
just postpone a resume until a moment, where the existing volume
is already suspended thus no I/O can be in flight to such device.

Note: however there is slight catch - that we now have basically
a different 'risk' case where a resume of such i.e. new external
origin LV might fail and we are already in suspend tree state -
resolving error path in this situation is untrivial as well...
2024-03-17 13:17:53 +01:00
386f0bfb4f thin: lock fs when converting to external origin
Ensure suspend is locking fs, when converting LV to external origin.
2024-03-17 13:16:35 +01:00
edc91caffb thin: external origins across thin-pool
Fix/support creation and usage of the external origin
across thin-pools - so thin LV can use thin LV from
some other thin-pool as external origin (read-only).
2024-03-16 10:40:54 +01:00
27bdd038a8 thin: validate usable volume for external origin
When creating external origin via 'lvcreate --type thin'
add the validation for LV being usable as external origin
since certain LVs cannot be really used this way.
Also call this function early during lvcreate cmdline arg
validation se we do not need to do unecesary operation.
2024-03-16 10:40:54 +01:00
9e2870cc9f activation: reduce table preloading
Over the time the code for preloading detached LVs got unnecessarily
complicate. But actually we need to preload only LVs that
were previously non-toplevel (invisible) LVs and became visible
toplevel LVs in the precommitted metadata.

If there would be needed some other rule, it would likely be a bug in
conversion code forgetting to set visibility flag on detached LV.

This reduces number of unnecessary repeated DM tree preloading.
2024-03-16 10:34:31 +01:00
d356561465 makefiles: correct install srcdir
When building in other dir, ensure srcdir is used to find helper
script (via vpath) through  $< usage.

Add also missing [INSTALL] prints for some installed files.
2024-03-16 10:31:31 +01:00
9d145c17c3 snapshots: avoid monitoring of inactive origins
External origins for thin volumes can be also used at the same time
as old(thick) snapshot origins. However in this case it's possible
the LV is only active as being 'external' origin, but old snapshot LVs
are not active. For this case before handling these
LVs for un/monitoring check the active state of origin LV.

This should prevent warnings of monitoring failures.
2024-03-16 10:23:55 +01:00
d1aacae0f7 lvm.conf: update scan_lvs description
to better reflect the devices file existence, and
to mention layered autoactivation in lvm udev rules.
2024-02-21 11:08:02 -06:00
e53703b88a make: generate 2024-02-19 14:26:40 +01:00
66be32fbc1 cleanup: remove unused code 2024-02-19 14:20:39 +01:00
4f936f2312 devices: refactor recursive dir create
Make recursive directory path creation reusable via
dir_create_recursive.

While we already have dm_create_dir() - it's not taking mode arg,
so let's make lvm's internal file helper function.
2024-02-19 14:20:39 +01:00
c534cf3bca label: simplify code 2024-02-19 14:20:39 +01:00
d486b379d0 bcache: remove duplicate _wait_all call
Since the  bcache_flush() is supposed to already use _wait_all()
remove duplicated invoce of this function.
2024-02-19 14:20:39 +01:00
d19235993e cache: check module in modules builtin
Instead of parsing the whole /proc/kallsyms use faster variant
of using modprobe tool logic.

lvm2 here wants to know whether the particular DM cache policy is
present in the kernel - however since the cache policy does not have
any kernel module parameters and it can be built-in to a kernel
there is no /sys/modules directory in such case and we would need to call
modprobe everytime we want detect such case.

The old solution tried to look for particular kernel symbol
(and like not the right way, as smq_exit might be actually ommitted).

New version checks MODULES_PATH/`uname -r`/modules.builtin for
whether is present cache policy module instead of CPU expensive parsing
of kallsyms.
2024-02-19 14:20:39 +01:00
1453ccd5b8 configure: add --with-modulesdir
Add configurable path for directory with kernel modules.
Following patch will use this directory to lookup:
/lib/modules/`uname -r`/modules.builtin
2024-02-19 14:20:39 +01:00
55937f9c8e vdo: read VDO stats via dm message
As the sysfs interface is seen somewhat obsolete, swith code
to prefer using DM 'stats' message to get our currently needed
info for VDO pool target.
2024-02-19 14:20:39 +01:00
4f9215e70f devices file: rename unused system.devices
If lvm.conf has use_devicesfile=0 and /etc/lvm/device/system.devices
exists, then rename it to system.devices-unused.YYYYMMDD.HHMMSS.
This prevents an old, incorrect system.devices from being used in
the future if lvm.conf is changed to use_devicesfile=1.
2024-02-15 11:40:37 -06:00
e59027e4f7 devices file: back up each version
Create backup copies of system.devices in /etc/lvm/devices/backup
named system.devices-YYYYMMDD.HHMMSS.NNNN.  NNNN is the version
counter from the file.

Each time that an lvm command writes a new system.devices file,
it also writes the same file in the backup directory.

A new comment line is added to system.devices with HASH=<num>
where <num> is a crc calculated from the uncommented lines in
system.devices.  This lets lvm detect if the file has been
modified outside of lvm itself.

If system.devices is edited directly, the next time a command
reads the file, the crc will not match the HASH value.  The
command will then rewrite system.devices with the correct HASH
value, and create a backup reflecting the edits.

A default limit of 50 backup files is kept, configurable by
lvm.conf devicesfile_backup_limit (set to 0 to disable backups.)
2024-02-15 11:40:37 -06:00
ee73875ff0 udev: ignore LVs containing PVs
If LVM LVs happen to contain PVs, they are passed to the lvm udev
rule for processing, where they should be ignored.  PVs on LVs
most likely belong to VM images, and don't belong to the host
which sees the LV.  It's unsafe for the host to use these PVs.
Without this change, the LV would be processed by pvscan which
would generally ignore it, either because of the devices file,
or because of the default lvm policy to not consider LVs as
potential PVs.  This change makes the udev rule consistent
with that policy and avoids the unnecessary system messages
produced when pvscan ignores the LV.
2024-02-08 14:51:46 -06:00
fe822f7043 system_id: explain the reason for choosing appmachineid over machineid
Since understanding the reason for choosing the appmachineid over the
direct use of machineid is not easily found, I extended to help text to
clarify this a bit.
2024-02-05 14:01:22 -06:00
82f187ce88 man: fix typo in -A description 2024-02-05 12:13:44 -06:00
1c3ae2b678 archiving: Fix doubled filename in vgcfgrestore 2024-01-24 14:11:19 +01:00
5533f034e2 thin_pool: correct refactoring chunk_size
Function to recalc chunk_size according to dev hints needs to be
used after chunk_size is being set to thin pool segment - correct
this ordering mistake introduced in previous refactoring commit.
2024-01-17 17:31:19 +01:00
9d9e43b87f vdo: correct vdo header size
Previous patch that introduced support for thinpool with vdo
not correctly handled header size - as this part is not fully usable
yet.  We are going to try to use the 0, but current state of code is not
yet compliant to this logic so keep vdo_header_size during conversion
and alos correctly pass through virtual_extents to vdo formating.
2024-01-17 17:30:10 +01:00
c81e204fd0 WHATS_NEW: update 2024-01-10 14:08:19 +01:00
cdeb491498 make generate 2024-01-10 14:08:19 +01:00
c8f9dd2368 tests: testing creation of compressed thin-pool 2024-01-10 14:02:22 +01:00
4ad98540bc lvmcmdline: support --pooldatavdo
Extend definitions for lvcreate & lvconvert to support
new option  --pooldatavdo y|n  with thinpools.
2024-01-10 14:02:22 +01:00
cd3275ce73 man: document creation of VDO thin-pool
Show some examples how to create and convert thin-pools
with VDO volume for thin-pool data.
2024-01-10 14:02:22 +01:00
db0de73d6e vdo: support creation of compressed thin-pools
Add code to handle creation of  thin-pool with VDO data backend
which can be seen as compressed deduplicated thin-pool.

To avoid need of changing to many internal APIs, pass the conversion
parameters for create thin-pool data volume via cmd_context.
2024-01-10 14:02:22 +01:00
6ec2f1f44b vdo: refactor conversion to vdo lv
Introduce struct vdo_convert_params {} to pass-in all the parameters
needed for the conversion of an LV to a vdopool + vdo LV.

Function convert_vdo_lv() is also able to create a new LV and swap
segments, so the passed in LV can be later on use for futher
conversion so this refactoring makes it ready for more enhanced
usage.
2024-01-10 14:02:22 +01:00
7544b9fc10 vdo: refactor vdo_params passing
Introduce vdo_convert_params and use vdo_params from this structure
also with lvcreate_params.

Later we will use this for convertion of thin-pool data volume to VDO.
2024-01-10 14:02:22 +01:00
4ccedceaa8 thin_pool: introduce --pooldatavdo
Introducing new arg --pooldatavdo y|n
2024-01-10 14:02:22 +01:00
c496f80379 pool: code refactoring
Move pool related manipulation code to pool_manip.c.
2024-01-10 14:02:22 +01:00
a176184b7d thin_pool: code refactoring
Move common code into thin_pool_set_params()
(just like we use  cache_set_params).
2024-01-10 14:02:22 +01:00
f3f7f5db89 cov: check for failing device_ids_read
TODO: not sure if here we should possibly exit from function.
2024-01-10 14:02:22 +01:00
2770485737 cov: remove unneeded header 2024-01-10 14:02:22 +01:00
18d3283157 cov: some stack tracing corrections
Checking some returned values and adding/correcting
some debug tracing.
2024-01-10 14:02:22 +01:00
a882878eba lvcreate: support vg profile for error_on_full 2024-01-10 14:02:22 +01:00
2135bbe558 vdo: flip return value to int
Change API to return just 0/1.
2024-01-10 14:02:22 +01:00
73967233e4 dev_manager: reuse _setup_task_run 2024-01-10 14:02:22 +01:00
b058498404 lv: remove unused declaration 2024-01-10 14:02:22 +01:00
b1e8af1c0c activate: use lv_layer
Avoid code duplication.
2024-01-10 14:02:22 +01:00
b69f73b13e raid: add messages to lvs command output in case RaidLVs require a refresh
If a RaidLV mapping is required to be refreshed as a result of temporarily failed
and recurred RAID leg device (pairs) caused by writes to the LV during failure,
the requirement is reported by volume health character r' in position 9 of the
LV's attribute field (see 'man lvs' about additional volume health characters).

As this character can be overlooked, this patch adds messages to the top
of the lvs command output informing the user explicitely about the fact.
2023-12-06 13:11:23 +01:00
d68c227aad man: update readonly description 2023-12-05 12:42:38 -06:00
7b64d9946d man: add inte(g)rity to man lvs 2023-12-05 09:08:24 -06:00
28786f826a spec: Uncomment some globals
These were incorrectly commented out, after escaping '%' these no longer
compile on some older machines.
2023-11-29 15:26:03 +01:00
ee31ba5023 spec: Install and package /etc/lvm/devices 2023-11-29 15:09:36 +01:00
d1f0b89e65 dmstats: Fix memory leak on error path 2023-11-28 22:00:14 +01:00
22e482d965 post-release 2023-11-21 14:38:53 +01:00
d786a8f820 pre-release 2023-11-21 14:37:11 +01:00
9cf9ff6caf make: generate 2023-11-21 14:22:35 +01:00
bbbe02b227 WHATS_NEW: spelling 2023-11-21 14:22:35 +01:00
f4edd87ffc raid: lvcreate and lvchange fail if --min_recovery_rate is defined
Fix typos in previous commit 3589e515d.

Both commands default [raid_](min|max)recoveryrate to 0 but ensure
min_recovery_rate is not larger than max_recoveryrate.  This results
in command failure without requesting the user to also define
max_recovery_rate >= min_recovery_rate.

Fix both commands by defining max_recovery_rate = min_recoveryrate
in case "lvcreate/lvchange --minrecoveryrate Size ..." requests a
larger value than current maxrecoveryrate without also giving option
2023-11-21 14:19:30 +01:00
3589e515dc raid: lvcreate and lvchange fail if --min_recovery_rate is defined
Both commands default [raid_](min|max)recoveryrate to 0 but ensure
min_recovery_rate is not larger than max_recoveryrate.  This results
in command failure without requestinng the user to also define
max_recovery_rate >= min_recovery_rate.

Fix both commands by defining max_recovery_rate = min_recoveryrate
in case "lvcreate/lvchange --minrecoveryrate Size ..." requests a
larger value than current maxrecoveryrate without also giving option
"--maxrecoveryrate Size ..." with a size greater or equal than min.
2023-11-20 17:14:01 +01:00
921ceddebf lvmconfig: uncomment the report section
so settings can be changed without uncommenting the
start/end of the section.
2023-11-17 13:52:49 -06:00
c44f3a5889 WHATS_NEW: lv_attr for iorig LVs 2023-11-17 13:29:11 -06:00
0e4fd4485f lvs: set first attr flag for raid integrity images
The first lv_attr flag is 'i' or 'I' for a raid image.
(i: raid image, I: out of sync raid image)
For integrity raid images (_iorig), the flag was not being set.
2023-11-17 13:26:23 -06:00
7ba0d8e07b WHATS_NEW: pvs -A 2023-11-16 08:46:23 -06:00
622284740a pvs, pvscan: new option -A to show PVs outside the devices file
pvs -A|--allpvs
	Show PVs that would otherwise be excluded by the devices file.

pvscan -A|--allpvs
	Show PVs that would otherwise be excluded by the devices file.
	For those devices that are included by the devices file,
	their device ID is displayed in place of the usual "lvm2"
	format and size.

(pvs -a|--all is unchanged, and shows devices not formatted as PVs.)
2023-11-16 08:45:46 -06:00
29c0763480 make: generate 2023-11-15 13:36:56 +01:00
6c6aebba88 WHATS_NEW: update
Remove stray line
2023-11-15 13:36:56 +01:00
8edc60ffdd spec: Fix spec file to work with mock
- missing BuildRequires

diff --git a/spec/source.inc b/spec/source.inc
index 7b44ef152..b04c500a2 100644
--- a/spec/source.inc
+++ b/spec/source.inc
@@ -12,8 +12,8 @@
 %global enable_lvmlockd 1
 %global enable_lvmpolld 1
 %global enable_dmfilemapd 0
-#%global enable_lvmlockd_dlm 0
-#%global enable_lvmlockd_sanlock 0
+#%%global enable_lvmlockd_dlm 0
+#%%global enable_lvmlockd_sanlock 0

 %if %{enable_udev}
 %service lvmpolld 1
@@ -43,7 +43,8 @@
 %with writecache internal
 %with integrity internal

-%global buildreq_udev systemd-devel
+# NOTE: Required by fedora 38+, maybe older
+%global buildreq_udev systemd-devel, systemd-units
 %global req_udev udev >= 181-1

@@ -60,15 +61,12 @@
  %global sanlock_version 3.3.0-1
  %global enable_lvmlockd_dlm 1
  %global enable_lvmlockd_sanlock 1
+ # FIXME: Check these conditions against RHEL builds!
  %if %{rhel}
-  %ifarch i686 x86_64 s390x
-   %global buildreq_lvmlockd_dlm dlm-devel >= %{dlm_version}
-  %else
+  %ifnarch i686 x86_64 s390x
    %global enable_lvmlockd_dlm 0
   %endif
-  %ifarch x86_64 ppc64le ppc64 aarch64
-   %global buildreq_lvmlockd_sanlock sanlock-devel >= %{sanlock_version}
-  %else
+  %ifnarch x86_64 ppc64le ppc64 aarch64
    %global enable_lvmlockd_sanlock 0
   %endif
  %endif
@@ -78,6 +76,12 @@
   %global enable_lvmlockd_dlm 1
  %endif
 %endif
+%if 0%{enable_lvmlockd_dlm}
+ %global buildreq_lvmlockd_dlm dlm-devel >= %{dlm_version}
+%endif
+%if 0%{enable_lvmlockd_sanlock}
+ %global buildreq_lvmlockd_sanlock sanlock-devel >= %{sanlock_version}
+%endif

 ##############################################################

@@ -164,6 +168,11 @@ Source92: build.inc
 Source93: packages.inc
 Source94: macros.inc

+BuildRequires: make
+BuildRequires: gcc
+%if %{enable_testsuite}
+BuildRequires: gcc-c++
+%endif
 BuildRequires: libselinux-devel >= 1.30.19-4, libsepol-devel
 BuildRequires: ncurses-devel
 %if %{enable_readline}
@@ -174,6 +183,9 @@ BuildRequires: libedit-devel
 %endif
 BuildRequires: module-init-tools
 BuildRequires: pkgconfig
+# TODO: Should these be conditional?
+BuildRequires: libaio-devel
+BuildRequires: libblkid-devel

 # Expands to nothing unless at least 2 arguments are given
 %define maybe() \
@@ -189,6 +201,8 @@ BuildRequires: pkgconfig
 %maybe BuildRequires: %{?buildreq_lvmlockd_sanlock}
 %maybe BuildRequires: %{?buildreq_python3_devel}
 %maybe BuildRequires: %{?buildreq_python3_setuptools}
+%maybe BuildRequires: %{?buildreq_python3_dbus}
+%maybe BuildRequires: %{?buildreq_python3_pyudev}

 %description
 LVM2 includes all of the support for handling read/write operations on
2023-11-15 10:37:57 +01:00
8f77a14b69 WHATS_NEW: update 2023-11-15 10:37:57 +01:00
db03270135 device: remove log_debug for nvme device 2023-11-09 13:31:01 -06:00
e71b663bf5 device_id: remove unused dev pointer from dev_id struct 2023-11-09 13:15:02 -06:00
631b8edefb device_id: ensure pvid buffers are ID_LEN+1
A pvid string read from system.devices could be less
then ID_LEN since system.devices fields can be edited.
Ensure the pvid buffer is ID_LEN+1 even if the string
read from the file is shorter.
2023-11-09 13:15:02 -06:00
de2b11f39a device_id: improve searched_devnames temp file
Include info in the temp file to confirm that it should be used.
The temp file is meant to suppress repeated, identical searches
for the same PVIDs on the same set of devices.  Write to the file
a count and hash of the missing PVIDs and a count and hash of the
devices to search.  A subsequent command will ignore and remove
the temp file if any of these values differ.  We don't want to
suppress a search if a change has occured, and a missing PV could
be found by scanning devices.
2023-11-09 13:14:55 -06:00
2b7c832847 lvmdevices: print changes for product_uuid or hostname
used by the recently added refresh feature
2023-11-07 14:30:48 -06:00
e38d974b50 lvmdevices: handle empty fields in new check and update
Expand the recent commit 37773c1055
"lvmdevices: new output and options for check and update"
to specifically cover entries with empty fields.
2023-11-03 15:28:26 -05:00
35cefa50fa device_id: change default search_for_devnames to all
Problematic scenario:
. the device for a PV has no wwid, so it's identified in system.devices
  with IDTYPE=devname IDNAME=/dev/foo
. user adds/enables a wwid for the device
. on reboot, the device name changes, e.g. now /dev/bar
. the code that searches for the new device name includes an
  optimization to skip looking on devs that have a wwid, on
  the basis that a device with a wwid won't have IDTYPE=devname
. this optimization causes lvm to not look for the PV on /dev/bar
  since that device now has a wwid, so the PV is not found
. the optimization is enabled by search_for_devnames="auto"
. change the default to search_for_devnames="all" which does not
  use the problematic optimization
2023-11-02 13:00:50 -05:00
37773c1055 lvmdevices: new output and options for check and update
- add new comparison between old and new entries, and use this
  as the basis for new dedicated output for check and update
- add new --refresh option to search for missing PVIDs on all
  devices, and possibly update the device ID
- internally, only use the term "refresh" for cases where a
  new device ID may be found and assigned for a missing PVID
2023-11-02 11:46:31 -05:00
a5628cf782 device_id: improve validate debug messages
Make the device_ids_validate messages consistent.

Consistently use "noupdate" and "update_needed" args.
2023-11-02 11:46:31 -05:00
ec47f0763d device_id: reduce messages
Don't print messages about devices file entries that are
missing or are being updated.
2023-11-02 11:46:31 -05:00
55e36d78a4 README: update with new list info
Server is changed for linux-lvm and lvm-devel mailing lists.
2023-10-31 19:07:47 +01:00
5210f6665c tests: unit test for raid status 2023-10-31 18:53:30 +01:00
0e2904d2c5 tests: longer timeout 2023-10-31 18:53:30 +01:00
3fa424f893 tests: lvmdbusd handles empty LvCommon.Devices
During vdo testing with smaller block devices the test needs to determine
which PVs in a VG are unused.  This was leveraging LvCommon.Devices, but
that isn't populated when a LV is resides on a LV pool instead of a PV.
This is a known limitation of the code at this time.  For now we will walk
all the PVs in the VG looking for ones that don't have any associated LVs
and use them instead.

Signed-off-by: Tony Asleson <tasleson@redhat.com>
2023-10-31 18:53:07 +01:00
3f084b06e9 device_mapper: raid status handle all a chars
When getting raid status from some older kernels, we may get an 'a'
for 'A' leg when doing initial synchronization.
This may prohibit removal of newly synchronized leg until synchronization
is finished.
So in this case change the status to look like being reported
from a newer kernel version.
2023-10-31 18:52:05 +01:00
282d947c36 tests: add devicesfile-misc 2023-10-23 15:17:29 -05:00
e291178633 device_id: simplify devname matching
Handle this case directly rather than going through the
process for reading other device ids.  Also simplify
matching alternate dm devnames.
2023-10-23 15:17:29 -05:00
46521a46d2 device_id: no idname should be NULL not empty string
One place was setting idname to "" instead of NULL when
there was no idname value.
2023-10-23 15:17:29 -05:00
9ff0615546 device_id: first match non-devname device ids
Incorrectly matching a dev to a devname id (due to changing devnames)
before matching the dev to a proper device id, can result in the
dev not being matched to the real id.
2023-10-23 15:17:29 -05:00
c36e012926 libdm: report: fix invalid JSON if using DM_REPORT_OUTPUT_MULTIPLE_TIMES and selection
When reporting in JSON format, we need to be able to find the 'last
displayed row', not just 'last row' as we did before. This is used
to decide whether to put the JSON_SEPARATOR (the ',' character)
between the lines when reporting in JSON format.

This is mainly important in case we use a combination of JSON format
and a report marked with DM_REPORT_OUTPUT_MULTIPLE_TIMES flag.
Such report may be reused several times with different selection
criteria each time. In that case, the report always contains all lines
in memory, even though some of them do not need to pass the selection
criteria that are currently used.

Without DM_REPORT_OUTPUT_MULTIPLE_TIMES flag, the report only contains
the lines that have passed the selection criteria, so the this wasn't
an issue in this case.

Fix suggested by Lars Ellenberg and reported here: https://github.com/lvmteam/lvm2/issues/130
2023-10-23 14:18:21 +02:00
d019c41f7a typo: update 2023-10-20 00:21:13 +02:00
c7851b9c34 tests: longer delay between table reloads
It looks like there is some kernel bug/limitation
that may cause invalid table load processing:

dmsetup load LVMTEST-LV1
device-mapper: reload ioctl on LVMTEST-LV1  failed: Invalid argument
  md/raid:mdX: reshape_position too early for auto-recovery - aborting.
           md: pers->run() failed ...
device-mapper: table: 253:38: raid: Failed to run raid array (-EINVAL)
device-mapper: ioctl: error adding target to table

However ATM there is not much we can do then make delays bigger.
TODO: fixing md core...
2023-10-20 00:21:13 +02:00
5d4b2f9ea9 tests: skip on problematic kernel 2023-10-20 00:21:13 +02:00
e41da923a3 lvconvert: fix "lvconvert -m 0" for in-sync legs
With commit d7e922480e
lvconvert -m   may fail if we try to remove 1st. leg that
is out-of-sync while other leg is in-sync.

Hot fix allows to proceed with such down conversion.

Signed-off-by: Heinz Mauelshagen <heinzm@redhat.com>
2023-10-20 00:20:15 +02:00
2b01af3de9 filters: fix condition
During revork in commit cf46f4baee
condition was inverted, the check for non-null string is needed.
2023-10-18 02:19:15 +02:00
2e56778038 tests: aux kills lvmdbusd more agressively
It's not exactly trivial to kill 'frozen' lvmdbusd.
So skip the test testing interruption and also add killall use.
2023-10-18 01:48:50 +02:00
beae68890c tests: wait till snapshot merge is finished
In case test runs with lvmpolld (and lvmlockd) wait till snapshot
merge is finished.
2023-10-18 01:47:13 +02:00
8b8c9dea8a tests: init of dmevent may take upto a second
Dynamic load of plugins takes a while...
2023-10-17 23:24:03 +02:00
249446e0aa tests: avoid busy looping
While waiting for the change, don't busy loop on CPU.
TODO: fix missing notification about device removal.
2023-10-17 16:49:23 +02:00
cb2873ba1c tests: ensure file is removed
Make sure there are no previous loop results.
2023-10-17 16:49:23 +02:00
493af2bb16 lvm: fix reporting path with HOME envvar
When envvar HOME is not present we were using invalid path with (null).
2023-10-17 16:49:23 +02:00
7e017abb30 make: generate 2023-10-17 16:48:50 +02:00
be9a64e654 device_id: make dmeventd use system.devices by default
When no dmeventd.devices exists, make it use system.devices
rather than no devices file at all.
2023-10-16 15:40:11 -05:00
a836872199 device_id: accept wwids containing QEMU HARDDISK
A wwid may be useful even when it contains the string
"QEMU HARDDISK", so allow these to be used.
2023-10-16 15:21:22 -05:00
d8d4260df8 device_id: improve handling of non-standard wwid prefixes 2023-10-16 15:12:12 -05:00
e6c6713a1b hints: correct fix for hints with device ids
Fixes commit 63b469c160
"device_id: fix hints with device ids"

It's not correct for internal filtering to be a factor
in validating the set of devs that are the basis for hints.

Instead, look for inconsistencies between a hint entry and
the corresponding devices file entry.
2023-10-16 14:13:27 -05:00
d12e843e4a tests: aux mdadm_assemble skip path
If the old mdadm fails to assembly array due to its internal buggy logic
skip the test instead of failure.
2023-10-16 00:11:35 +02:00
f55dc3006e tests: simplify line counting
No need for pipes
2023-10-15 21:48:22 +02:00
098bc780a2 tests: better synchronization 2023-10-15 21:48:22 +02:00
dfaa891281 tests: fsck with yes
Fsck may need to update metadata even after clean unmount.
2023-10-15 19:51:43 +02:00
d5e58768aa tests: check for blkid
When libblkid is not present (older systems) we can't use new -fs tests at
all so skip these tests.
2023-10-15 14:43:13 +02:00
63885da5b9 tests: shorting batch line output 2023-10-15 14:42:14 +02:00
5cc54458b7 tests: old way to disable copy contructor
Mark them private.
2023-10-14 23:37:38 +02:00
d2d8d0ab5a tests: io stream class saver
Restore io stream when changed by modifiers.
Also simplify getenv access.
2023-10-14 23:14:26 +02:00
1a67bfe396 tests: extend the usability for older systems
Extend the test a bit futher so we can keep logic of resize
working similarly well for older and newer systems.

Test uses new 'aux have_fsinfo'function to regnize compiled
version of lvm.
2023-10-14 23:13:46 +02:00
26766dcf73 tests: aux add have_fsinfo
Add function to detect whether lvm2 was compiled with
blkid.h with BLKID_SUBLKS_FSINFO

Currently it can be detected by support of '--fs checksize'.
2023-10-14 23:12:57 +02:00
c6efab0111 cov: avoid resoure leaks on error path 2023-10-14 23:12:57 +02:00
e8e5e6ee3c cov: check next_get token exists 2023-10-14 23:12:57 +02:00
6afaaca2e5 cov: enusure pointer to idname exists 2023-10-14 23:12:57 +02:00
9668d40d5a resize: reduce without prompt for no-fs case
Apply the same logic for 'lvreduce' which exists for newer
systems (compiled with HAVE_BLKID_SUBLKS_FSINFO)
also for older systems for one very common practical case where
the active LV does not have any blkid known signature/filesystem.

New variant recognized this situation and allowed to proceed
without requesting a prompt, while the older variant always
requested confirmation prompt.

With this patch command now works equily for both variants
for 'active LV' without signature and allows to reduce LV
without prompting.
2023-10-14 23:10:21 +02:00
43020cc474 WHATS_NEW{_DM}: update 2023-10-14 01:04:10 +02:00
0627716f8a configure: update 2023-10-14 01:04:10 +02:00
dd7663d2ae configure.ac: enhancemetns
Simplify configuration with enabling options:
- For --enable-dmeventd automatically --enable-cmdlib.
- For --enable-dbus-service auto --enable-notify-dbus.

Fix check linux/fiemap.h for dmfilemapd.
2023-10-14 01:04:10 +02:00
afe1b2bef7 debug: initialize empty string 2023-10-14 01:04:10 +02:00
46eeb62b04 pool: fix recalculate of pool chunk_size
Before checking seg_type of the first area, check there is
some existing area.
Since we now support error and zero segtypes, these do not have
any PV area present.
2023-10-14 01:04:10 +02:00
85c7629345 libdm: versionion symbol for enhanced dm_task_run
When new app links with current dm_task_run() that propagates ioctl()
errno - ensure it will not be usable with older version without this
supported feature.
2023-10-14 01:04:10 +02:00
b162475391 makefiles: fix missing libs
Recent commit  dc8837f079
became actually to strict - we always want to build lib.a files.
2023-10-13 16:34:48 +02:00
0bbbe08343 dmfilemapd: ensure program_id is initialized
Assing program_id before return 1,
and also stay C99 compatible with size_t declaration.
2023-10-13 16:04:25 +02:00
0b11b08b6e tests: handle empty table better 2023-10-13 15:00:55 +02:00
8b8b8ac1f8 configure: update 2023-10-13 14:33:56 +02:00
9fa364414c tests: skip for missing mkfs.xfs 2023-10-13 14:33:56 +02:00
1605d39b93 tests: comment about version checking to aux.sh
If there would be futher version checking needed,
make a notice there are now two -V formats.
2023-10-13 14:25:02 +02:00
be2b3d5ab8 tests: increase delay 2023-10-13 14:25:02 +02:00
061c008e15 tests: some minor enhancement of udev test
Reduce pgrep usage.
2023-10-13 14:25:02 +02:00
53da646495 tests: fail tests when machine have suspended devs
If the machine has suspended devices present in the DM table,
it's better to fail the test.
2023-10-13 14:25:02 +02:00
627535f33e tests: use function to restart dmeventd
Move restart to single function.
2023-10-13 14:25:02 +02:00
f117d47ffa configure.ac: version checking for new dmpd tools
New rust version of thin_check returns now also binary name in version,
so adapt the version checking to handle this variant.
2023-10-13 14:25:02 +02:00
48fd9fbd02 configure.ac: support for static linking
Introduce couple configure options:

--without-blkid
--without-systemd
--without-udev

These can be useful for build with --disable-shared
where those libraries are often distibuted without
their static libraries.

However such compiled static binaries then have limitted usage.
2023-10-13 14:25:02 +02:00
dc8837f079 configure.ac: handle --disable-shared flag
Since LVM 2.02 it appears that compiling LVM on a platform which
lacks a shared library linker/loader will fail to produce any
binaries (dmsetup, lvm2, etc).

Adds support for the standard --disable-shared flag, and
use it to disable attempts at building shared libraries.

Modified-by: zkabelac
2023-10-13 14:25:02 +02:00
fb124f0839 device_mapper: pair with libdm _create_and_load_v4
Apply same enhancement also for internal device mapper library
from the commit: 25ef7a7b1a.
2023-10-13 14:24:49 +02:00
0ff027ae2c dmstats: only generate aux data separator if group tag is defined
Fix a bug in _stats_set_aux() that causes bogus data to appear
in the 'userdata' field of stats reports when previously grouped
regions are ungrouped:

/var/tmp/File With Spaces: Created new group with 1 region(s) as group ID 0.

Removed group ID 0 on fedora-root

Name             GrpID RgID ObjType RgStart RgSize  #Areas ArSize  ProgID  UserData
fedora-root          -    0 region    6.39g 100.00m      1 100.00m dmstats #-
                                                                           ^^
This is the aux_data separator character followed by empty user data.
The _stats_set_aux() function should only emit the separator if
there is a valid group descriptor for the region.
2023-10-12 11:31:14 +00:00
995c7b503b Add more dmstats integration tests
Add new tests for filemap, group/ungroup, histograms, precise timestamps
and userdata.
2023-10-12 11:31:14 +00:00
9aa47f9768 Quote path value in --filemap debug messages
Improves readability of debugging output when file paths contain
whitespace.
2023-10-12 11:31:14 +00:00
7d8981dd3f dmstats: support group aliases with embedded whitespace
Creating a group with a name that contains whitespace causes an error in
the @stats_set_aux message:

device-mapper: message ioctl on  (253:0) failed: Invalid argument
Could not create regions from file /var/tmp/File With Spaces.

Fix this by quoting the group alias and backslash escaping any
embedded space characters.
2023-10-12 11:31:14 +00:00
33931431c3 Refactor _stats_parse_list_region()
Refactor the function that parses regions from @stats_list data to
separate the parsing of variable string data from the fixed parts
of the @stats_list response.
2023-10-12 11:31:14 +00:00
ac41deeeac Rename _stats_set_aux() argument
The aux_data argument of _stats_set_aux() is the user-defined data
to be stored with the stats region. Rename the argument to better
reflect this.
2023-10-12 11:31:14 +00:00
f0fd03b122 dmstats: use correct value for precise in _stats_create_file() 2023-10-12 11:31:14 +00:00
eda99fc383 Clean up group struct in _stats_create_group() error path
Fix a double free in the error path from _stats_create_group() by
clearing the group struct embedded in the dm_stats handle before
returning:

    device-mapper: message ioctl on  (253:0) failed: Invalid argument
    Could not create regions from file /var/tmp/File With Spaces.
    free(): double free detected in tcache 2
    Aborted (core dumped)
2023-10-12 11:31:14 +00:00
25ef7a7b1a _create_and_load_v4: propagate ioctl errors back to caller
When setting up dm-verity devices with signed root hashes it is very
useful to have a recognizable error code when a key is not present in
the kernel keyring. Turns out the kernel actually returns ENOKEY in that
case, but this gets lost in libdevmapper.

This fixes this: in _create_and_load_v4() it copies the error code from
the ioctl from the sub-tasks back to the main task field on failure.

This is not enough to make libcryptsetup actually propagate the ENOKEY
correctly, that also needs a patch to libcryptsetup, but this is part of
the puzzle.
2023-10-11 15:35:33 +02:00
63b469c160 device_id: fix hints with device ids
Fix some interactions between device IDs and hints.  Hints
may limit the scanned devices which should not always trigger
a search for the PVs that were intentionally not scanned.
Hints should also be invalidated if they contain a device
that's become excluded by an internal filter such as the
device_id filter.
2023-10-10 11:47:29 -05:00
f20be398a1 device_id: refresh devname idnames if any are not found
Search for a PV on other devices if it's a devname entry
and the name doesn't exist on the system.  This restores
code that should not have been removed in commit 1901a47df
"device_id: fix conditions for device_ids_refresh"
2023-10-10 11:46:21 -05:00
25a87ea16a device_id: fix lvmdevices update segfault
From commit 1901a47df1
"device_id: fix conditions for device_ids_refresh"
2023-10-06 12:24:34 -05:00
f960fe0578 tests: delay_dev to slowdown pvmove
throtling mirror device is becoming useless with faster CPUS,
as way to many data can be transferred before throttling steps-in.
So prefer using  dm-delay for test and keep throttling as fallback.
2023-10-06 10:51:15 +02:00
2c3742039c tests: skip test if the memory cannot be allocated in kernel 2023-10-06 10:51:15 +02:00
f5512315d2 tests: ignore failure from stop 2023-10-06 10:51:15 +02:00
37329e4184 tests: add delay to let dmevent initalize
There is short time period needed to fully initilize dmeventd and
handle 'kill' signal.
2023-10-06 10:51:15 +02:00
44f86d38f9 debug: fix message severity levels
Add some missing WARNS and correct some severity levels.
2023-10-06 10:50:26 +02:00
1901a47df1 device_id: fix conditions for device_ids_refresh
Fix commit 847f1dd99c
"device_id: rewrite validation of devname entries"

which began calling device_ids_refresh() in cases where it
was unnecessary, leading to extra PV searches and warnings.
Specifically, a command like "lvs <vg>" would use the hints
file to scan only devices for the named VG.  This means that
scanning other PVs would be skipped, and device IDs of those
PVs could not be validated because there are no PVID values
to verify.  This missing info would cause messages about
the missing info, and would cause device_ids_refresh to
search for the PVs that had been intentionally skipped.
2023-10-05 15:33:55 -05:00
bccfd92f4a tests: previous patch wrongly replaced tab
Tab overwrote first char instead of insert.
Actually it should be a single function.
2023-10-05 01:11:54 +02:00
ede63b5029 tests: more complex check for resize of reiserfs
Detection of how the command is supposed to behave actually depends on
the configure.h compilation and whether binary is compiled with
HAVE_BLKID_SUBLKS_FSINFO.

This makes it somewhat complicated in a way how to recognize which
behavior is expected.

Currently we can eventually recognize by checking error output
of some 'random' lvresize command and see if the --fs checksize is
actually recognized and rejected.  If this changes - test needs
to be updated.
2023-10-05 00:03:30 +02:00
b80404f2c6 tests: utils use read without slash mangling
Do not use backslash as escape character for path.
2023-10-04 23:58:54 +02:00
470f1058a8 tests: better coredump lookup
Some bash version may have problem with contruct:
done < <(

Replace it with array reading.
2023-10-04 23:58:54 +02:00
e3adccb528 tests: retry removal
After umout we may race with system udevd rule - so
just retry once again after 1s sleep - that should be
enough - otherwise we would need some loop here...
2023-10-04 22:05:22 +02:00
e72e130e9d tests: convert to heredoc string
Multi-line echo command are problemat across variety of bash version
and may have produce shorter results.
Convert to stable heredoc string with 'tab' skipping <<- for better
formating.
2023-10-04 22:05:22 +02:00
4edaa9fdf5 filters: leave device_id_sysfs_dir only for device_id
Do not use filters for sysfs with device_id.
2023-10-04 22:03:56 +02:00
8f61a127b5 tests: fix reader for runner
Since we now push more data into journal, parser reading this file
for --continue mode need to be adapted.
Also properly align batch mode with '.' for max test length name.
2023-10-03 21:32:12 +02:00
cf46f4baee filters: sysfs use device_id_sysfs_dir
This is mainly useful in internal testing - but keep sysfs dir also
passed to filter.
Also drop use of static variable within sysfs filter and base whole
config at creation time.
2023-10-03 21:30:22 +02:00
0e8c631f5e tests: old g++ needs explicit cast 2023-10-03 12:59:38 +02:00
c818f3dabc tests: give some more time to die
VMs are not top performers here...
2023-10-03 12:46:32 +02:00
48fd6d6d40 tests: restore old fsync method
New code isn't portable across wider range of c++ compilers.
2023-10-03 12:46:32 +02:00
6f52091668 tests: give dmeventd some time to restart
We need to wait for a new dmeventd as fork new daemon from bash.
2023-10-03 02:01:29 +02:00
d01e9de8b8 tests: add RT_LIBS for older g++ 2023-10-03 02:01:29 +02:00
13bf42b8b8 tests: restore fsync for runner
Restore fsync() call For more accurate tracking by buildbot.
Try different rather tricky way of static_cast to use
already opened FD instead of seperate open(),fsync(),close().

It's pretty strange there is no way to enforce fsync() for
C++ iostreams.  Flush() is actully not equal.
2023-10-03 01:58:23 +02:00
a540b3f189 make: generate 2023-10-03 00:02:46 +02:00
36bccbc4f3 tests: skip some tests on valgrind run
Skip some tests that takes too much time with valgrind pass.
2023-10-03 00:02:46 +02:00
3c70c243c5 tests: aux use dmsetup concise
A bit faster creation of multiple devices with dmsetup --concise.
Also solves the 'cookies' handling.
2023-10-03 00:02:02 +02:00
19df4510c2 tests: faster creation of 200 PVs
Use already existing optmized aux version
2023-10-03 00:01:34 +02:00
80899f7010 tests: runner compatible with older g++
Avoid using some constructs available with newer C++ only.
Moving timing into to journal instead of list file.
2023-10-03 00:00:01 +02:00
ffaff7afa6 tests: better handling of system dir
Use more consistenly location of etc dir in tests.
Read value of etc dir via lvm cmd.
2023-10-02 14:25:52 +02:00
e3cee67d77 tests: reiserfs needs fsadm
With plain -r we currenly issue an error message.
2023-10-02 14:25:52 +02:00
368ab3051f tests: reduce slowing down of device
Too high value currently may result in occasional race problem with
device deactivation.
2023-10-02 14:25:52 +02:00
529fe9ef75 tests: aux reuse already pgrep of dmeventd
Test already checks if there is any dmeventd running in the system
in the inittest.
2023-10-02 14:25:52 +02:00
e3dd3424fc tests: enhance runner
Add Timespec class to increase time resolution to miliseconds
(can switch to microseconds if ever needed).
Use more const and const_interators and pass by reference.
Output rusage also to list result file.
Reduce inlining of C++ constructors.
2023-10-02 14:24:04 +02:00
d7b4a4ce01 debug: stacktracing failure 2023-10-02 14:13:12 +02:00
df9e5f39a7 debug: correct check for failing close 2023-10-02 14:13:12 +02:00
88aa285a79 devices: refresh device ids if the system changes
If the system changes, locate PVs that appear on different devices,
and update the device IDs in the devices file.  A system change is
detected by saving the DMI product_uuid or hostname in the devices
file, and comparing it to the current system value.  If a root PV
is restored or copied to a new system with different devices, then
the product_uuid or hostname should change, and trigger lvm to
locate PVIDs from system.devices on new devices.
2023-09-27 15:22:11 -05:00
d06378373e WHATS_NEW_DM: update 2023-09-26 01:32:48 +02:00
cb8486a9b2 tests: check exit_on works 2023-09-26 01:24:38 +02:00
d54deae0ad debug: correcting check for error
Correct trace for erroring case of close.
2023-09-26 01:23:00 +02:00
e930ee93f7 debug: correct level
No error for just tracing message.
2023-09-26 01:23:00 +02:00
a9d7a9d128 dmeventd: implement exit_on file check
When exit on file is present in a system and term/break signal is
catched, them dmeventd is no longger refusing to exit.

For the correct shutdown, there should be ideally unmonitoring call,
however in some case it's very hard to implement this correct procedure.

With this 'exit on' file dmeventd at least avoid 'blocking' shutdown,
before systemd kills use with -9 anyway possibly even in some unwanted
stated of internal dmeventd processing (i.e. in the middle of some lvm
command processing).
2023-09-26 01:23:00 +02:00
3da18a06d8 configure: autoreconf 2023-09-26 01:23:00 +02:00
744cdc3ba8 configure.ac: add --with-dmeventd-exit-on-path 2023-09-26 01:23:00 +02:00
80d34abf49 dmeventd: info status report
To quickly get info about some internal dmeventd status,
implment   'dmeventd -i' support.

Reported messages are some 'raw' internal informations mainly
useful to developers.
2023-09-26 01:23:00 +02:00
637d812df5 dmeventd: unregister all devices on restart
Instead of just exiting in the middle of monitoring,
unregisted all monitored devices first and then exit.

To speedup this path, all send internal SIGINT when thread
unregiters itself, to wakup-up main sleeping loop.
2023-09-26 01:23:00 +02:00
c31dcf3632 dmeventd: use return
Use 'return' instead of calling exit() when possible.
2023-09-26 01:23:00 +02:00
396024713f dm-event: reset descriptors
Reset descriptors after closing them to -1.
2023-09-26 01:23:00 +02:00
a203499ba3 dm-event: release buffer on dm_event_get_version
Avoid memory leak in this function.
2023-09-26 01:23:00 +02:00
90713c84f3 dm-event: enhance timestamp for debugging
Add microseconds for timestamps in dm-event trace messages.
Also collect timestamps only when debugging when they are used.
2023-09-26 01:23:00 +02:00
a8fd6de907 lvmdbusd: fix syntax warning
python3.12 reported SyntaxWarning: invalid escape sequence '\/'
2023-09-20 15:55:28 +02:00
fc2feabef7 WHATS_NEW: updates 2023-09-19 14:54:51 +02:00
984c024ef2 typos: misc 2023-09-19 14:54:51 +02:00
c7c51329f4 tests: check pvmove with raid legs
Check pvmove correctly handles raid legs on input
(testing previous pvmove fix).
2023-09-19 14:54:51 +02:00
e2f29c4989 pvmove: fix building sibling raid lv name
Make a local copy of the 'idx' string to avoid
overlapping during the rebuild of name.

This fixes cases where users specified raid
component LVs for moving.

Reported-by: kotarou3@github.com
2023-09-19 14:47:27 +02:00
970e4d295e tests: add fsck after split 2023-09-14 10:08:26 +02:00
f5781144ab vdo: typo fix
Argh - lastmin mods...
2023-09-14 10:01:43 +02:00
9d7061f1a3 tests: skip test when lvmdbusd runs on the system
lvmdbusd changes $RUNDIR results.
2023-09-14 01:45:34 +02:00
f9d17f1f6d tests: update for work in fake dev environment
No write outside of $LVM_TEST_DIR  (removed /test access).
Use 'aux prepare_scsi_debug_dev' for automated scsi_debug handling
Properly use "" around shell vars.
Smarter read of PVS values.
Relax requirement to only work with real /dev dir.
2023-09-14 01:45:34 +02:00
fac2e07333 tests: enforce full fs check 2023-09-14 01:45:34 +02:00
fba81cf3e9 tests: pvmove large disk area
With some faster test hw machine we need to make this test
a bit more resource consuming.
2023-09-14 01:45:34 +02:00
738c4b84fb tests: missing to check for writecache support
Ono more case requires writecache presence.
2023-09-14 01:45:34 +02:00
de4cb219fb tests: aux using singl lvmconf call
lvmconf can handle multiple options in a single pass.
2023-09-14 01:45:34 +02:00
4276c703c5 tests: aux try with extra sleep
Since udev_wait is not really adding any major delay to wait
for any udev worker processing - add extra sleep .1.
2023-09-14 01:45:34 +02:00
f968833570 vdo: avoid using of valuesonly
To retain backward compatibility with some older version of lvm
avoid using --valuesonly option with lvmconfig.
2023-09-14 01:44:27 +02:00
1885655e9a test: improve aux teardown
Handle the case of device teardown where the first pass
could have only a single, but opened device, for removal.
In such case we want to at least once go through
the udev_wait and retry removal again.

TODO: maybe a sleep .1  might be usable as well with udev_wait
2023-09-13 13:38:15 +02:00
e75ac1b4c0 gcc: warning: missing braces around initializer
Fix warning emitted by some older gcc...
2023-09-13 13:38:15 +02:00
e1cfc075c2 vdo: better support for devicesfile
Instead of relying on 'pvs' output - check directly system
configuation and use lvmdevice accrording to use_devicesfile setting.

Also drop use of --fs ignore for filesystem extension for better
backward compatibility with older lvm version.

Shuffle code a bit so the '--no-snapshot' path does not execute
a few unnecessary commands.
2023-09-13 13:38:15 +02:00
8cbfd72f68 WHATS_NEW: updates 2023-09-12 14:44:32 +02:00
ab73ad4e5f gcc: fix warnings for x32 architecture
Warning from x32 ABI compilation.
2023-09-12 14:41:22 +02:00
b1b60887f0 debug: missing dots 2023-09-12 14:39:14 +02:00
d9cebeaf34 vdo: lvm_import_vdo enhancements
Work also with devices that may have ':' inside their generated
/dev/disk/by-id

Ensure there is no race with systems' auto activation while using
the snapshot for conversion.

Update system's vdoconf.yml after the use of snapshot for conversion.

Skip unnecesary prompt for 'convert' while using snapshot and query only
for final snaphot merge.

Prohibit conversion for a device with the PV header.

Enhance 'trap' protection for more signals.

Improve clean() recovery path.

Replace bash 'test' command with [].

Correct some output message to print $TOOL.

Support also options without '-' in the middle i.e. --nosnapshot.

For shellcheck predefine all variables extracted from vdoconf.yml.
2023-09-12 14:30:48 +02:00
fa49651301 lvresize: fix 32 bit overflow in size calculation 2023-09-11 12:18:12 -05:00
2eb34edeba make: generate 2023-09-04 18:52:02 +02:00
5a44135233 tests: disable logging for lvmdbusd
Since lvmdbusd testing tends to do its own logging,
try for now to disable very generic logging mechnanism
of the test suite and see the result.

Some lvmdbusd test seems to rely on some log/file logic
which is modified with the use of these shell vars.
2023-09-04 18:52:02 +02:00
2b8b51291f tests: check for writecache
Writecache needs writecache kernel target to be present.
2023-09-04 18:52:02 +02:00
cc8178e911 tests: check for binaries
vdo wrapper tool uses some 'locally installed' binaries
for vdoformat and vdoprepareforlvm
Chech for their presence.

Skip this test with lvmlockd.
2023-09-04 17:48:41 +02:00
e9eeb84040 WHATS_NEW: update 2023-09-03 22:51:22 +02:00
86cf593e87 tests: vdo scsi convert
Somewhat tricky test to check VDO import of a SCSI device.
2023-09-03 22:44:08 +02:00
b85f9c183c tests: vdo convert
Require VDO version 6.2.3.

Skip the part of the test that needs vdo wrapper and 2 different
versions of vdoprepareforlvm to prepare shifted VDO header
at the 2MiB offset.
2023-09-03 22:33:11 +02:00
39f312108d tests: check passing PV list 2023-09-03 22:33:11 +02:00
06464f7cfc tests: vdo wrapper support symlinks
Enhance internal VDO replacement wrapper script to handle symlinks
for i.e. SCSI device like VDO manager.
2023-09-03 22:33:11 +02:00
9087ace2af aux: teardown also devices with testing UUID
Hunt also for devices with LVMTEST prefix in UUID.

Call teardown_devs_prefixed - so if they hold RAM or SCSI
they are closed before trying to remove kernel modules.
2023-09-03 22:15:48 +02:00
d34d1f0173 debug: trace result failure 2023-09-03 22:03:33 +02:00
670d982568 debug: drop stack from regular path 2023-09-03 22:03:33 +02:00
97770d5aeb debug: check for syscalls
Add some debug checks for possibly failing syscalls.
2023-09-03 22:03:33 +02:00
a48847269a clang: ensure all variables intialized
Just in case of some wierd kernel bug, which would forget
to report these values...
2023-09-03 22:03:33 +02:00
6a0e54f84f clang: ensure status is initilized
Initialize status before handling error path.
2023-09-03 22:03:33 +02:00
cb61d2294a filesystem: move stat after open check
To avoid time-of-check-time-of-use clash, take the stat()
after successful open with fstat().
Also add some debugs for failing sys calls.
2023-09-03 22:03:33 +02:00
29630b2d7f dmeventd: move var set to locked section
It should not change the actual code flow, however make the
set of the current_event variable inside locked section.
2023-09-03 22:03:33 +02:00
aa7f2ac954 lvconvert: thin conversion accept passed PVs
When creating thin pool or check pool there is allocated LV
for metadata and for such allocation user should be able to
specify list of PVs on cmdline.

Also fix unused passed list of PV for thick to thin conversion,
where the code was using whole PV set from a VG (but since it's
been not enabled on cmdline, user could not hit this issue).
Also remove unneeded initialization of use_pvh.
2023-09-03 22:03:33 +02:00
c693aa8dac vdo: enhance import script for devices file
When the import is used on a system, that uses devices file,
the final activation was impossible for the case the converted
volume was not present in devices file.
Currently add volume automatically in such case.

Also add some more debugging output from the script.

TODO: Consider enhnacing lvconvert with extending devices file.
2023-09-03 22:03:33 +02:00
b81835b5ca vdo: lvm_import_vdo uses devname from vdoconf.yml
VDO is using specific path for some device paths.
i.e. for /dev/sda it could be /dev/disk/by-id/scsi-xxxxx.

This used to be not a problem before lvm2 started to use snapshot,
but now it needs to replace matching device path.
So switch to the path naming used in vdoconf.yml file.
2023-09-03 16:01:07 +02:00
c37416b6aa lvmlockd: client mutex ordering
Avoid deadlock between threads on mutexes (in theory.)
2023-08-31 13:15:07 -05:00
65d23a1d75 vgchange: acquire an exclusive VG lock for refresh
Concurrent vgchange --refresh commands can lead to hung
tasks in dm code.

Signed-off-by: wangzhiqiang <wangzhiqiang95@huawei.com>
2023-08-30 15:47:42 -05:00
092f58a762 man: dmsetup: document --headings 2023-08-30 18:37:18 +02:00
1f02c5f2e4 tests: add shell/report-headings.sh 2023-08-28 15:44:58 +02:00
2ab2da5e02 man: update lvmreport man page about report/headings and --headings 2023-08-28 15:44:58 +02:00
5a6d1369f6 make: generate 2023-08-28 15:44:58 +02:00
5a1248f1d4 dmsetup: support printing full column names in report headings
Add '--headings none|abbrev|full|0|1|2' command line option to select
the heading type.

  none|0   - no headings
  abbrev|1 - column name abbreviations
  full|2   - full column names (column names are equal to exact names
             that -o|--options also accepts to set report output)
2023-08-28 15:44:57 +02:00
14d0a9eef6 report: support printing full column names in report headings
Reuse existing report/headings config setting to make it possible to
change the type of headings to display:
  0 - no headings
  1 - column name abbreviations (default and original functionality)
  2 - full column names (column names are equal to exact names that
      -o|--options also accepts to set report output)

Also, add '--headings none|abbrev|full|0|1|2' command line option
so we are able to select the heading type for each LVM reporting
command directly.
2023-08-28 15:44:57 +02:00
12b60e7c25 libdm: report: support reporting field IDs in headings
Add new DM_REPORT_OUTPUT_FIELD_IDS_IN_HEADINGS report output flag.
If enabled, column IDs are reported instead of column names in report
headings.

The 'column IDs' are IDs as found in 'const struct dm_report_field_type *fields'
array that is passed during report initialization (that is, a call to
dm_report_init/dm_report_init_with_selection). In this case, the 'id'
dm_report_field_type member is used instead of the 'heading' member.
2023-08-28 15:44:57 +02:00
c4b42e9f59 gitignore: update 2023-08-28 15:44:00 +02:00
71ff21f57c gcc: initialize variables 2023-08-23 15:10:40 +02:00
941c4a20d6 tests: better slowdown 2023-08-23 13:47:39 +02:00
73abdedbc9 CI: Add timeout
Increase timeout from default 1h to 2h.
2023-08-22 16:39:32 +02:00
5803d9b689 tests: skip some tests with valgrind
Valgrind tends to be too slow for any kind of slowing down,
thus skip some tests that are time sensitive.
2023-08-17 22:52:08 +02:00
61499e870a debug: common error handling 2023-08-17 22:52:08 +02:00
ba36ba8853 cleanup: move allocation code
Allocate new memory after validation passed.
2023-08-17 22:52:08 +02:00
dde5b81079 lvconvert: run error path code only for shared VG
Error path for locking only for share VG.
2023-08-17 22:52:08 +02:00
ad73f571b8 lvconvert: move _pmspare handling before conversion 2023-08-17 20:14:47 +02:00
8698f9dce6 pool: use predefined name for metadata LV
While create new LV for pool volume, use name from 'pool_metadata%d' naming
sequence. This LV is later on renamed to  pool_t/cmeta, but if there
is any error in the middle, we may evenutally leave some 'volume',
With this name it can be slightly more obvious how it got there,
but also when we handle _pmspare name - we get slightly more predictible
name used there for it.

However for a standard usage this commit shall no visible impact as the
name is used temporarily just for cleaning LV.
2023-08-17 20:10:21 +02:00
6ca97e6e62 lvmlockd: fix lvconvert to thin-pool 2023-08-16 15:29:20 -05:00
696ee52ffd lvmlockd: let lockd_init_lv_args set lock_args
Set the lock_args string in addition to doing initialization.
lvconvert calls lockd_init_lv_args() directly, skipping
the normal lockd_init_lv() which usually sets lock_args.
2023-08-16 15:29:20 -05:00
096196281e lvmlockd: fix thick to thin lv conversion 2023-08-16 15:29:19 -05:00
5a96ca4a7f tests: update pool uuid handling
Pools now preserve meta LV UUID with swapmetadata operation
to make the usage of lvmlockd easier.

Update test to reflect this change.
2023-08-16 15:14:29 +02:00
728617d25d gcc: cleanup warnings
Correcting signess comparation.
Also use standalone /* fall through */ comment as that's
the only one supported by gcc to quiet warning.
2023-08-16 15:13:25 +02:00
085c3821a8 cleanup: no longer used
Previous commit made this var unused.
2023-08-16 15:13:00 +02:00
41e4cefc2e make: make install_libexec a target of install_lvm2
This makes sure libexec scripts are available for lvm2 commands.
2023-08-16 15:13:00 +02:00
54617805b8 lvconvert: use vg mempool
Keep allocation for a VG within vg memory pool.
2023-08-16 13:31:01 +02:00
13225f1371 lvconvert: fix regresion from integrity check
Testing code sliped into commit and cause regression in testing for
a raid with integrity.
2023-08-16 11:25:54 +02:00
e548afd175 lvconvert swapmetadata: update lvmlockd locking for uuid exchange
lvmlockd locking for swapmetadata adjusted for commit
ac36153e99 lvconvert: preserve UUID for swapped metadata

Now that the LV uuid is swapped between LVs, the lvmlockd lock can
simply be moved between them, and the same lock can continue to be
used for the LV outside of the pool.
2023-08-15 13:13:06 -05:00
060491c4ee WHATS_NEW: update 2023-08-14 17:02:11 +02:00
b764665f4d debug: add missing log_error
Report error with failure.
2023-08-14 17:02:11 +02:00
ee6519f8e2 debug: use just single label 2023-08-14 17:02:11 +02:00
741a166f3c debug: use common error exit path 2023-08-14 17:02:11 +02:00
23019946c2 lvconvert: vdo needs writable LV 2023-08-14 17:02:11 +02:00
2f3d8659b1 commands: add lv_is_writable 2023-08-14 17:02:11 +02:00
0b7239ebc7 lvconvert: fix ret values fro integrity remove
Fix return value from _lvconvert_integrity_remove()
as it is expected to match _add() and be 0/1.

Also add some missing log_error() messages.
2023-08-14 17:02:11 +02:00
80377eeb13 lvconvert: preserve UUID on pool repair
Once lvm2 repairs pool's metadata LV and preserves the original metadata LV
with unmodified metadata, for such LV in VG use newly created UUID for new
_pmspare and actually preserve UUID for this hidden _pmspare (if it
exists).
2023-08-14 17:02:11 +02:00
ac36153e99 lvconvert: preserve UUID for swapped metadata
When swapping metadata LV for a pool volume, preserve UUID for metadata
LV during the swap - this allows to better utilise locks with lvmlockd.
2023-08-14 17:02:09 +02:00
2928891bd0 lvconvert swapmetadata: fix lvmlockd locking
The lockd lock needs to be freed for the LV that is becoming
the new metadata LV, and a new lockd lock needs to be created
for the old metadata LV that is becoming an independent LV.
Fixes b3e45219c2
2023-08-08 16:57:22 -05:00
847f1dd99c device_id: rewrite validation of devname entries
The old approach was too complicated and didn't work correctly
in some cases.
2023-08-04 11:45:40 -05:00
abdb87dd23 CI: Add .gitlab-ci.yml 2023-08-03 11:00:23 +02:00
606ecae5d7 post-release 2023-08-02 14:42:16 +02:00
016e469caf pre-release 2023-08-02 14:41:12 +02:00
1fe2a74995 WHATS_NEW: update 2023-08-02 14:38:23 +02:00
9385bea571 make: generate 2023-08-02 12:22:16 +02:00
0e9fe272bc report: fix pv_major and pv_minor report field type
We incorrectly marked pv_major and pv_minor fields as being of string
type, even though the values were already correctly handled as integers
internally. This confused -S|--select that tried to compare string
values instead of integers.

Reported here: https://github.com/lvmteam/lvm2/issues/122
2023-07-31 13:44:09 +02:00
7cc414135a lvmdevices: add --delnotfound to delete entries for missing devices
Used with update: lvmdevices --update --delnotfound.
Removes all devices file entries for which no matching device is found.
2023-07-24 14:56:32 -05:00
e3cc3e55c8 vgmknodes: skipping thin pool is not an error 2023-07-24 12:03:06 -05:00
b2431d105e tests: catch all output
Previous fix was invalid (after some in-place shuffling)
'dd' copied goes to 'stderr' so we need to catch all output.
Grep needs to check output of tee tool.
Ensure 'C' locales are in use with 'dd'.
2023-07-17 16:34:14 +02:00
1c2782354c vdo: use long --verbose
vdo tools needs long option.
2023-07-17 16:22:29 +02:00
32b2e416cc tests: new logic for repair
meta name deduced from cachepool name.
2023-07-17 14:30:39 +02:00
ace8a2a868 WHATS_NEW: update 2023-07-17 13:47:57 +02:00
39cc12e7c2 tests: use zero device
Change the test to use 'zero' backend, so we could use larger size
and get 'larger' buffer of dirty blocks for fast CPUs...
2023-07-17 13:42:58 +02:00
06e39625ee tests: check for loaded brd
Skip the test if the brd is already loaded in the system.
2023-07-17 13:21:59 +02:00
284fdb1745 tests: mark test as warning
Until more universal solution for thin-pool corruption gets in place.
2023-07-17 12:44:48 +02:00
96b2c20991 debug: add backtrace 2023-07-17 12:44:37 +02:00
09e17f99c5 cleanup: remove double //
dev_dir ends with /.
2023-07-17 12:44:23 +02:00
469bcc28ac cleanup: remove duplicated code
Commit cac4a9743a moved setting
if layer structed to the function front, but the old code
was still left in original place.
2023-07-17 12:44:23 +02:00
d6771e513e lvconvert: code shuffle
Use cachepool name for create name for metadata backup LV.
(so we do not generate 2 'sequences' of metadata filenames.)
Move path preparion before handling _pmspare.
Also drop extra call to sync_local_dev_names() as it's
already got in sync with call of exec_cmd().
2023-07-17 12:44:23 +02:00
f078ffc5e6 lvconvert: add support --setactivationskip
When repair thinpool or cachepool, lvm2 leaves original metadata
volume backup. To avoid potential damage of those data, mark such
volume as 'read-only' and also allow user to use --setactivationskip
option for this volume.

TODO: likely better default would be to automatically skip, but
that might need some more thinking about recovery reporting doc.
2023-07-17 12:44:23 +02:00
d040b68aee lvconvert: use public LVs for recovery
Replace the use of internal /dev/mapper names with the use of
public LV names /dev/vg/lv for use with repair tools.
For this make the activation of _pmspare LV to be handled as
a component activation with public name.
Metadata is already atomatically activated this way (as readonly).

So if there is any 'error' happening, we leave public LVs in
system.
2023-07-17 12:44:23 +02:00
409a79621a vdo: refactor code
Shuffle code to use prepare_exec_args().
Simplify generation of options string within a single char buffer.
2023-07-17 12:44:23 +02:00
4d2311655b lvm-exec: refactor code
Add prepare_exec_args() for reading option list for
thin/cache_repair, thin/cache_check.
2023-07-17 12:44:23 +02:00
f78b02477b lv_manip: refactor code
Simplify initialization of exec buffer.
Check for misconfigured 'fsadm' executable path.
2023-07-17 12:44:23 +02:00
c5e4326337 active: device name limit is NAME_LEN
Use existing NAME_LEN instead of 257 value.
Add missing backtrace.
2023-07-17 12:43:39 +02:00
0670338e0b WHATS_NEW: update 2023-07-15 11:05:35 +02:00
f6104adcb6 tests: updates
Pass more args with some 'aux' commands:
wipefs_a, enable_dev, disable_dev
(so it's a bit more efficient using single udev_wait call).
Use prepare_vg instead of prepare_pvs.
2023-07-15 11:05:35 +02:00
55b498b6b5 tests: avoid using /test dir
Keep using test directory for created files.
Trap errors and remove brd in this case.
Use some shell builtins to reduce fork count.
Use "$VAR".
Run 'pvs' with devlist (so not acceing other system devices).
2023-07-15 11:05:35 +02:00
9b23ff5d50 tests: add fsck before resize2fs 2023-07-15 11:05:35 +02:00
ac25dd9be6 tests: faster check for flushing
Try minimizing delay in detecting 'cleaner' policy precence,
so we can fast interrupt running lvconvert.
2023-07-15 11:05:35 +02:00
f71d3cce93 tests: ensure single leg is broken
Make sure only the first raid5 leg, that contains searched string
is being modified, so we do not 'damage'  2legs at once.
2023-07-15 11:05:35 +02:00
914d793858 aux: fix version checking
New dmpd tools return version string in different format,
so update code to understand both variant.

Also hide some shell var setting to local functions.
2023-07-15 11:05:35 +02:00
81ef1fd0cc debug: print WARNING:
Add WARNING: in front of log_warn() messages.
2023-07-15 11:05:35 +02:00
b3e45219c2 lvconvert: hanle metadataswap with lvmlockd 2023-07-15 11:05:35 +02:00
fdf2571679 mm: add libzstd to ignore list
No need to lock-in-RAM libzstd (linked from systemd).
2023-07-15 11:05:06 +02:00
1c60c6785c tests: check --test
Check lvconvert --thin is not adding more LVs.
Enable testing with lvmlockd.

TODO: lvmlockd is missing support for --test.
2023-07-14 16:53:34 +02:00
482501c21f tests: more checks with active thin lv
Check --usepolicy works primarily when thin-pool -tpool is there.
Also let the test run with lvmlockd.
2023-07-14 16:52:51 +02:00
a997714648 tests: skip with lvmpolld
Not needed with lvmpolld pass.
2023-07-14 16:52:51 +02:00
b89fc0564b cleanup: indent 2023-07-14 16:52:51 +02:00
a2b2ae35b2 lvresize: improve usepolices
lvresize --usepolicy requires resized LVs to be active.
(So it's not only required for shared VG).

The test for active pool needs to use lv_info to query 'layer'
otherwise the pool is considered inactive if it was not activated
explicitely - thun 'implicit' activation with VDO or ThinLV was
not managed by --usepolicy option.
2023-07-14 16:52:51 +02:00
8cbba1d164 lvmlockd: enable vdo conversion
As we turn 'already' active/locked LV into a data LV of vdopool,
we just keep active lock for such volume (uuid is preserved).
2023-07-14 16:52:51 +02:00
75b28ab49d lvmlockd: query the simplest check first
Check for visibility of the LV first.

TODO:

Short check list and test only for those that can't be locked,
but they are visible LVs.
2023-07-14 16:52:51 +02:00
8eb3a5b557 lvconvert: thin convert locking
Fix locking when converting thick to thin LV, ensure
we take pool lock for shared VG.
2023-07-14 16:51:46 +02:00
bdcfd2d730 lvconvert: no metadata for test mode
Avoid trying to build real metadata in --test mode.
2023-07-14 16:20:30 +02:00
93484c2a62 man-generator: ensure p is defined
In error path, p pointer could have been undefined.
2023-07-13 21:56:47 +02:00
97fc0ca49b debug: missed properly modify pointer type 2023-07-13 21:52:20 +02:00
f24eb81dbe tests: improve LD_LIBRARY_PATH setting
Some linkers do need libdevmapper-event-lvm2.so.2.03,
so add also this symlink to the tests  /lib dir.
This fixes the need to use previous LD_LIBRARY_PATH complex
setting and now works with much shorter list.
2023-07-13 21:31:18 +02:00
4ae2dde5c3 tests: update
Just drop debug log in case of error happenig later,
so we do not print uneeded info...
2023-07-13 21:31:18 +02:00
2ecd290c0d tests: use conf=fdatasync
Since we write here in 1k blocksize - we can't use direct.
2023-07-13 21:31:18 +02:00
ae512e20f5 tests: skip test if daemon is running
Skip the test, to avoid making all test failed when there is
'left' daemon running.
2023-07-13 21:31:18 +02:00
7171260b94 makefiles: install lvmdbusd executable
Use a different mechanism to ensure, lvmdbudd is executable at
install destination.
2023-07-13 21:31:18 +02:00
f8712c6cab makefiles: remove autom4te.cache
For 'make distclean' remove also autom4te.cache
(from autoreconf).
2023-07-13 21:31:18 +02:00
5ce236a691 gcc: correct signess comparation
Compare int to int and unsigned to unsigned...
2023-07-13 21:31:18 +02:00
64b28e0839 lvchange: add log_error for failure path
When change of monitoring fails, ensure there is log_error() printed.
2023-07-13 21:31:18 +02:00
cb2d32bdc4 debug: fix sscanf type
Last commit c38b668fc3 was pushed
with type 'scanf' instead of 'sscanf' needed for buffer reading.
Interestingly this caused scanning from 'stdin' descriptor and
thus failures in lvm shell usage.
2023-07-13 21:31:18 +02:00
6e3b51681f Update README 2023-07-12 15:53:45 +02:00
6f1318c474 WHATS_NEW: update 2023-07-12 15:18:38 +02:00
33f022617a tests: some fixes for lvmlockd testing 2023-07-12 15:18:38 +02:00
85fb46d8a6 tests: reduce paths added to LD_LIBRARY_PATH
Add only stricly needed paths to compiled .so objects.
2023-07-12 15:18:38 +02:00
80bad4a3b4 tests: check for writecache presence
Test is using writecache.
2023-07-12 15:18:38 +02:00
a51c68aacb tests: makefile build proper tools list
Add compiled components to the list.
2023-07-12 15:18:38 +02:00
4d70e7bf78 debug: use display_lvname 2023-07-12 15:18:38 +02:00
c38b668fc3 debug: fix parsing of /proc/self/stat
The code in init_log_file relies on the process name (COMM) to not
contain whitespaces. This change fixes it by looking up the right-most
parenthesis to safely jump past COMM.

For more context see:
https://www.openwall.com/lists/oss-security/2022/12/21/6

Code is only used with testing, so it should have no impact on regular
users.

Reported-by: Hugues Evrard <hevrard@google.com>

mm
2023-07-12 15:18:38 +02:00
7ec97ed5f2 cov: fix memleak in vgchange
Release allocated  vgname from get_single_vgname_cmd_arg()
when it is not returned via *vgname_ret.
2023-07-12 15:18:38 +02:00
491ee5d106 cov: hide some messages
Living with these...
2023-07-12 15:18:38 +02:00
4c78bdcfaa autoconf: update py-compile
Use newer version of this script from:
https://raw.githubusercontent.com/autotools-mirror/automake/4bd4640e03670e267d9763d377f107c09b4f2202/lib/py-compile

Reported-by: Adam Willamson
2023-07-12 15:18:38 +02:00
857f5d6e65 lvconvert: correction for thin conversion
Updates for 39457234db.
Off-by-one for option array - need 20 fields.
Missed to clear lock_args for cachepool.
2023-07-12 15:18:38 +02:00
b3b6c6b576 README: Move to gitlab 2023-07-10 18:03:51 +02:00
52f939caa7 WHATS_NEW: updates 2023-07-10 17:13:33 +02:00
00b5d7b037 lv: followup seg_monitor reporting
With 3596558861 it's been introduced
a more fine grained description.
However 'disabled' might be actually more confusing then empty field,
so keep only the info about 'not enabled'aka dmevend is not allowed
to monitor LV which otherwise could be monitored.
2023-07-10 17:13:33 +02:00
9abcf5cb48 tests: use aux functionality
Use aux wait_recalc and wait_for_sync  for faster processing.
2023-07-10 17:13:33 +02:00
935813457f tests: update thin 2023-07-10 17:13:33 +02:00
9ba9e99716 man: update for new syntax 2023-07-10 17:13:33 +02:00
70c911b63f pool: improve message for data persistance
Inform a user that pools using either error or zero LVs are
not able to keep any data persistant.
2023-07-10 17:13:32 +02:00
39457234db lvconvert: support conversion to thin volume
Update pool conversion function to handle also conversion of
thick LV to thin LV by moving thick LV into thin pool data LV
and creating fully provissioned thin LV on top of this volume.

Reworking existing conversion to use insert_layer_for_lv co
the uuid is now kept with thin-pool - this should however not
really matter as we are doing full deactivation & activation cycle.

With conversion to thin LV user can use same set of arguments
to set chunk-size.

TODO: add some smart code to decide best values for chunks sizes.
2023-07-10 17:13:32 +02:00
f35fa8c178 cleanup: typos 2023-07-10 17:13:32 +02:00
96123b9059 cleanup: use spelling synchronize
Use single spelling form for synchronize.
2023-07-10 17:13:32 +02:00
98a34e43ab tests: caching of single thin volume 2023-07-10 17:13:32 +02:00
721bee1b70 tests: cache with error and zero 2023-07-10 17:13:32 +02:00
975368ba18 tests: skip on kernels 2023-07-10 17:13:32 +02:00
077b46e014 lv_manip: fix move_lv_segments moved bits
For proper functionality of insert_layer_for_lv we need to
move more bits to layerd LV.

Add some missing new types and correct usage of caller,
so the new LV type is set after the movement.
2023-07-10 17:13:32 +02:00
e022805f1d pool: do not pass empty string in callback
When preparing cmdline to executing dmpd tool, avoid adding
empty string ("") on such line.
2023-07-10 17:13:32 +02:00
e36028b7d2 cache: update validation rules
Validate cache origin in front of the prompt.
Also add some rules to command description file.

TODO:
more validation needed also for lvcreate,
more complex rules with "OR" seems to be needed.
2023-07-10 17:13:32 +02:00
88f1e7a9a7 cache: support more segtypes for caching
Enable support to cache thin/error/zero virtual targets.

Use can now select whether he want to cache whole thin-pool,
or an individual thin volume out of whole thin-pool.
Support using zero and error LVs as data volume for
cachepool is possibly useful for benchmarking, not much
can be expected from such setup.
2023-07-10 17:13:32 +02:00
0dee6fc28c cache: handle error segtype
Allow to convert error LV.
2023-07-10 17:13:32 +02:00
9bbbc1b265 cachepool: skip wipe for nonzeroeable segments
Avoid activation when going to skip zeroing of 'error' segtype
(so it's not erroring out).
Also skip zeroing for 'zero' segtype LV (already being zero).
2023-07-10 17:13:32 +02:00
558890ad0e pool: support passing data_lv for recalculation
Support data_lv to be passed as parameter when it's not yet
attached to the pool.
2023-07-10 17:13:32 +02:00
5175e87fda commands: error and zero segtype handling
Add function to work with error and zero LVs more easily.
2023-07-10 17:13:32 +02:00
226429058c commands: enhance error checking for generator
No exit value 0, when the parser hits an error.
Increase some buffers since as some arg lists are getting longer.
2023-07-10 17:13:32 +02:00
44b070415b commands: support query for lv_is_cow 2023-07-10 17:13:32 +02:00
d43a79eec9 segtype: add missing macros for error and zero segment
Add macros for checking error and zero segment as we do
with other segtypes.
2023-07-10 17:13:32 +02:00
5154054af4 snapshot: no error when extending above max size
When lvm2 calculates the maximal usable COW size and crops the user
requested size to this value, don't return the error result from
the 'lvextend' operation.

We already apply the same logic when resizing thin-pool beyond
the supported maximal size.

FIXME: The return code error logic here is somewhat fuzzy.
2023-07-10 17:13:32 +02:00
b90c5d6015 vdo: support version 4
Properly parse VDO volumes formatted with geometry block version 4.0.
2023-07-10 17:13:32 +02:00
e84b00964f pool: avoid using artificial name internally 2023-06-29 13:55:27 +02:00
3596558861 lv: more details about monitoring lvs
Show "not supported" when LV does not support dmeventd monitoring.
Show "disabled" for LV with disabled dmeventd monitoring.
(lvdisplay -m)
2023-06-29 13:10:42 +02:00
8a07f57ba4 lvm_import_vdo: spelling fixes 2023-06-29 13:10:42 +02:00
8b75bbe47d vdo: lvm_import_vdo correct parsing output
Output from vdo manager may actually indent output with spaces,
so trim leading and ending space.

Also add support for verbosity flag for vdo conversion tool.
2023-06-29 13:10:42 +02:00
e48c9826e3 vdo: indent for lvdisplay 2023-06-29 13:10:42 +02:00
6ff65e6755 vdo: check_point_frequence is unused option
This vdo parameter existed in the early stage of integration of vdo into lvm2,
but later it's been removed from vdoformat tool - so actually if
there would be any non-zero value it would cause error on lvcreate.
Option was not stored on disk in lvm2 metadata.

Remove this vdo parameter from lvm2 sources.

(Although this vdo parameter will be still accepted on cmdline through
 --vdosettings option, but it will be ignored.)
2023-06-29 13:10:42 +02:00
fa434a1837 tests: simplify 2023-06-25 13:02:36 +02:00
b8db2c0a4a tests: require raid target 2023-06-25 13:02:36 +02:00
04860b6324 tests: correct checked devices
Fix the testing logic.
With raid5 device the layout of files on a filesystem does not define
which leg will actually contain the block we try to damage.
So test will now figure out which device has damaged block.

Use 'check' functionality and also drop unneeded random write as we
now can identify easily in other way.
2023-06-25 13:02:36 +02:00
5848f75278 tests: correct generated metadata
Newer thin_check actually rejects such restored data.
2023-06-25 12:00:57 +02:00
0a5712ada4 WHATS_NEW: update 2023-06-23 18:08:10 +02:00
9756824f64 make: generate 2023-06-23 18:08:10 +02:00
46fe47b8e0 debug: add backtraces 2023-06-23 18:08:03 +02:00
a1d5fba666 aux: add configuration for thin_restore and check_restore 2023-06-23 18:06:22 +02:00
aed91e49ae tests: improve test for machine_id 2023-06-23 18:06:22 +02:00
39d6a9601f tests: ensure test defines its own etc dir
Compilation may configure it's own /etc path so ensure the test
has a defined location for access to this dir during testing.

Also prepare machine_id filei (with the use of uuidgen tool)
for the test.
2023-06-23 18:06:22 +02:00
2cb43449ee tests: fix path to dev dir
Correct some explicit references to /dev and use $DM_DEV_DIR.
2023-06-23 18:06:22 +02:00
fec3087eef thin: add cfg support for thin_restore and cache_restore
Add configurable paths for thin_restore and cache_restore.
2023-06-23 18:06:22 +02:00
8d09124c62 tests: update test for automatic virtual size correction
lvm_import_vdo will adjust the virtual size within conversion
so the volume can be use without any futher tweaking.
2023-06-23 18:06:22 +02:00
657dde6208 lvm_import_vdo: correct the converted virtual size
Ensure the volume after conversion has the properly aligned size to the
volume group extent size. This would be visible when using virtual size,
that cannot be divided by extent size.

Before the user had to manually adjust the size after conversion to get
access to all data stored on VDO volume.
2023-06-23 18:05:03 +02:00
ea6b5b694b lvcreate: allow thin snapshot syntax that broke
The command "lvcreate --type thin --snapshot ..." to create a thin
snapshot would fail.

commit d651b340e6 removed the optional
"--type thin" from the command definition "lvcreate --snapshot LV_thin",
and added --type thin as AUTOTYPE.  This was correct and should not have
changed anything if all the command defs were correct, but it broke
the "lvcreate --type thin --snapshot" case.  It reveals a problem in a
different command definintion:  "lvcreate --type thin LV_thin" that was
missing --snapshot in its OO list.
2023-06-20 15:47:01 -05:00
1dbb86f8c7 tests: lvresize fs mounted multiple times 2023-06-20 13:13:06 -05:00
7c3eca833f lvresize: fix multiple mounts
which was mistaken as a mounted LV that had been renamed.
2023-06-16 12:11:51 -05:00
228a8e8c1f device_id: ignore leading and trailing spaces for sys_wwid and sys_serial
Leading and trailing underscores are also ignored to handle device ids
written by previous versions which replaced all spaces with underscores.
2023-06-15 15:17:14 -05:00
f0b48a23d9 tests: Skip integrity tests if target not present 2023-06-14 13:48:51 +02:00
4cf005d395 tests: tmp is used for TMPDIR
Fixes tests failing due to previous commit 734d9791f8.
2023-06-14 13:23:41 +02:00
7ac5dbfd09 WHATS_NEW: update 2023-06-09 18:01:35 +02:00
9105890d43 tests: updates
Add some more complicated conversion tests.
2023-06-09 18:01:16 +02:00
7f661a24c4 tests: vdo manager wrapper tool updates
Support size specification in KiB units.
Add some theoretical support for some new options from vdoprepareforlvm.
2023-06-09 18:01:16 +02:00
734d9791f8 tests: tmp dir inside test dir
Keep even temporary files within testing dir so generated files are
not left behind in system's /tmp directory.
2023-06-09 18:01:16 +02:00
4d64838048 cov: drop unneeded constness
If we want to have const structure - use a const pointer to avoid,
however making individual members const make it only assingle
in construct time and we already violate this logic since
we memcpy into the structure -  so drop these unnecessary consts...
2023-06-09 18:01:16 +02:00
17ee5df857 vdo: man updates for lvm_import_vdo 2023-06-09 18:01:16 +02:00
be6c34212b vdo: enhance lvm_vdo_import
Add support for usage of 'dm-snapshot' for doing whole device conversion
in a snapshot which could be merged once the whole conversion has been
made.
This helps with cases where there would be any unexpected failure in the
middle of conversion process and user can continue using original
device until problem in conversion is fixed.

Import tool now uses 'truncate' tool to create a small backend file (20M) for loop device
to hold COW exception store.

Option  --vdo-config has been added to allow specifing location of vdo
configuration file.

Option --no-snapshot allows to use import tool without creation of
snapshot, however recovery after finished VDO conversion and unfinished
lvm2 conversion is then very difficult.

Option --uuid-prefix allow to specify DM UUID prefix for snapshot
device.

Use read with -r.
2023-06-09 18:01:16 +02:00
00633f8b66 vdo: fix and enhance vdo metadata reader
Improve metadata parser to handle volume_geometry bio_offset,
which needs to be substracted from 'region' start_block when present.

This bio_offset block is non-zero i.e. with converted VDO volumes.

Also fix some converted structure value (but they are not in use).
2023-06-09 18:01:16 +02:00
fcf2057b38 cmd_enum: correct inclusion
Ensure we use generated header file for this build from -Iinclude.

Reported-by: Anton Lundin <glance@ac2.se>
2023-06-09 18:01:16 +02:00
74feebdab7 device_id: fix handling of non-PV with duplicate serial number
Fix in the code that matches devices to system.devices entries when
the devices have the same serial number.  A non-PV device in
system.devices has no pvid value, and the code was segfaulting
when checking the null pvid value.
2023-06-08 12:24:05 -05:00
8e53b3bc14 man: lvmraid update limitations 2023-06-05 10:43:51 -05:00
e2ecc6c763 reporter: restore report type to initial value after processing report_for_selection
If we are executing 'report_for_selection' to do an internal report
just for the selection itself (not for display), we can call it more
than once. In that case, we are reusing the same selection handle
(e.g. inside 'process_each_lv_in_vg').

The selection handle has 'report_type' field which is a union of all
report types needed for the report based on selection fields we actually
use.

The 'report_type' is further clarified based on checks and rules inside
'_get_final_report_type' which 'report_for_selection' calls. Then, this
final report type unambiguously identifies proper branch to take in
'report_all_in_{pv,vg,lv}' that is called next.

If the 'report_for_selection' is called more than once with the same
selection handle, we need to make sure that we always restore the report
type to its initial value, so all the rules inside 'report_for_selection'
are applied correctly next time.

This patch fixes the missing restoration of the 'report_type' value in
'selection_handle' that is reused for recurring 'report_for_selection'
calls.

An example scenario where this failed was with selecting an LV for
removal with "lvremove --select" while using a field in the selection
that required extra DM info or DM status call for the LV (that is,
"Logical Volume Device Info Fields" and "Logical Volume Device Status Fields"
as visible in 'lvs -S help').
2023-05-31 09:38:11 +02:00
0591131a53 lvreduce: simplify _lvseg_get_stripes integrity check
Simplify unnecessary loop to avoid coverity complaint.
2023-05-25 12:09:41 -05:00
4cdb178968 device_id: ignore trailing underscores in t10 wwid from devices file
In previous lvm versions, trailing spaces at the end of a t10 wwid would
be replaced with underscores, so the IDNAME string in system.devices
would look something like "t10.123_".  Current versions of lvm ignore
trailing spaces in a t10 wwid, so the IDNAME string used would be
"t10.123".  The different values would cause lvm to not recognize a
device in system.devices with the trailing _.  Fix this by ignoring
trailing underscores in the IDNAME string from system.devices.
2023-05-19 14:05:10 -05:00
24e4b6df11 tests: integrity-caching: ensure raid redundancy
The recent fix 05c2b10c5d ensures that raid LV images are not
using the same devices.  This was happening in the lvextend commands
used by this test, so fix the test to use more devices to ensue
redundancy.
2023-05-17 14:15:25 -05:00
3a75704756 tests: integrity: snapshots now work on raid+integrity 2023-05-17 11:10:45 -05:00
3b4e7d1625 toollib: provide proper hint for referencing VG uuid in case of duplicate VG names
vgrename does not support -S|--select, so do not provide a hint about
using it. Instead, provide a hint about using VG uuid directly.

❯  vgs
  WARNING: VG name vg1 is used by VGs DXjcSK-gWfu-5gLh-9Kbg-sG49-dtRr-GqXzGL and MVMfyM-sjOa-M2xV-AT4Y-JddR-h4SP-UO5Ttk.
  Fix duplicate VG names with vgrename uuid, a device filter, or system IDs.
  VG     #PV #LV #SN Attr   VSize   VFree
  vg1      1   0   0 wz--n- 124.00m 124.00m
  vg1      1   0   0 wz--n- 124.00m 124.00m

(vgrename does not support -S|--select)
❯  vgrename vg1 vg2
  WARNING: VG name vg1 is used by VGs DXjcSK-gWfu-5gLh-9Kbg-sG49-dtRr-GqXzGL and MVMfyM-sjOa-M2xV-AT4Y-JddR-h4SP-UO5Ttk.
  Fix duplicate VG names with vgrename uuid, a device filter, or system IDs.
  Multiple VGs found with the same name: skipping vg1
  Use VG uuid in place of the VG name.

(vgchange does support -S|--select)
❯  vgchange --addtag a vg1
  WARNING: VG name vg1 is used by VGs DXjcSK-gWfu-5gLh-9Kbg-sG49-dtRr-GqXzGL and MVMfyM-sjOa-M2xV-AT4Y-JddR-h4SP-UO5Ttk.
  Fix duplicate VG names with vgrename uuid, a device filter, or system IDs.
  Multiple VGs found with the same name: skipping vg1
  Use --select vg_uuid=<uuid> in place of the VG name.
2023-05-16 17:17:55 +02:00
fd6e113bba raidintegrity: allow snapshots 2023-05-11 11:02:52 -05:00
05c2b10c5d Fix "multisegment RAID1, allocator uses one disk for both legs"
In case of e.g. 3 PVs, creating or extending a RaidLV causes SubLV
collocation thus putting segments of diffent rimage (and potentially
larger rmeta) SubLVs onto the same PV.  For redundant RaidLVs this'll
compromise redundancy.  Fix by detecting such bogus allocation on
lvcreate/lvextend and reject the request.
2023-05-10 18:35:21 +02:00
bf794b66f4 tests: more updates for 300M xfs
Fix some sizing for larger xfs testing.
Also fix resize of reiserfs which requires resize_fsadm.
2023-05-10 16:19:46 +02:00
bc28082b99 tests: skip this testing without newer blkid
Testing xfs --fs functionality needs new blkid.
2023-05-10 16:19:46 +02:00
d418fc14f4 cov: hide some false positives
Hide some false positives.

Note: there must not a be blank line after coverity hiding comment.
2023-05-10 16:19:46 +02:00
cc7c41abbd cov: remove unneeded header file inclusion 2023-05-10 15:27:48 +02:00
7b52a663a6 cov: validate dev_get_primary_dev result
Make sure primary_dev is defined when using it.
2023-05-10 15:27:48 +02:00
0cc5c2203b tests: needs to be exported for tracing 2023-05-06 22:43:22 +02:00
7267322fc1 tests: adapt for xfs 300M min size
Some test still were missed to be converted for XFS 300M min size.
2023-05-06 22:43:22 +02:00
4af8063c96 tests: different check for mounted volume
It appears newer mount allows repeated mounting ??
Anyway - do the check with grep.
2023-05-06 22:43:22 +02:00
2fde4b6baa tests: check for lvmdbusd running in the system
Check for running (possibly leftover) lvmdbusd running in the
system - as this daemon may interfere with this test as in this
case both be operating on same  'live' data in /run/lvm.
2023-05-06 22:43:22 +02:00
aa19f2aa3d tests: update lvextend tests
Make test faster by agregating sets of operation to work on a single
created filesystem yet checking all the variants of extension and reduction.

Split 'xfs' part into separate test and convert it for use of the
minimal size 300M nowdays required by mkfs.xfs.
2023-05-06 22:43:22 +02:00
6e8ede833b aux: retry brd removal
Try to remove brd twice if there is some collision with udevd.
Instanciate only 1 ramdisk.
Use just 'eval' for '--nameprefixes' results.
2023-05-06 22:41:23 +02:00
87eae82195 aux: wipefs_a takes list of devices
Enhance function to take list of device so set of devices
can be wiped with a single call:

aux wipefs_a  "$dev1" "$dev2"
2023-05-06 22:40:23 +02:00
534269d0fb vdo: document feature option 2023-05-06 20:38:57 +02:00
58293173cf cov: check syscall result 2023-05-06 20:38:57 +02:00
f038fc3b17 cov: remove unused but set variables 2023-05-06 20:38:57 +02:00
c451d7925d cleanup: correcting some log_print
Correcting to log_print_unless_silent(),
so -qq can do some work.
2023-05-06 20:38:49 +02:00
39b2bd06b8 cov: some initializers 2023-05-06 19:22:05 +02:00
4fd2f433ad cov: hide problem with 64bit time_t 2023-05-06 19:22:05 +02:00
242bf56413 cov: validata top_lv
Add explicit pointer check is never NULL.
2023-05-06 19:22:05 +02:00
fae0ed8f10 cov: ensure there is either vg or error_vg
Make it explicitely visible to coverity that
_process_pvs_in_vg() is not passing  NULL vg.
2023-05-06 19:22:05 +02:00
871d9f379f cov: ensure NULL baton is not dereferenced 2023-05-06 19:22:05 +02:00
662020c221 cov: simplier code
Avoid coverity to contruct some abstract scenarions of 'cft'
modification and simplify the code at the same time.
2023-05-06 19:22:05 +02:00
d7e922480e Fix "lvconvert -m 0 will always take rimage_0 even if it is out-of-sync"
Bail out in case first rimage is out-of-sync.
Refresh first, i.e. "lvchange --resync $RaidLV",
then retry downgrade to linear after resynchronization.
2023-05-05 20:51:58 +02:00
368381fd40 lvreduce: make _lvseg_get_stripes handle integrity layer
lvreduce uses _lvseg_get_stripes() which was unable to get raid stripe
info with an integrity layer present.  This caused lvreduce on a
raid+integrity LV to fail prematurely when checking stripe parameters.
An unhelpful error message about stripe size would be printed.
2023-05-03 11:34:59 -05:00
c4440b5b49 pvck: improve error for write to existing file 2023-04-28 13:31:39 -05:00
6d262eaf64 lvmcache: fix valgrind error when dropping md duplicate
When lvmcache info is dropped because it's an md component,
then the lvmcache vginfo can also be dropped, but the list
iterator was still using the list head in vginfo, so break
from the loop earlier to avoid it.
2023-04-25 14:46:36 -05:00
ffead4f333 tests: adapt waiting for pvmove start
Previous commit cause the pvmove could actually be started in unexpected
order - so make sure, we are not starting new pvmove in same VG until
the previous one is started.
2023-04-25 19:51:52 +02:00
7f2939d328 tests: utils now print also df_h
Add info about space usage on devices after the test.

Add some more skipped dirs.
2023-04-25 19:02:39 +02:00
7b88c9f619 tests: some aux corrections
Keep backups within test_dir instead of dev_dir (so it doesn't
leak large files there if the tests are run over real /dev dir).

Move restoring of dm_mirror throttling before test_dir is removed.
2023-04-25 18:59:04 +02:00
4a003ba671 tests: fix pattern for raid4
Since the strip in raid4 might be XOR - we might eventually end
with 2 blocks of 'B' on 2 disks - so will rest of stripe with 'b'.
2023-04-25 00:12:31 +02:00
7c8901dabd tests: use 300M lv size for xfs 2023-04-25 00:12:31 +02:00
e42b56c31b tests: try to retry remove of scsi_debug
Not quite sure if this helps anything, some of testing
machines can't reliably remove scsi_debug, reporting
they are in use - but it's not easily reproducible...
2023-04-25 00:12:31 +02:00
b8aea8ae7d tests: handle multiple devs with wait_pvmove_lv_ready
aux wait_pvmove_lv_ready() now handles multiple pvmove LVs
at one go - which allows a bit fast checking - although
at some point we may need to switch to use delayed devs
since mirror throttling seems to be no longer working well,
as CPU are getting so fast, that most of data are already
pvmoved before throttling has any chance to do something...
2023-04-25 00:12:31 +02:00
8476a09ee5 tests: skip some unneeded test
Skip irelevant tests for polld & lockd pass.
2023-04-25 00:12:31 +02:00
a51b6d5e42 aux: use unused brd device for testing
When 'brd' device can be removed (is unused AKA not opened),
remove such device and use again for testing.

Let's assume user has no unused brd device left in the system.

When the 'tests' sometimes fail to cleanup devices, with this
change futher cleanup from some next test may evenually release
brd device and make it available for testing.
2023-04-25 00:12:31 +02:00
5e4c0701d9 aux: more efficient lvmlock shutdown 2023-04-25 00:12:31 +02:00
8947964f10 wipe_lv: use zeroing ioctl only for large sizes
There is no easy way to detect, whether device supports zeroing,
and kernel also zeroes device when it's not directly supported,
but with extra message:

operation not supported error, dev X, sector Y op 0x9:(WRITE_ZEROES)...

So to avoid generating such message with every 'lvcreate', use for
zeroing of upto 8K just standard write of zeroed page.
(maybe we can go with even larger sizes).
2023-04-25 00:12:31 +02:00
31cfcf7ce9 fix dev_name use in add_areas_line
This function was relying on dev_name() returning NULL
to indicate no device, but dev_name never returns NULL.
2023-04-24 15:49:00 -05:00
afc02ae6e7 lvmdbus: preserve PATH envvar 2023-04-23 12:49:37 +02:00
ce8835d4c4 tests: enforce 4K block for integrity fs
With raid tests it's important we don't get spread of 4K file
across 1K block on a multiple disk stripe - so use 4K block size
for ext4 fs.
2023-04-23 00:03:43 +02:00
7cf5feb7d2 aux: loop doesn't support zeroing discard
To avoid logging unsupported WRITE_ZEROES with loop,
disable usage for this backend device.
2023-04-23 00:02:33 +02:00
bbc67abeed tests: hide some more file in error trace
Hide unneeded dev nodes.
2023-04-22 11:25:39 +02:00
f239ce2353 makefiles: forgotten to install some test config
rpm testing missed config files.
2023-04-22 11:25:39 +02:00
1f4e3832e0 test: use aux wait_recalc
Use aux function.
2023-04-22 11:25:39 +02:00
2043bb0e38 test: convert to use ext4
Modify test to check same properties with less demanding ext4.
2023-04-22 11:25:39 +02:00
b0f26a135b aux: don't use to new dd options
Actually  oseek comes only with rawhide's version,
just use the standard option name.
2023-04-21 22:01:40 +02:00
8bcf46a0ac tests: add data sync 2023-04-21 14:52:43 +02:00
80ebec099d aux: add wait_recalc
Share function across tests.
2023-04-21 14:52:43 +02:00
4e0aab7428 tests: convert to use ext4
Convert test to use only ext4 instead of 300M demanding XFS.
Shorten  'B' files to 4K and use 4K strip size with >raid1 arrays
so we do not risk spreading of the file across stripe.

Also use easier 'aux corrupt_dev()' method to introduce a bit
corruption into a block device with integrity.

TODO: shorten _wait_recalc (should't be needed).
2023-04-21 14:52:43 +02:00
b2360437e0 tests: use aux clear_dev
Use wrapper over 'blkdiscard -z'
2023-04-21 14:52:43 +02:00
c331a3b1da aux: add corrupt_dev
Add function to corrupt some bytes in give file path presenting
a device.  1st. patern in just once replaced with 2nd. pattern.

Usable to simulate some bit corruption for integrity devices.
2023-04-21 14:52:43 +02:00
11562bcc6b aux: add clear_dev
Function that will use 'blkdiscard -z' and fallbacks
to 'dd' when such option is not available.
2023-04-21 14:52:43 +02:00
b030ef31de post-release 2023-04-21 10:36:06 +02:00
54efdab230 pre-release 2023-04-21 10:35:10 +02:00
7807672975 lvmdbusd: Add a flag to activate LVs in shared mode to Lv.Activate 2023-04-20 12:09:11 -05:00
317071ec53 cache: fix snapshot of cache with cachevol
Creating a snapshot of a cache LV with a cachevol would fail
because cache_check was not being skipped.
2023-04-10 12:44:22 -05:00
8458ff9ad1 remove extra change from support 16KB page size 2023-04-07 15:57:28 -05:00
b443eac6ef support 16KB page size 2023-04-07 14:26:09 -05:00
b1789b84c3 WHATS_NEW: update 2023-04-06 13:45:42 +02:00
e59e7aa0ab tests: use less demanding ext4 2023-04-06 13:41:30 +02:00
7b5291a8ed tests: lower demand for disk resources
Convert test to use a single skeleton and only different pieces
keep in separate tests.

Lower raid disk usage to smaller size and switch to ext4
as way less demanding fileystem.
2023-04-06 13:34:26 +02:00
e8e6347ba3 vdo: use fixed size vdopool wrapper
Instead of using size of 'empty header' in vdopool use fixed size 4K
for a 'wrappeing' vdo-pool device.

This fixes the issue when user tried to activate vdo-pool after
a conversion from vdo managed device with 'vgchange -ay' - where
this command activated all LVs with 'vdo-pool' wrapping device as well,
but this converted pool uses  0-length header.

This 4k size should usually prevent other tools like 'blkid' recognize
such device as anything - so it shouldn't cause any problems with
duplicate indentification of devices.
2023-04-06 11:06:04 +02:00
334117ee00 cleanup: rename function
Rename _thin_lv_has_device_id and use common function naming
with _lv_has_thin_device_id().
2023-04-06 11:06:04 +02:00
1fb3e08033 cleanup: simplify 2023-04-06 11:06:04 +02:00
a7cf55c6a1 configure: update
autoreconf
2023-04-06 11:06:04 +02:00
0f2c48a10e configure.ac: print locking dir
Correcting output results from configure script when
printing locking dir.

Shuffle dmfilemapd close to dmeventd option and tracing.

Couple indent changes.
2023-04-06 11:06:04 +02:00
51117b5793 integrity: hide creation of internal LVs
Creation of 'hidden' local LVs should be visible only in
verbose mode (-v) when creating a raid LV with integrity.
2023-04-06 11:06:04 +02:00
390ff5be2f raidintegrity: allow writecache and cache
Allow writecache|cache over raid+integrity LV.
2023-04-05 14:24:07 -05:00
ebbc3f7ab3 tests: integrity fixes
wait_recalc was mistakenly being called on raid without integrity
wait_recalc loop was exiting without error
2023-04-05 14:24:07 -05:00
300c8209a8 lvmdbusd: Correct seg. fault on s390x ELN
syscall 186 is specific to x86 64bit.  As this is different from arch
to arch and between same arch different arch size we will only grab
thread ID using built-in python support if it is supported.

Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2166931
2023-03-30 11:04:49 -05:00
f7ca470abe lvmdbusd: Correct locking for _common_log
Reduce the lock time and include the flush in the lock.

Reported by: Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
2023-03-30 11:04:42 -05:00
d6f8f59239 Fix import of utils from lvmdbusd.cfg
Signed-off-by: Adam Williamson <awilliam@redhat.com>
2023-03-21 22:42:25 -05:00
238e377777 post-release 2023-03-21 13:36:36 +01:00
3e0ee8dbad pre-release 2023-03-21 13:35:48 +01:00
6204fda003 make: generate 2023-03-21 13:33:14 +01:00
49dbeb9b45 tests: nomda-restoremissing
This test was broken by commit 69ea2e3f9
"vg_read: keep MISSING_PV when device with no mda reappears"
Change the test to match the new behavior.
2023-03-20 12:42:50 -05:00
ddfe839dd1 lvmdbusd: Add a new 'Shared' property to the Vg interface
Signed-off-by: Vojtech Trefny <vtrefny@redhat.com>
2023-03-15 09:09:38 -05:00
0c73d3545b lvmdbustest: Correct env. logic
Signed-off-by: Tony Asleson <tasleson@redhat.com>
2023-03-14 09:36:38 -05:00
baf99ff974 lvmdbustest: Add notes on error injection testing
Not doing this by default for automated build testing as it generates a
lot of output and slows things down by another ~10%.
2023-03-10 12:51:53 -06:00
1c550d7124 lvmdbustest: Add env. variable to skip signal testing
This is currently need if we are collecting code coverage data as we don't
handle this unit test correctly.
2023-03-10 12:51:53 -06:00
f8876290bf lvmdbustest: Check for needed env. variables 2023-03-10 12:51:53 -06:00
568e8c71d7 lvmdbustest: Don't use hard coded /tmp for error inject log 2023-03-10 12:51:53 -06:00
66e79aab36 lvmdbusd: Add a retries during initial load
When the daemon is starting we do an initial fetch of lvm state.  If we
happened to get some type of failure with lvm during this time we would
exit.  During error injection testing this happened enough that
the unit tests were unable to finish.  Add retries to ensure we can get
started during error injection testing.
2023-03-10 12:51:53 -06:00
9c3b91a513 lvmdbustest: Shutdown cleanly with "exit"
Make the error injection wrapper handle the exit case, so that we can
clean up gracefully when instructed to do so.
2023-03-10 12:51:53 -06:00
9714f3ec4f lvmdbustest: Only inject 1 missing key error
Previously we were injecting a missing key in the lv, vg, and pv.
Given the order of processing in lvmdbusd, this prevented us from
exercising all the error paths.  Change to returning just 1 instead.
2023-03-10 12:51:53 -06:00
2359023009 lvmdbustest: Correctly set up env. for error injection 2023-03-10 12:51:53 -06:00
70a5ebc052 lvmdbustest: open log file with "a"
So we retain the log across fork & exec and lvm shell testing.
2023-03-10 12:51:53 -06:00
1949afa24b lvmdbusd: Handle missing key in get_key
When we sort the LVs, we can stumble on a missing key, protect against
this as well.

Seen in error injection testing:
Traceback (most recent call last):
  File "/home/tasleson/projects/lvm2/daemons/lvmdbusd/fetch.py", line 198, in update_thread
    num_changes = load(*_load_args(queued_requests))
  File "/home/tasleson/projects/lvm2/daemons/lvmdbusd/fetch.py", line 83, in load
    rc = MThreadRunner(_main_thread_load, refresh, emit_signal).done()
  File "/home/tasleson/projects/lvm2/daemons/lvmdbusd/utils.py", line 726, in done
    raise self.exception
  File "/home/tasleson/projects/lvm2/daemons/lvmdbusd/utils.py", line 732, in _run
    self.rc = self.f(*self.args)
  File "/home/tasleson/projects/lvm2/daemons/lvmdbusd/fetch.py", line 40, in _main_thread_load
    (lv_changes, remove) = load_lvs(
  File "/home/tasleson/projects/lvm2/daemons/lvmdbusd/lv.py", line 148, in load_lvs
    return common(
  File "/home/tasleson/projects/lvm2/daemons/lvmdbusd/loader.py", line 37, in common
    objects = retrieve(search_keys, cache_refresh=False)
  File "/home/tasleson/projects/lvm2/daemons/lvmdbusd/lv.py", line 72, in lvs_state_retrieve
    lvs = sorted(cfg.db.fetch_lvs(selection), key=get_key)
  File "/home/tasleson/projects/lvm2/daemons/lvmdbusd/lv.py", line 35, in get_key
    pool = i['pool_lv']
KeyError: 'pool_lv'
2023-03-10 12:51:53 -06:00
3d854b39bd lvmdbusd: Replace assert with exception
Instead of using an assert we will raise an LvmBug exception
2023-03-10 12:51:53 -06:00
e79c6feb08 tests: update missing-pv
add more checks and expand comments explaining behavior
2023-03-08 16:31:28 -06:00
69ea2e3f94 vg_read: keep MISSING_PV when device with no mda reappears
Remove old code that became incorrect at some point.
It's probably a fragment of an old condition that was left
behind because it wasn't understood.  We don't want to drop
the MISSING_PV flag just because the PV has no mda in use.
The device that was missing may have stale data, so the user
needs to decide if the device should be removed or restored.
2023-03-08 16:31:28 -06:00
937f1d3209 tests: vg-raid-takeover
Different sequences of steps that could be used to handle raid LVs
after VG takeover (what would happen in cluster failover) combined
with the loss of a disk.
2023-03-08 16:31:28 -06:00
aa85ed1784 vgchange: allow changing system ID with majority of PVs
when used with --majoritypvs.  This allows the fail-over
of a VG between systems by changing the VG system ID when
a PV is missing.
2023-03-08 16:30:54 -06:00
da44f2b6fe lvmlockd: clean up get_local_nodeid
Hard to see if fclose calls were correct, and coverity couldn't figure
it out either, so make it clear.
2023-03-08 11:11:32 -06:00
cd14d3fcc0 toollib: fix segfault if using -S|--select with log/report_command_log=1 setting
When we are using -S|--select for non-reporting tools while using command log
reporting (log/report_command_log=1 setting), we need to create an internal
processing handle to handle the selection itself. In this case, the internal
processing handle to execute the selection (to process the -S|--select) has
a parent handle (that is processing the actual non-reporting command).

When this parent handle exists, we can't destroy the command log report
in destroy_processing_handle as there's still the parent processing to
finish. The parent processing may still generate logs which need to be
reported in the command log report. If the command log report was
destroyed prematurely together with destroying the internal processing
handle for -S|--select, then any subsequent log request from processing
the actual command (and hence an attermpt to access the command log report)
ended up with a segfault.

See also: https://bugzilla.redhat.com/show_bug.cgi?id=2175220
2023-03-07 15:29:54 +01:00
c8f2125b85 lvmdbusd: Add needed env. variables
When running lvmdb.py by itself for testing we need these.
2023-03-06 10:26:44 -06:00
df6120e9f7 lvmdbusd: Move cfg.lvmdebug data init
Move this to the cfg file itself, so that initialization runs when it
gets processed.
2023-03-06 10:25:22 -06:00
8e27dfd405 lvmdbustest: Test duplicate VG rename 2023-03-03 11:17:30 -06:00
3e616230f2 lvmdbustest: Add more info on asserts 2023-03-02 11:44:16 -06:00
95afd315b1 lvmdbustest: Don't hard code to /tmp
During lvm testing they use an alternative tmp directory.
2023-03-01 15:59:18 -06:00
50e6efafb9 lvmdbustest: Add more output for test_log_file_option 2023-03-01 15:52:23 -06:00
80f6655956 lvmdbustest.py: Increase udev timeout 2023-03-01 15:26:37 -06:00
4cbe789f9c lvmdbusd: Remove unused import 2023-02-27 09:57:18 -06:00
b0e75bd356 lvmdbusd: Add lock to prevent concurrent lvm shell access
There is a window of time where the following can occur.

1. An API request is in process to the lvm shell, we have written some
   command to the lvm shell and we are blocked on that thread waiting
2. A signal arrives to the daemon which causes us to exit.  The signal
   handling code path goes directly to the lvm shell and writes
   "exit\n".  This causes the lvm shell to simply exit.
3. The thread that was waiting for a response gets an EIO as the child
   process has exited.  This bubbles up a failure.

This is addressed by placing a lock in the lvm shell to prevent
concurrent access to the shell.  We also gather additional debug data
when we get an error in the lvm shell read path.  This should help if
the lvm shell exits/crashes on its own.
2023-02-27 09:07:43 -06:00
e3b7395af4 lvmdbustest.py: Remove use of root_dir in glob
This feature has only been in python since 10/2021.
2023-02-27 09:07:37 -06:00
1857eb9fe0 lvresize: fix check for mounted and renamed LV to handle spaces
Replace spaces with \040 in directory paths from getmntent (mtab).

The recent commit 5374a44c57 compares mount point directory paths
from /etc/mtab and /proc/mounts, in order to detect when a mounted
LV has been renamed.  The directory path comparison does not work
correctly when the path contains spaces because getmntent uses
ascii space chars and proc replaces spaces with \040.
2023-02-23 16:55:36 -06:00
86ac529b99 configure: update 2023-02-23 16:46:35 +01:00
551d27a327 WHATS_NEW: updates 2023-02-23 16:46:35 +01:00
c8868041d8 configure.ac: use pkg-config to detect static libs
Add some Gentoo based patches for better support of static linking.
This are not tested nor supported by upstream developers.
Usage requires presence of several libraries in their static form
which is however not commonly available.

Selinux modified by zkabelac to still work on older sofrware which
did not provided libselinux.pc at a time - see keep the old check
present and use pkg-config only when possible.
2023-02-23 16:46:35 +01:00
2b7fa40aac configure.ac: add STATIC_LDFLAGS
Add support for specif STATIC_LDFLAGS when linking static binaries.
2023-02-23 16:46:35 +01:00
2b592a67d6 configure.ac: misc 2023-02-23 16:46:35 +01:00
255e8c8eaa configure.ac: fail configure for missing libraries
When user enables lockd libraris, code needs to fail, when then are
missing. Also when notify-dbus support if enabled, and libsystemd is
missing, abort configuration.
2023-02-23 16:46:35 +01:00
ad66600e48 configure.ac: update dlm check
Check for pkg-config --libs libdlm_lt  and test if the returned value
contains word 'pthread' - if so, it's likely a buggy result from
incorrect config file and use directly  -ldlm_lt for this case.
2023-02-23 16:46:35 +01:00
d91bc6904d makefiles: add pthread to libdevmapper pkgconfig
Add pthread to pkg_config file.
2023-02-23 16:46:35 +01:00
e0c95f15a7 makefiles: avoid grep
Avoid getting annoyting grep warning and use just awk to get the
value.
2023-02-23 16:46:35 +01:00
c1cecc3dc5 aux: lvmdbus checks for JSONDecodeError
Skip lvmdbus testing with too old python.
2023-02-23 16:46:35 +01:00
d11e12264f tests: add missing quotes
Add quotes around paths and also add fixme for checking
system is actually usable for a test with all running
services.
2023-02-23 16:46:35 +01:00
f5acdc2d79 tests: use aux mdadm wrapper
Wrapper takes care of proper MD device name around its various
incarnations.
2023-02-23 16:46:35 +01:00
d7c4fb7743 tests: remove option chunk for mdadm raid1
Not sure why, but --chunk specification for mdadm raid1 is no longer
'wanted' ???
2023-02-23 16:46:35 +01:00
6943afe9d5 tests: add fixme 2023-02-23 16:01:50 +01:00
d5c0b68dde tests: some skips with 6.2 kernel
Fix did not managed to get to final release so skip test on this kernel.
2023-02-23 16:01:50 +01:00
25cb6a042f vgimport: invalidate hints
There may be some unconventional methods of sharing disks with vgimport
where hints could cause confusion.  Hints should be disabled when
sharing disks, or pvscan --cache used to regenerate hints as needed,
but invalidating hints from vgimport might help reduce confusion.
2023-02-22 16:19:48 -06:00
0f6da9926d post-release 2023-02-21 15:36:24 +01:00
f7dd2562c5 pre-release 2023-02-21 15:33:32 +01:00
993bd2ffc8 lvmdbustest: Check and remove lvm debug collection files
In setup/teardown ensure we check for and remove any lvm debug
collection, to prevent FS from filling up.
2023-02-20 12:01:53 -06:00
e18d60b336 lvmdbusd: Disable collecting lvm debug data by default 2023-02-20 12:01:53 -06:00
5561281f0a lvmdbusd: Fix grammar 2023-02-20 12:01:53 -06:00
a861f0425e configure: update 2023-02-17 00:08:50 +01:00
13b216fbdf tests: safety first... 2023-02-17 00:08:50 +01:00
1788b4b3aa tests: lvmdbus testing use --debug optinally now
To shorten down logging output of lvmdbus - use for now lvmdbus
with --debug option only when LVM_DEBUG_LVMDBUS=1 is set.
2023-02-17 00:08:50 +01:00
06c5c29443 tests: check failing vdo conversion
When we detect not usable vdo on a machine, check lvconvert fails.
2023-02-17 00:08:50 +01:00
d58b475f63 makefiles: move include earlier 2023-02-17 00:00:12 +01:00
b9697acbd6 configure.ac: various minor updates 2023-02-17 00:00:12 +01:00
1cd71a5fe3 configure.ac: remove unneded vars and settings 2023-02-17 00:00:12 +01:00
bb4ed5c23d configure.ac: fix incorrect check for valid configuration 2023-02-17 00:00:12 +01:00
c23d09bbce configure.ac: use standardized LIBS and CFLAGS
Convert lvmlockd to use configure _LIBS and _CFLAGS for
discovered libraries.

TODO: ATM we ignore discovered libdlm and use libdlm_lt instead.
Also libseagate_ilm is hard to find unicorn for testing.
2023-02-17 00:00:12 +01:00
d106ac04ab configure.ac: use LIBSYSTEMD
Convert naming SYSTEMD_CFLAGS/LIB -> LIBSYSTEMD_CFLAGS/LIBS
to better fit library check for libsystemd.

Build lvmlockd with SD_NOTIFY when we have defined LIBSYSTEMD_LIBS.
2023-02-17 00:00:12 +01:00
3ef26494f2 debug: missing backtraces 2023-02-17 00:00:12 +01:00
7bc5c8ac3d cov: avoid using strcpy
Coverity is complaining about unchecked strcpy here, which is
irelevant as we preallocate buffer to fit in copied string,
however we could actually reuse these size and use just memcpy().
So lets make some simple conversions.
2023-02-17 00:00:04 +01:00
fb930c2165 lvconvert: use log_print_unless_silent
For better -qq.
2023-02-16 13:15:03 +01:00
501cc19034 lvconvert: fix return codes
Several inverted return code resulted the command returned
a success as exit code, while the function errored internally.
2023-02-16 13:15:03 +01:00
08265641f3 pvscan: remove warning about excluded root dev
This was trying to warn about a misconfig where the root PV
was excluded by the devices file, but it wasn't covering all
cases.  Also, it's not very useful because the root LV is
usually activated directly in the initrd.
2023-02-15 10:21:13 -06:00
bd05318ba2 pvscan: filter does not need to be checked for symlink names
With the recent use of DEVLINKS, there is no longer any real
point in checking the filter for symlink names.  Removing
this check should not change behavior with or without symlinks
in the filter.
2023-02-15 10:19:57 -06:00
07cd341bd8 configure: update 2023-02-13 14:30:47 +01:00
1e55e5c60a configure.ac: more cleanup
Some variable simplification,
correct messages with PATH_SBIN.
2023-02-13 14:30:47 +01:00
f46610e9b0 configure.ac: remove UDEV_SYSTEMD_BACKGROUND_JOBS
Missed to go with 042fbd43d2.
2023-02-13 14:30:47 +01:00
b6efa827ee configure.ac: fix support for LOCKDIDM
Commit 7a8b7b4add introducing lockidm
support missed to use AC_SUBST() for a variable and provide it only
in prebuilt configure, so with the next autoreconf this variable
was lost and IDM support was no longer compiled.

Fixes: https://github.com/lvmteam/lvm2/issues/98
Reported-by: Tom Prohofsky
2023-02-13 14:30:47 +01:00
7f2864b5b1 acinclude.m4: add local copy of PKG_CHECK_VAR
Just in case an old distro tries to autoreconf and doesn't
come with newer pkg_ macros.
2023-02-13 14:30:46 +01:00
8630a19d1e tests: use PWD for dbus testing
lvmdbusd ATM is leaking too many log files.
At least try to keep them removed with test failure.
2023-02-13 14:30:43 +01:00
7ea62f640c tests: skip test without mkfs.ext4 2023-02-13 13:41:59 +01:00
2241982f96 cov: drop unneeded header 2023-02-13 13:41:59 +01:00
02fdb2480e man: update lvmcache cache setting
Correct setting of migration_threshold and add clarify
how the user can restore default cache settings for cache policies.
Also document mq aliasing with smq for newer kernels.
2023-02-13 13:41:59 +01:00
31076942f1 makefiles: update doc
Document using of target useful for checking variable content.
2023-02-13 13:41:59 +01:00
4791a4fc68 makefiles: allow using configure cppflags
Configure defines 'CPPFLAGS' and we should use defined value
for compilation.

Reported-by: debian
2023-02-13 13:41:59 +01:00
50f73de4b2 makefiles: use configured systemd library paths
Use discovered/selected systemd library from configure.
2023-02-13 13:41:59 +01:00
0fc2d418f7 WHATS_NEW_DM: update 2023-02-13 13:41:59 +01:00
9b78f7eee9 libdm: match reactivation of sibling for snapshot
Apply same code for libdm as in device_mapper dir from
commit c8a5948a71.
2023-02-13 13:41:59 +01:00
7e14835a46 libdm: improve parallel create of control node
When two parallel commands would have tried to create our
/dev/mapper/control node at the same time, one of them could
actually fail even if the 2nd. command actually mknod()
this control node correctly.

So for EEXIST case add detection if the control node is ok.

This may possibly help with some race case in early boot.
2023-02-13 13:41:59 +01:00
cf0dc9a13c filesystem: use PATH_MAX for linux paths 2023-02-12 23:56:29 +01:00
615347da20 configure: update 2023-02-10 22:31:43 +01:00
1416bb3837 configure.ac: check for blkid when required
We still need to support build without any blkid present,
so use PKG_CHECK_EXISTS() instead of direct failure
from PKG_CHECK_MODULES for too old version.
2023-02-10 22:29:33 +01:00
d1bfa400a1 WHATS_NEW: update 2023-02-10 20:54:05 +01:00
21edfc4a5e configure: update 2023-02-10 20:54:05 +01:00
391138ff30 configure.ac: support systemd-run binary path
Allow users to specify their path to systemd-run binary:

configure --with-systemd-run=/my/path/system-run

By defaults it autodetected in $PATH and fallbacks to:
/usr/bin/systemd-run.
2023-02-10 20:54:05 +01:00
2a72f8a49c configure.ac: better blkid test
Previous commit e67ebc5c40 used incorrect check
for blkid version.
Fix it by always checking for at least version 2.24,
as we can't use older version anyway.
Added BLKID_SUBLKS_FSINFO is present in newer version.
2023-02-10 20:53:10 +01:00
7d419b374a tests: reduce shellcheck warns
Reduce warnings in tests.
2023-02-10 17:50:27 +01:00
773bc01377 tests: cleanup some shellcheck warns
Reduce shellcheck warnings about missing {} for possible array
dereference.

Make sure we are not loosing error code when assigning local vars
and explicitely ignore 'errors' from standalone lines when needed.

Add some missing quotes.

Use $() instead of ancient ``

Avoid writing some temporary data into /tmp - test need to store
files within its own 'testdir' - so it can be properly discarded.
2023-02-10 17:50:27 +01:00
cc2293f18e tests: avoid using length
Use ${#  for length instead.
2023-02-10 17:50:27 +01:00
30b9d4d4aa tests: remove blank line 2023-02-10 17:50:27 +01:00
b29b8e0bb2 tests: fix cutandpaste bug in wrapper
Use correct variable name for assign.
2023-02-10 17:50:27 +01:00
a0437225aa makefiles: avoid piping
Addressing problem for user of system without default bash shell.

As reported "set -o pipefail" is a bashism that causes the build to
fail when /bin/sh does not point to bash.
For example, this has been observed causing build failures
on Gentoo when /bin/sh is symlinked to /bin/dash.

Rule has been reworked and we started to use .DELETE_ON_ERROR to
ensure that with any errors during file generation, such invalid
file is automatically removed.

Rules were reworked to avoid using pipe and instead use temporary
files when necessary.
Printing lines with echo was replaced with POSIX recomended 'printf'
as proposed by reporter since handling of escape characters and
the "-n" flag for "echo" aren't portable across shells.

Also some build deps has been added.

Bug: https://bugzilla.redhat.com/show_bug.cgi?id=1822280
Gentoo-bug: https://bugs.gentoo.org/682404
Gentoo-bug: https://bugs.gentoo.org/716496
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1822280

Reported-by: Michael Orlitzky <michael@orlitzky.com>

TODO: investage if the temporary files could be handled via some
intermediate target solution - ATM I couldn't make it work equally
well as current solution use shell 'trap' to remove temp file.
2023-02-10 17:50:27 +01:00
a032e07578 makefiles: keep removing anchient files
Commit dropping lvmetad support 117160b27e
also removed cleaning of its generated files. However we need to keep
this functionality, otherwise we can leak them during various bisect.
Easier is to keep such rules forever.

Also commit c1ab9fb37f moved cmds.h to
include, so again keep it removed so it's not left there and in any
case could not misslead anyone.
2023-02-10 17:50:27 +01:00
35e1f15e03 lvresize_fs_helper: cleanup shellcheck warns
Use commands directly in 'if cmd; then'.
Use shell vars in $(( )) in recommended way.
2023-02-10 17:50:27 +01:00
b681b774dc configure: update 2023-02-10 17:50:27 +01:00
e67ebc5c40 configure.ac: misc updates
Use literal assignments with "" for better visibility in text editor.
Use more [] for AC_ macro args.
2023-02-10 17:50:27 +01:00
042fbd43d2 configure.ac: remove some lvmetad leftovers
Remove unused parts of configure and udev rules since lvmetad is gone.
2023-02-10 17:50:27 +01:00
1fb5107eea lvresize: better detection of BLKID_SUBLKS_FSINFO
Use configure detection instead of trying to directly include
blkid.h inside lvresize.c - where we do not pass in BLKID_CFLAGS
and since we actually do not need to use blkid there, introeduce
test variable HAVE_BLKID_SUBLKS_FSINFO and avoid trying to
use blkid.h in this place - this also fixes builing problem for
systems without blkid.h.
2023-02-10 17:50:27 +01:00
cf204ce55e configure.ac: only use AS_CASE for conditional blocks
Like `AS_IF([...])`, `AS_CASE` bubbles nested `AC_REQUIRE()` to the
top-level.
2023-02-10 17:50:27 +01:00
583cb699cf configure.ac: only use AS_IF for conditional blocks
`AS_IF([...])` is more portable, as it respects macro expansions of
`AC_REQUIRE()`.

This is recommended Autoconf best practice, since in nested
conditionals, it is generally unknowable whether some macro invokes
`AC_REQUIRE()` deep down:
https://www.gnu.org/software/autoconf/manual/autoconf-2.71/html_node/Common-Shell-Constructs.html#index-AS_005fIF-1

As a result, the hacky `pkg_config_init` function is not needed
anymore, since any `PKG_*` invocation will ensure that
`PKG_PROG_PKG_CONFIG` will have been called, due to the fact that
`AC_REQUIRE()` will trickle up.
2023-02-10 17:50:27 +01:00
d456c1f3c5 configure.ac: use only portable POSIX shell
`[[ ... ]]` only works in bash, and not in POSIX sh, specifically
dash fails on this, which is a popular alternative to bash for running
configure scripts.

test's `-a` and `-o` options are considered obsolescent by POSIX,
because they interact badly with expressions and can become ambiguous
depending on string arguments:
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html

`==` only works in bash.
2023-02-10 17:50:27 +01:00
631762d6db metadata-exported.h: correcting definition
Fixing minor mismatch between definition and declaration of
update_thin_pool_params().
2023-02-10 17:50:27 +01:00
e3534d0f68 lvm: fix typos
Patch aec5e573af was fixing some
of typos only in generated file, but they need to be fixed in
the source files.
2023-02-10 17:50:27 +01:00
a1a1439215 vgimportdevices: LOCK_EX requires <sys/file.h> include
https://linux.die.net/man/2/flock

Bug: https://bugs.gentoo.org/887259
2023-02-10 17:50:27 +01:00
be124ae810 vgimportclone: fix non-duplicate PV with non-unique basevgname arg
Fix hang of vgimportclone command when:
the PV(s) being imported are not actually clones/duplicates, and
the -n vgname arg is the same as the current vgname.

(Not the intended use of the command, but it should still work.)

In this case, the old and new vgnames ended up being the same, when
the code expected they would be different.  A file lock on both the
old and new vgnames is used, so when both flocks are on the same
file, the second blocks indefinitely.

Fix the new vgname to be the old name plus a numeric suffix, which
is the expected result.
2023-02-09 17:37:22 -06:00
94f77a4d8d udev: import previous results of blkid when in suspended state
Follow-up for e10f67e917.

The commit e10f67e917 tries to keep device
node symlinks even if the device is in the suspended state. However,
necessary properties that may previously obtained by the blkid command
were not imported at least in the .rules file. So, unless ID_FS_xyz
properties are imported by another earlier .rules file, the device node
symlinks are still lost when event is processed in the suspended state.

Let's explicitly import the necessary properties.

RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=2158628
GHPR: https://github.com/lvmteam/lvm2/pull/105
2023-02-07 09:37:27 +01:00
dc99f0def1 device_id: ignore quotes in device id
A t10 wwid string was found containing a " character
which breaks vg metadata parsing.  Ignore any quotation
marks in device id strings.
2023-02-06 12:24:18 -06:00
57ad78d436 vg_read: remove unused code for md components
This code was no longer used after ommit
87ee401eea
2023-02-02 16:15:13 -06:00
8498874147 udev: remove rule for explicit creation of /dev/mapper/control
We used KERNEL=="device-mapper", NAME="/dev/mapper/control" udev rule to
create the /dev/mapper/control file. The "NAME" rule should be only used
to rename network devices, otherwise udev issues a warning message. The
device-mapper driver has proper DEVNAME=/dev/mapper/control propagated
in the uevent environment when it is loaded so we don't need further
instruction on where to create the node - udev knows already.

Also, these days, it is created directly by kernel inside devtmpfs.
This makes the NAME="/dev/mapper/control" rule completely obsolete.
2023-02-02 15:41:47 +01:00
e7c8a82506 udev: don't reset SYSTEMD_READY in udev for PVs on MD and loop
Since 67722b3123, we have a new mechanism
to run the autoactivation from udev. With this change, we also replaced
the way the LVM autoactivation service is instantiatiated - instead of
setting the SYSTEM_WANTS udev variable (which systemd read and then
instantiated the service), we're now directly instantiating the
transient 'lvm-activate-<vgname>' service by calling systemd-run.

As such, we don't need to bother with setting the SYSTEMD_READY variable
for foreign devices anymore (in this case, MD and loop devices on top of
which there's a PV).

Before, we set the SYSTEMD_READY variable to make sure that the SYSTEMD_WANTS
is applied correctly - the service instantiation was edge-triggered by
flipping the SYSTEMD_READY from 0 to 1 and at the same time having the
SYSTEMD_WANTS variable set to the service name to instantiate. We're
using systemd-run now so this condition does not apply anymore.

Also, it was not completely correct to set SYSTEMD_READY for foreign
devices because there might be cases where this could cause issues,
see also https://github.com/lvmteam/lvm2/issues/94.
2023-02-01 14:46:52 +01:00
94eda42e7a lv/vgchange: when refreshing whole vg skip snapshot
When refreshing all LVs in a VG, skip processing of thick snapshots,
since they will be refreshed through its origin LV.
Should reduce some unnecessary ioctl().
2023-02-01 11:48:53 +01:00
0ec087e8b8 debug: compatibility with x32 ABI
Keep the conversion 64bit as on x32 arch time_t is 64bit value
and we may loose precision  (y2038).

TODO: like use universal string for time printing as in log/log.c
_set_time_prefix()
2023-02-01 11:47:47 +01:00
c8a5948a71 device_mapper: reactivate siblings for snapshot
When activating origin and its thick snapshots, ensure the
origin's LV udev processing is finished first and after this
reactivate its snapshot so the udev can scan them afterwards.

This should fix the problems for users using UUID of such device
in their fstab and occasionaly mounted snapshot instead of origin LV.
2023-02-01 11:47:47 +01:00
85aa236946 device_mapper: reduce unnecessary looping passed
While looping through the list of nodes, check if there is higher
priority present and another iteration is still needed.
2023-02-01 11:47:47 +01:00
f89c369a01 archive: update message
Better suggesting message as suggested by RHBZ 2123151.
2023-02-01 11:47:30 +01:00
6d14144d31 pvscan: recognize "pci" as a common symlink component in filters
In case the filter strings don't include "/dev/disk", and only
include "pci".
2023-01-31 15:30:35 -06:00
c9fdc828ff vgchange autoactivation: skip regex filter containing symlinks
"vgchange -aay --autoactivation event" is called by our udev rule.
When the udev rule runs, symlinks for devices may not all be created
yet.  If the regex filter contains symlinks, it won't work correctly.
This command uses devices that already passed through pvscan.  Since
pvscan applies the regex filter correctly, this command inherits the
filtering from pvscan and can skip the regex filter itself.

See the previous commit
"pvscan: use alternate device names from DEVLINKS to check filter"
2023-01-31 15:30:35 -06:00
17a3585cbb pvscan: use alternate device names from DEVLINKS to check filter
pvscan --cache <dev> is called by our udev rule at a time when all
the symlinks for <dev> may not be created yet (by other udev rules.)
The regex filter in lvm.conf may refer to <dev> using a symlink name
that hasn't yet been created, which would cause <dev> to not match
the filter regex.  The DEVLINKS env var, set by udev, contains all
the symlink names for <dev> that have been or will be created.
So, we add all these symlink names to dev->aliases, as if we had
found them in /dev.  This allows <dev> to be recognized by a regex
filter containing a symlink for <dev>.
2023-01-31 15:30:35 -06:00
d9f8acb65a lvresize: fail early if crypt device is missing
If extending an LV with crypto_LUKS on it, and the crypt device
is missing, then fail the command before extending the LV.
2023-01-30 17:12:11 -06:00
5374a44c57 lvresize: fail early if mounted LV was renamed
If a mounted LV is renamed, then fs resizing utilities will fail,
so detect this condition and fail the command before any changes
are made.
2023-01-26 14:02:20 -06:00
8adfcddc35 Revert "lvresize: enable crypt resizing with --force"
It looks like force was not being used to enable crypt resize,
but rather to force an inconsistency between LV and crypt
sizes, so this is either not needed or force in this case
should have some other meaning.

This reverts commit ed808a9b54.
2023-01-25 10:10:57 -06:00
49c650423a Revert "makefiles: fix grep warning from make"
This reverts commit 92199ad0b9.

This breaks make rpm.
2023-01-25 09:46:18 +01:00
ed808a9b54 lvresize: enable crypt resizing with --force
Update previous commit
  "lvresize: only resize crypt when fs resize is enabled"
to enable crypt resizing when --force is set and --resizefs
is not set.  This is because it's been allowed in the past
and people have used it, but it's not a good idea.
2023-01-20 12:04:55 -06:00
3bb5576528 lvresize: only resize crypt when fs resize is enabled
There were a couple of cases where lvresize, without --fs resize,
was resizing the crypt layer above the LV.  Resizing the crypt
layer should only be done when fs resizing is enabled (even if the
fs is already small enough due to being independently reduced.)

Also, check the size of the crypt device to see if it's already
been reduced independently, and skip the cryptsetup resize if
it's not needed.
2023-01-19 11:52:14 -06:00
92199ad0b9 makefiles: fix grep warning from make
Remove unnecessary '\'.
2023-01-16 12:37:40 +01:00
3a58e08b8c makefiles: comment out hiding dir entering
While the output of building looks more polished, text editors fail to
find source file from compile errors - so until we start to print
all file with full paths - comment out this make build parameter.
2023-01-16 12:37:40 +01:00
3bedceec38 libdm: correcting ifdef possition
Fix building without ioctl support.
2023-01-16 12:37:40 +01:00
aa09232dc4 tests: vdo resizing 2023-01-16 12:37:40 +01:00
c20f01a0cb vdo: resize requires active vdopool volume
ATM kernel VDO target does not handle resize of inactive VDO LVs
so prevent users corrupting such LVs and require active such LVs.
2023-01-16 12:37:40 +01:00
2451bc568f vdo: fix and enhance vdo constain checking
Enhance checking vdo constains so it also handles changes of active VDO LVs
where only added difference is considered now.

For this also the reported informational message about used memory
was improved to only list consuming RAM blocks.
2023-01-16 12:37:40 +01:00
1bed2cafe8 vdo: read live vdo size configuration
Introduce struct vdo_pool_size_config usable to calculate necessary
memory size for active VDO volume.

Function lv_vdo_pool_size_config() is able to read out this
configuration out of runtime DM table line.
2023-01-16 12:37:40 +01:00
773b88e028 vdo: check memory only in non critical section
When we are actually resizing VDO device - we need to check size only in
non-critical section - otherwise we are checking
2023-01-16 12:37:38 +01:00
f486eb60d5 lvresize: use standard extent conversion function
We need to validate whether the requested resizing size can be
expressed with given extent_size.
2023-01-16 12:35:00 +01:00
bb34ebd4e4 fix typo
Signed-off-by: lilinjie <lilinjie@uniontech.com>
(cherry picked from commit 81b1f5bc3bac0e2e9099b67162da7d1a4995c5f4)
2023-01-11 13:52:12 +01:00
2ab81a3513 lvmlockd: Fix syntax error in previous commit 2023-01-11 13:34:38 +01:00
7c9c3ba5d5 lvmlockd: fix report of lv_active_exclusively for special lv types
Cover a case missed by the recent commit e0ea0706d
"report: query lvmlockd for lv_active_exclusively"

Fix the lv_active_exclusively value reported for thin LVs.
It's the thin pool that is locked in lvmlockd, and the thin
LV state was mistakenly being queried and not found.

Certain LV types like thin can only be activated exclusively, so
always report lv_active_exclusively true for these when active.
2023-01-10 15:37:15 -06:00
789904bd57 tests: vgimportclone with incomplete pv list and nomda pv 2023-01-05 14:47:49 -06:00
c4b898a53e vgimportclone: fix importing PV without metadata
If one of the PVs in the VG does not hold metadata, then the
command would fail, thinking that PV was from a different VG.
Also add missing free on that error path.
2023-01-05 14:28:31 -06:00
2580f007f0 tests: lvresize-fs-crypt using helper only for crypt dev 2023-01-03 14:35:26 -06:00
81acde7ffd lvresize: fix cryptsetup resize in helper
typo used "cryptresize" as command name

this affects cases where the file system is resized
independently, and then the lvresize command is used
which only needs to resize the crypt device and the LV.
2023-01-03 11:40:53 -06:00
aec5e573af doc: fix typos in documentation
Typos found with codespell.
2023-01-03 16:09:58 +01:00
118145b072 post-release 2023-01-03 16:02:07 +01:00
2abb029f2a pre-release 2022-12-22 16:07:35 +01:00
2772d29917 WHATS_NEW: update 2022-12-22 16:06:04 +01:00
edd6d84159 pvscan: free unused device_id
Fix memleak in function.
2022-12-20 15:04:36 +01:00
8f091d3798 cov: use long type for time_t calcs
Some for y38k - calculations can handle 64b time_t.
2022-12-20 15:04:36 +01:00
f443d16fd7 cov: fix buffer size usage
Count with extra 1 byte for buffer end '\0'.
2022-12-20 15:04:36 +01:00
44a2f2df92 cov: remove unused header files 2022-12-20 15:04:36 +01:00
b6b1c19365 vdo: fix reader error path
Nothing to be closed on this error path.
2022-12-20 15:04:36 +01:00
4baef0f93f lvextend: fix overprovisioning check for thin lvs
18722dfdf4 lvresize: restructure code
mistakenly changed the overprovisioning check from applying
to all lv_is_thin_type lvs to only lv_is_thin_pool lvs, so
it no longer applied when extending thin lvs.  The result
was missing warning messages when extending thin lvs.
2022-12-15 10:00:17 -06:00
fa7fe5cbbe writecache: support settings metadata_only and pause_writeback
Two new settings for tuning dm-writecache.
2022-12-08 16:53:36 -06:00
9ce55a43d0 lvchange: handle unrecognized writecache setting
It was being ignored.
2022-12-08 15:48:30 -06:00
6613a61d3b device_id: fix segfault verifying serial for non-pv
The recent change that verifies sys_serial system.devices entries
using the PVID did not exclude non-PV devices from being checked.
The verification code would attempt to use du->pvid which was null
for the non-PVs causing a segfault.
2022-12-02 12:25:10 -06:00
a74468116e device_id: check return value of label_read_pvid
for covscan
2022-12-01 11:49:51 -06:00
e71b434663 device_id: _get_devs_with_serial_numbers add missing free
on malloc failure path
2022-12-01 11:43:24 -06:00
7552ed9010 device_id: add null id->name null check
for covscan
2022-12-01 10:38:48 -06:00
f80273a107 lvmcache: fix strncpy len for wwid 2022-12-01 10:03:06 -06:00
55b29c1c3d lvmlockd: fix missing closedir
in get_local_nodeid from recent lock purge feature:
  lvmlockd: purge the lock resources left in previous lockspace
2022-12-01 09:55:11 -06:00
e63b0c7262 lvmdbusd: Add command_log_selection to command line
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2145114
2022-11-29 12:56:55 -06:00
8f60c49451 lvmdbusd: Move get_error_msg to utils
Moving this so we can re-use outside of lvm_shell_proxy.
2022-11-29 12:56:55 -06:00
61917fbac2 lvmdbustest: Add test to ensure error collection
Recreates https://bugzilla.redhat.com/show_bug.cgi?id=2145114
2022-11-29 12:56:55 -06:00
a02268e938 man: dmsetup concise format consitency
Use <name> consistenly.
2022-11-25 16:41:53 +01:00
a5042375de dmsetup: fix udev event handling for create
With newer kernels (>5.13)  DM_CREATE no longer generates
uevent for DM devices without table.
There are even no sysfs block device entries in such case,
although device has asigned major:minor and it is being listed
by 'dmsetup info'.

So this patch calculates amount of 'table' lines and in case
no table line comes from cmdline or stdin - waiting on cookie
is avoided generically instead of disabling just case with
option --notable - which then also skipped handling of an
option --addnodeoncreate (which is however historical and
should be avoided)

As a result there should be no leaking udev cookies and endlessly
waiting commands like this:

dmsetup create mytestdev  </dev/null
2022-11-25 16:41:53 +01:00
ae916f77c9 configure: update 2022-11-25 15:55:56 +01:00
fdd8feb60e lvmpolld: fix strerror_r check for musl
We can't assume that strerror_r returns char* just because _GNU_SOURCE is
defined. We already call the appropriate autoconf test, so let's use its
result (STRERROR_R_CHAR_P).

Note that in configure, _GNU_SOURCE is always set, but we add a defined
guard just in case for futureproofing.

Bug: https://bugs.gentoo.org/869404
2022-11-25 15:55:23 +01:00
3dee7b7266 configure: allow for overriding of readelf
This allows users to use e.g. `llvm-readelf`
on systems with binutils as default.

Bug: https://bugs.gentoo.org/840628
2022-11-25 15:54:57 +01:00
2da4ca7ce1 tests: devicesfile-vpd-ids add nvme wwid 2022-11-21 10:57:30 -06:00
e0ea0706dc report: query lvmlockd for lv_active_exclusively
Query LV lock state in lvmlockd to report lv_active_exclusively
for active LVs in a shared VGs.  As with all lvmlockd state,
it is from the perspective of the local node.

Signed-off-by: corubba <corubba@gmx.de>
2022-11-11 13:30:25 -06:00
779fc3c045 report: adjust lv_active_remotely for shared VGs
Add a note to the manpage that lvmlockd is unable to determine
accurately and without side-effects whether a LV is remotely active.
Also change the value of the lv_active_remotely option from false to
undefined for shared VGs to distinctly communicate that inability to
users. Only for local VGs it can be definitely stated that they are not
remotely active.

Signed-off-by: corubba <corubba@gmx.de>
2022-11-11 12:08:59 -06:00
c77384785d post-release 2022-11-10 14:21:57 +01:00
f8127c45c5 pre-release 2022-11-10 14:11:32 +01:00
6b96bf7bc2 make: generate 2022-11-10 13:58:09 +01:00
403779333b vdo: improve validation message
Rephrase.
2022-11-08 12:40:21 +01:00
b9f35e07db lvcreate: fix error path return values
Return failing error code for return path, as 'return 0' in this
case was returning success.
2022-11-08 12:39:25 +01:00
0fed9b0971 tests: update test to handle different status
Since now we change deduplication with V4 table line change,
the modification tends to be faster and we can capture for a few ms
also 'status' about opening or closing deduplication index.
Use 'grep -E' to handle both words.
2022-11-08 11:10:21 +01:00
8e9410594b vdo: enhance detection of virtual size
Improve detection of VDO virtual size - so it's not reading VDO
metadata when VDO device is already active and instead we reuse
existing table line for knowing existing metadata size.

NOTE: if there is ever going to be added support for reduction
of VDO virtual size - this method will need to be reworked to
allow size difference only within 'extent_size' alignment.
2022-11-08 11:10:21 +01:00
218c7d44b5 vdo: replace errors with debug
As we actully use reading of VDO metadata only as extra 'information' source,
and not error command - switch to 'log_debug()' severity with messages
out of parser code.
2022-11-08 11:07:20 +01:00
c98617c593 devices: factor common list functions
which were duplicated in various places
2022-11-07 11:38:46 -06:00
761b922178 device_id: handle duplicate serial numbers
Handle multiple devices using the same serial number as
their device id.  After matching devices to devices file
entries, if there is a discrepency between the ondisk PVID
and the devices file PVID, then rematch devices to
devices file entries using PVID, looking at all disks
on the system with the same serial number.
2022-11-07 08:56:02 -06:00
bdab36cf3f device_id: look for serial number in other locations
Only /sys/dev/block/major:minor/device/serial was read to find
a disk serial number, but a serial number seems to be reported
more often in other locations, so check these also:
/sys/dev/block/major:minor/device/vpd_pg80
/sys/class/block/vda/serial (for virtio disks only)
2022-11-07 08:56:02 -06:00
36a923926c device_mapper: vdo V4 avoid messaging
With V4 format build table line with compression and
deduplication and skip sending any messages to set up
these parameters.
2022-11-02 13:59:34 +01:00
2e79b005c2 dev_manager: accept misalined vdo pools.
Since lvm2 may create VDO pool virtual size aligned only on extent size
while VDO itself is just 4K aligned - we need to support such misalign.
2022-11-02 13:59:34 +01:00
829ab01708 device_mapper: add parser for vdo metadata
Add very simplistic parser of vdo metadata to be able to obtain
logical_blocks stored within vdo metadata - as lvm2 may
submit smaller value due to internal aligment rules.

To avoid creation of mismatching table line - use this number
instead the one provided by lvm2.
2022-11-02 13:59:34 +01:00
17baeb65a9 configure: update use_devicesfile in example.conf
Example.conf missed to properly replace default value for
use_devicesfile setting and left there @VAR@.
2022-11-02 13:59:34 +01:00
81f10c1d1e vgchange systemid: use tag or select
The command can do this but the command defs
were missing the annotation to allow it.
2022-10-31 08:54:33 -05:00
f188c9e403 device_id: remove debug trace
for common case where a device id type is not used.
2022-10-24 16:20:28 -05:00
830ece75e8 cmd: save device_id_sysfs_dir
read and save device_id_sysfs_dir to avoid spamming
debug output from find_config_tree_str.
2022-10-24 16:20:28 -05:00
94dde57699 lvmdbusd: Handle PV signature copy
If something manually copies a PV signature to a block device we will
miss it.  Handle this case too.
2022-10-20 15:10:35 -05:00
736547e7bb lvmdbustest: Add test for copy signature
Add test to ensure we detect when a PV signature is copied to a block
device.
2022-10-20 15:10:35 -05:00
8a1c73ddbe lvmdbusd: Always leverage udev
Previously we utilized udev until we got a dbus notification from lvm
command line tools.  This however misses the case where something outside
of lvm clears the signatures on a block device and we fail to refresh the
state of the daemon.  Change the behavior so we always monitor udev events,
but ignore those udev events that pertain to lvm members.

Note: --udev command line option no longer does anything and simply
outputs a message that it's no longer used.

Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1967171
2022-10-20 15:10:35 -05:00
5a6ae2d4d8 lvmdbustest: Add test for wipefs
Ensure that if an external program or user calles wipefs on a PV that we
correctly update the state of the daemon.
2022-10-20 15:10:35 -05:00
0f56c1ad12 lvmnotify.c: Check to see if dbus daemon is running
The lvm dbus daemon will auto activate on dbus API calls.  To
prevent the dbus daemon starting when lvm command line tools are
being used we will check to see if the daemon is running first.
If the daemon is not running, we will not notify the daemon.

For this check to work it requires the changes done previously
with commit: 3fdf449348

Reviewed-by: David Teigland <teigland@redhat.com>
2022-10-19 14:22:12 -05:00
04097d9f62 lvreduce: change error message about --fs options 2022-10-12 10:05:14 -05:00
4f4554164b lvmlockd: Fix sanlock lvmlock lv size calculation
The number of extents for the sanlock lvmlock lv is calculated using
integer division, which rounds towards zero. With a physical extent size
of 129M, instead of the requested 256M the lv is only 129M (1 extent).
With any physical extent size greater than 256M the lv creation fails
because the number of extents is zero.

This is fixed by replacing the integer division with a division macro
that rounds up and thus guarantees that the size of the lv will always
be equal or greater than the requested size. Using the examples above, a
pes of 129M will result in a 258M lv (2 extents), pes of 300M in a 300M
lv (1 extent).

The re-calculation of the lv size in bytes and megabytes is only so the
debug output shows the correct values. The size in mb there is still
not byte-perfect-accurate, but good enough for a human-readable estimate;
and the exact size in bytes and extents is right next to it.

Signed-off-by: corubba <corubba@gmx.de>
2022-10-12 09:19:01 -05:00
908555459f toollib: do not process just created historical LV
When executing process_each_lv_in_vg, we process live LVs first and
after that, we process any historical LVs. In case we have just removed
an LV, which also means we have just made it "historical" and so it
appears as fresh item in vg->historical_lvs list, we have to skip it
when we get to processing historical LVs inside the same process_each_lv_in_vg
call.

The simplest approach here, without introducing another LV list, is to
simply mark such historical LVs as "fresh" directly in struct
historical_logical_volume when we have just removed the original LV
and created the historical LV for it. Then, we just need to check the
flag when processing historical LVs and skip it if it is "fresh".

When we read historical LVs out of metadata, they are marked as
"not fresh" and so they can be processed as usual.

This was mainly an issue in conjuction with -S|--select use:

	#  lvmconfig --type diff
	metadata {
		record_lvs_history=1
	}

(In this example, a thin pool with lvol1 thin LV and lvol2 and lvol3 snapshots.)

	#  lvs -H vg -o name,pool_lv,full_ancestors,full_descendants
	  LV    Pool FAncestors  FDescendants
	  lvol1 pool             lvol2,lvol3
	  lvol2 pool lvol1       lvol3
	  lvol3 pool lvol2,lvol1
	  pool

	#  lvremove -S 'name=lvol2'
	  Logical volume "lvol2" successfully removed.
	  Historical logical volume "lvol2" successfully removed.

...here, the historical LV lvol2 should not have been removed because
we have just removed its original non-historical lvol2 and the fresh
historical lvol2 must not be included in the same processing spree.
2022-10-12 15:14:59 +02:00
f6f2737015 lvreduce: require active LV when no fs option is used
Without an --fs option set, make lvreduce of an inactive LV
fail and report that the LV must be active.
2022-10-11 12:48:31 -05:00
fc52e87f06 tests: add comments to fsadm-renamed
to explain the what and why of the steps that are
not obvious
2022-10-11 12:48:31 -05:00
657df00c96 lvmlockd: fix warning 2022-10-11 12:35:38 -05:00
fc01dd8900 tests: skip lvresize tests without mkfs.xfs 2022-10-10 13:25:50 -05:00
13c63f0cfa lvmdevices: use deviceidtype option strictly
Only use the device id type specified by --deviceidtype,
and fail if that type is not available for the device.
2022-10-10 11:47:29 -05:00
c4e6d675de tests: device ids using vpd data 2022-10-10 11:47:29 -05:00
79e67fc5e4 device id: add new types using values from vpd_pg83
The new device_id types are: wwid_naa, wwid_eui, wwid_t10.
The new types use the specific wwid type in their name.
lvm currently gets the values for these types by reading
the device's vpd_pg83 sysfs file (this could change in the
future if better methods become available for reading the
values.)

If a device is added to the devices file using one of these
types, prior versions of lvm will not recognize the types
and will be unable to use the devices.

When adding a new device, lvm continues to first use sys_wwid
from the sysfs wwid file.  If the device has no sysfs wwid file,
lvm now attempts to use one of the new types from vpd_pg83.

If a devices file entry with type sys_wwid does not match a
given device's sysfs wwid file, the sys_wwid value will also
be compared to that device's other wwids from its vpd_pg83 file.
If the kernel changes the wwid type reported from the sysfs
wwid file, e.g. from a device's t10 id to its naa id, then lvm
should still be able to match it correctly using the vpd_pg83
data which will include both ids.
2022-10-10 11:47:29 -05:00
8de87e0207 device id: change space handling in t10 wwid
t10 wwids are now edited in the same way that multipath does,
which is replacing a series of spaces with one _.  Previously
lvm replaced every space with one _.  Devices file entries
with the old form will be converted to the new shorter form.
2022-10-10 11:47:29 -05:00
380ab3f45c device id wwid adjustments
Move the functions handling dev wwids.

Add dev flags indicating that wwids have been read from
sysfs wwid file or sysfs vpd_pg83 file.  This can be
used to avoid rereading these.

Improve filter-mpath search for a device's wwid in
/etc/multipath/wwids, to avoid unnecessary rereading
of wwids from sysfs files.

Type 8 wwids from vpd_pg83 with naa or eui names should be
saved as those types.
2022-10-10 11:47:29 -05:00
39e6c4f749 lvmlockd: purge the lock resources left in previous lockspace
If lvmlockd in cluster is killed accidently or any other reason, the
lock resources will become orphaned in the VG lockspace. When the
cluster manager tries to restart this daemon, the LVs will probably
become inactive because of resource schedule policy and thus the lock
resouce will be omited during the adoption process. This patch will
try to purge the lock resources left in previous lockspace, so the
following actions can work again.
2022-10-07 09:45:57 -05:00
a23588d77c lvresize: move the lockd_lv earlier
the lock should cover any potential activation,
not just the resizing changes
2022-10-03 12:42:02 -05:00
599cbd7dd3 lvmdbusd: Correct env. variable
Make this match the unit test expectation and the form we use for
other env. variables.
2022-09-30 11:51:23 -05:00
b09de683c7 blkid: fix BLKID_SUBLKS_FSINFO usage
Use this flag for all fs info lookups, including BLOCK_SIZE,
if it is defined in blkid.h.
2022-09-29 15:25:32 -05:00
5a0052a1d3 lvresize: give special advice to reiserfs users 2022-09-28 11:54:13 -05:00
1924fed308 lvresize: exclude new fs handling at build time
Exclude the new fs resizing capabilities at build time
(rather than run time) if the necessary libblkid features
are not available.  When excluded, all fs resizing options
are translated to resize_fsadm.  Accessing the new
features now requires rebuilding lvm if libblkid is
upgraded.
2022-09-28 11:16:43 -05:00
b39ad99325 lvresize: let env var set lvresize_fs_helper_path 2022-09-27 15:42:18 -05:00
7f1ef25b46 remove unused variables 2022-09-27 15:42:18 -05:00
50281e5710 change messages about libblkid features
remove message about missing libblkid features

change message recommending resize_fsadm when libblkid
features are not available.
2022-09-27 15:13:31 -05:00
3ca44e13be lvreduce: use temporary flag when activating lv to check for fs
This flag is meant to suppress udev processing of the LV.
2022-09-27 12:59:17 -05:00
c1ab9fb37f make: move cmds.h
generate the header in the include dir so it
can be easily used from both lib and tools dirs.
2022-09-27 09:06:06 -05:00
fd05b79aad lvmdbustest: Add test to stress mode changing
Add a test to toggle from fork & exec to lvm shell repeatedly, to stress
test it.
2022-09-22 17:14:10 -05:00
897b326ccc lvmdbustest: Re-work setUp
Place the addCleanup at the end as we don't want to go through clean up
if we don't make it through setUp.  If we don't do this we can remove VGs
that we didn't create in the unit test.
2022-09-22 17:10:13 -05:00
7966f1dd18 lvmdbustest: Refuse to remove a VG we didn't create
One of our previous commits introduced the side effect that we could
inadvertently remove a VG we didn't create, and lose data.
2022-09-22 16:19:16 -05:00
40018cbf53 lvmdbustest: Make vg name suffix more unique 2022-09-22 16:17:20 -05:00
36a8fb20bf lvmdbusd: Correct lvm shell signal & child process handling
Previously when the __del__ method ran on LVMShellProxy we would blindly
call terminate().  This was a race condition as the underlying process
may/maynot be present.  When the process is still present the SIGTERM will
end up being seen by lvmdbusd too.  Re-work the code so that we
first try to wait for the child process to exit and only then if it hasn't
exited will we send it a SIGTERM.  We also ensure that when this is
executed we will briefly ignore a SIGTERM that arrives for the daemon.
2022-09-22 08:33:06 -05:00
c21783d492 covscan: free wwid strings in lvmcache 2022-09-21 12:15:13 -05:00
e97cf8552c make: generate 2022-09-21 14:58:34 +02:00
3a7aeebf7d tests: validate CONFIG_HZ_1000
If we plan to use dm throttling for mirror targets - we actually
have to check whether kernel runs with CONFIG_HZ_1000 - if it does
not the whole idea of throttling is actually not working in the
testsuite as within a single 'tick' with HZ 100 way too much date
is being moved on any modern hardware - and since there is no plan
to change this in kernel - we simply avoid using throttling on such
kernel and test needs to work differently - either ignore results
or use much larger mirror sizes...
2022-09-21 14:58:34 +02:00
96f303eb08 tests: discard update 2022-09-21 14:58:34 +02:00
cbfdb87358 makefiles: use single libs definition 2022-09-21 14:58:34 +02:00
1bf1aca544 tests: integrity switch to ext4
Since we would need to create a lot of 300M filesystem,
switch this test suite to ext4.
2022-09-21 14:58:34 +02:00
9c2ed74221 lvmdbusd: Register for SIGTERM
Ensure we log that we are exiting on this signal too.
2022-09-20 16:37:01 -05:00
d88998f516 lvmdbusd: Correct get_object_path_by_uuid_lvm_id
When checking to see if the PV is missing we incorrectly checked that the
path_create was equal to PV creation.  However, there are cases where we
are doing a lookup where the path_create == None.  In this case, we would
fail to set lvm_id == None which caused a problem as we had more than 1
PV that was missing.  When this occurred, the second lookup matched the
first missing PV that was added to the object manager.  This resulted in
the following:

Traceback (most recent call last):
  File "/usr/lib/python3.9/site-packages/lvmdbusd/utils.py", line 667, in _run
    self.rc = self.f(*self.args)
  File "/usr/lib/python3.9/site-packages/lvmdbusd/fetch.py", line 25, in _main_thread_load
    (changes, remove) = load_pvs(
  File "/usr/lib/python3.9/site-packages/lvmdbusd/pv.py", line 46, in load_pvs
    return common(
  File "/usr/lib/python3.9/site-packages/lvmdbusd/loader.py", line 55, in common
    del existing_paths[dbus_object.dbus_object_path()]

Because we expect to find the object in existing_paths if we found it in
the lookup.

resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2085078
2022-09-20 16:36:53 -05:00
a0fc61177e make: Fix build in chroot
When building in a buildroot, must create libexec directory explicitly.
2022-09-20 15:56:13 +02:00
178564317a spec: Workaround for failing build
Commit 18722dfdf4 introduced a dependency
on file from tools/ into lib/.

TODO: revert this once the issue is resolved.
2022-09-20 15:12:44 +02:00
8686657664 lvmdbusd: Remove --reportformat
Latest upstream build of lvm results in the following error when
trying to use lvmshell.

"Argument --reportformat cannot be used in interactive mode.,
Error during parsing of command line."
2022-09-16 10:49:37 -05:00
3d3c517b0b lvmdbustest: Add wrapper for injecting errors
Useful for forcing lvmdbusd down error paths.
2022-09-16 10:49:37 -05:00
11c033c222 lvmdbusd: Include lvm debug output for lvmshell
Move the option to add the debug file into lvm_full_report_json so that
we collect the debug data when we fork & exec lvm and when we use lvm
shell.
2022-09-16 10:49:37 -05:00
a4b7f988d8 lvmdbusd: Call readlines instead of readline
Better to drain everything we have now that our IO is line orientated
when using a ptty.
2022-09-16 10:49:37 -05:00
8e1e40c499 lvmdbusd: Raise IOError instead of ignoring
We end up in a bad state if we simply eat IOErrors here.  Exit the lvmshell
process and raise the IOError.
2022-09-16 10:49:37 -05:00
2c5762038a lvmdbusd: Correct log_error for shell proxy 2022-09-16 10:49:37 -05:00
d51fb57f1a lvmdbusd: Check for KeyError in refresh
Bubble up a LvmBug if we get a KeyError on a lvm column name.
2022-09-16 10:49:37 -05:00
feaf46863b lvmdbusd: Use common func. for checking missing LV keys 2022-09-16 10:49:37 -05:00
ed9072dad8 lvmdbusd: Correct undefined var 2022-09-16 10:49:37 -05:00
a326e35cda lvmdbustest: Check for self.pvs
If we don't make it through setUp, self.pvs will not exist.
2022-09-16 10:49:37 -05:00
ead80d134d lvmdbustest: Move signals to last
When we do the signal testing we default back to fork & exec.  Put these
on the end to maximize our lvm shell testing until we fix this proper.
2022-09-16 10:49:37 -05:00
9fc24b1d3b lvmdbusd: Handle 'exit' for lvm_shell_proxy
Useful for testing `exit_shell` when running interactively.
2022-09-16 10:49:37 -05:00
b3d13c50d7 lvmdbusd: Use pseudo tty to get "lvm>" prompt again
When lvm is compiled with editline, if the file descriptors don't look like
a tty, then no "lvm> " prompt is done.  Having lvm output the shell prompt
when consuming JSON on a report file descriptor is very useful in
determining if lvm command is complete.
2022-09-16 10:49:37 -05:00
664a06650d lvmdbusd: Remove PID from log messages
Previously the daemon would output PID:TID.  If it's running under systemd
it skips outputting PID as systemd already does this.
2022-09-16 10:49:37 -05:00
b6dc96d8ef lvmdbustest: Utilize addCleanup in unit test
Register the clean up with addCleanup so we ensure clean_up gets run
regardless of what happens in setUp.
2022-09-16 10:49:37 -05:00
e977b70bfb lvmdbusd: Remove duplicate code
The logic for _cache_lv and _writecache_lv was identical except for which
underlying lvm command to run.  Factor out common.
2022-09-16 10:49:37 -05:00
f4c03faa65 lvmdbusd: Raise LvmBug exception for invalid JSON
This will cause lvm debug data to get logged if it's available.
2022-09-16 10:49:37 -05:00
85fcbfd9d7 lvmdbusd: Instruct lvm to output debug to file for fullreport
Historically we have seen a few different errors which occur when we call
fullreport.  Failing exit code and JSON which is missing one or more keys.
Instruct lvm to dump the debug to a file during fullreport calls when we
fork & exec lvm. If we encounter an error, ouput the debug data.
The reason this isn't being done when lvmshell is used is because we
don't have an easy way to test the error paths.

This change is complicated by the following:

1. We don't know if fullreport was good until we evaluate all the JSON.
   This is done a bit after we have called into lvm and returned.
2. We don't want to orphan the debug file used by lvm if the daemon is
   killed. Thus we try to minimize the window where the debug file hasn't
   already been unlinked.  A RFE to pass an open FD to lvm for this
   purpose is outstanding.

The temp. file is:
-rw------. 1 root root /tmp/lvmdbusd.lvm.debug.XXXXXXXX.log
2022-09-16 10:49:37 -05:00
d42bdb07de lvmdbusd: Re-work error handling
Introduce an exception which is used for known existing issues with lvm.
This is used to distinguish between errors between lvm itself and lvmdbusd.
In the case of lvm bugs, when we simply retry the operation we will log
very little.  Otherwise, we will dump a full traceback for investigation
when we do the retry.
2022-09-16 10:49:37 -05:00
cb32b0a87f lvmdbusd: Use common function for traceback
We were using a number of different ways to achieve the same result.  Use
a common function to make this consistent.
2022-09-16 10:49:37 -05:00
22942f4916 lvmdbusd: Don't output debug for fullreport exit code 5
This is expected with an exported vg
2022-09-16 10:49:37 -05:00
f5876a1f3f lvmdbustest: Skip test_nesting if scan_lvs is not enabled 2022-09-16 10:49:37 -05:00
e5c41b94b8 lvmdbusd: refactor and correct fetch thread logic
Simplify the fetch thread and correct the logic used for selecting the
options which are used when we batch update a state refresh.
2022-09-16 10:49:37 -05:00
25abe41b00 lvmdbusd: Re-work error handling for run_cmd
Instead of lumping all the exceptions, break them out to handle the dbus
exceptions separately, to reduce the amount of debug information that ends
up in the journal that has questionable value.
2022-09-16 10:49:37 -05:00
e6e874922e lvmdbusd: Handle SIGINT quietly
Change how we exit on SIGINT so that we don't output needless debug.
2022-09-16 10:49:37 -05:00
0296e56073 lvmdbusd: Don't report recoverable error
Lvm occasionally fails to return all the request JSON keys in the output of
"fullreport".  This happens very rarely.  When it does the daemon was reporting
the resulting informational exception:

MThreadRunner: exception
Traceback (most recent call last):
  File "/usr/lib/python3.9/site-packages/lvmdbusd/utils.py", line 667, in _run
    self.rc = self.f(*self.args)
  File "/usr/lib/python3.9/site-packages/lvmdbusd/fetch.py", line 40, in _main_thread_load
    (lv_changes, remove) = load_lvs(
  File "/usr/lib/python3.9/site-packages/lvmdbusd/lv.py", line 143, in load_lvs
    return common(
  File "/usr/lib/python3.9/site-packages/lvmdbusd/loader.py", line 37, in common
    objects = retrieve(search_keys, cache_refresh=False)
  File "/usr/lib/python3.9/site-packages/lvmdbusd/lv.py", line 95, in lvs_state_retrieve
    l['vdo_operating_mode'],
KeyError: 'vdo_operating_mode'

The daemon retries the operation, which usually works and the daemon continues.
However, simply reporting this informational stack trace is causing CI and other
automated tests to fail as they expect no tracebacks in the log output.

Remove the reporting of this code path unless it persists and causes the daemon
to give up and exit.

Ref: https://bugzilla.redhat.com/show_bug.cgi?id=2120267
2022-09-16 10:49:37 -05:00
2918994873 lvmdbusd: WS, imports, grammar 2022-09-16 10:49:37 -05:00
b0c7220dbb lvmdbusd: Add debug circular buffer
When the daemon isn't started with --debug we will keep a circular
buffer of the past N number of debug messages which we will output
when we encounter an issue.
2022-09-16 10:49:37 -05:00
f65f7da760 lvmdbustest: Skip test_singleton_daemon running systemd svc. 2022-09-16 10:49:37 -05:00
a5e6947d74 lvmdbusd: Set LVM_COMMAND_PROFILE=lvmdbusd
We need this to prevent lvm from interleaving the JSON output with errors
written to stderr.
2022-09-16 10:49:37 -05:00
9693709b46 lvmdbustest: Add systemctl daemon start 2022-09-16 10:49:37 -05:00
f252e05aae lvmdbustest: Add test for ensuring only 1 instance of daemon 2022-09-16 10:49:37 -05:00
d16c0a3e2b lvmdbustest: Add test_sigint test
Get the daemon busy and send it SIGINT to ensure the daemon exits.
2022-09-16 10:49:37 -05:00
52415b5708 lvmdbustest: Add optional option to _create_num_lvs
This allows us to create the LVs async., thus queuing them up in daemon.
2022-09-16 10:49:37 -05:00
d05d2328e0 lvmdbustest: Factor out tearDown implementation for re-use 2022-09-16 10:49:37 -05:00
de0258a600 lvmdbustest: Add DaemonInfo class
This class handles identifying daemon, sending signals to it, and starting
it back up again.
2022-09-16 10:49:37 -05:00
ec50979b03 lvmdbusd: Correct typos 2022-09-16 10:49:37 -05:00
3d8882db83 lvmdbusd: fix hangs on SIGINT
Rather than trying to bubble up return codes that get us to exit cleanly
it's better to just raise an exception to bail.  In some cases functions
don't have return codes, so they cannot be checked.
2022-09-16 10:49:37 -05:00
f4cb78a4e1 lvmdbustest: Add test removing incomplete job
When you try to remove a job that is incomplete you get a dbus exception.
Test for this error condition.
2022-09-16 10:49:37 -05:00
2ca4a2dbf3 lvmdbustest: Add test for external event
Ensure that when we trigger an external event that we don't incorrectly
handle multiple --config options.
2022-09-16 10:49:37 -05:00
4a202c11ff lvmdbustest: Add test for passing log file in options 2022-09-16 10:49:37 -05:00
60e4ba36e0 lvmdbusd: Remove unused locking functionality
I don't think we have ever utilized this, remove.
2022-09-16 10:49:37 -05:00
cfc87157a4 lvmdbusd: Make sure to set cfg.got_external_event
We were incorrectly only setting this if --udev wasn't present on the
command line.  In all cases when we see a manager.ExternalEvent we want
to set this.
2022-09-16 10:49:37 -05:00
068073e924 lvmdbusd: Correct typos 2022-09-16 10:49:36 -05:00
abf22df46c lvmdbusd: Handle no lastlog
Depending on when an occurs, it maynot have any information available for
lastlog.  In this case try to grab an error message from the original
response.
2022-09-16 10:49:36 -05:00
cef3c75dd4 lvmdbustest: nesting improvements 2022-09-16 10:49:36 -05:00
6b9cc7432e lvmdbusd: Remove exclusionary language 2022-09-16 10:49:36 -05:00
c13efb2ffc lvmdbusd: Remove unneeded command line args 2022-09-16 10:49:36 -05:00
b3d8366ff2 lvmdbusd: Add SIGUSR2 to dump flight recorder 2022-09-16 10:49:36 -05:00
05f7fa5a85 lvmdbusd: Re-work flight recorder data
Introduce a new lock for the flight recorder, so that we can dump it when
a command is block waiting for lvm to complete.  Also in all paths we will
addthe metadata to the flight recorder before it's done, so we will have
it when a command hangs and we dump the flight recorder. Add the missing
bits after the command has finished.

Cleaned up the output too.
2022-09-16 10:49:36 -05:00
ea45ba753e lvmdbustest: Remove force exception in _wait_for_job
We put this in to test one of the paths in the damon, but unfortunately
if we hit the race condition where the job actually is done we will try
to call j.Wait(1) after the remove.  This fails with:

dbus.exceptions.DBusException: org.freedesktop.DBus.Error.UnknownMethod:
Method "Wait" with signature "i" on interface "com.redhat.lvmdbus1.Job"
doesn't exist

Which is caused by the dbus object no longer existing.  We could handle
this, but the issue is we no longer have the ability to get the result to
return, they have been lost.

A better solution would be to write a specific unit test to force this code
path and handle all the possible outcomes.
2022-09-16 10:49:36 -05:00
3fdf449348 lvmdbusd: Add lockfile
The daemon cannot handle multiple copies of itself running at the
same time, ensure this cannot happen.
2022-09-16 10:49:36 -05:00
1a4384979c lvmdbusd: Move arg. setup/checking to function 2022-09-16 10:49:36 -05:00
3eb19c4b7a lvmdbusd: Remove addl. checks on --nojson
We check earlier that if you specify --nojson we will exit.
2022-09-16 10:49:36 -05:00
4b4d431631 lvmdbustest: Include major number 259
When you have > 16 partitions for a block device the major number
changes, include them for testing.
2022-09-16 10:49:36 -05:00
9ffa1ef884 lvmdbustest: Use updated pyudev syntax
Previous syntax has been deprecated.
2022-09-16 10:49:36 -05:00
0887896847 vgremove: remove online files in run dir
These files are automatically cleared on reboot given
that /run is tmpfs, and that remains the primary way
of clearing online files.

But, if there's extreme use of vgcreate+pvscan+vgremove
between reboots, then removing online files in vgremove
will limit the number of unused online files using space
in /run.
2022-09-14 14:19:29 -05:00
a2d33cdfc5 configure: update 2022-09-14 15:16:30 +02:00
bf386411b8 tests: skip new lvresize tests when missing new libblkid 2022-09-13 15:37:10 -05:00
264827cb98 lvresize: add new options and defaults for fs handling
The new option "--fs String" for lvresize/lvreduce/lvextend
controls the handling of file systems before/after resizing
the LV.  --resizefs is the same as --fs resize.

The new option "--fsmode String" can be used to control
mounting and unmounting of the fs during resizing.

Possible --fs values:

checksize
  Only applies to reducing size; does nothing for extend.
  Check the fs size and reduce the LV if the fs is not using
  the affected space, i.e. the fs does not need to be shrunk.
  Fail the command without reducing the fs or LV if the fs is
  using the affected space.

resize
  Resize the fs using the fs-specific resize command.
  This may include mounting, unmounting, or running fsck.
  See --fsmode to control mounting behavior, and --nofsck to
  disable fsck.

resize_fsadm
  Use the old method of calling fsadm to handle the fs
  (deprecated.) Warning: this option does not prevent lvreduce
  from destroying file systems that are unmounted (or mounted
  if prompts are skipped.)

ignore
  Resize the LV without checking for or handling a file system.
  Warning: using ignore when reducing the LV size may destroy the
  file system.

Possible --fsmode values:

manage
  Mount or unmount the fs as needed to resize the fs,
  and attempt to restore the original mount state at the end.

nochange
  Do not mount or unmount the fs. If mounting or unmounting
  is required to resize the fs, then do not resize the fs or
  the LV and fail the command.

offline
  Unmount the fs if it is mounted, and resize the fs while it
  is unmounted. If mounting is required to resize the fs,
  then do not resize the fs or the LV and fail the command.

Notes on lvreduce:

When no --fs or --resizefs option is specified:
. lvextend default behavior is fs ignore.
. lvreduce default behavior is fs checksize
  (includes activating the LV.)

With the exception of --fs resize_fsadm|ignore, lvreduce requires
the recent libblkid fields FSLASTBLOCK and FSBLOCKSIZE.
FSLASTBLOCK*FSBLOCKSIZE is the last byte used by the fs on the LV,
which determines if reducing the fs is necessary.
2022-09-13 15:15:05 -05:00
18722dfdf4 lvresize: restructure code
Rewrite top level resize function to prepare for adding
new fs resizing.
2022-09-09 16:18:55 -05:00
55e9494e5f remove libblkid flag BLKID_SUBLKS_FSINFO
This flag is not needed in fs_block_size_and_type()
added in the previous commit.
2022-09-09 16:14:27 -05:00
b869a6ff7a fix fs block size detection
blkid_get_tag_value() is not a reliable way to query the fs
BLOCK_SIZE, so use the "probe" functions instead.
2022-09-09 15:50:00 -05:00
6b05d6bd83 gitignore: update 2022-09-07 15:00:15 +02:00
19db3b3e45 tests: cache use 300M XFS 2022-09-07 15:00:15 +02:00
e295610d42 tests: fsadm 300m xfs 2022-09-07 15:00:15 +02:00
570dbad527 tests: writecache adapt to 300M XFS 2022-09-07 15:00:15 +02:00
6990cbc166 tests: use conv=fdatasync
When we only need wait for result - avoid using slow 'oflag=sync'
with virtual layers
2022-09-07 15:00:15 +02:00
9f39977344 tests: add /dev requirement
This test could only be run when user passes  LVM_TEST_DEVDIR=/dev
as it requires and expects actions to be going in this dir, skip
otherwise.

Also 'extend_filter' manages multiple args in on lvm.conf update.
2022-09-07 15:00:15 +02:00
0ed3f7a1bf tests: add thin requirement 2022-09-07 15:00:15 +02:00
1a3e773f37 tests: lvextend update for 300M XFS 2022-09-07 15:00:15 +02:00
afcf954491 tests: no caching for blkid in testing 2022-09-07 15:00:15 +02:00
80b782f86f tests: make damage optional
Investigate how to damage thin-pool across different versions/platforms.
Until them - use  'should' for test result.
2022-09-07 15:00:15 +02:00
e1e05cf2b5 tests: check for at least 1G of RAM
This test requires quite some RAM to be there.
2022-09-07 15:00:15 +02:00
a6e47a1612 tests: remove slash 2022-09-07 15:00:15 +02:00
8a92a526a0 tests: skip this test for 5.19
mdraid has some breakage - so 5.19 is crashing
(possibly even some more older version - that can be added as well)
Test seems to pass with 6.0-rc kernel.
2022-09-07 15:00:15 +02:00
15ad2b8e55 tests: vdo emulation without vdo binary
Avoid inserting 'vdo' binary into path - and use
alias and VDO_BINARY shell vars for emulation.
2022-09-07 14:58:01 +02:00
acbeaa7a8d tests: rework makefile
Improve dependency tracking
Use 'foreach()' with better tracing support
Link whole 'shell' dir instead of linking individual *.sh files
2022-09-07 14:58:01 +02:00
2c7b913049 make: update make.tmpl
Add new define 'newline' for use in 'foreach()'
Add new $(SHOW) for makefile printing output
Add 'make print-VAR' for easier debugging of Makefiles' variables.
2022-09-07 14:58:01 +02:00
85b436642b python: variable without destdir
PYTHON_PREFIX without $(DESTDIR)
2022-09-07 14:58:01 +02:00
e757965222 gcc: eliminate warnings
Gcc starts to show new warning - although unlikely to be able to hit
initialize variables to 0.
2022-09-07 14:58:01 +02:00
973d0bd5b7 report: fix lv_active column type from STR to BIN
Fix lv_active to be of BIN type instead of STR. This allows lv_active to
follow the report/binary_values_as_numeric setting as well as --binary
cmd line switch. Also, it makes it possible to use -S|--select with
either textual or numeric representation of the value, like 'lvs -S
active=active' but also 'lvs -S active=1'.
2022-09-06 15:49:27 +02:00
0eebd9d780 vgimportdevices: fix locking when creating devices file
Take the devices file lock before creating a new devices file.
(Was missed by the change to preemptively create the devices
file prior to setup_devices(), which was done to improve the
error path.)
2022-08-30 14:52:00 -05:00
3c49a2e43c vgimportdevices: change result when devices are not added
When using --all, if one VG is skipped, continue adding
other VGs, and do not return an error from the command
if some VGs are added. (A VG is skipped if it's missing PVs.)

If the command fails during devices file setup or device
scanning, then remove the devices file if it has been
newly created by the command, and exit with an error.

If devices from a named VG are not imported (e.g. the
VG is missing devices), then remove the devices file if
it has been newly created by the command, and exit with
an error.

If --all VGs are being imported, and no devices are found
to include in the devices file, then remove the devices
file if it has been newly created by the command, and
exit with an error.
2022-08-30 14:52:00 -05:00
b553bf6fa8 mm: use mallinfo2 when available
Switch to mallinfo2() from a deprecated mallinfo() glibc call
since struct size members where to small for 64b CPUs.
2022-08-30 13:56:16 +02:00
8370d117d7 mm: preallocate memory only with glibc
Use mallinfo() only with glibc.
2022-08-30 13:55:52 +02:00
5aa8683e86 configure: remove some obsolete or duplicate checks
As autoupdate suggested, drop unneeded checks.
2022-08-30 13:54:19 +02:00
bda93ed4bc configure: check for mallinfo2 2022-08-30 13:54:19 +02:00
60ca2ce20f thin: rename internal function
Names matching internal code layout.
Functionc in thin_manip.c uses thin_pool in its name.
Keep 'pool' only for function working for both cache and thin pools.

No change of functionality.
2022-08-30 13:54:19 +02:00
8d70cfe600 report: values: add note about self-decriptive values to report 2022-08-26 15:08:33 +02:00
e6b6a09f90 args: add ARG_NONINTERACTIVE for cmds not supported in lvm shell
Certain args can't be used in lvm shell ("interactive mode") because
they are not supported there. Add ARG_NONINTERACTIVE flag to mark
such args and error out if we're in interactive mode and at the same
time we detect use of such argument.

Currently, this is the case for --reportformat arg - we don't support
changing the format per command in lvm shell. The whole shell is running
under a reportformat chosen at shell's start.
2022-08-26 12:17:50 +02:00
800436d2af libdm: report: fix escaping of JSON quote char in reported fields
Commit 73ec3c954b added a way to print
only a part of the report string (repstr) to support decoding individual
string list items out of repstr.

The repstr is normally printed through _safe_repstr_output so that any
JSON_QUOTE character ('"') found within the repstr is escaped to not
interfere with value quoting in JSON format.

However, the commit 73ec3c954b missed
checking the 'len' argument passed to _safe_repstr_output function when
adding the rest of the repstr after all previous JSON_QUOTE characters
were escaped (when calling the last dm_pool_grow_object). When 'len'
is 0, we need to calculate the 'len' ourselves in the function by
simply calling strlen. This is because 'len' is passed to the function
only if we're taking a part of repstr, not as a whole.
2022-08-24 12:10:10 +02:00
508782a913 shell: add pre-cmd log report object type and enable lastlog for it
If we failed or logged anything before we actually execute given command
in lvm shell, we couldn't report the log using lastlog command after.
This patch adds specific 'pre-cmd' log report object type to identify
such log messages and enables lastlog to report even this log.
2022-08-22 14:06:34 +02:00
8c3cfc75c7 devices file: fix pvcreate --uuid matching pvid entry with no device id
pvcreate with --uuid would segfault if a devices file entry matched
the specified pvid, but the devices file entry had no device_id, which
could happen if the entry has a devname idtype.
2022-08-19 13:34:36 -05:00
1a981e9b6e devices: drop double // from sysfs path
dm_sysfs_dir() comes internally as  /sys/.
2022-08-19 14:56:57 +02:00
718e38d5fa dmsetup: check also for ouf of range value
Check errno result from strtoull().
2022-08-19 14:56:57 +02:00
a3eb6ba425 mm: remove libaio from being skipped
Since libaio is now used also in critical section,
keep the libaio locked in memory.
2022-08-19 14:56:57 +02:00
e26c21cb8d vdo: extend volume and pool without flush
When the volume size is extended, there is no need to flush
IO operations (nothing can be targeting new space yet).
VDO target is supported as target that can safely work with
this condition.

Such support is also needed, when extending VDOPOOL size
while the pool is reaching its capacity - since this allows
to continue working without reaching 'out-of-space' condition
due to flushing of all in flight IO.
2022-08-19 14:56:55 +02:00
309df239e3 vdo: reset errno before strtoull
Missed errno reset in commit ebad057579.
2022-08-19 14:55:47 +02:00
ac2c78544f config: check for possible mempool errors in _out_line_fn 2022-08-17 12:52:02 +02:00
8a23683a59 config: remove unnecessary copy of config line's space prefix before printing
When we wanted to insert '#' before a config line (to comment it out),
we used dm_pool_strndup to temporarily copy the space prefix first so
we can assemble the final line with:

   "<space_prefix># <key>=<value>":

out of original:

  "<space_prefix><key>=<value>".

The space_prefix copy is not necessary, we can just use fprintf's
precision modifier "%.*s" to print the exact part if we alrady
know space_prefix length.
2022-08-17 10:47:43 +02:00
b4cc28c2ef lvmconfig: add --valuesonly option
The new --valuesonly option causes the lvmconfig output to contain only
values without keys for each config node. This is practical mainly in
case where we use lvmconfig in scripts and we want to assign the value
to a different custom key or simply output the value itself without the
key.

For example:

  # lvmconfig --type full activation/raid_fault_policy
  raid_fault_policy="warn"

  # lvmconfig --type full activation/raid_fault_policy --valuesonly
  "warn"

  # my_var=$(lvmconfig --type full activation/raid_fault_policy --valuesonly)

  # echo $my_var
  "warn"
2022-08-17 10:47:24 +02:00
81839cc4eb report: report numeric values (not string synonyms) for NUM and BIN fields with json_std format
Internally, NUM and BIN fields are marked as DM_REPORT_FIELD_TYPE_NUM_NUMBER
through libdevmapper API. The new 'json_std' format mandates that the report
string representing such a value must be a number, not an arbitrary string.
This is because numeric values in 'json_std' format do not have double quotes
around them. This practically means, we can't use string synonyms
("named reserved values") for such values and the report string must always
represent a proper number.

With 'json' and 'basic' formats, this is not an issue because 'basic' format
doesn't have any structure or typing at all and 'json' format puts all values
in quotes, including numeric ones.
2022-08-16 13:42:50 +02:00
ce58e9d5b3 _vg_read_raw_area: fix segfault caused by using null pointer
When we tested lvm2, the kernel injected various random faults.

(gdb) bt
...
(gdb) p vg
$1 = (struct volume_group *) 0x0
(gdb) p use_previous_vg
$2 = (unsigned int *) 0x0

Signed-off-by: Wu Guanghao <wuguanghao3@huawei.com>
2022-08-15 09:39:02 -05:00
6b2e4ec5dc autoreconf: support newer archs
Update to more recent version of configure script to support more
new architecture types like RISCV64. Tools in use ATM:

autoconf-2.71-3.fc37.noarch
autoconf-archive-2022.02.11-3.fc37.noarch
automake-1.16.5-9.fc37.noarch

Resolves https://bugzilla.redhat.com/show_bug.cgi?id=2118243
2022-08-15 13:32:55 +02:00
bba96e8680 vdo: fix --vdosettings parser
Parser was incorrectly parsing vdo_use_features - move the skip
of 'use_' prefix into internal loop which handles skipping of '_'.
2022-08-15 13:32:55 +02:00
fc5bc5985d vdo: use only verbose log level for reformating
When lvcreate is makeing VDO pool and user has not specified -V size,
ATM we actually run  'vdoformat' twice to get properly 'extent' aligned
size matching lvm2 properties - so the 2nd. run of vdoformat actually
can stay with 'log_verbose()' so the standard printed result
is not showing confusing info (which is now also correctly using
print_unless_silent)
2022-08-15 13:32:55 +02:00
d0697be500 lvconvert: correct test support for vdo-pool 2022-08-15 13:32:55 +02:00
12ffa753f6 WHATS_NEW: update 2022-08-11 13:03:29 +02:00
af2b51d25f test: add report-format test 2022-08-11 11:10:11 +02:00
fc8fda6417 report: fix pe_start column type from NUM to SIZ
The 'pe_start' column was incorrectly marked as being of type NUM.
This was not correct as pe_start is actually of type SIZ, which means
it can have a size suffix and hence it's not a pure numeric value.

Proper column type is important for selection to work correctly, so we
can also do comparisons while using suffixes.

This is also important for new "json_std" output format which does not
put double quotes around pure numeric values. With pe_start incorrectly
marked as NUM instead of SIZ, this produced invalid JSON output
like '"pe_start" = 1.00m' because it contained the 'm' (or other)
size suffix. If properly marked as SIZ, this is then put in double
quotes like '"pe_start" = "1.00m"'.
2022-08-11 11:10:11 +02:00
b318c9c20f make: generate 2022-08-11 11:10:11 +02:00
efd083f668 man: update lvmreport man page about json_std format 2022-08-11 11:10:11 +02:00
aa7cec61ed args: recognize 'json_std' for --reportformat cmd line arg 2022-08-11 11:10:11 +02:00
6cba28a335 config: recognize 'json_std' for report/output_format config setting 2022-08-11 11:10:11 +02:00
73ec3c954b libdm: report: use proper JSON array for string list output in JSON_STD format
In JSON format, we print string list this way:

  "key" = "item1,item2,...,itemN"

while in JSON_STD format, we print string list this way:

  "key" = ["item1","item2",...,"itemN"]
2022-08-11 11:10:11 +02:00
fbee18f6e5 libdm: report: separate basic and JSON+JSON_STD format in _output_field
Use separate functions to handle basic and JSON+JSON_STD format.
It's clearer this way than interleaving both in the same function.
2022-08-11 11:10:11 +02:00
31cd8346ae libdm: report: enhance the way string list is stored internally
Before, we stored only the report string itself for a string list
in field->report_string. The field->report_string has either
sorted items or not, depending on what we need for a field -
some report fields have sorted output, some don't...

The field->sort_value.value then contains pointer to the exact
field->report_string. The field->sort_value.items ALWAYS keeps
sorted array of individual items, represented as '[position,length]'
pairs pointing to the field->sort_value.value string.

This approach was fine as far as we didn't need to apply further
formatting to field->report_string. However, if we need to apply
further formatting to field->report_string content, taking into
account individual items, we also need to know where each item
starts and what is its length. Before, we only knew this when
items in report string were sorted, but not in the unsorted version.

We can't rely on the delimiter (default ",") only to separate items
back out of report string, because that delimiter can be contained
in the item value itself.

So this patch enhances the field->report_string for a string list so
it also contains '[position,length]' pairs for each individual item
inside field->report_string. We store this array right beyond the
string itself and we encode it in the same manner we already did for
field->sort_value.items before.

If field->report_string has sorted items, the field->sort_value.items
just points to the array of items we store beyond the report string.
If field->report_string has unsorted items, we store separate array
of items for both field->report_string and field->sort_value.

This patch also cleans up the _report_field_string_list function a bit
so it's easier and more straightforward to follow than the original
version.

Example. If we have "abc", "xy", "defgh" as list on input with ","
as delimiter, then:

  - field->report_string will have:

    - if we need field->report_string unsorted:

        abc,xy,defgh\0{[3,12],[0,3],[4,2],[7,5]}
        |____________||________________________|
           string      array of [pos,len] pairs
                       |____||________________|
                       #items      items

    - if we need field->report_string sorted:

                 repstr_extra
                      |
                      V
        abc,defgh,xy\0{[3,12],[0,3],[4,5],[10,2]}
        |____________||________________________|
           string      array of [pos,len] pairs
                       |____||________________|
                       #items      items

  - field->sort_value will have:

    - if field->report_string is unsorted:

        field->sort_value.value = field->report_string
        field->sort_value.items = {[0,3],[0,3],[7,5],[4,2]}
                                    (that is 'abc,defgh,xy')

    - if field->report_string is sorted already:

        field->sort_value.value = field->report_string
        field->sort_value.items = repstr_extra
                                  (that is also 'abc,defgh,xy')
2022-08-11 11:10:11 +02:00
1e31621ceb libdm: report: use 'null' for undefined numeric values in JSON_STD output
For JSON_STD format, use 'null' if a field has no value at all.

In JSON format, we print undefined numeric values this way:

  "key" = ""

while in JSON_STD format, we print undefined numeric values this way:

  "key" = null

(Keep in mind that 'null' is different from 0 (zero value) which is
a defined value.)
2022-08-11 11:10:11 +02:00
99299eb728 libdm: report: remove double quotes around numeric values in JSON_STD output
In JSON format, we print numeric values this way:

  "key" = "N"

while in JSON_STD format, we print numeric value this way:

  "key" = N

(Where N is a numeric value.)
2022-08-11 11:10:11 +02:00
02f015990b libdm: report: add DM_REPORT_GROUP_JSON_STD group
The original JSON formatting will be still available using the original
DM_REPORT_GROUP_JSON identifier. Subsequent patches will add enhancements
to JSON formatting code so that it adheres more to JSON standard - this
will be identified by new DM_REPORT_GROUP_JSON_STD identifier.
2022-08-11 11:10:11 +02:00
2fc52b6c41 config: add correct unconfigured value for use_devicesfile 2022-08-09 16:17:45 +02:00
4e6ed2c458 spec: use --with-default-use-devices-file=1 for rhel9+ 2022-08-09 16:17:43 +02:00
31f9c4bfab configure: fix typo 2022-08-09 16:17:40 +02:00
9cdd258646 spec: Use libedit for newer distributions 2022-08-09 16:17:36 +02:00
2fa9916493 shell: also output error message about max number of args hit with JSON format
If using JSON format for lvm shell's output, the error message about
exceeding the maximum number of arguments was not reported on output if
this condition was ever hit.

This is because the JSON format (as well as any other future format)
requires extra formatting compared to "basic" format and so it also
requires extra calls when it comes to reporting. The report needs to
be added to a report group and then popped and put on output with
specialized "dm_report_group_output_and_pop_all".

This "output and pop" is normally executed after we execute the command
in the lvm shell. When we didn't get to the command exection at all because
some precondition was not met (like hitting the limit for the number of
arguments for the command here), we skipped this important call and
so there was no log report output.

Right now, it's only this exact error message for which we need to call
"output and pop" directly, all the other error messages are about
initializing and setting the log report itself which we can't report
obviously.

Before this patch:

  lvm> pvs 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
  lvm>

With this patch applied:

  lvm> pvs 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
  {
      "log": [
          {"log_seq_num":"1", "log_type":"error", "log_context":"shell", "log_object_type":"cmd", "log_object_name":"", "log_object_id":"", "log_object_group":"", "log_object_group_id":"", "log_message":"Too many arguments, sorry.", "log_errno":"-1", "log_ret_code":"0"}
      ]
  }

If there's any other error message in the future before we execute the
command itself, we also need to call the "output and pop" directly.
2022-08-08 15:46:52 +02:00
99ce09ae77 apply multipath_component_detection=0 to duplicate PV handling
multipath_component_detection=0 has always applied to the filter-based
component detection.  Also apply this setting to the duplicate-PV
handling which also eliminates multipath components (based on duplicate
PVs having the same wwid.)
2022-07-25 13:50:43 -05:00
c0f8e6675c make: generate 2022-07-11 01:18:24 +02:00
4d2f9a4ff3 cov: restore disable_dm_devs also for error path
Keep the structure correct for failing error path,
alhtough likely this particual var will not be used.
2022-07-11 01:18:24 +02:00
5c463584f6 cov: remove unused headers 2022-07-11 01:18:24 +02:00
493acb9195 vdo: suffle code for better error path handling
For failing dm_ no need to report 2nd. error,
but we missed to report error with 'updated==NULL'.
2022-07-11 01:18:24 +02:00
e2e31d9acf vdo: enhance lvcreate validation
When creating VDO pool based of  % values, lvm2 is now more clever
and avoids to create 'unsupportable' sizes of physical backend
volumes as 16TiB is maximum size supported by VDO target
(and also limited by maximum supportable slabs (8192) based on slab
size.

If the requested virtual size is approaching max supported size 4PiB,
switch header size to 0.
2022-07-11 01:18:24 +02:00
1c18ed3b4a vdo: support v4 kernel target line
Check and use new available table line v4, if kernel supports it.
2022-07-11 01:18:24 +02:00
a477490e81 vdo: add reformating to extent size aligned virtual size
Newer VDO kernel target require to have matching virtual size - this
however cause incompatiblity when lvcreate is let to format VDO data
device and read the usable size from vdoformat.
Altough this is a kernel regression and will likely get fixed,
lvm2 can actually reformat VDO device to use properly aligned VDO LV
size to make this problem disappear.
2022-07-11 01:18:24 +02:00
ebad057579 vdo: check vdo memory constrains
Add function to check for avaialble memory for particular VDO
configuration - to avoid unnecessary machine swapping for configs
that will not fit into memory (possibly in locked section).

Formula tries to estimate RAM size machine can use also with
swapping for kernel target - but still leaving some amount of
usable RAM.

Estimation is based on documented RAM usage of VDO target.

If the /proc/meminfo would be theoretically unavailable, try to use
'sysinfo()' function, however this is giving only free RAM without
the knowledge about how much RAM could be eventually swapped.

TODO: move _get_memory_info() into generic lvm2 API function used
by other targets with non-trivial memory requirements.
2022-07-11 01:18:24 +02:00
9f3eff002c vdo: report supported range in error path 2022-07-11 01:18:24 +02:00
b5c8e591ed vdo: use defines also for configuration defines
Keep single source for most of values printed in lvm.conf
(still needs some conversion)

Correct max for logical threads to 60
(we may refuse some older configuration which might eventually
user higher numbers - but so far let's assume no user have ever set this
as it's been non-trivial and if would complicate code unnecessarily.)

Accept maximum of 4PiB for virtual size of VDO LV
(lvm2 will drop 'header borders to 0 for this case').
2022-07-11 01:18:24 +02:00
f445624c33 vdo: update info about memory
Add more info about kernel target memory allocation associated with
VDO pool usage.
2022-07-11 01:18:24 +02:00
8ca2b1bc21 vdo: use single validator
Add era lenght validation into dm_vdo_validate_target_params()
and reuse this validator also for _check_lv_segment().
2022-07-11 01:18:24 +02:00
fe6fb1ec52 man: space after size
Put space between size and SI unit.
Automatically make this 'space' as fixed size by Makefile sed script.
2022-07-11 01:18:24 +02:00
d2667bc25b vdo: fix conversion of vdo_slab_size_mb 2nd
Patch 1b070f366b should have
been already fixing this issue but since it the incorrect
patch rebasing the change to vdo_slabSize got lost.
So again now with explicit one-line patch.
2022-07-11 01:18:24 +02:00
92b4fcf57f exit with error when --devicesfile name doesn't exist 2022-07-06 10:10:58 -05:00
d0f94e763d lvmdbustest: Add test for property "Get"
We typically use "GetAll", so add test for "Get" and check values.
2022-06-30 10:55:16 -05:00
01ef2f2525 lvmdbusd: Remove try/except for mkfifo
We should never run into this error condition when using tempfile.mkdtemp.
2022-06-30 10:55:16 -05:00
0d957dcacc lvmdusd: Remove non lvm JSON output support 2022-06-30 10:55:16 -05:00
73121e3f07 lvmdbustest: Increase number of LVs
As storage is getting faster, we need to create more LVs to pass this test.
2022-06-30 10:55:16 -05:00
8fa8dfdb8c lvmdbustest: Correct comment spelling/grammar 2022-06-30 10:55:16 -05:00
55059e002a lvmdbustest: Test job remove path when job not complete 2022-06-30 10:55:16 -05:00
d393436727 lvmdbusd: Correct grammar in lvm shell proxy comments 2022-06-30 10:55:16 -05:00
6914942685 lvmdbusd: Don't require "lvm> " prompt for shell
Depending on how lvm is compiled, it may not present the "lvm> " prompt
when using the lvm shell.  Don't require it to be present.

Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=2090391
2022-06-30 10:55:16 -05:00
eee89a941e lvmdbusd: Job prop. Get/GetAll exec. immediately
This allows API user the ability to check on the status of a long running
job without blocking in the request queue.
2022-06-30 10:55:16 -05:00
7a2090655d lvmdbusd: Remove the use of sub shell for lvm shell
This reduces the number of processes and improves security.
2022-06-30 10:55:16 -05:00
b3d7aff6a3 lvmdbusd: Fix env variable LVM_DBUSD_TEST_MODE
Make it more logical.
2022-06-30 10:55:16 -05:00
47c61907b4 lvmdbusd: Change unit test vdo minimum size 2022-06-30 10:55:16 -05:00
51d9b686c0 lvmdbusd: Add debug output for which lvm binary is used 2022-06-30 10:55:16 -05:00
b3407b16c1 lvmdbusd: re-work lvm shell main
Add an optional single argument "bisect" to use with git bisect for
automation.  Normal case is no arguments when running stand-alone.
2022-06-30 10:55:16 -05:00
58c6c9e9aa lvmdbusd: Simplify child process env
We don't need to duplicate the entire env from the parent, supply only what
is needed.
2022-06-30 10:55:16 -05:00
37733cd4eb lvmdbusd: Correct conditional for lvm child process running
Poll returns None when process is running, else exit value.  If poll returns
0 we will fail to exit the select loop.
2022-06-30 10:55:16 -05:00
db5277c971 pvdisplay: restore --reportformat option
Fixes commit b8f4ec846 "display: ignore --reportformat"
by restoring the --reportformat option to pvdisplay.
Adding -C to pvdisplay turns the command into a reporting
command (like pvs, vgs, lvs) in which --reportformat can
be useful.
2022-06-24 10:40:54 -05:00
3b0f9cec7e filter-mpath: get wwids from sysfs vpd_pg83
to compare with wwids in /etc/multipath/wwids when
excluding multipath components.  The wwid printed
from the sysfs wwid file may not be the wwid used
in multipath wwids.  Save the wwids found for each
device on dev->wwids to avoid repeating reading
and parsing the sysfs files.
2022-06-08 15:06:01 -05:00
2bea95764e tests: skip running tests for non root user
Testing needs 'root' privileges.
Only 'make run-unit-test' can work without them.
2022-06-07 17:14:09 +02:00
4a49851207 tests: update for wrapper
Update calling vdo manager since our vdo wrapper has a simple shell
arg parser so it needs args without '='

Also correct using  DM_DEV_DIR for 'pvcreate'
2022-06-07 17:14:09 +02:00
2ecfd503ed tests: add lvm_vdo_wrapper
Introduce a replacement vdo manager wrapper for testing.
When using test suite on a system without vdo manager (which has got
deprecated) - we still need its functionality to prepare 'vdo volume'
for testing lvm_import_vdo.

Wrapper currently need 2 binaries from older 'vdo 6.2' package -
to be named:
oldvdoformat - format VDO metadata with older format
oldvdoprepareforlvm - shift vdo metadata by 1MiB
2022-06-07 17:14:08 +02:00
1b070f366b vdo: fix conversion of vdo_slab_size_mb
When converting VDO volume, the parameter vdo_slabSize was
incorrectly copied as vdo_blockMapCacheSize, however this parameter
is then no longer used for any table line creation so the wrong
value was only stored in metadata.

Also use just single get_kb_size_with_unit_ and remove it's duplicate
functionality with get_mb_size_with_unit_.

Use $VERB for vdo remove call.
2022-06-07 17:14:08 +02:00
c302903dba filter-mpath: handle other wwid types in blacklist
Fixes commit 494372b4ee
  "filter-mpath: use multipath blacklist"
to handle wwids with initial type digits 1 and 2 used
for t10 and eui ids.  Originally recognized type 3 naa.
2022-06-06 11:39:02 -05:00
bfe072e438 devices file: fail if --devicesfile filename doesn't exist
A typo of the filename after --devicesfile should result in a
command error rather than the command falling back to using no
devices file at all.  Exception is vgcreate|pvcreate which
create a new devices file if the file name doesn't exist.
2022-05-27 14:27:03 -05:00
9dfa6f3879 devices file: move clean up after command is run
devices_file_exit wasn't being called between lvm_shell
commands, so the file lock wouldn't be released.
2022-05-27 12:38:43 -05:00
a30013ff4f post-release 2022-05-18 18:18:14 +02:00
6d1e894a86 pre-release 2022-05-18 18:17:06 +02:00
9aa3ea1c98 make: generate 2022-05-18 18:15:30 +02:00
7ec0726ce3 toollib: fix segfault when handling selection with historical LVs
When processing historical LVs inside process_each_lv_in_vg for
selection, we need to use dummy "_historical_lv" for select_match_lv.

This is because a historical LV is not an actual LV, but only a tiny
representation with subset of original properties that we recorded
(name, uuid...).

To use the same processing functions we use for full-fledged non-historical
LVs, we need to use the prefilled "_historical_lv" structure which has all
the other missing properties hard-coded.
2022-05-05 11:13:39 +02:00
ff6022d400 make: generate 2022-05-03 19:09:52 +02:00
5e060b8fa7 vdo: support --vdosettings
Allow to use --vdosettings with lvcreate,lvconvert,lvchange.
Support settings currenly only configurable via lvm.conf.
With lvchange we require inactivate LV for changes to be applied.

Settings block_map_era_length has supported alias block_map_period.
2022-05-03 19:09:52 +02:00
dd28460017 improve description of devices option 2022-05-02 09:47:02 -05:00
494372b4ee filter-mpath: use multipath blacklist
Explicit wwid's from these sections control whether the
same wwid in /etc/multipath/wwids is recognized as a
multipath component.  Other non-wwid keywords are not
used, and may require disabling the use of the multipath
wwids file in lvm.conf.
2022-04-22 16:07:47 -05:00
5c50590b22 tests: devicesfile-edit.sh fix loop file name
don't remove dash from loop file name
2022-04-21 11:31:06 -05:00
bee575d678 devices file: remove extraneous unlock in vgchange -u
vgchange -u exit path was unlocking the devices file in cases
when it wasn't needed, which produced an warning.
2022-04-13 12:19:04 -05:00
d14245c724 lvmlockd: return error from vgcreate init_vg_sanlock
in vgcreate for shared sanlock vg, if sanlock_write_resource
returns an unexpected error, then make init_vg_sanlock fail
which will cause the vgcreate to fail.
2022-04-08 11:34:04 -05:00
99f9bb28c9 filters: remove unused internal filter 2022-04-06 12:51:34 -05:00
6cb0b44cd2 filter: remove unused EAGAIN case and flag
The case of filters returning EAGAIN and using the
FILTER_AFTER_SCAN flag is no longer used.
2022-04-06 12:51:34 -05:00
fb7698b0ce lvmdevices: --deldev using device id
When used with --deviceidtype, --deldev can specify
a device id to remove.
2022-04-06 12:51:34 -05:00
151ce8b276 vgimportdevices: fix incorrect deviceidtype usage
When a VG has PVs with different device id types,
it would try to use the idtype of the previous PV
in the loop.  This would produce an unncessary warning,
or could lead to using the devname idtype when a better
idtype is available.
2022-04-06 12:20:26 -05:00
f840dbb320 pvscan: warn about /dev/sda excluded by devices file
In most installations, /dev/sda* or /dev/vda* should be included
in system.devices because the root, home, etc LVs are usually on
sda or vda.

Add a special case warning when a pvscan autoactivation command
sees that /dev/sda* or /dev/vda* are excluded by system.devices,
either not listed or having a different device id.
2022-04-01 13:38:21 -05:00
8db3b11e4e change messages about filtered devices
Change messages that refer to devices being "excluded by filters"
to say just "excluded".  This will avoid mistaking the word
"filters" with the lvm.conf filter setting.
2022-04-01 13:38:21 -05:00
23a9bd549a lvmdevices update: correct multipath entries
Remove multipath components.
Add multipath devs that have multipath components listed.
2022-04-01 13:38:21 -05:00
6e22be20c6 devices file: warn about missing multipath entry
Warn if a scsi device is listed in the devices file that
is used by a multipath device that is not listed.  This
will happen if a scsi device is listed in the devices
file and then an mpath device is set up to use it.

The way to correct this would be to remove the devices
file entry for the component device and add a new entry
for the multipath device.
2022-04-01 13:38:21 -05:00
0937113146 thin: fix message processing on thin-pool extension
When thin-pool had queued some delete message on extension operation
such message has been 'lost' and thin-pool kernel metadata has been
left with a thin volume that no longer existed for lvm2 metadata.
2022-03-30 14:49:04 +02:00
86a0a652a9 fix args entry for nolocking
typo in previous commit
2022-03-25 17:25:29 -05:00
f1578b4a5d Move nolocking warning to man page
It's more logical to warn about --nolocking in the man page
before it's used rather than after it's used and too late.
Also, warnings are usually for things the user may not know.
2022-03-25 15:43:53 -05:00
72f0b637d2 vgchange monitor: don't use udev info
vgchange --monitor y is run during startup when udev is being
initialized and is not yet ready to be used.
2022-03-25 14:13:56 -05:00
c7a5b5cca0 pvscan: don't use udev for external device info
pvscan is used to populate udev info, so it can't expect
to use that udev info.
2022-03-09 11:54:59 -06:00
bef1363c00 writecache: check memory usage
warn if writecache neds > 50% of system memory, and
confirm if writecache needs > 90% of system memory.
2022-03-01 16:29:53 -06:00
cc73d99886 devices: only close PVs on LVs when scan_lvs is enabled
This code is only needed when lvm scans PVs that are stacked on LVs.
2022-03-01 14:11:05 -06:00
7b1a857d5a devices: use dev-cache aliases handling from label scan functions
The label scan functions where doing some device alias validation
which is now better handled by the dev-cache layer, so just use
that.
2022-02-28 17:37:12 -06:00
4eb04c8c05 devices: fix dev_name assumptions
dev_name(dev) returns "[unknown]" if there are no names
on dev->aliases.  It's meant mainly for log messages.

Many places assume a valid path name is returned, and
use it directly.  A caller that wants to use the path
from dev_name() must first check if the dev has any
paths with dm_list_empty(&dev->aliases).
2022-02-24 17:22:04 -06:00
00c3069872 devices: initial use of existing option
Use dev_cache_get_existing() in a few common, high level
locations where it's obvious that only existing dev-cache
entries are wanted.  This can be expanded and used in more
locations (or dev_cache_get can stop creating new entries.)
2022-02-24 17:22:03 -06:00
7e70041e32 devices: drop incorrect paths from aliases list
along with some basic checks for cases when a device
has no aliases.

lvm itself creates many situations where a struct device
has no valid paths, when it activates and opens an LV,
does something with it, e.g. zeroing, and then closes
and deactivates it.  (dev-cache is intended for PVs, and
the use of LVs should be moved out of dev-cache in a
future patch.)
2022-02-24 17:22:03 -06:00
1126be8f8d devices: simplify dev_cache_get_by_devt
remove unused args, and no callers need or want a
repeated dev_cache_scan if there is no dev from the
lookup.
2022-02-24 17:21:58 -06:00
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
6144dac897 man lvmcache: mention writecache memory usage 2022-02-21 11:35:58 -06:00
96c99d647e man: update cachesettings option description
to be more consistent with man page description
2022-02-16 15:37:54 -06:00
ec2119bedd man lvmcache: add more writecache cachesettings info 2022-02-16 15:21:09 -06:00
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
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
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
d2e7a05573 clang: add extra check
Make clang happier.
2022-02-16 01:00:36 +01:00
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
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
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
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
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
13122bcc33 make: generate 2022-02-07 20:02:11 +01:00
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
8dccc2314e post-release 2022-02-07 18:02:07 +01:00
6987f318ec pre-release 2022-02-07 18:00:54 +01:00
563105bba9 tests: devicesfile-edit
test lvmdevices add/del
2022-02-03 16:58:12 -06:00
3fce6a81f8 lvmdevices: make deldev work for missing device 2022-02-03 16:56:03 -06:00
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
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
208af8db2a tests: skip test part when missed in kernel 2022-01-31 15:11:47 +01:00
b36fce26a2 activation: use lv_is_active
Use existing lv_is_active
2022-01-31 14:56:11 +01:00
f8d12913e7 tools: missing sync after deactivation
Caching of DM states optimisation revealed some missing
synchronisation points.
2022-01-31 14:55:42 +01:00
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
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
a425729da9 test: remove leaked exit 2022-01-26 15:32:30 +01:00
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
cf68bf7b6c gcc: snprintf may need here upto 18 bytes
Although hypothetical case....
2022-01-26 15:09:58 +01:00
7f1f7ad694 lvcreate: code move 2022-01-26 15:09:58 +01:00
89cec5b65a test: check writecache profile support
FIXME
2022-01-26 15:09:58 +01:00
b95506815f man: doc writecache profile support 2022-01-26 15:09:58 +01:00
d8dbabb28e lvcreate: cachesettings works also with writecache 2022-01-26 15:09:58 +01:00
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
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
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
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
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
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
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
0c80ea8847 remove unused variable
resulting from commit cb798ee1c1
  "lvmcache: remove lvmcache_update_vg_from_write"
2022-01-13 11:41:39 -06:00
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
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
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
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
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
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
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
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
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
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
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
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
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
47ac2659d5 activate: cache driver_version result 2021-12-20 16:13:28 +01:00
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
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
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
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
0f71183f94 man lvmautoactivation: replace systemctl with journalctl 2021-12-14 12:02:08 -06:00
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
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
d803d9202c man: add section about static autoactivation 2021-12-06 13:20:32 -06:00
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
455c29b10d print warning about unrecognized journal option value 2021-12-02 12:40:52 -06:00
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
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
d5402e55f6 devices file: don't write in test mode 2021-12-01 10:08:08 -06:00
71e7ebb3e4 tests devicesfile-devname.sh drop mdadm chunk 2021-12-01 08:56:05 -06:00
36095ac374 spec: Add lvmautoactivation man page 2021-12-01 15:36:34 +01:00
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
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
009007484b man: lvmautoactivation
new topical man page describing autoactivation
2021-11-29 11:10:02 -06:00
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
114e1cfee5 fix spelling of pruning 2021-11-19 12:02:35 -06:00
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
b8f4ec846d display: ignore --reportformat
Using the option would do nothing useful but would
print extraneous braces.
2021-11-17 10:40:27 -06:00
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
5c71aa7510 tests pv-ext-flags: work with devices file 2021-11-16 14:29:22 -06:00
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
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
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
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
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
4926061d32 tests: udev-pvscan-vgchange clear services 2021-11-12 12:10:26 -06:00
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
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
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
20c550ab10 tests: udev-pvscan-vgchange fix wait
the service now remains after completion
2021-11-11 16:04:24 -06:00
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
92e741eda0 vgchange: move autoactivation setup code
into its own function, no functional change.
2021-11-10 14:44:11 -06:00
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
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
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
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
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
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
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
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
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
594f6ca970 rename pvscan_cache_single to expect_missing_vg_device in cmd 2021-11-04 11:08:38 -05:00
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
6ea8d975b2 lvmdevices: increase open file limit 2021-11-03 08:50:57 -05:00
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
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
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
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
ae355ffc3f pvscan: fix messages from coverity changes 2021-10-20 16:12:55 -05:00
819a35cc91 post-release 2021-10-20 11:13:28 +02:00
ef4521831d pre-release 2021-10-20 11:12:39 +02:00
36be4d68f6 WHATS_NEW: update 2021-10-20 11:10:37 +02:00
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
60dc44b707 dev-cache: enhance dir scan also for non-udev build 2021-10-18 21:50:56 +02:00
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
c60bac4661 configure: update 2021-10-18 19:17:27 +02:00
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
a172a02a9a cleanup: use const char buffer 2021-10-18 19:17:27 +02:00
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
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
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
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
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
e7b5f490c5 cov: ignore close result 2021-10-15 23:40:29 +02:00
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
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
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
704 changed files with 56877 additions and 28118 deletions

32
.gitignore vendored
View File

@ -14,8 +14,14 @@
*.so
*.so.*
*.sw*
*.su
*.patch
*~
# gcov files:
*.gcda
*.gcno
.export.sym
.exported_symbols_generated
.gdb_history
@ -39,12 +45,19 @@ make.tmpl
coverity/coverity_model.xml
# gcov files:
*.gcda
*.gcno
/.cache/
/compile_commands.json
/doc/.ikiwiki
/public
/libdm/.symver_check
daemons/clvmd
daemons/dmfilemapd
daemons/lvmetad/
tools/man-generator
tools/man-generator.c
test/.lib-dir-stamp
test/.tests-stamp
@ -102,6 +115,8 @@ test/api/thin_percent.t
test/api/vglist.t
test/api/vgtest.t
test/lib/aux
test/lib/cache-mq.profile
test/lib/cache-smq.profile
test/lib/check
test/lib/clvmd
test/lib/dm-version-expected
@ -111,6 +126,7 @@ test/lib/dmstats
test/lib/fail
test/lib/flavour-ndev-cluster
test/lib/flavour-ndev-cluster-lvmpolld
test/lib/flavour-ndev-devicesfile
test/lib/flavour-ndev-lvmetad
test/lib/flavour-ndev-lvmetad-lvmpolld
test/lib/flavour-ndev-lvmpolld
@ -120,6 +136,7 @@ test/lib/flavour-udev-cluster-lvmpolld
test/lib/flavour-udev-lvmetad
test/lib/flavour-udev-lvmetad-lvmpolld
test/lib/flavour-udev-lvmlockd-dlm
test/lib/flavour-udev-lvmlockd-idm
test/lib/flavour-udev-lvmlockd-sanlock
test/lib/flavour-udev-lvmlockd-test
test/lib/flavour-udev-lvmpolld
@ -132,8 +149,13 @@ test/lib/lvm
test/lib/lvm-wrapper
test/lib/lvmchange
test/lib/lvmdbusd.profile
test/lib/lvmdevices
test/lib/lvmetad
test/lib/lvmlockctl
test/lib/lvmlockd
test/lib/lvmpolld
test/lib/lvm_import_vdo
test/lib/lvm_vdo_wrapper
test/lib/not
test/lib/paths
test/lib/paths-common
@ -143,5 +165,7 @@ test/lib/test
test/lib/thin-performance.profile
test/lib/utils
test/lib/version-expected
test/lib/vgimportdevices
test/unit/dmraid_t.c
test/unit/unit-test

104
.gitlab-ci.yml Normal file
View File

@ -0,0 +1,104 @@
stages:
- approve
- test
approve1:
stage: approve
script:
- echo "Approved..."
rules:
# TODO: Filter only safe repositories, or user in developers
- if: $CI_PROJECT_PATH != "csonto/lvm2" && $CI_PROJECT_PATH != "lvmteam/lvm2"
when: manual
# TODO: for other branches than main/rhel: run pipeline only when requested:
- if: $CI_COMMIT_BRANCH != "main" && $CI_COMMIT_BRANCH !~ "^rhel.*"
when: manual
- when: on_success
allow_failure: false
pages:
image: elecnix/ikiwiki
stage: test
script:
- ikiwiki --setup ikiwiki.setup --libdir themes/ikistrap/lib
artifacts:
paths:
- public
only:
refs:
- main
changes:
- doc/**/*
- ikiwiki.setup
# TODO:
# - check results of autoreconf and make generate - may need additional commit
# - we need a particular setup (rawhide OR latest supported fedora?)
# - do make rpm and publish results as artifacts - we will use packit/COPR for this eventually
# Run on any commits to main (master), rhel8, rhel9 branches
test-job:
stage: test
parallel:
matrix:
- TAG: rhel8
CONFIGURE: >
--with-cluster=internal
--enable-cmirrord
- TAG: rhel9
CONFIGURE: >
--with-default-use-devices-file=1
--enable-app-machineid
--enable-editline
--disable-readline
artifacts:
paths:
- test/results/
expire_in: 1 week
tags:
- ${TAG}
timeout: 2h
script:
# Common options go here, diffs to the above matrix
- >
./configure ${CONFIGURE}
--enable-fsadm
--enable-write_install
--enable-pkgconfig
--enable-cmdlib
--enable-dmeventd
--enable-blkid_wiping
--enable-udev_sync
--with-thin=internal
--with-cache=internal
--enable-lvmpolld
--enable-lvmlockd-dlm --enable-lvmlockd-dlmcontrol
--enable-lvmlockd-sanlock
--enable-dbus-service --enable-notify-dbus
--enable-dmfilemapd
--with-writecache=internal
--with-vdo=internal --with-vdo-format=/usr/bin/vdoformat
--with-integrity=internal
--disable-silent-rules
- make
- rm -rf test/results
- mkdir -p /dev/shm/lvm2-test
- mount -o remount,dev /dev/shm
# TODO: Need to distinguish failed test from failed harness
# TODO: Also need a way to find if run is incomplete, e.g. full disk resulting in many skipped tests
- VERBOSE=0 BATCH=1 LVM_TEST_DIR=/dev/shm/lvm2-test make check || true
- rm -rf /dev/shm/lvm2-test
- cut -d' ' -f2 test/results/list | sort | uniq -c
# Filter artifacts - keep only logs from tests which are not pass
- cd test/results && rm $(grep 'passed$' list | cut -d' ' -f1 | sed -e 's|/|_|g' -e 's|.*|\0.txt|')
# TODO: Keep a list of known failures, and translate into regexp - or simply use python...
- if grep failed test/results/list | grep -v '\\\(dbustest\|lvconvert-mirror\)\.sh' | sort; then false; else true; fi
rules:
# Filter only safe repositories, or user in developers:
# NOTE: Already done in approve stage, may be more caution than necessary
- if: $CI_PROJECT_PATH != "csonto/lvm2" && $CI_PROJECT_PATH != "lvmteam/lvm2"
when: manual
- when: on_success

View File

@ -38,7 +38,7 @@ ifeq ($(MAKECMDGOALS),distclean)
udev po
tools.distclean: test.distclean
endif
DISTCLEAN_DIRS += lcov_reports*
DISTCLEAN_DIRS += lcov_reports* autom4te.cache
DISTCLEAN_TARGETS += config.cache config.log config.status make.tmpl
include make.tmpl
@ -47,7 +47,7 @@ include $(top_srcdir)/base/Makefile
include $(top_srcdir)/device_mapper/Makefile
include $(top_srcdir)/test/unit/Makefile
lib: libdaemon $(BASE_TARGET) $(DEVICE_MAPPER_TARGET)
lib: include libdaemon $(BASE_TARGET) $(DEVICE_MAPPER_TARGET)
daemons: lib libdaemon tools
scripts: lib
tools: lib libdaemon
@ -55,7 +55,7 @@ po: tools daemons
man: tools
all_man: tools
test: tools daemons
unit-test run-unit-test: test
unit-test run-unit-test: test libdm
daemons.device-mapper: libdm.device-mapper
tools.device-mapper: libdm.device-mapper
@ -127,6 +127,7 @@ all_man:
install_system_dirs:
$(INSTALL_DIR) $(DESTDIR)$(DEFAULT_SYS_DIR)
$(INSTALL_ROOT_DIR) $(DESTDIR)$(DEFAULT_SYS_DIR)/devices
$(INSTALL_ROOT_DIR) $(DESTDIR)$(DEFAULT_ARCHIVE_DIR)
$(INSTALL_ROOT_DIR) $(DESTDIR)$(DEFAULT_BACKUP_DIR)
$(INSTALL_ROOT_DIR) $(DESTDIR)$(DEFAULT_CACHE_DIR)
@ -171,6 +172,7 @@ help:
@echo " lcov-dated Generate lcov with timedate suffix."
@echo " lcov-reset Reset lcov counters"
@echo " man Build man pages."
@echo " print-VARIABLE Resolve make variable."
@echo " rpm Build rpm."
@echo " run-unit-test Run unit tests."
@echo " tags Generate c/etags."

29
README
View File

@ -1,7 +1,5 @@
This tree contains the LVM2 and device-mapper tools and libraries.
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.
@ -12,20 +10,30 @@ Tarballs are available from:
https://github.com/lvmteam/lvm2/releases
The source code is stored in git:
https://sourceware.org/git/?p=lvm2.git
git clone git://sourceware.org/git/lvm2.git
mirrored to:
https://github.com/lvmteam/lvm2
https://gitlab.com/lvmteam/lvm2
Clone:
git clone git@gitlab.com:lvmteam/lvm2.git
Anonymous access:
git clone https://gitlab.com/lvmteam/lvm2.git
Mirrored to:
* https://github.com/lvmteam/lvm2
git clone https://github.com/lvmteam/lvm2.git
git clone git@github.com:lvmteam/lvm2.git
* https://sourceware.org/git/?p=lvm2.git
git clone https://sourceware.org/git/lvm2.git
git clone git://sourceware.org/git/lvm2.git
Mailing list for general discussion related to LVM2:
linux-lvm@redhat.com
Subscribe from https://www.redhat.com/mailman/listinfo/linux-lvm
linux-lvm@lists.linux.dev
Subscribe via email to: linux-lvm+subscribe@lists.linux.dev
Archive https://lore.kernel.org/linux-lvm/
Older archive https://listman.redhat.com/archives/linux-lvm/
Mailing lists for LVM2 development, patches and commits:
lvm-devel@redhat.com
Subscribe from https://www.redhat.com/mailman/listinfo/lvm-devel
lvm-devel@lists.linux.dev
Subscribe via email to: lvm-devel+subscribe@lists.linux.dev
Archive https://lore.kernel.org/lvm-devel/
Older archive https://listman.redhat.com/archives/lvm-devel/
lvm2-commits@lists.fedorahosted.org (Read-only archive of commits)
Subscribe from https://fedorahosted.org/mailman/listinfo/lvm2-commits
@ -41,6 +49,7 @@ Website:
Report upstream bugs at:
https://bugzilla.redhat.com/enter_bug.cgi?product=LVM%20and%20device-mapper
or open issues at:
https://gitlab.com/groups/lvmteam/-/issues
https://github.com/lvmteam/lvm2/issues
The source code repository used until 7th June 2012 is accessible using CVS:

View File

@ -21,10 +21,15 @@ You MUST disable (or mask) any LVM daemons:
- clvmd
- cmirrord
Some lvm.conf options should be set:
- global/event_activation = 0
- activation/monitoring = 0
For running cluster tests, we are using singlenode locking. Pass
`--with-clvmd=singlenode` to configure.
NOTE: This is useful only for testing, and should not be used in produciton
NOTE: This is useful only for testing, and should not be used in production
code.
To run D-Bus daemon tests, existing D-Bus session is required.

View File

@ -1 +1 @@
2.03.14(2)-git (2021-08-11)
2.03.28(2)-git (2024-10-02)

View File

@ -1 +1 @@
1.02.181-git (2021-08-11)
1.02.202-git (2024-10-02)

350
WHATS_NEW
View File

@ -1,5 +1,195 @@
Version 2.03.14 -
Version 2.03.28 -
==================
Version 2.03.27 - 02nd October 2024
===================================
Fix swap device size detection using blkid for lvresize/lvreduce/lvextend.
Detect GPT partition table and pass partition filter if no partitions defined.
Add global/sanlock_align_size option to configure sanlock lease size.
Disable mem locking when activation/reserved_stack or reserved_memory is 0.
Fix locking issues in lvmlockd leaving thin pool locked.
Deprecate vdo settings vdo_write_policy and vdo_write_policy.
Lots of typo fixes across lvm2 code base (codespell).
Corrected integrity parameter interleave_sectors for DM table line.
Ignore -i|--stripes, -I|--stripesize for lvextend on raid0 LV, like raid10.
Do not accept duplicate device names for pvcreate.
Version 2.03.26 - 23rd August 2024
==================================
Fix internal error reported by pvmove on a VG with single PV.
Also accept --mknodes --refresh for vgscan.
Fix vgmknodes --refresh to wait for udev before checking /dev content.
Use log/report_command_log=1 config setting by default for JSON output format.
Fix unreleased memory pools on RAID lvextend.
Add --integritysettings option to manipulate dm-integrity settings.
Version 2.03.25 - 12nd July 2024
================================
Utilize more radix_tree instead of dm_hash and btree.
Refactor DM uuid caching from device_mapper directory.
Enhance checking for DM uuid device.
Fix lvm shell command completion on tab key (2.03.24).
Avoid lockd_vg call to lvmlockd for local VGs.
Allow forced change of locktype from none.
Handle OPTIONS defined in /etc/sysconfig/lvmlockd.
Version 2.03.24 - 16th May 2024
===============================
Lvconvert supports VDO options for thin-pool with vdo conversion.
Improve placement to .data.rel.ro and .rodata sections.
Fix support for -y and -W when creating thinpool with vdo.
Better support for runtime valgrind detection.
Allow command interruption when communicating with dmeventd.
Fix resize of VDO volume used for thin pool data volume.
Use -Wl,-z,now and -Wl,--as-needed for compilation by default.
Require 3.7 as minimal version for sanlock.
Share code for closing opened descriptors on program startup.
Fix memleak in lvmcache.
Add configure --with-default-event-activation=ON setting.
Fix return value from reporter function when hitting internal error.
Skip checking of pools for lvremove and vgremove commands.
VDO modprobes dm-vdo for 6.9 kernel and kvdo for older kernel version.
Fix lvs reporting for VDO volumes with new upstream kernel driver.
Don't import DM_UDEV_DISABLE_OTHER_RULES_FLAG in LVM rules, DM rules cover it.
Fix table line generation for cache snapshots using cachevol.
Enhance lvconvert support for external origins stacking.
When swapping LV names also swap properties like hostname, time and data.
Fix removal of stacked external origins.
Lock filesystem when converting volume to read-only external origin.
Support external origin between different thin-pool.
Improve validation of acceptable volumes for external origins.
Reduce amount of preloaded devices for complex device trees.
Avoid logging problems from monitoring snapshots with inactive origins.
Check for cache policy module presence in kernel's builtin modules file.
Add configure --with-modulesdir to select kernel modules directory.
Support creation of thin-pool with VDO use for its data volume.
Version 2.03.23 - 21st November 2023
====================================
Set the first lv_attr flag for raid integrity images to i or I.
Add -A option for pvs and pvscan to show PVs outside devices file.
Improve searched_devnames temp file usage to prevent redundant scanning.
Change default search_for_devnames from auto to all.
Add lvmdevices --refresh to search for missing PVIDs on all devices.
Add comparison between old and new entries in lvmdevices --check.
Fix device_id matching order - match non-devname first.
Fix "lvconvert -m 0" when there is other than first in-sync leg.
Use system.devices as default for dmeventd when dmeventd.devices is undefined.
Accept WWIDs containing QEMU HARDDISK for device_id.
Improve handling of non-standard WWID prefixes used for device_id.
Configure automatically enables cmdlib for dmeventd and notify-dbus for dbus.
Fix hint calculation for pools with zero or error segment.
Configure supports --disable-shared to build only static binaries.
Configure supports --without-{blkid|systemd|udev} for easier static build.
Refresh device ids if the system changes.
Fix pvmove when specifying raid components as moved LVs.
Enhance error detection for lvm_import_vdo.
Support PV lists with thin lvconvert.
Fix support for lvm_import_vdo with SCSI VDO volumes.
Fix locking issue leading to hanging concurrent vgchange --refresh.
Recognise lvm.conf report/headings=2 for full column names in report headings.
Add --headings none|abbrev|full cmd line option to set report headings type.
Fix conversion to thin pool using lvmlockd.
Fix conversion from thick into thin volume using lvmlockd.
Require writable LV for conversion to vdo pool.
Fix return value from lvconvert integrity remove.
Preserve UUID for pool metadata spare.
Preserve UUID for swapped pool metadata.
Rewrite validation of device name entries used as device_id.
version 2.03.22 - 02nd August 2023
==================================
Fix pv_major/pv_minor report field types so they are integers, not strings.
Add lvmdevices --delnotfound to delete entries for missing devices.
Always use cachepool name for metadata backup LV for lvconvert --repair.
Make metadata backup LVs read-only after pool's lvconvert --repair.
Improve VDO and Thin support with lvmlockd.
Handle 'lvextend --usepolicies' for pools for all activation variants.
Fix memleak in vgchange autoactivation setup.
Update py-compile building script.
Support conversion from thick to fully provisioned thin LV.
Cache/Thin-pool can use error and zero volumes for testing.
Individual thin volume can be cached, but cannot take snapshot.
Better internal support for handling error and zero target (for testing).
Resize COW above trimmed maximal size is does not return error.
Support parsing of vdo geometry format version 4.
Add lvm.conf thin_restore and cache_restore settings.
Handle multiple mounts while resizing volume with a FS.
Handle leading/trailing spaces in sys_wwid and sys_serial used by device_id.
Enhance lvm_import_vdo and use snapshot when converting VDO volume.
Fix parsing of VDO metadata.
Fix failing -S|--select for non-reporting cmds if using LV info/status fields.
Allow snapshots of raid+integrity LV.
Fix multisegment RAID1 allocator to prevent using single disk for more legs.
version 2.03.21 - 21st April 2023
=================================
Fix activation of vdo-pool for with 0 length headers (converted pools).
Avoid printing internal init messages when creation integration devices.
Allow (write)cache over raid+integrity LV.
version 2.03.20 - 21st March 2023
=================================
Fix segfault if using -S|--select with log/report_command_log=1 setting.
Configure now fails when requested lvmlockd dependencies are missing.
Add some configure Gentoo enhancements for static builds.
version 2.03.19 - 21st February 2023
====================================
Configure supports --with-systemd-run executed from udev rules.
Enhancement for build with MuslC systemd and non-bash system shells (dash).
Do not reset SYSTEMD_READY variable in udev for PVs on MD and loop devices.
Ensure udev is processing origin LV before its thick snapshots LVs.
Fix and improve runtime memory size detection for VDO volumes.
version 2.03.18 - 22nd December 2022
====================================
Fix issues reported by coverity scan.
Fix warning for thin pool overprovisioning on lvextend (2.03.17).
Add support for writecache metadata_only and pause_writeback settings.
Fix missing error messages in lvmdbusd.
Version 2.03.17 - 10th November 2022
====================================
Add new options (--fs, --fsmode) for FS handling when resizing LVs.
Fix 'lvremove -S|--select LV' to not also remove its historical LV right away.
Fix lv_active field type to binary so --select and --binary applies properly.
Switch to use mallinfo2 and use it only with glibc.
Error out in lvm shell if using a cmd argument not supported in the shell.
Fix lvm shell's lastlog command to report previous pre-command failures.
Keep libaio locked in memory in critical section.
Extend VDO and VDOPOOL without flushing and locking fs.
Add --valuesonly option to lvmconfig to print only values without keys.
Updates configure with recent autoconf tooling.
Fix lvconvert --test --type vdo-pool execution.
Add json_std output format for more JSON standard compliant version of output.
Fix vdo_slab_size_mb value for converted VDO volume.
Fix many corner cases in device_id, including handling of S/N duplicates.
Fix various issues in lvmdbusd.
Version 2.03.16 - 18th May 2022
===============================
Fix segfault when handling selection with historical LVs.
Add support --vdosettings with lvcreate, lvconvert, lvchange.
Filtering multipath devices respects blacklist setting from multipath
configuration.
lvmdevices support for removing by device id using --deviceidtype and
--deldev.
Display writecache block size with lvs -o writecache_block_size.
Improve cachesettings description in man lvmcache.
Fix losing of delete message on thin-pool extension.
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.
@ -7,7 +197,7 @@ Version 2.03.14 -
Filter out unsupported MQ/SMQ cache policy setting.
Fix memleak in mpath filter.
Support newer location for VDO statistics.
Add support for VDO async-unsage write policy.
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.
@ -74,8 +264,8 @@ Version 2.03.12 - 07th May 2021
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.
Support metadata profiles with volume VDO pool conversions.
Support -Zn for conversion of already formatted 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.
@ -105,7 +295,7 @@ Version 2.03.11 - 08th January 2021
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 when wiping LVs.
Support interruption for bcache waiting.
Fix bcache when device has too many failing writes.
Fix bcache waiting for IO completion with failing disks.
@ -148,7 +338,7 @@ Version 2.03.10 - 09th August 2020
Version 2.03.09 - 26th March 2020
=================================
Fix formating of vdopool (vdo_slab_size_mb was smaller by 2 bits).
Fix formatting 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
@ -232,7 +422,7 @@ Version 2.03.03 - 07th June 2019
Ignore foreign and shared PVs for pvscan online files.
Add config setting to control fields in debug file and verbose output.
Add command[pid] and timestamp to debug file and verbose output.
Fix missing growth of _pmsmare volume when extending _tmeta volume.
Fix missing growth of _pmspare volume when extending _tmeta volume.
Automatically grow thin metadata, when thin data gets too big.
Add synchronization with udev before removing cached devices.
Add support for caching VDO LVs and VDOPOOL LVs.
@ -245,14 +435,14 @@ Version 2.03.03 - 07th June 2019
Change scan_lvs default to 0 so LVs are not scanned for PVs.
Thin-pool selects power-of-2 chunk size by default.
Cache selects power-of-2 chunk size by default.
Support reszing for VDOPoolLV and VDOLV.
Support resizing for VDOPoolLV and VDOLV.
Improve -lXXX%VG modifier which improves cache segment estimation.
Ensure migration_threshold for cache is at least 8 chunks.
Restore missing man info lvcreate --zero for thin-pools.
Drop misleadning comment for metadata minimum_io_size for VDO segment.
Drop misleading comment for metadata minimum_io_size for VDO segment.
Add device hints to reduce scanning.
Introduce LVM_SUPPRESS_SYSLOG to suppress syslog usage by generator.
Fix generator quering lvmconfig unpresent config option.
Fix generator querying lvmconfig unpresent config option.
Fix memleak on bcache error path code.
Fix missing unlock on lvm2 dmeventd plugin error path initialization.
Improve Makefile dependency tracking.
@ -314,7 +504,7 @@ Version 2.02.178-rc1 - 24th May 2018
--with-cache switch for ./configure has been removed.
Include new unit-test framework and unit tests.
Extend validation of region_size for mirror segment.
Reload whole device stack when reinitilizing mirror log.
Reload whole device stack when reinitializing mirror log.
Mirrors without monitoring are WARNING and not blocking on error.
Detect too big region_size with clustered mirrors.
Fix evaluation of maximal region size for mirror log.
@ -359,7 +549,7 @@ Version 2.02.178-rc1 - 24th May 2018
Restore pvmove support for wide-clustered active volumes (2.02.177).
Avoid non-exclusive activation of exclusive segment types.
Fix trimming sibling PVs when doing a pvmove of raid subLVs.
Preserve exclusive activation during thin snaphost merge.
Preserve exclusive activation during thin snapshot merge.
Avoid exceeding array bounds in allocation tag processing.
Add --lockopt to common options and add option to skip selected locks.
@ -375,7 +565,7 @@ Version 2.02.177 - 18th December 2017
Fix lvmlockd to use pool lock when accessing _tmeta volume.
Report expected sanlock_convert errors only when retries fail.
Avoid blocking in sanlock_convert on SH to EX lock conversion.
Deactivate missing raid LV legs (_rimage_X-missing_Y_Z) on decativation.
Deactivate missing raid LV legs (_rimage_X-missing_Y_Z) on deactivation.
Skip read-modify-write when entire block is replaced.
Categorise I/O with reason annotations in debug messages.
Allow extending of raid LVs created with --nosync after a failed repair.
@ -397,7 +587,7 @@ Version 2.02.177 - 18th December 2017
Check raid reshape flags in vg_validate().
Add support for pvmove of cache and snapshot origins.
Avoid using precommitted metadata for suspending pvmove tree.
Ehnance pvmove locking.
Enhance pvmove locking.
Deactivate activated LVs on error path when pvmove activation fails.
Add "io" to log/debug_classes for logging low-level I/O.
Eliminate redundant nested VG metadata in VG struct.
@ -487,13 +677,13 @@ Version 2.02.173 - 20th July 2017
Version 2.02.172 - 28th June 2017
=================================
Add missing NULL to argv array when spliting cmdline arguments.
Add missing NULL to argv array when splitting cmdline arguments.
Add display_percent helper function for printing percent values.
lvconvert --repair handles failing raid legs (present but marked 'D'ead).
Do not lvdisplay --maps unset settings of cache pool.
Fix lvdisplay --maps for cache pool without policy settings.
Support aborting of flushing cache LV.
Reenable conversion of data and metadata thin-pool volumes to raid.
Re-enable conversion of data and metadata thin-pool volumes to raid.
Improve raid status reporting with lvs.
No longer necessary to '--force' a repair for RAID1.
Linear to RAID1 upconverts now use "recover" sync action, not "resync".
@ -561,7 +751,7 @@ Version 2.02.169 - 28th March 2017
Support cache segment with configurable metadata format.
Add allocation/cache_metadata_format profilable settings.
Use function cache_set_params() for both lvcreate and lvconvert.
Skip rounding on cache chunk size boudary when create cache LV.
Skip rounding on cache chunk size boundary when create cache LV.
Improve cache_set_params support for chunk_size selection.
Fix metadata profile allocation/cache_[mode|policy] setting.
Fix missing support for using allocation/cache_pool_chunk_size setting.
@ -611,8 +801,8 @@ Version 2.02.169 - 28th March 2017
Extend metadata validation of external origin LV use count.
Fix dm table when the last user of active external origin is removed.
Improve reported lvs status for active external origin volume.
Fix table load for splitted RAID LV and require explicit activation.
Always active splitted RAID LV exclusively locally.
Fix table load for split RAID LV and require explicit activation.
Always active split RAID LV exclusively locally.
Do not use LV RAID status bit for segment status.
Check segtype directly instead of checking RAID in segment status.
Reusing exiting code for raid image removal.
@ -675,7 +865,7 @@ Version 2.02.166 - 26th September 2016
Use --alloc normal for mirror logs even if the mimages were stricter.
Use O_DIRECT to gather metadata in lvmdump.
Ignore creation_time when checking for matching metadata for lvmetad.
Fix possible NULL pointer derefence when checking for monitoring.
Fix possible NULL pointer dereference when checking for monitoring.
Add lvmreport(7) man page.
Don't install lvmraid(7) man page when raid excluded. (2.02.165)
Report 0% as dirty (copy%) for cache without any used block.
@ -715,7 +905,7 @@ Version 2.02.164 - 15th August 2016
Version 2.02.163 - 10th August 2016
===================================
Add profile for lvmdbusd which uses lvm shell json report output.
Restrict in-command modification of some parms in lvm shell.
Restrict in-command modification of some params in lvm shell.
Apply LVM_COMMAND_PROFILE early for lvm shell.
Refactor reporting so lvm shell log report collects whole of cmd execution.
Support LVM_*_FD envvars to redirect output to file descriptors.
@ -868,11 +1058,11 @@ Version 2.02.152 - 30th April 2016
==================================
Use any inherited tags when wiping metadata sub LVs to ensure activation.
Add str_list_wipe.
Improve support for interrupting procesing of volumes during lvchange.
Improve support for interrupting processing of volumes during lvchange.
Use failed command return code when lvchanging read-only volume.
Show creation transaction_id and zeroing state of pool with thin volume.
Stop checking for dm_cache_mq policy with cache target 1.9 (alias to smq).
Check first /sys/module/dm_* dir existance before using modprobe.
Check first /sys/module/dm_* dir existence before using modprobe.
Remove mpath from 10-dm.rules, superseded by 11-dm-mpath.rules (mpath>=0.6.0).
Version 2.02.151 - 23rd April 2016
@ -897,7 +1087,7 @@ Version 2.02.150 - 9th April 2016
=================================
Avoid using flushing dm status ioctl when checking for usable DM device.
Check for devices without LVM- uuid prefix only with kernels < 3.X.
Reuse %FREE size aproximation with lvcreate -l%PVS thin-pool.
Reuse %FREE size approximation with lvcreate -l%PVS thin-pool.
Allow the lvmdump directory to exist already provided it is empty.
Show lvconverted percentage with 2 decimal digits.
Fix regression in suspend when repairing --type mirror (2.02.133).
@ -974,7 +1164,7 @@ Version 2.02.143 - 21st February 2016
Fix error path when sending thin-pool message fails in update_pool_lv().
Support reporting CheckNeeded and Fail state for thin-pool and thin LV.
For failing thin-pool and thin volume correctly report percentage as INVALID.
Report -1, not 'unkown' for lv_{snapshot_invalid,merge_failed} with --binary.
Report -1, not 'unknown' for lv_{snapshot_invalid,merge_failed} with --binary.
Add configure --enable-dbus-service for an LVM D-Bus service.
Replace configure --enable-python_bindings with python2 and python3 versions.
If PV belongs to some VG and metadata missing, skip it if system ID is used.
@ -1003,7 +1193,7 @@ Version 2.02.141 - 25th January 2016
Restore support for command breaking in process_each_lv_in_vg() (2.02.118).
Use correct mempool when process_each_lv_in_vg() (2.02.118).
Fix lvm.8 man to show again prohibited suffixes.
Fix configure to set proper use_blkid_wiping if autodetected as disabled.
Fix configure to set proper use_blkid_wiping if autodetection as disabled.
Initialise udev in clvmd for use in device scanning. (2.02.116)
Add seg_le_ranges report field for common format when displaying seg devices.
Honour report/list_item_separator for seg_metadata_le_ranges report field.
@ -1153,7 +1343,7 @@ Version 2.02.129 - 26th August 2015
Fix shared library generation to stop exporting internal functions.(2.02.120)
Accept --cachemode with lvconvert.
Fix and improve reporting properties of cache-pool.
Enable usage of --cachepolicy and --cachesetting with lvconvert.
Enable usage of --cachepolicy and --cachesettings with lvconvert.
Don't allow to reduce size of thin-pool metadata.
Fix debug buffer overflows in cmirrord logging.
Add --foreground and --help to cmirrord.
@ -1310,7 +1500,7 @@ Version 2.02.119 - 2nd May 2015
Add --enable-halvm and --disable-halvm options to lvmconf script.
Add --services, --mirrorservice and --startstopservices option to lvmconf.
Use proper default value of global/use_lvmetad when processing lvmconf script.
Respect allocation/cling_tag_list during intial contiguous allocation.
Respect allocation/cling_tag_list during initial contiguous allocation.
Add A_PARTITION_BY_TAGS set when allocated areas should not share tags.
Make changes persist with python addTag/removeTag.
Set correct vgid when updating cache when writing PV metadata.
@ -1388,7 +1578,7 @@ Version 2.02.116 - 30th January 2015
Scan pools in for_each_sub_lv() and add for_each_sub_lv_except_pools().
Fix lvm2app lvm_lv_get_property return value for fields with info/status ioctl.
Fix lvm2app regression in lvm_lv_get_attr causing unknown values (2.02.115).
Set default cache_mode to writehrough when missing in metadata.
Set default cache_mode to writethrough when missing in metadata.
Preserve chunk size with repair and metadata swap of a thin pool.
Fix raid --splitmirror 1 functionality (2.02.112).
Fix tree preload to handle splitting raid images.
@ -1454,13 +1644,13 @@ Version 2.02.112 - 11th November 2014
Properly report error when taking snapshot of any cache type LV.
Add basic thread debugging messages to dmeventd.
Include threads being shutdown in dmeventd device registration responses.
Inital support for external users of thin pools based on transaction_id.
Initial support for external users of thin pools based on transaction_id.
Report some basic percentage info for cache pools.
Introduce size_mb_arg_with_percent() for advanced size arg reading.
Add extra support for '.' as decimal point in size args.
Add configure parameters for default segment type choices.
Add global/sparse_segtype_default setting to use thin for --type sparse.
Update and correct lvcreate and lvcovert man pages.
Update and correct lvcreate and lvconvert man pages.
Mark pools and snapshots as unzeroable volumes.
Check for zeroing of volume after segment type is fully detected.
Better support for persistent major and minor options with lvcreate.
@ -1513,7 +1703,7 @@ Version 2.02.112 - 11th November 2014
Support DEBUG_MEMLOCK to trap unsupported mmap usage.
Enable cache segment type by default.
Ensure only supported volume types are used with cache segments.
Fix inablility to specify cachemode when 'lvconvert'ing to cache-pool.
Fix inability to specify cachemode when 'lvconvert'ing to cache-pool.
Grab cluster lock for active LVs when setting clustered attribute.
Use va_copy to properly pass va_list through functions.
Add function to detect rotational devices.
@ -1581,7 +1771,7 @@ Version 2.02.108 - 23rd July 2014
Enhance lvconvert thin, thinpool, cache and cachepool command line support.
Display 'C' only for cache and cache-pool target types in lvs.
Prompt for confirmation before change LV into a snapshot exception store.
Return proper error codes for some failing lvconvert funtions.
Return proper error codes for some failing lvconvert functions.
Add initial code to use cache tools (cache_check|dump|repair|restore).
Support lvdisplay --maps for raid.
Add --activationmode degraded to activate degraded raid volumes by default.
@ -1600,7 +1790,7 @@ Version 2.02.108 - 23rd July 2014
Support lvremove -ff to remove thin volumes from broken thin pools.
Require --yes to skip raid repair prompt.
Change makefile %.d generation to handle filename changes without make clean.
Fix use of buildir in make pofile.
Fix use of builddir in make pofile.
Enhance private volumes UUIDs with suffixed for easier detection.
Do not use reserved _[tc]meta volumes for temporary LVs.
Leave backup pool metadata with _meta%d suffix instead of reserved _tmeta%d.
@ -1705,7 +1895,7 @@ Version 2.02.106 - 10th April 2014
Include 'lvm dumpconfig --type missing' and '--type diff' output to lvmdump.
Return failure when specifying negative size for pvresize.
Fix memory corruption in cmd context refresh if clvmd leaks opened device.
Reinitialise lvmcache properly on fork to fix premature polldaemon exit.
Reinitialize lvmcache properly on fork to fix premature polldaemon exit.
Add 'lvm dumpconfig --type diff' to show differences from defaults.
Fix swap signature detection for devices smaller then 2MB.
Use dm_malloc function in clvmd.c.
@ -1732,7 +1922,7 @@ Version 2.02.106 - 10th April 2014
Don't print an error and accept empty value for global/thin_disabled_features.
Update API for internal function build_dm_uuid().
Do not try to check empty pool with scheduled messages.
Fix return value in pool_has_message() when quering for any message.
Fix return value in pool_has_message() when querying for any message.
Cleanup all client resources on clvmd exit.
Use dm_zalloc to clear members of clvmd client struct.
Use BLKID_CFLAGS when compiling with blkid support.
@ -1774,7 +1964,7 @@ Version 2.02.106 - 10th April 2014
Fix test when checking target version for available thin features.
Detect thin feature external_origin_extend and limit extend when missing.
Rename internal pool_can_resize_metadata() to thin_pool_feature_supported().
Issue error if libbblkid detects signature and fails to return offset/length.
Issue error if libblkid detects signature and fails to return offset/length.
Update autoconf config.guess/sub to 2014-01-01.
Online thin pool metadata resize requires 1.10 kernel thin pool target.
@ -1847,7 +2037,7 @@ Version 2.02.104 - 13th November 2013
=====================================
Workaround VG refresh race during autoactivation by retrying the refresh.
Handle failures in temporary mirror used when adding images to mirrors.
Fix and improve logic for implicitely exclusive activations.
Fix and improve logic for implicitly exclusive activations.
Return success when LV cannot be activated because of volume_list filter.
Return proper error state for remote exclusive activation.
Fix missing lvmetad scan for PVs found on MD partitions.
@ -2010,11 +2200,11 @@ Version 2.02.99 - 24th July 2013
Add support for persistent flagging of LVs to be skipped during activation.
Add --type profilable to lvm dumpconfig to show profilable config settings.
Add --mergedconfig to lvm dumpconfig for merged --config/--profile/lvm.conf.
Relase memory and unblock signals in lock_vol error path.
Release memory and unblock signals in lock_vol error path.
Define LVM2_* command errors in lvm2cmd.h and use in dmeventd plugins.
Move errors.h to tools dir.
Add man page entries for profile configuration and related options.
Improve error loging when user tries to interrupt commands.
Improve error logging when user tries to interrupt commands.
Rename _swap_lv to _swap_lv_identifiers and move to allow an additional user.
Rename snapshot segment returning methods from find_*_cow to find_*_snapshot.
liblvm/python API: Additions: PV create/removal/resize/listing
@ -2215,7 +2405,7 @@ Version 2.02.98 - 15th October 2012
Do not start dmeventd for lvchange --resync when monitoring is off.
Remove pvscan --cache from lvm2-lvmetad init script.
Remove ExecStartPost with pvscan --cache from lvm2-lvmetad.service.
Report invalid percentage for property snap_percent of non-snaphot LVs.
Report invalid percentage for property snap_percent of non-snapshot LVs.
Disallow conversion of thin LVs to mirrors.
Fix lvm2api data_percent reporting for thin volumes.
Do not allow RAID LVs in a clustered volume group.
@ -2265,7 +2455,7 @@ Version 2.02.98 - 15th October 2012
Version 2.02.97 - 7th August 2012
=================================
Improve documention of allocation policies in lvm.8.
Improve documentation of allocation policies in lvm.8.
Increase limit for major:minor to 4095:1048575 when using -My option.
Add make install_systemd_generators.
Add generator for lvm2 activation systemd units.
@ -2349,7 +2539,7 @@ Version 2.02.96 - 8th June 2012
Check for buffer overwrite in get_cluster_type() in clvmd.
Fix global/detect_internal_vg_cache_corruption config check.
Update lcov Makefile target to support all dmeventd plugins.
Fix initializiation of thin monitoring. (2.02.92)
Fix initialization of thin monitoring. (2.02.92)
Cope with improperly formatted device numbers in /proc/devices. (2.02.91)
Exit if LISTEN_PID environment variable incorrect in lvmetad systemd handover.
Use pvscan --cache instead of vgscan in lvmetad scripts.
@ -2362,7 +2552,7 @@ Version 2.02.96 - 8th June 2012
Add --with-thin-check configure option for path to thin_check.
Fix error message when pvmove LV activation fails with name already in use.
Better structure layout for device_info in dev_subsystem_name().
Change message severity for creation of VG over uninitialised devices.
Change message severity for creation of VG over uninitialized devices.
Fix error path for failed toolcontext creation.
Detect lvm binary path in lvmetad udev rules.
Don't unlink socket on lvmetad shutdown if instantiated from systemd.
@ -2397,7 +2587,7 @@ Version 2.02.94 - 3rd March 2012
Add some close() and dev_close() error path backtraces.
Set stdin/stdout/stderr to /dev/null for polldaemon.
Limit the max size of processed clvmd message to ~8KB.
Do not send uninitialised bytes in cluster error reply messages.
Do not send uninitialized bytes in cluster error reply messages.
Use unsigned type for bitmask instead of enum type for lvm properties.
Add missing cleanup of excl_uuid hash on some exit paths of clvmd.
Check for existence of vg_name in _format1/_pool_vg_read().
@ -2470,7 +2660,7 @@ Version 2.02.91 - 12th February 2012
Version 2.02.90 - 1st February 2012
===================================
sync_local_dev_names before (re)activating mirror log for initialisation.
sync_local_dev_names before (re)activating mirror log for initialization.
Disable partial activation for thin LVs and LVs with all missing segments.
Do not print warning for pv_min_size between 512KB and 2MB.
Clean up systemd unit ordering and requirements.
@ -2489,7 +2679,7 @@ Version 2.02.89 - 26th January 2012
Add data_percent and metadata_percent for thin pools to lvs -v.
Add data_lv & metadata_lv fields to lvs for thin pools.
Add data_percent & pool_lv fields to lvs for thin volumes.
Rename origin_only parm to use_layer for lv_info and use with thin LVs.
Rename origin_only param to use_layer for lv_info and use with thin LVs.
Add lv_thin_pool_transaction_id to read the transaction_id value.
Use {suspend,resume}_origin_only when up-converting RAID, as mirrors do.
Always add RAID metadata LVs to deptree (even when origin_only is set).
@ -2519,7 +2709,7 @@ Version 2.02.89 - 26th January 2012
Add _dev_init to initialize common struct device members.
Always zalloc struct device during initialization.
Fix missing thread list manipulation protection in dmeventd.
Do not derefence lv pointer in _percent_run() function before NULL check.
Do not dereference lv pointer in _percent_run() function before NULL check.
Allow empty strings for description and creation_host config fields.
Issue deprecation warning when removing last lvm1-format snapshot.
Reinstate support for snapshot removal with lvm1 format. (2.02.86)
@ -2590,11 +2780,11 @@ Version 2.02.89 - 26th January 2012
Change vg_revert to void and remove superfluous calls after failed vg_commit.
Use execvp for CLVMD restart to preserve environment settings.
Restart CLVMD with same cluster manager.
Fix log_error() usage in raid and unknown segtype initialisation.
Fix log_error() usage in raid and unknown segtype initialization.
Improve testing Makefile.
Fix install_ocf make target when srcdir != builddir. (2.02.80)
Support env vars LVM_CLVMD_BINARY and LVM_BINARY in clvmd.
Fix restart of clvmd (preserve exlusive locks). (2.02.64)
Fix restart of clvmd (preserve exclusive locks). (2.02.64)
Add 'Volume Type' lv_attr characters for RAID and RAID_IMAGE.
Add activation/retry_deactivation to lvm.conf to retry deactivation of an LV.
Replace open_count check with holders/mounted_fs check on lvremove path.
@ -2660,13 +2850,13 @@ Version 2.02.87 - 12th August 2011
Cache and share generated VG structs.
Fix possible format instance memory leaks and premature releases in _vg_read.
Suppress locking error messages in monitoring init scripts.
If pipe in clvmd fails return busy instead of using uninitialised descriptors.
If pipe in clvmd fails return busy instead of using uninitialized descriptors.
Add ability to reduce the number of mirrors in raid1 arrays to lvconvert.
Add dmeventd plugin for raid.
Replace free_vg with release_vg and move it to vg.c.
Remove INCONSISTENT_VG flag from the code.
Remove lock from cache in _lock_vol even if unlock fails.
Initialise clvmd locks before lvm context to avoid open descriptor leaks.
Initialize clvmd locks before lvm context to avoid open descriptor leaks.
Remove obsolete gulm clvmd cluster locking support.
Suppress low-level locking errors and warnings while using --sysinit.
Remove unused inconsistent_seqno variable in _vg_read().
@ -2739,7 +2929,7 @@ Version 2.02.85 - 29th April 2011
Issue discards on lvremove and lvreduce etc. if enabled and supported.
Add seg_pe_ranges and devices fields to liblvm.
Fix incorrect tests for dm_snprintf() failure.
Fix some unmatching sign comparation gcc warnings in the code.
Fix some unmatching sign comparison gcc warnings in the code.
Support lv_extend() on empty LVs.
Avoid regenerating cache content when exported VG buffer is unchanged.
Extend the set of memory regions that are not locked to memory.
@ -2765,7 +2955,7 @@ Version 2.02.85 - 29th April 2011
Use only vg_set_fid and new pv_set_fid fn to assign the format instance.
Make create_text_context fn static and move it inside create_instance fn.
Add mem and ref_count fields to struct format_instance for own mempool use.
Use new alloc_fid fn for common format instance initialisation.
Use new alloc_fid fn for common format instance initialization.
Optimise _get_token() and _eat_space().
Add _lv_postorder_vg() to improve efficiency for all LVs in VG.
Add gdbinit script for debugging.
@ -2774,10 +2964,10 @@ Version 2.02.85 - 29th April 2011
Avoid possible endless loop in _free_vginfo when 4 or more VGs have same name.
Use empty string instead of /dev// for LV path when there's no VG.
Don't allocate unused VG mempool in _pvsegs_sub_single.
Do not send uninitialised bytes in local clvmd messages.
Do not send uninitialized bytes in local clvmd messages.
Support --help option for clvmd and return error for unknown option.
Avoid reading freed memory when printing LV segment type.
Fix syslog initialisation in clvmd to respect lvm.conf setting.
Fix syslog initialization in clvmd to respect lvm.conf setting.
Fix possible overflow in maximum stripe size and physical extent size.
Improve pvremove error message when PV belongs to a VG.
Extend normal policy to allow mirror logs on same PVs as images if necessary.
@ -2791,7 +2981,7 @@ Version 2.02.85 - 29th April 2011
Restructure existing pv_setup and pv_write and add pv_initialise.
Add internal interface to support adding and removing metadata areas.
Allow internal indexing of metadata areas (PV id + mda order).
Generalise internal format_instance infrastrusture for PV and VG use.
Generalise internal format_instance infrastructure for PV and VG use.
Handle decimal digits with --units instead of ignoring them silently.
Fix remaining warnings and compile with -Wpointer-arith.
Fix gcc warnings for unused variables and const casts.
@ -2805,7 +2995,7 @@ Version 2.02.85 - 29th April 2011
Make pv_min_size configurable and increase to 2048KB to exclude floppy drives.
Add find_config_tree_int64 to read 64-bit ints from config.
Ensure resuming exclusive cluster mirror continues to use local mirror target.
Clear temporary postorder LV status flags to allow re-use with same LV struct.
Clear temporary postorder LV status flags to allow reuse with same LV struct.
Remove invalid snapshot umount mesg which floods syslog from dmeventd plugin.
Add extended examples to pvmove man page.
Support LVM_TEST_DEVDIR env var for private /dev during testing.
@ -2860,7 +3050,7 @@ Version 2.02.80 - 10th January 2011
Speed up command processing by caching resolved config tree.
Pass config_tree to renamed function import_vg_from_config_tree().
Detect NULL handle in get_property().
Fix superfluous /usr in ocf_scriptdir instalation path.
Fix superfluous /usr in ocf_scriptdir installation path.
Add --with-ocfdir configurable option.
Add aclocal.m4 (for pkgconfig).
Fix memory leak in persistent filter creation error path.
@ -2892,7 +3082,7 @@ Version 2.02.79 - 20th December 2010
Add copy_percent and snap_percent to liblvm.
Enhance vg_validate to ensure integrity of LV and PV structs referenced.
Enhance vg_validate to check composition of pvmove LVs.
Create /var/run/lvm directory during clvmd initialisation if missing.
Create /var/run/lvm directory during clvmd initialization if missing.
Use new dm_prepare_selinux_context instead of dm_set_selinux_context.
Avoid revalidating the label cache immediately after scanning.
Support scanning for a single VG in independent mdas.
@ -3161,7 +3351,7 @@ Version 2.02.68 - 23rd June 2010
Add device name and offset to raw_read_mda_header error messages.
Honour log argument when down-converting stacked mirror.
Sleep to workaround clvmd -S race: socket closed early and server drops cmd.
Use early udev synchronisation and update of dev nodes for clustered mirrors.
Use early udev synchronization and update of dev nodes for clustered mirrors.
Remove incorrect inclusion of kdev_t.h from cmirrord/functions.h.
Add man pages for lvmconf and non-existent lvmsadc and lvmsar tools.
Exit successfully when using -o help (but not -o +help) with LVM reports.
@ -3189,7 +3379,7 @@ Version 2.02.67 - 4th June 2010
Avoid selecting names under /dev/block if there is an alternative.
Update clustered log kernel module name to log-userspace for 2.6.31 onwards.
Add replicators' LVs to dtree for activation.
Supress activation message if there is a missing replicator VG.
Suppress activation message if there is a missing replicator VG.
Fix scripts/relpath.awk to work in mawk
Extend lock_vol to check for missing replicator VGs first.
Update _process_one_vg and process_each_lv_in_vg to populate cmd_vg.
@ -3240,7 +3430,7 @@ Version 2.02.65 - 17th May 2010
Version 2.02.64 - 30th April 2010
=================================
Avoid pointless initialisation when the 'version' command is run directly.
Avoid pointless initialization when the 'version' command is run directly.
Fix memory leak for invalid regex pattern input.
Display invalid regex pattern for filter configuration in case of error.
Remove no-longer-used arg_ptr_value.
@ -3399,7 +3589,7 @@ Version 2.02.60 - 23rd January 2010
Disable memory debugging if dmeventd is configured. (Not thread-safe.)
Fix first log message prefix in syslog for dmeventd plugins.
Fix exported symbols names for dmeventd lvm2 wrapper plugin.
Make failed locking initialisation messages more descriptive.
Make failed locking initialization messages more descriptive.
Version 2.02.59 - 21st January 2010
===================================
@ -3415,7 +3605,7 @@ Version 2.02.59 - 21st January 2010
Fix detection of completed snapshot merge.
Add Red Hat cmirror initscript (unfinished).
Add cmirrord man page (incomplete).
Make cluster log communication structures architecture independant.
Make cluster log communication structures architecture independent.
Fix cluster log in-memory bitmap handling.
Improve snapshot merge metadata import validation.
Improve target type compatibility checking in _percent_run().
@ -3491,7 +3681,7 @@ Version 2.02.57 - 12th January 2010
Impose limit of 8 mirror images to match the in-kernel kcopyd restriction.
Use locking_type 3 (compiled in) for lvmconf --enable-cluster.
Remove list.c and list.h with no-longer-used dm_list macros and functions.
Log failure type and recognise type 'F' (flush) in dmeventd mirror plugin.
Log failure type and recognize type 'F' (flush) in dmeventd mirror plugin.
Extend internal PV/VG/LV/segment status variables from 32-bit to 64-bit.
Version 2.02.56 - 24th November 2009
@ -3529,14 +3719,14 @@ Version 2.02.54 - 26th October 2009
Fix clvmd segfault when refresh_toolcontext fails.
Remember to clear 'global lock held during cache refresh' state after use.
Use udev flags support in LVM and apply various fixes to udev rules.
Delay announcing mirror monitoring to syslog until initialisation succeeded.
Delay announcing mirror monitoring to syslog until initialization succeeded.
Handle metadata with unknown segment types more gracefully.
Set default owner and group to null.
Add dmeventd.static to the build.
Disable realtime support code by default.
Make clvmd return 0 on success rather than 1.
Add --pvmetadatacopies for pvcreate, vgcreate, vgextend, vgconvert.
Add implict pvcreate support to vgcreate and vgextend.
Add implicit pvcreate support to vgcreate and vgextend.
Correct example.conf to indicate that lvm2 not lvm1 is the default format.
Remove an unused stray LVM1_SUPPORT ifdef.
Only include selinux libs in libdevmapper.pc when selinux build enabled.
@ -3716,7 +3906,7 @@ Version 2.02.48 - 30th June 2009
Reinstate partial activation support in clustered mode. (2.02.40)
Allow metadata correction even when PVs are missing.
Use 'lvm lvresize' instead of 'lvresize' in fsadm.
Do not use '-n' realine option in fsadm for busybox compatiblity.
Do not use '-n' realine option in fsadm for busybox compatibility.
Add vg_lock_newname() library function for vgrename, vgsplit and vgcreate.
Round up requested readahead to at least one page and print warning.
Try to repair vg before actual vgremove when force flag provided.
@ -3777,7 +3967,7 @@ Version 2.02.46 - 21st May 2009
Fix first_seg() call for empty segment list.
Add install_lvm2 makefile target to install only the LVM2 components.
Reject missing PVs from allocation in toollib.
Fix PV datalignment for values starting prior to MDA area. (2.02.45)
Fix PV dataalignment for values starting prior to MDA area. (2.02.45)
Add sparse devices: lvcreate -s --virtualoriginsize (hidden zero origin).
Fix minimum width of devices column in reports.
Add lvs origin_size field.
@ -3850,7 +4040,7 @@ Version 2.02.45 - 3rd March 2009
Separate PV label attributes which do not need parse metadata when reporting.
Remove external dependency on the 'cut' command from fsadm.
Fix pvs segfault when pv mda attributes requested for not available PV.
Add fsadm support for reszing ext4 filesysystems.
Add fsadm support for resizing ext4 filesystems.
Move locking_type reading inside init_locking().
Rename get_vgs() to get_vgnames() and clarify related error messages.
Allow clvmd to be built with all cluster managers & select one on cmdline.
@ -4027,7 +4217,7 @@ Version 2.02.37 - 6th June 2008
Refactor some vginfo manipulation code.
Add assertions to trap deprecated P_ and V_ lock usage.
Add missing mutex around clvmd lvmcache_drop_metadata library call.
Fix uninitialised mutex in clvmd if all daemons are not running at startup.
Fix uninitialized mutex in clvmd if all daemons are not running at startup.
Avoid using DLM locks with LCK_CACHE type P_ lock requests.
When asked to drop cached committed VG metadata, invalidate cached PV labels.
Drop metadata cache before writing precommitted metadata instead of after.
@ -4074,7 +4264,7 @@ Version 2.02.34 - 10th April 2008
Mention default --clustered setting in vgcreate man page.
Add config file overrides to clvmd when it reads the active LVs list.
Fix vgreduce to use vg_split_mdas to check sufficient mdas remain.
Add (empty) orphan VGs to lvmcache during initialisation.
Add (empty) orphan VGs to lvmcache during initialization.
Fix orphan VG name used for format_pool.
Create a fid for internal orphan VGs.
Update lvmcache VG lock state for all locking types now.
@ -4092,7 +4282,7 @@ Version 2.02.34 - 10th April 2008
Fix redundant lvresize message if vg doesn't exist.
Fix another allocation bug with clvmd and large node IDs.
Add find_lv_in_lv_list() and find_pv_in_pv_list().
Fix uninitialised variable in clvmd that could cause odd hangs.
Fix uninitialized variable in clvmd that could cause odd hangs.
Add vgmerge tests.
Add pvseg_is_allocated() for identifying a PV segment allocated to a LV.
Add list_move() for moving elements from one list to another.
@ -4100,7 +4290,7 @@ Version 2.02.34 - 10th April 2008
Correct command name in lvmdiskscan man page.
clvmd no longer crashes if it sees nodeids over 50.
Fix potential deadlock in clvmd thread handling.
Refactor text format initialisation into _init_text_import.
Refactor text format initialization into _init_text_import.
Escape double quotes and backslashes in external metadata and config data.
Add functions for escaping double quotes in strings.
Rename count_chars_len to count_chars.
@ -4150,7 +4340,7 @@ Version 2.02.31 - 19th January 2008
Version 2.02.30 - 17th January 2008
===================================
Set default readahead to twice maximium stripe size.
Set default readahead to twice maximum stripe size.
Reinstate VG extent size and stripe size defaults (halved). (2.02.29)
Add lists of stacked LV segments using each LV to the internal metadata.
Change vgsplit -l (for unimplemented --list) into --maxlogicalvolumes.
@ -4522,7 +4712,7 @@ Version 2.02.11 - 12th October 2006
Capture error messages in clvmd and pass them back to the user.
Remove unused #defines from filter-md.c.
Make clvmd restart init script wait until clvmd has died before starting it.
Add -R to clvmd which tells running clvmds to reload their device cache.
Add -R to clvmd which tells running clvmd to reload their device cache.
Add LV column to reports listing kernel modules needed for activation.
Show available fields if report given invalid field. (e.g. lvs -o list)
Add timestamp functions with --disable-realtime configure option.
@ -4849,7 +5039,7 @@ Version 2.01.08 - 22nd March 2005
Improve detection of external changes affecting internal cache.
Add 'already in device cache' debug message.
Add -a to pvdisplay -C.
Avoid rmdir opendir error messsages when dir was already removed.
Avoid rmdir opendir error messages when dir was already removed.
Tighten signal handlers.
Avoid some compiler warnings.
Additional rename failure error message.
@ -5080,7 +5270,7 @@ Version 2.00.17 - 20 June 2004
fsadm support for fsck and resizing - needs testing.
Add read-only GFS pool support.
Add lvm2create_initrd script from http://poochiereds.net/svn/lvm2/
Fix rounding of large diplayed sizes.
Fix rounding of large displayed sizes.
Suppress decimal point when using units of sectors/bytes.
Additional kernel target checks before pvmove & snapshot creation.
Add i2o_block.
@ -5295,3 +5485,5 @@ Display output. Some metadata information cannot yet be displayed.
Recovery tools to salvage "lost" metadata directly from the disks:
but we hope the new format will mean such tools are hardly ever needed!

View File

@ -1,5 +1,77 @@
Version 1.02.181 -
Version 1.02.202 -
===================
Version 1.02.201 - 02nd October 2024
====================================
Cleanup udev sync semaphore if dm_{udev_create,task_set}_cookie fails.
Improve error messages on failed udev cookie create/inc/dec operation.
Version 1.02.200 - 23rd August 2024
===================================
Version 1.02.199 - 12nd July 2024
=================================
Version 1.02.198 - 16th May 2024
================================
Fix static only compilation of libdevmapper.a and dmsetup tool.
Use better code for closing opened descriptors when starting dmeventd.
Correct dmeventd -R for systemd environment.
Restart of dmeventd -R checks pid file to detect running dmeventd first.
Query with dmeventd -i quickly ends when there is no running dmeventd.
Enhance dm_get_status_raid to handle mismatching status or reported legs.
Create /dev/disk/by-label symlinks for DM devs that have crypto as next layer.
Persist udev db for DM devs on cleanup used in initrd to rootfs transition.
Process synthetic udev events other than 'add/change' as 'change' events.
Increase DM_UDEV_RULES_VSN to 3 to indicate changed udev rules.
Rename DM_NOSCAN to .DM_NOSCAN so it's not stored in udev db.
Rename DM_SUSPENDED to .DM_SUSPENDED so it's not stored in udev db.
Do not import DM_UDEV_DISABLE_OTHER_RULES_FLAG from db in 10-dm-disk.rules.
Test DISK_RO after importing properties from db in 10-dm.rules.
Also import ID_FS_TYPE in 13-dm-disk.rules from db if needed.
Version 1.02.197 - 21st November 2023
=====================================
Fix invalid JSON report if using DM_REPORT_OUTPUT_MULTIPLE_TIMES and selection.
Propagate ioctl errno from dm_task_run when creating new table line.
Add support for group aliases in dmstats.
Add support for exit-on file for dmeventd to reduce shutdown delays.
Add configure option --with-dmeventd-exit-on-path to specify default path.
Add dmsetup --headings none|abbrev|full to set report headings type.
Add DM_REPORT_OUTPUT_FIELD_IDS_IN_HEADINGS to provide alternative headings.
Version 1.02.196 - 02nd August 2023
===================================
Version 1.02.195 - 21st April 2023
==================================
Version 1.02.193 - 21st March 2023
==================================
Version 1.02.191 - 21st February 2023
=====================================
Improve parallel creation of /dev/mapper/control device node.
Import previous ID_FS_* udev records in 13-dm-disk.rules for suspended DM dev.
Remove NAME="mapper/control" rule from 10-dm.rules to avoid udev warnings.
Version 1.02.189 - 22nd December 2022
=====================================
Improve 'dmsetup create' without given table line with new kernels.
Version 1.02.187 - 10th November 2022
=====================================
Add DM_REPORT_GROUP_JSON_STD for more JSON standard compliant output format.
Version 1.02.185 - 18th May 2022
================================
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.
@ -24,7 +96,7 @@ Version 1.02.173 - 09th August 2020
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).
Fix dm_list iterators with gcc 10 optimization (-ftree-pta).
Dmeventd handles timer without looping on short intervals.
Version 1.02.169 - 11th February 2020
@ -55,7 +127,7 @@ Version 1.02.155 - 18th December 2018
=====================================
Include correct internal header inside libdm list.c.
Enhance ioctl flattening and add parameters only when needed.
Add DM_DEVICE_ARM_POLL for API completness matching kernel.
Add DM_DEVICE_ARM_POLL for API completeness matching kernel.
Do not add parameters for RESUME with DM_DEVICE_CREATE dm task.
Fix dmstats report printing no output.
@ -84,7 +156,7 @@ Version 1.02.147-rc1 - 24th May 2018
Reuse uname() result for mirror target.
Recognize also mounted btrfs through dm_device_has_mounted_fs().
Add missing log_error() into dm_stats_populate() returning 0.
Avoid calling dm_stats_populat() for DM devices without any stats regions.
Avoid calling dm_stats_populate() for DM devices without any stats regions.
Support DM_DEBUG_WITH_LINE_NUMBERS envvar for debug msg with source:line.
Configured command for thin pool threshold handling gets whole environment.
Fix tests for failing dm_snprintf() in stats code.
@ -133,7 +205,7 @@ Version 1.02.141 - 28th June 2017
Add dm_percent_to_round_float for adjusted percentage rounding.
Reset array with dead rimage devices once raid gets in sync.
Drop unneeded --config option from raid dmeventd plugin.
dm_get_status_raid() handle better some incosistent md statuses.
dm_get_status_raid() handle better some inconsistent md statuses.
Accept truncated files in calls to dm_stats_update_regions_from_fd().
Restore Warning by 5% increment when thin-pool is over 80% (1.02.138).
@ -328,7 +400,7 @@ Version 1.02.112 - 28th November 2015
=====================================
Show error message when trying to create unsupported raid type.
Improve preloading sequence of an active thin-pool target.
Drop extra space from cache target line to fix unneded table reloads.
Drop extra space from cache target line to fix unneeded table reloads.
Version 1.02.111 - 23rd November 2015
=====================================
@ -343,7 +415,7 @@ Version 1.02.110 - 30th October 2015
Disable thin monitoring plugin when it fails too often (>10 times).
Fix/restore parsing of empty field '-' when processing dmeventd event.
Enhance dm_tree_node_size_changed() to recognize size reduction.
Support exit on idle for dmenventd (1 hour).
Support exit on idle for dmeventd (1 hour).
Add support to allow unmonitor device from plugin itself.
New design for thread co-operation in dmeventd.
Dmeventd read device status with 'noflush'.
@ -516,7 +588,7 @@ Version 1.02.93 - 21st January 2015
Version 1.02.92 - 24th November 2014
====================================
Fix memory corruption with sorting empty string lists (1.02.86).
Fix man dmsetup.8 syntax warning of Groff
Fix man dmsetup.8 syntax warning of Groff.
Accept unquoted strings and / in place of {} when parsing configs.
Version 1.02.91 - 11th November 2014
@ -535,7 +607,7 @@ Version 1.02.90 - 1st September 2014
Version 1.02.89 - 26th August 2014
==================================
Improve libdevmapper-event select() error handling.
Add extra check for matching transation_id after message submitting.
Add extra check for matching transaction_id after message submitting.
Add dm_report_field_string_list_unsorted for str. list report without sorting.
Support --deferred with dmsetup remove to defer removal of open devices.
Update dm-ioctl.h to include DM_DEFERRED_REMOVE flag.
@ -622,7 +694,7 @@ Version 1.02.82 - 4th October 2013
Version 1.02.81 - 23rd September 2013
=====================================
Tidy dmeventd fifo initialisation.
Tidy dmeventd fifo initialization.
Version 1.02.80 - 20th September 2013
=====================================
@ -647,7 +719,7 @@ Version 1.02.78 - 24th July 2013
Always return success on dmeventd -V command call.
Fix parsing of 64bit snapshot status in dmeventd snapshot plugin.
Add dm_get_status_snapshot() for parsing snapshot status.
Detecte mounted fs also via reading /proc/self/mountinfo.
Detect mounted fs also via reading /proc/self/mountinfo.
Add dm_mountinfo_read() for parsing /proc/self/mountinfo.
Report error for nonexisting devices in dmeventd communication.
Prevent double free error after dmeventd call of _fill_device_data().
@ -744,7 +816,7 @@ Version 1.02.71 - 20th February 2012
Add "watch" rule to 13-dm-disk.rules.
Detect failing fifo and skip 20s retry communication period.
Add DM_DEFAULT_NAME_MANGLING_MODE environment variable as an override.
Add dm_lib_init to automatically initialise device-mapper library on load.
Add dm_lib_init to automatically initialize device-mapper library on load.
Replace any '\' char with '\\' in dm table specification on input.
Add mangle command to dmsetup to provide renaming to correct mangled form.
Add 'mangled_name' and 'unmangled_name' fields to dmsetup info -c -o.
@ -838,7 +910,7 @@ Version 1.02.66 - 12th August 2011
Fix memory leak in dmsetup _message() memory allocation error path.
Use new oom killer adjustment interface (oom_score_adj) when available.
Add systemd unit files for dmeventd.
Fix read-only identical table reload supression.
Fix read-only identical table reload suppression.
Version 1.02.65 - 8th July 2011
===============================
@ -853,7 +925,7 @@ Version 1.02.65 - 8th July 2011
Add dm_get_suspended_counter() for number of devs in suspended state by lib.
Fix "all" report field prefix matching to include label fields with pv_all.
Delay resuming new preloaded mirror devices with core logs in deptree code.
Accept new kernel version 3 uname formats in initialisation.
Accept new kernel version 3 uname formats in initialization.
Version 1.02.64 - 29th April 2011
==================================
@ -867,7 +939,7 @@ Version 1.02.64 - 29th April 2011
Improve stack debug reporting in dm_task_create().
Fallback to control node creation only if node doesn't exist yet.
Change dm_hash binary functions to take void *key instead of char *.
Fix uninitialised memory use with empty params in _reload_with_suppression_v4.
Fix uninitialized memory use with empty params in _reload_with_suppression_v4.
Lower severity of selabel_lookup and matchpathcon failure to log_debug.
Add test for failed allocation from dm_task_set_uuid() in dmeventd.
Add dm_event_get_version to dmeventd for use with -R.
@ -1036,7 +1108,7 @@ Version 1.02.44 - 15th February 2010
Version 1.02.43 - 21st January 2010
===================================
Remove bitset, hash and pool headers superceded by libdevmapper.h.
Remove bitset, hash and pool headers superseded by libdevmapper.h.
Fix off-by-one error causing bad cluster mirror table construction.
Version 1.02.42 - 14th January 2010
@ -1092,7 +1164,7 @@ Version 1.02.37 - 15th September 2009
Version 1.02.36 - 6th August 2009
=================================
Add udevcookies, udevcomplete, udevcomplete_all and --noudevwait to dmsetup.
Add libdevmapper functions to support synchronisation with udev.
Add libdevmapper functions to support synchronization with udev.
Version 1.02.35 - 28th July 2009
================================
@ -1160,7 +1232,7 @@ Version 1.02.27 - 25th June 2008
Version 1.02.26 - 6th June 2008
===============================
Initialise params buffer to empty string in _emit_segment.
Initialize params buffer to empty string in _emit_segment.
Skip add_dev_node when ioctls disabled.
Make dm_hash_iter safe against deletion.
Accept a NULL pointer to dm_free silently.
@ -1216,7 +1288,7 @@ Version 1.02.20 - 15th June 2007
Version 1.02.19 - 27th April 2007
=================================
Standardise protective include file #defines.
Standardize protective include file #defines.
Add regex functions to library.
Avoid trailing separator in reports when there are hidden sort fields.
Fix segfault in 'dmsetup status' without --showkeys against crypt target.
@ -1247,7 +1319,7 @@ Version 1.02.16 - 25th January 2007
Streamline dm_report_field_* interface.
Add cmdline debug & version options to dmeventd.
Add DM_LIB_VERSION definition to configure.h.
Suppress 'Unrecognised field' error if report field is 'help'.
Suppress 'Unrecognized field' error if report field is 'help'.
Add --separator and --sort to dmsetup (unused).
Make alignment flag optional when specifying report fields.
@ -1495,3 +1567,5 @@ Version 1.00.08 - 27 Feb 2004
Fixed DESTDIR for make install/install_static_lib.
Updated README/INSTALL to reflect move to sources.redhat.com.
Updated autoconf files to 2003-06-17.

View File

@ -62,6 +62,24 @@ AC_DEFUN([AC_TRY_LDFLAGS],
fi
])
dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE,
dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
dnl -------------------------------------------
dnl Since: 0.28
dnl
dnl Retrieves the value of the pkg-config variable for the given module.
AC_DEFUN([PKG_CHECK_VAR],
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl
_PKG_CONFIG([$1], [variable="][$3]["], [$2])
AS_VAR_COPY([$1], [pkg_cv_][$1])
AS_VAR_IF([$1], [""], [$5], [$4])dnl
])dnl PKG_CHECK_VAR
# ===========================================================================
# http://www.gnu.org/software/autoconf-archive/ax_gcc_builtin.html
# ===========================================================================

319
aclocal.m4 vendored
View File

@ -1,6 +1,6 @@
# generated automatically by aclocal 1.16.2 -*- Autoconf -*-
# generated automatically by aclocal 1.16.5 -*- Autoconf -*-
# Copyright (C) 1996-2020 Free Software Foundation, Inc.
# Copyright (C) 1996-2021 Free Software Foundation, Inc.
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -69,8 +69,8 @@ AC_DEFUN([AX_PYTHON_MODULE],[
fi
])
# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
# serial 11 (pkg-config-0.29.1)
# pkg.m4 - Macros to locate and use pkg-config. -*- Autoconf -*-
# serial 12 (pkg-config-0.29.2)
dnl Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
dnl Copyright © 2012-2015 Dan Nicholson <dbn.lists@gmail.com>
@ -112,13 +112,13 @@ dnl
dnl See the "Since" comment for each macro you use to see what version
dnl of the macros you require.
m4_defun([PKG_PREREQ],
[m4_define([PKG_MACROS_VERSION], [0.29.1])
[m4_define([PKG_MACROS_VERSION], [0.29.2])
m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1,
[m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])])
])dnl PKG_PREREQ
dnl PKG_PROG_PKG_CONFIG([MIN-VERSION])
dnl ----------------------------------
dnl PKG_PROG_PKG_CONFIG([MIN-VERSION], [ACTION-IF-NOT-FOUND])
dnl ---------------------------------------------------------
dnl Since: 0.16
dnl
dnl Search for the pkg-config tool and set the PKG_CONFIG variable to
@ -126,6 +126,12 @@ dnl first found in the path. Checks that the version of pkg-config found
dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is
dnl used since that's the first version where most current features of
dnl pkg-config existed.
dnl
dnl If pkg-config is not found or older than specified, it will result
dnl in an empty PKG_CONFIG variable. To avoid widespread issues with
dnl scripts not checking it, ACTION-IF-NOT-FOUND defaults to aborting.
dnl You can specify [PKG_CONFIG=false] as an action instead, which would
dnl result in pkg-config tests failing, but no bogus error messages.
AC_DEFUN([PKG_PROG_PKG_CONFIG],
[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$])
@ -146,6 +152,9 @@ if test -n "$PKG_CONFIG"; then
AC_MSG_RESULT([no])
PKG_CONFIG=""
fi
fi
if test -z "$PKG_CONFIG"; then
m4_default([$2], [AC_MSG_ERROR([pkg-config not found])])
fi[]dnl
])dnl PKG_PROG_PKG_CONFIG
@ -157,7 +166,7 @@ dnl Check to see whether a particular set of modules exists. Similar to
dnl PKG_CHECK_MODULES(), but does not set variables or print errors.
dnl
dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG])
dnl only at the first occurence in configure.ac, so if the first place
dnl only at the first occurrence in configure.ac, so if the first place
dnl it's called might be skipped (such as if it is within an "if", you
dnl have to call PKG_CHECK_EXISTS manually
AC_DEFUN([PKG_CHECK_EXISTS],
@ -213,7 +222,7 @@ AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl
pkg_failed=no
AC_MSG_CHECKING([for $1])
AC_MSG_CHECKING([for $2])
_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
_PKG_CONFIG([$1][_LIBS], [libs], [$2])
@ -223,17 +232,17 @@ and $1[]_LIBS to avoid the need to call pkg-config.
See the pkg-config man page for more details.])
if test $pkg_failed = yes; then
AC_MSG_RESULT([no])
AC_MSG_RESULT([no])
_PKG_SHORT_ERRORS_SUPPORTED
if test $_pkg_short_errors_supported = yes; then
$1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1`
else
$1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1`
$1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1`
else
$1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1`
fi
# Put the nasty error message in config.log where it belongs
echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
# Put the nasty error message in config.log where it belongs
echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
m4_default([$4], [AC_MSG_ERROR(
m4_default([$4], [AC_MSG_ERROR(
[Package requirements ($2) were not met:
$$1_PKG_ERRORS
@ -244,8 +253,8 @@ installed software in a non-standard prefix.
_PKG_TEXT])[]dnl
])
elif test $pkg_failed = untried; then
AC_MSG_RESULT([no])
m4_default([$4], [AC_MSG_FAILURE(
AC_MSG_RESULT([no])
m4_default([$4], [AC_MSG_FAILURE(
[The pkg-config script could not be found or is too old. Make sure it
is in your PATH or set the PKG_CONFIG environment variable to the full
path to pkg-config.
@ -255,10 +264,10 @@ _PKG_TEXT
To get pkg-config, see <http://pkg-config.freedesktop.org/>.])[]dnl
])
else
$1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
$1[]_LIBS=$pkg_cv_[]$1[]_LIBS
$1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
$1[]_LIBS=$pkg_cv_[]$1[]_LIBS
AC_MSG_RESULT([yes])
$3
$3
fi[]dnl
])dnl PKG_CHECK_MODULES
@ -413,7 +422,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-2020 Free Software Foundation, Inc.
# Copyright (C) 1999-2021 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -492,7 +501,7 @@ AC_DEFUN([AM_PATH_PYTHON],
])
if test "$PYTHON" = :; then
dnl Run any user-specified action, or abort.
dnl Run any user-specified action, or abort.
m4_default([$3], [AC_MSG_ERROR([no suitable Python interpreter found])])
else
@ -501,27 +510,132 @@ AC_DEFUN([AM_PATH_PYTHON],
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.
dnl
AC_CACHE_CHECK([for $am_display_PYTHON version], [am_cv_python_version],
[am_cv_python_version=`$PYTHON -c "import sys; print('%u.%u' % sys.version_info[[:2]])"`])
[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
dnl values of PYTHON_PREFIX and PYTHON_EXEC_PREFIX. These are made
dnl distinct variables so they can be overridden if need be. However,
dnl general consensus is that you shouldn't need this ability.
AC_SUBST([PYTHON_PREFIX], ['${prefix}'])
AC_SUBST([PYTHON_EXEC_PREFIX], ['${exec_prefix}'])
dnl At times (like when building shared libraries) you may want
dnl At times, e.g., when building shared libraries, you may want
dnl to know which OS platform Python thinks this is.
dnl
AC_CACHE_CHECK([for $am_display_PYTHON platform], [am_cv_python_platform],
[am_cv_python_platform=`$PYTHON -c "import sys; sys.stdout.write(sys.platform)"`])
AC_SUBST([PYTHON_PLATFORM], [$am_cv_python_platform])
# Just factor out some code duplication.
dnl emacs-page
dnl If --with-python-sys-prefix is given, use the values of sys.prefix
dnl and sys.exec_prefix for the corresponding values of PYTHON_PREFIX
dnl and PYTHON_EXEC_PREFIX. Otherwise, use the GNU ${prefix} and
dnl ${exec_prefix} variables.
dnl
dnl The two are made distinct variables so they can be overridden if
dnl need be, although general consensus is that you shouldn't need
dnl this separation.
dnl
dnl Also allow directly setting the prefixes via configure options,
dnl overriding any default.
dnl
if test "x$prefix" = xNONE; then
am__usable_prefix=$ac_default_prefix
else
am__usable_prefix=$prefix
fi
# Allow user to request using sys.* values from Python,
# instead of the GNU $prefix values.
AC_ARG_WITH([python-sys-prefix],
[AS_HELP_STRING([--with-python-sys-prefix],
[use Python's sys.prefix and sys.exec_prefix values])],
[am_use_python_sys=:],
[am_use_python_sys=false])
# Allow user to override whatever the default Python prefix is.
AC_ARG_WITH([python_prefix],
[AS_HELP_STRING([--with-python_prefix],
[override the default PYTHON_PREFIX])],
[am_python_prefix_subst=$withval
am_cv_python_prefix=$withval
AC_MSG_CHECKING([for explicit $am_display_PYTHON prefix])
AC_MSG_RESULT([$am_cv_python_prefix])],
[
if $am_use_python_sys; then
# using python sys.prefix value, not GNU
AC_CACHE_CHECK([for python default $am_display_PYTHON prefix],
[am_cv_python_prefix],
[am_cv_python_prefix=`$PYTHON -c "import sys; sys.stdout.write(sys.prefix)"`])
dnl If sys.prefix is a subdir of $prefix, replace the literal value of
dnl $prefix with a variable reference so it can be overridden.
case $am_cv_python_prefix in
$am__usable_prefix*)
am__strip_prefix=`echo "$am__usable_prefix" | sed 's|.|.|g'`
am_python_prefix_subst=`echo "$am_cv_python_prefix" | sed "s,^$am__strip_prefix,\\${prefix},"`
;;
*)
am_python_prefix_subst=$am_cv_python_prefix
;;
esac
else # using GNU prefix value, not python sys.prefix
am_python_prefix_subst='${prefix}'
am_python_prefix=$am_python_prefix_subst
AC_MSG_CHECKING([for GNU default $am_display_PYTHON prefix])
AC_MSG_RESULT([$am_python_prefix])
fi])
# Substituting python_prefix_subst value.
AC_SUBST([PYTHON_PREFIX], [$am_python_prefix_subst])
# emacs-page Now do it all over again for Python exec_prefix, but with yet
# another conditional: fall back to regular prefix if that was specified.
AC_ARG_WITH([python_exec_prefix],
[AS_HELP_STRING([--with-python_exec_prefix],
[override the default PYTHON_EXEC_PREFIX])],
[am_python_exec_prefix_subst=$withval
am_cv_python_exec_prefix=$withval
AC_MSG_CHECKING([for explicit $am_display_PYTHON exec_prefix])
AC_MSG_RESULT([$am_cv_python_exec_prefix])],
[
# no explicit --with-python_exec_prefix, but if
# --with-python_prefix was given, use its value for python_exec_prefix too.
AS_IF([test -n "$with_python_prefix"],
[am_python_exec_prefix_subst=$with_python_prefix
am_cv_python_exec_prefix=$with_python_prefix
AC_MSG_CHECKING([for python_prefix-given $am_display_PYTHON exec_prefix])
AC_MSG_RESULT([$am_cv_python_exec_prefix])],
[
# Set am__usable_exec_prefix whether using GNU or Python values,
# since we use that variable for pyexecdir.
if test "x$exec_prefix" = xNONE; then
am__usable_exec_prefix=$am__usable_prefix
else
am__usable_exec_prefix=$exec_prefix
fi
#
if $am_use_python_sys; then # using python sys.exec_prefix, not GNU
AC_CACHE_CHECK([for python default $am_display_PYTHON exec_prefix],
[am_cv_python_exec_prefix],
[am_cv_python_exec_prefix=`$PYTHON -c "import sys; sys.stdout.write(sys.exec_prefix)"`])
dnl If sys.exec_prefix is a subdir of $exec_prefix, replace the
dnl literal value of $exec_prefix with a variable reference so it can
dnl be overridden.
case $am_cv_python_exec_prefix in
$am__usable_exec_prefix*)
am__strip_prefix=`echo "$am__usable_exec_prefix" | sed 's|.|.|g'`
am_python_exec_prefix_subst=`echo "$am_cv_python_exec_prefix" | sed "s,^$am__strip_prefix,\\${exec_prefix},"`
;;
*)
am_python_exec_prefix_subst=$am_cv_python_exec_prefix
;;
esac
else # using GNU $exec_prefix, not python sys.exec_prefix
am_python_exec_prefix_subst='${exec_prefix}'
am_python_exec_prefix=$am_python_exec_prefix_subst
AC_MSG_CHECKING([for GNU default $am_display_PYTHON exec_prefix])
AC_MSG_RESULT([$am_python_exec_prefix])
fi])])
# Substituting python_exec_prefix_subst.
AC_SUBST([PYTHON_EXEC_PREFIX], [$am_python_exec_prefix_subst])
# Factor out some code duplication into this shell variable.
am_python_setup_sysconfig="\
import sys
# Prefer sysconfig over distutils.sysconfig, for better compatibility
@ -541,96 +655,95 @@ try:
except ImportError:
pass"
dnl Set up 4 directories:
dnl emacs-page Set up 4 directories:
dnl pythondir -- where to install python scripts. This is the
dnl site-packages directory, not the python standard library
dnl directory like in previous automake betas. This behavior
dnl is more consistent with lispdir.m4 for example.
dnl 1. pythondir: where to install python scripts. This is the
dnl site-packages directory, not the python standard library
dnl directory like in previous automake betas. This behavior
dnl is more consistent with lispdir.m4 for example.
dnl Query distutils for this directory.
AC_CACHE_CHECK([for $am_display_PYTHON script directory],
[am_cv_python_pythondir],
[if test "x$prefix" = xNONE
then
am_py_prefix=$ac_default_prefix
else
am_py_prefix=$prefix
fi
am_cv_python_pythondir=`$PYTHON -c "
dnl
AC_CACHE_CHECK([for $am_display_PYTHON script directory (pythondir)],
[am_cv_python_pythondir],
[if test "x$am_cv_python_prefix" = x; then
am_py_prefix=$am__usable_prefix
else
am_py_prefix=$am_cv_python_prefix
fi
am_cv_python_pythondir=`$PYTHON -c "
$am_python_setup_sysconfig
if can_use_sysconfig:
sitedir = sysconfig.get_path('purelib', vars={'base':'$am_py_prefix'})
sitedir = sysconfig.get_path('purelib', vars={'base':'$am_py_prefix'})
else:
from distutils import sysconfig
sitedir = sysconfig.get_python_lib(0, 0, prefix='$am_py_prefix')
from distutils import sysconfig
sitedir = sysconfig.get_python_lib(0, 0, prefix='$am_py_prefix')
sys.stdout.write(sitedir)"`
case $am_cv_python_pythondir in
$am_py_prefix*)
am__strip_prefix=`echo "$am_py_prefix" | sed 's|.|.|g'`
am_cv_python_pythondir=`echo "$am_cv_python_pythondir" | sed "s,^$am__strip_prefix,$PYTHON_PREFIX,"`
;;
*)
case $am_py_prefix in
/usr|/System*) ;;
*)
am_cv_python_pythondir=$PYTHON_PREFIX/lib/python$PYTHON_VERSION/site-packages
;;
esac
;;
#
case $am_cv_python_pythondir in
$am_py_prefix*)
am__strip_prefix=`echo "$am_py_prefix" | sed 's|.|.|g'`
am_cv_python_pythondir=`echo "$am_cv_python_pythondir" | sed "s,^$am__strip_prefix,\\${PYTHON_PREFIX},"`
;;
*)
case $am_py_prefix in
/usr|/System*) ;;
*) am_cv_python_pythondir="\${PYTHON_PREFIX}/lib/python$PYTHON_VERSION/site-packages"
;;
esac
])
;;
esac
])
AC_SUBST([pythondir], [$am_cv_python_pythondir])
dnl pkgpythondir -- $PACKAGE directory under pythondir. Was
dnl PYTHON_SITE_PACKAGE in previous betas, but this naming is
dnl more consistent with the rest of automake.
dnl 2. pkgpythondir: $PACKAGE directory under pythondir. Was
dnl PYTHON_SITE_PACKAGE in previous betas, but this naming is
dnl more consistent with the rest of automake.
dnl
AC_SUBST([pkgpythondir], [\${pythondir}/$PACKAGE])
dnl pyexecdir -- directory for installing python extension modules
dnl (shared libraries)
dnl 3. pyexecdir: directory for installing python extension modules
dnl (shared libraries).
dnl Query distutils for this directory.
AC_CACHE_CHECK([for $am_display_PYTHON extension module directory],
[am_cv_python_pyexecdir],
[if test "x$exec_prefix" = xNONE
then
am_py_exec_prefix=$am_py_prefix
else
am_py_exec_prefix=$exec_prefix
fi
am_cv_python_pyexecdir=`$PYTHON -c "
dnl
AC_CACHE_CHECK([for $am_display_PYTHON extension module directory (pyexecdir)],
[am_cv_python_pyexecdir],
[if test "x$am_cv_python_exec_prefix" = x; then
am_py_exec_prefix=$am__usable_exec_prefix
else
am_py_exec_prefix=$am_cv_python_exec_prefix
fi
am_cv_python_pyexecdir=`$PYTHON -c "
$am_python_setup_sysconfig
if can_use_sysconfig:
sitedir = sysconfig.get_path('platlib', vars={'platbase':'$am_py_prefix'})
sitedir = sysconfig.get_path('platlib', vars={'platbase':'$am_py_exec_prefix'})
else:
from distutils import sysconfig
sitedir = sysconfig.get_python_lib(1, 0, prefix='$am_py_prefix')
from distutils import sysconfig
sitedir = sysconfig.get_python_lib(1, 0, prefix='$am_py_exec_prefix')
sys.stdout.write(sitedir)"`
case $am_cv_python_pyexecdir in
$am_py_exec_prefix*)
am__strip_prefix=`echo "$am_py_exec_prefix" | sed 's|.|.|g'`
am_cv_python_pyexecdir=`echo "$am_cv_python_pyexecdir" | sed "s,^$am__strip_prefix,$PYTHON_EXEC_PREFIX,"`
;;
*)
case $am_py_exec_prefix in
/usr|/System*) ;;
*)
am_cv_python_pyexecdir=$PYTHON_EXEC_PREFIX/lib/python$PYTHON_VERSION/site-packages
;;
esac
;;
#
case $am_cv_python_pyexecdir in
$am_py_exec_prefix*)
am__strip_prefix=`echo "$am_py_exec_prefix" | sed 's|.|.|g'`
am_cv_python_pyexecdir=`echo "$am_cv_python_pyexecdir" | sed "s,^$am__strip_prefix,\\${PYTHON_EXEC_PREFIX},"`
;;
*)
case $am_py_exec_prefix in
/usr|/System*) ;;
*) am_cv_python_pyexecdir="\${PYTHON_EXEC_PREFIX}/lib/python$PYTHON_VERSION/site-packages"
;;
esac
])
;;
esac
])
AC_SUBST([pyexecdir], [$am_cv_python_pyexecdir])
dnl pkgpyexecdir -- $(pyexecdir)/$(PACKAGE)
dnl 4. pkgpyexecdir: $(pyexecdir)/$(PACKAGE)
dnl
AC_SUBST([pkgpyexecdir], [\${pyexecdir}/$PACKAGE])
dnl Run any user-specified action.
$2
fi
])
@ -653,7 +766,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-2020 Free Software Foundation, Inc.
# Copyright (C) 2001-2021 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,

1712
autoconf/config.guess vendored

File diff suppressed because it is too large Load Diff

2949
autoconf/config.sub vendored

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
#!/bin/sh
#!/usr/bin/sh
# install - install a program, script, or datafile
scriptversion=2006-10-14.15
scriptversion=2020-11-14.01; # UTC
# This originates from X11R5 (mit/util/scripts/install.sh), which was
# later released in X11R6 (xc/config/util/install.sh) with the
@ -35,57 +35,62 @@ scriptversion=2006-10-14.15
# FSF changes to this file are in the public domain.
#
# Calling this script install-sh is preferred over install.sh, to prevent
# `make' implicit rules from creating a file called install from it
# 'make' implicit rules from creating a file called install from it
# when there is no Makefile.
#
# This script is compatible with the BSD install script, but was written
# from scratch.
tab=' '
nl='
'
IFS=" "" $nl"
IFS=" $tab$nl"
# set DOITPROG to echo to test this script
# Set DOITPROG to "echo" to test this script.
# Don't use :- since 4.3BSD and earlier shells don't like it.
doit="${DOITPROG-}"
if test -z "$doit"; then
doit_exec=exec
else
doit_exec=$doit
fi
doit=${DOITPROG-}
doit_exec=${doit:-exec}
# Put in absolute file names if you don't have them in your path;
# or use environment vars.
mvprog="${MVPROG-mv}"
cpprog="${CPPROG-cp}"
chmodprog="${CHMODPROG-chmod}"
chownprog="${CHOWNPROG-chown}"
chgrpprog="${CHGRPPROG-chgrp}"
stripprog="${STRIPPROG-strip}"
rmprog="${RMPROG-rm}"
mkdirprog="${MKDIRPROG-mkdir}"
chgrpprog=${CHGRPPROG-chgrp}
chmodprog=${CHMODPROG-chmod}
chownprog=${CHOWNPROG-chown}
cmpprog=${CMPPROG-cmp}
cpprog=${CPPROG-cp}
mkdirprog=${MKDIRPROG-mkdir}
mvprog=${MVPROG-mv}
rmprog=${RMPROG-rm}
stripprog=${STRIPPROG-strip}
posix_glob=
posix_mkdir=
# Desired mode of installed file.
mode=0755
# Create dirs (including intermediate dirs) using mode 755.
# This is like GNU 'install' as of coreutils 8.32 (2020).
mkdir_umask=22
backupsuffix=
chgrpcmd=
chmodcmd=$chmodprog
chowncmd=
chgrpcmd=
stripcmd=
mvcmd=$mvprog
rmcmd="$rmprog -f"
mvcmd="$mvprog"
stripcmd=
src=
dst=
dir_arg=
dstarg=
no_target_directory=
dst_arg=
usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
copy_on_change=false
is_target_a_directory=possibly
usage="\
Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
or: $0 [OPTION]... SRCFILES... DIRECTORY
or: $0 [OPTION]... -t DIRECTORY SRCFILES...
or: $0 [OPTION]... -d DIRECTORIES...
@ -95,91 +100,116 @@ In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
In the 4th, create DIRECTORIES.
Options:
-c (ignored)
-d create directories instead of installing files.
-g GROUP $chgrpprog installed files to GROUP.
-m MODE $chmodprog installed files to MODE.
-o USER $chownprog installed files to USER.
-s $stripprog installed files.
-t DIRECTORY install into DIRECTORY.
-T report an error if DSTFILE is a directory.
--help display this help and exit.
--version display version info and exit.
--help display this help and exit.
--version display version info and exit.
-c (ignored)
-C install only if different (preserve data modification time)
-d create directories instead of installing files.
-g GROUP $chgrpprog installed files to GROUP.
-m MODE $chmodprog installed files to MODE.
-o USER $chownprog installed files to USER.
-p pass -p to $cpprog.
-s $stripprog installed files.
-S SUFFIX attempt to back up existing files, with suffix SUFFIX.
-t DIRECTORY install into DIRECTORY.
-T report an error if DSTFILE is a directory.
Environment variables override the default commands:
CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG
CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
RMPROG STRIPPROG
By default, rm is invoked with -f; when overridden with RMPROG,
it's up to you to specify -f if you want it.
If -S is not specified, no backups are attempted.
Email bug reports to bug-automake@gnu.org.
Automake home page: https://www.gnu.org/software/automake/
"
while test $# -ne 0; do
case $1 in
-c) shift
continue;;
-c) ;;
-d) dir_arg=true
shift
continue;;
-C) copy_on_change=true;;
-d) dir_arg=true;;
-g) chgrpcmd="$chgrpprog $2"
shift
shift
continue;;
shift;;
--help) echo "$usage"; exit $?;;
-m) mode=$2
shift
shift
case $mode in
*' '* | *' '* | *'
'* | *'*'* | *'?'* | *'['*)
echo "$0: invalid mode: $mode" >&2
exit 1;;
esac
continue;;
case $mode in
*' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
echo "$0: invalid mode: $mode" >&2
exit 1;;
esac
shift;;
-o) chowncmd="$chownprog $2"
shift
shift
continue;;
shift;;
-s) stripcmd=$stripprog
shift
continue;;
-p) cpprog="$cpprog -p";;
-t) dstarg=$2
shift
shift
continue;;
-s) stripcmd=$stripprog;;
-T) no_target_directory=true
shift
continue;;
-S) backupsuffix="$2"
shift;;
-t)
is_target_a_directory=always
dst_arg=$2
# Protect names problematic for 'test' and other utilities.
case $dst_arg in
-* | [=\(\)!]) dst_arg=./$dst_arg;;
esac
shift;;
-T) is_target_a_directory=never;;
--version) echo "$0 $scriptversion"; exit $?;;
--) shift
break;;
--) shift
break;;
-*) echo "$0: invalid option: $1" >&2
exit 1;;
-*) echo "$0: invalid option: $1" >&2
exit 1;;
*) break;;
esac
shift
done
if test $# -ne 0 && test -z "$dir_arg$dstarg"; then
# We allow the use of options -d and -T together, by making -d
# take the precedence; this is for compatibility with GNU install.
if test -n "$dir_arg"; then
if test -n "$dst_arg"; then
echo "$0: target directory not allowed when installing a directory." >&2
exit 1
fi
fi
if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
# When -d is used, all remaining arguments are directories to create.
# When -t is used, the destination is already specified.
# Otherwise, the last argument is the destination. Remove it from $@.
for arg
do
if test -n "$dstarg"; then
if test -n "$dst_arg"; then
# $@ is not empty: it contains at least $arg.
set fnord "$@" "$dstarg"
set fnord "$@" "$dst_arg"
shift # fnord
fi
shift # arg
dstarg=$arg
dst_arg=$arg
# Protect names problematic for 'test' and other utilities.
case $dst_arg in
-* | [=\(\)!]) dst_arg=./$dst_arg;;
esac
done
fi
@ -188,13 +218,26 @@ if test $# -eq 0; then
echo "$0: no input file specified." >&2
exit 1
fi
# It's OK to call `install-sh -d' without argument.
# It's OK to call 'install-sh -d' without argument.
# This can happen when creating conditional directories.
exit 0
fi
if test -z "$dir_arg"; then
trap '(exit $?); exit' 1 2 13 15
if test $# -gt 1 || test "$is_target_a_directory" = always; then
if test ! -d "$dst_arg"; then
echo "$0: $dst_arg: Is not a directory." >&2
exit 1
fi
fi
fi
if test -z "$dir_arg"; then
do_exit='(exit $ret); exit $ret'
trap "ret=129; $do_exit" 1
trap "ret=130; $do_exit" 2
trap "ret=141; $do_exit" 13
trap "ret=143; $do_exit" 15
# Set umask so as not to create temps with too-generous modes.
# However, 'strip' requires both read and write access to temps.
@ -205,16 +248,16 @@ if test -z "$dir_arg"; then
*[0-7])
if test -z "$stripcmd"; then
u_plus_rw=
u_plus_rw=
else
u_plus_rw='% 200'
u_plus_rw='% 200'
fi
cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
*)
if test -z "$stripcmd"; then
u_plus_rw=
u_plus_rw=
else
u_plus_rw=,u+rw
u_plus_rw=,u+rw
fi
cp_umask=$mode$u_plus_rw;;
esac
@ -222,9 +265,9 @@ fi
for src
do
# Protect names starting with `-'.
# Protect names problematic for 'test' and other utilities.
case $src in
-*) src=./$src ;;
-* | [=\(\)!]) src=./$src;;
esac
if test -n "$dir_arg"; then
@ -232,6 +275,10 @@ do
dstdir=$dst
test -d "$dstdir"
dstdir_status=$?
# Don't chown directories that already exist.
if test $dstdir_status = 0; then
chowncmd=""
fi
else
# Waiting for this to be detected by the "$cpprog $src $dsttmp" command
@ -242,196 +289,154 @@ do
exit 1
fi
if test -z "$dstarg"; then
if test -z "$dst_arg"; then
echo "$0: no destination specified." >&2
exit 1
fi
dst=$dst_arg
dst=$dstarg
# Protect names starting with `-'.
case $dst in
-*) dst=./$dst ;;
esac
# If destination is a directory, append the input filename; won't work
# if double slashes aren't ignored.
# If destination is a directory, append the input filename.
if test -d "$dst"; then
if test -n "$no_target_directory"; then
echo "$0: $dstarg: Is a directory" >&2
exit 1
if test "$is_target_a_directory" = never; then
echo "$0: $dst_arg: Is a directory" >&2
exit 1
fi
dstdir=$dst
dst=$dstdir/`basename "$src"`
dstbase=`basename "$src"`
case $dst in
*/) dst=$dst$dstbase;;
*) dst=$dst/$dstbase;;
esac
dstdir_status=0
else
# Prefer dirname, but fall back on a substitute if dirname fails.
dstdir=`
(dirname "$dst") 2>/dev/null ||
expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$dst" : 'X\(//\)[^/]' \| \
X"$dst" : 'X\(//\)$' \| \
X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
echo X"$dst" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
}
/^X\(\/\/\)[^/].*/{
s//\1/
q
}
/^X\(\/\/\)$/{
s//\1/
q
}
/^X\(\/\).*/{
s//\1/
q
}
s/.*/./; q'
`
dstdir=`dirname "$dst"`
test -d "$dstdir"
dstdir_status=$?
fi
fi
case $dstdir in
*/) dstdirslash=$dstdir;;
*) dstdirslash=$dstdir/;;
esac
obsolete_mkdir_used=false
if test $dstdir_status != 0; then
case $posix_mkdir in
'')
# Create intermediate dirs using mode 755 as modified by the umask.
# This is like FreeBSD 'install' as of 1997-10-28.
umask=`umask`
case $stripcmd.$umask in
# Optimize common cases.
*[2367][2367]) mkdir_umask=$umask;;
.*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
# With -d, create the new directory with the user-specified mode.
# Otherwise, rely on $mkdir_umask.
if test -n "$dir_arg"; then
mkdir_mode=-m$mode
else
mkdir_mode=
fi
*[0-7])
mkdir_umask=`expr $umask + 22 \
- $umask % 100 % 40 + $umask % 20 \
- $umask % 10 % 4 + $umask % 2
`;;
*) mkdir_umask=$umask,go-w;;
esac
posix_mkdir=false
# The $RANDOM variable is not portable (e.g., dash). Use it
# here however when possible just to lower collision chance.
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
# With -d, create the new directory with the user-specified mode.
# Otherwise, rely on $mkdir_umask.
if test -n "$dir_arg"; then
mkdir_mode=-m$mode
trap '
ret=$?
rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null
exit $ret
' 0
# Because "mkdir -p" follows existing symlinks and we likely work
# directly in world-writeable /tmp, make sure that the '$tmpdir'
# directory is successfully created first before we actually test
# 'mkdir -p'.
if (umask $mkdir_umask &&
$mkdirprog $mkdir_mode "$tmpdir" &&
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
then
if test -z "$dir_arg" || {
# Check for POSIX incompatibilities with -m.
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
# other-writable bit of parent directory when it shouldn't.
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
test_tmpdir="$tmpdir/a"
ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
case $ls_ld_tmpdir in
d????-?r-*) different_mode=700;;
d????-?--*) different_mode=755;;
*) false;;
esac &&
$mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
}
}
then posix_mkdir=:
fi
rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
else
mkdir_mode=
# Remove any dirs left behind by ancient mkdir implementations.
rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
fi
posix_mkdir=false
case $umask in
*[123567][0-7][0-7])
# POSIX mkdir -p sets u+wx bits regardless of umask, which
# is incompatible with FreeBSD 'install' when (umask & 300) != 0.
;;
*)
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
if (umask $mkdir_umask &&
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
then
if test -z "$dir_arg" || {
# Check for POSIX incompatibilities with -m.
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
# other-writeable bit of parent directory when it shouldn't.
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
ls_ld_tmpdir=`ls -ld "$tmpdir"`
case $ls_ld_tmpdir in
d????-?r-*) different_mode=700;;
d????-?--*) different_mode=755;;
*) false;;
esac &&
$mkdirprog -m$different_mode -p -- "$tmpdir" && {
ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
}
}
then posix_mkdir=:
fi
rmdir "$tmpdir/d" "$tmpdir"
else
# Remove any dirs left behind by ancient mkdir implementations.
rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
fi
trap '' 0;;
esac;;
trap '' 0;;
esac
if
$posix_mkdir && (
umask $mkdir_umask &&
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
umask $mkdir_umask &&
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
)
then :
else
# The umask is ridiculous, or mkdir does not conform to POSIX,
# mkdir does not conform to POSIX,
# or it failed possibly due to a race condition. Create the
# directory the slow way, step by step, checking for races as we go.
case $dstdir in
/*) prefix=/ ;;
-*) prefix=./ ;;
*) prefix= ;;
esac
case $posix_glob in
'')
if (set -f) 2>/dev/null; then
posix_glob=true
else
posix_glob=false
fi ;;
/*) prefix='/';;
[-=\(\)!]*) prefix='./';;
*) prefix='';;
esac
oIFS=$IFS
IFS=/
$posix_glob && set -f
set -f
set fnord $dstdir
shift
$posix_glob && set +f
set +f
IFS=$oIFS
prefixes=
for d
do
test -z "$d" && continue
test X"$d" = X && continue
prefix=$prefix$d
if test -d "$prefix"; then
prefixes=
else
if $posix_mkdir; then
(umask=$mkdir_umask &&
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
# Don't fail if two instances are running concurrently.
test -d "$prefix" || exit 1
else
case $prefix in
*\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
*) qprefix=$prefix;;
esac
prefixes="$prefixes '$qprefix'"
fi
fi
prefix=$prefix/
prefix=$prefix$d
if test -d "$prefix"; then
prefixes=
else
if $posix_mkdir; then
(umask $mkdir_umask &&
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
# Don't fail if two instances are running concurrently.
test -d "$prefix" || exit 1
else
case $prefix in
*\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
*) qprefix=$prefix;;
esac
prefixes="$prefixes '$qprefix'"
fi
fi
prefix=$prefix/
done
if test -n "$prefixes"; then
# Don't fail if two instances are running concurrently.
(umask $mkdir_umask &&
eval "\$doit_exec \$mkdirprog $prefixes") ||
test -d "$dstdir" || exit 1
obsolete_mkdir_used=true
# Don't fail if two instances are running concurrently.
(umask $mkdir_umask &&
eval "\$doit_exec \$mkdirprog $prefixes") ||
test -d "$dstdir" || exit 1
obsolete_mkdir_used=true
fi
fi
fi
@ -444,14 +449,25 @@ do
else
# Make a couple of temp file names in the proper directory.
dsttmp=$dstdir/_inst.$$_
rmtmp=$dstdir/_rm.$$_
dsttmp=${dstdirslash}_inst.$$_
rmtmp=${dstdirslash}_rm.$$_
# Trap to clean up those temp files at exit.
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
# Copy the file name to the temp name.
(umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
(umask $cp_umask &&
{ test -z "$stripcmd" || {
# Create $dsttmp read-write so that cp doesn't create it read-only,
# which would cause strip to fail.
if test -z "$doit"; then
: >"$dsttmp" # No need to fork-exec 'touch'.
else
$doit touch "$dsttmp"
fi
}
} &&
$doit_exec $cpprog "$src" "$dsttmp") &&
# and set any options; do chmod last to preserve setuid bits.
#
@ -459,49 +475,67 @@ do
# ignore errors from any of these, just make sure not to ignore
# errors from the above "$doit $cpprog $src $dsttmp" command.
#
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \
&& { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \
&& { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \
&& { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
{ test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
{ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
# Now rename the file to the real destination.
{ $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null \
|| {
# The rename failed, perhaps because mv can't rename something else
# to itself, or perhaps because mv is so ancient that it does not
# support -f.
# If -C, don't bother to copy if it wouldn't change the file.
if $copy_on_change &&
old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
set -f &&
set X $old && old=:$2:$4:$5:$6 &&
set X $new && new=:$2:$4:$5:$6 &&
set +f &&
test "$old" = "$new" &&
$cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
then
rm -f "$dsttmp"
else
# If $backupsuffix is set, and the file being installed
# already exists, attempt a backup. Don't worry if it fails,
# e.g., if mv doesn't support -f.
if test -n "$backupsuffix" && test -f "$dst"; then
$doit $mvcmd -f "$dst" "$dst$backupsuffix" 2>/dev/null
fi
# Now remove or move aside any old file at destination location.
# We try this two ways since rm can't unlink itself on some
# systems and the destination file might be busy for other
# reasons. In this case, the final cleanup might fail but the new
# file should still install successfully.
{
if test -f "$dst"; then
$doit $rmcmd -f "$dst" 2>/dev/null \
|| { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null \
&& { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }; }\
|| {
echo "$0: cannot unlink or rename $dst" >&2
(exit 1); exit 1
}
else
:
fi
} &&
# Rename the file to the real destination.
$doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
# Now rename the file to the real destination.
$doit $mvcmd "$dsttmp" "$dst"
}
} || exit 1
# The rename failed, perhaps because mv can't rename something else
# to itself, or perhaps because mv is so ancient that it does not
# support -f.
{
# Now remove or move aside any old file at destination location.
# We try this two ways since rm can't unlink itself on some
# systems and the destination file might be busy for other
# reasons. In this case, the final cleanup might fail but the new
# file should still install successfully.
{
test ! -f "$dst" ||
$doit $rmcmd "$dst" 2>/dev/null ||
{ $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
{ $doit $rmcmd "$rmtmp" 2>/dev/null; :; }
} ||
{ echo "$0: cannot unlink or rename $dst" >&2
(exit 1); exit 1
}
} &&
# Now rename the file to the real destination.
$doit $mvcmd "$dsttmp" "$dst"
}
fi || exit 1
trap '' 0
fi
done
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# eval: (add-hook 'before-save-hook 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-end: "$"
# time-stamp-time-zone: "UTC0"
# time-stamp-end: "; # UTC"
# End:

View File

@ -1,9 +1,9 @@
#!/bin/sh
# py-compile - Compile a Python program
scriptversion=2011-06-08.12; # UTC
scriptversion=2023-03-30.00; # UTC
# Copyright (C) 2000-2014 Free Software Foundation, Inc.
# Copyright (C) 2000-2023 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -16,7 +16,7 @@ scriptversion=2011-06-08.12; # UTC
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# along with this program. If not, see <https://www.gnu.org/licenses/>.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
@ -27,7 +27,7 @@ scriptversion=2011-06-08.12; # UTC
# bugs to <bug-automake@gnu.org> or send patches to
# <automake-patches@gnu.org>.
if [ -z "$PYTHON" ]; then
if test -z "$PYTHON"; then
PYTHON=python
fi
@ -62,13 +62,19 @@ while test $# -ne 0; do
;;
-h|--help)
cat <<\EOF
Usage: py-compile [--help] [--version] [--basedir DIR] [--destdir DIR] FILES..."
Usage: py-compile [options] FILES...
Byte compile some python scripts FILES. Use --destdir to specify any
leading directory path to the FILES that you don't want to include in the
byte compiled file. Specify --basedir for any additional path information you
do want to be shown in the byte compiled file.
Options:
--basedir DIR Prefix all FILES with DIR, and include in error messages.
--destdir DIR Prefix all FILES with DIR before compiling.
-v, --version Display version information.
-h, --help This help screen.
Example:
py-compile --destdir /tmp/pkg-root --basedir /usr/share/test test.py test2.py
@ -94,77 +100,143 @@ EOF
shift
done
files=$*
if test -z "$files"; then
usage_error "no files given"
if test $# -eq 0; then
usage_error "no files given"
fi
# if basedir was given, then it should be prepended to filenames before
# byte compilation.
if [ -z "$basedir" ]; then
pathtrans="path = file"
if test -z "$basedir"; then
pathtrans="path = file"
else
pathtrans="path = os.path.join('$basedir', file)"
pathtrans="path = os.path.join('$basedir', file)"
fi
# if destdir was given, then it needs to be prepended to the filename to
# byte compile but not go into the compiled file.
if [ -z "$destdir" ]; then
filetrans="filepath = path"
if test -z "$destdir"; then
filetrans="filepath = path"
else
filetrans="filepath = os.path.normpath('$destdir' + os.sep + path)"
filetrans="filepath = os.path.normpath('$destdir' + os.sep + path)"
fi
$PYTHON -c "
import sys, os, py_compile, imp
python_major=`$PYTHON -c 'import sys; print(sys.version_info[0])'`
if test -z "$python_major"; then
usage_error "could not determine $PYTHON major version"
fi
files = '''$files'''
case $python_major in
[01])
usage_error "python version 0.x and 1.x not supported"
;;
esac
python_minor=`$PYTHON -c 'import sys; print(sys.version_info[1])'`
# NB: When adding support for newer versions, prefer copying & adding new cases
# rather than try to keep things merged with shell variables.
# First byte compile (no optimization) all the modules.
# This works for all currently known Python versions.
$PYTHON -c "
import sys, os, py_compile
try:
import importlib
except ImportError:
importlib = None
# importlib.util.cache_from_source was added in 3.4
if (
hasattr(importlib, 'util')
and hasattr(importlib.util, 'cache_from_source')
):
destpath = importlib.util.cache_from_source
else:
destpath = lambda filepath: filepath + 'c'
sys.stdout.write('Byte-compiling python modules...\n')
for file in files.split():
for file in sys.argv[1:]:
$pathtrans
$filetrans
if not os.path.exists(filepath) or not (len(filepath) >= 3
and filepath[-3:] == '.py'):
continue
sys.stdout.write(file)
if (
not os.path.exists(filepath)
or not (len(filepath) >= 3 and filepath[-3:] == '.py')
):
continue
sys.stdout.write(file + ' ')
sys.stdout.flush()
if hasattr(imp, 'get_tag'):
py_compile.compile(filepath, imp.cache_from_source(filepath), path)
else:
py_compile.compile(filepath, filepath + 'c', path)
sys.stdout.write('\n')" || exit $?
py_compile.compile(filepath, destpath(filepath), path)
sys.stdout.write('\n')" "$@" || exit $?
# this will fail for python < 1.5, but that doesn't matter ...
# Then byte compile w/optimization all the modules.
$PYTHON -O -c "
import sys, os, py_compile, imp
import sys, os, py_compile
# pypy does not use .pyo optimization
if hasattr(sys, 'pypy_translation_info'):
try:
import importlib
except ImportError:
importlib = None
# importlib.util.cache_from_source was added in 3.4
if (
hasattr(importlib, 'util')
and hasattr(importlib.util, 'cache_from_source')
):
destpath = importlib.util.cache_from_source
else:
destpath = lambda filepath: filepath + 'o'
# pypy2 does not use .pyo optimization
if sys.version_info.major <= 2 and hasattr(sys, 'pypy_translation_info'):
sys.exit(0)
files = '''$files'''
sys.stdout.write('Byte-compiling python modules (optimized versions) ...\n')
for file in files.split():
for file in sys.argv[1:]:
$pathtrans
$filetrans
if not os.path.exists(filepath) or not (len(filepath) >= 3
and filepath[-3:] == '.py'):
continue
sys.stdout.write(file)
if (
not os.path.exists(filepath)
or not (len(filepath) >= 3 and filepath[-3:] == '.py')
):
continue
sys.stdout.write(file + ' ')
sys.stdout.flush()
if hasattr(imp, 'get_tag'):
py_compile.compile(filepath, imp.cache_from_source(filepath, False), path)
else:
py_compile.compile(filepath, filepath + 'o', path)
sys.stdout.write('\n')" 2>/dev/null || :
py_compile.compile(filepath, destpath(filepath), path)
sys.stdout.write('\n')" "$@" 2>/dev/null || exit $?
# Then byte compile w/more optimization.
# Only do this for Python 3.5+, see https://bugs.gnu.org/38043 for background.
case $python_major.$python_minor in
2.*|3.[0-4])
;;
*)
$PYTHON -OO -c "
import sys, os, py_compile, importlib
sys.stdout.write('Byte-compiling python modules (more optimized versions)'
' ...\n')
for file in sys.argv[1:]:
$pathtrans
$filetrans
if (
not os.path.exists(filepath)
or not (len(filepath) >= 3 and filepath[-3:] == '.py')
):
continue
sys.stdout.write(file + ' ')
sys.stdout.flush()
py_compile.compile(filepath, importlib.util.cache_from_source(filepath), path)
sys.stdout.write('\n')" "$@" 2>/dev/null || exit $?
;;
esac
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'write-file-hooks 'time-stamp)
# eval: (add-hook 'before-save-hook 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-time-zone: "UTC0"
# time-stamp-end: "; # UTC"
# End:

View File

@ -31,10 +31,10 @@ CLEAN_TARGETS += $(BASE_DEPENDS) $(BASE_OBJECTS) \
$(BASE_TARGET)
$(BASE_TARGET): $(BASE_OBJECTS)
@echo " [AR] $@"
$(SHOW) " [AR] $@"
$(Q) $(RM) $@
$(Q) $(AR) rsv $@ $(BASE_OBJECTS) > /dev/null
ifeq ("$(DEPENDS)","yes")
ifeq ("$(USE_TRACKING)","yes")
-include $(BASE_DEPENDS)
endif

View File

@ -30,10 +30,10 @@ struct dm_hash_table {
unsigned num_nodes;
unsigned num_hint;
unsigned mask_slots; /* (slots - 1) -> used as hash mask */
unsigned collisions; /* Collissions of hash keys */
unsigned collisions; /* Collisions 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 ? */
unsigned same_hash; /* Was there a collision with same masked hash and len ? */
struct dm_hash_node **slots;
};
@ -41,7 +41,7 @@ struct dm_hash_table {
static unsigned _hash(const void *key, unsigned len)
{
/* Permutation of the Integers 0 through 255 */
static unsigned char _nums[] = {
static const 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,
@ -348,7 +348,7 @@ int dm_hash_insert_allow_multiple(struct dm_hash_table *t, const char *key,
/*
* Look through multiple entries with the same key for one that has a
* matching val and return that. If none have maching val, return NULL.
* matching val and return that. If none have matching val, return NULL.
*/
void *dm_hash_lookup_with_val(struct dm_hash_table *t, const char *key,
const void *val, uint32_t val_len)

View File

@ -19,6 +19,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
//----------------------------------------------------------------
@ -69,7 +70,7 @@ struct node48 {
};
struct node256 {
uint32_t nr_entries;
uint32_t nr_entries;
struct value values[256];
};
@ -99,7 +100,7 @@ struct radix_tree *radix_tree_create(radix_value_dtr dtr, void *dtr_context)
static inline void _dtr(struct radix_tree *rt, union radix_value v)
{
if (rt->dtr)
rt->dtr(rt->dtr_context, v);
rt->dtr(rt->dtr_context, v);
}
// Returns the number of values removed
@ -118,8 +119,8 @@ static unsigned _free_node(struct radix_tree *rt, struct value v)
break;
case VALUE:
_dtr(rt, v.value);
nr = 1;
_dtr(rt, v.value);
nr = 1;
break;
case VALUE_CHAIN:
@ -178,9 +179,9 @@ unsigned radix_tree_size(struct radix_tree *rt)
return rt->nr_entries;
}
static bool _insert(struct radix_tree *rt, struct value *v, uint8_t *kb, uint8_t *ke, union radix_value rv);
static bool _insert(struct radix_tree *rt, struct value *v, const uint8_t *kb, const uint8_t *ke, union radix_value rv);
static bool _insert_unset(struct radix_tree *rt, struct value *v, uint8_t *kb, uint8_t *ke, union radix_value rv)
static bool _insert_unset(struct radix_tree *rt, struct value *v, const uint8_t *kb, const uint8_t *ke, union radix_value rv)
{
unsigned len = ke - kb;
@ -207,7 +208,7 @@ static bool _insert_unset(struct radix_tree *rt, struct value *v, uint8_t *kb, u
return true;
}
static bool _insert_value(struct radix_tree *rt, struct value *v, uint8_t *kb, uint8_t *ke, union radix_value rv)
static bool _insert_value(struct radix_tree *rt, struct value *v, const uint8_t *kb, const uint8_t *ke, union radix_value rv)
{
unsigned len = ke - kb;
@ -234,7 +235,7 @@ static bool _insert_value(struct radix_tree *rt, struct value *v, uint8_t *kb, u
return true;
}
static bool _insert_value_chain(struct radix_tree *rt, struct value *v, uint8_t *kb, uint8_t *ke, union radix_value rv)
static bool _insert_value_chain(struct radix_tree *rt, struct value *v, const uint8_t *kb, const uint8_t *ke, union radix_value rv)
{
struct value_chain *vc = v->value.ptr;
return _insert(rt, &vc->child, kb, ke, rv);
@ -248,7 +249,7 @@ static unsigned min(unsigned lhs, unsigned rhs)
return rhs;
}
static bool _insert_prefix_chain(struct radix_tree *rt, struct value *v, uint8_t *kb, uint8_t *ke, union radix_value rv)
static bool _insert_prefix_chain(struct radix_tree *rt, struct value *v, const uint8_t *kb, const uint8_t *ke, union radix_value rv)
{
struct prefix_chain *pc = v->value.ptr;
@ -313,7 +314,7 @@ static bool _insert_prefix_chain(struct radix_tree *rt, struct value *v, uint8_t
return true;
}
static bool _insert_node4(struct radix_tree *rt, struct value *v, uint8_t *kb, uint8_t *ke, union radix_value rv)
static bool _insert_node4(struct radix_tree *rt, struct value *v, const uint8_t *kb, const uint8_t *ke, union radix_value rv)
{
struct node4 *n4 = v->value.ptr;
if (n4->nr_entries == 4) {
@ -343,7 +344,7 @@ static bool _insert_node4(struct radix_tree *rt, struct value *v, uint8_t *kb, u
return true;
}
static bool _insert_node16(struct radix_tree *rt, struct value *v, uint8_t *kb, uint8_t *ke, union radix_value rv)
static bool _insert_node16(struct radix_tree *rt, struct value *v, const uint8_t *kb, const uint8_t *ke, union radix_value rv)
{
struct node16 *n16 = v->value.ptr;
@ -382,7 +383,7 @@ static bool _insert_node16(struct radix_tree *rt, struct value *v, uint8_t *kb,
return true;
}
static bool _insert_node48(struct radix_tree *rt, struct value *v, uint8_t *kb, uint8_t *ke, union radix_value rv)
static bool _insert_node48(struct radix_tree *rt, struct value *v, const uint8_t *kb, const uint8_t *ke, union radix_value rv)
{
struct node48 *n48 = v->value.ptr;
if (n48->nr_entries == 48) {
@ -417,20 +418,20 @@ static bool _insert_node48(struct radix_tree *rt, struct value *v, uint8_t *kb,
return true;
}
static bool _insert_node256(struct radix_tree *rt, struct value *v, uint8_t *kb, uint8_t *ke, union radix_value rv)
static bool _insert_node256(struct radix_tree *rt, struct value *v, const uint8_t *kb, const uint8_t *ke, union radix_value rv)
{
struct node256 *n256 = v->value.ptr;
bool r, was_unset = n256->values[*kb].type == UNSET;
r = _insert(rt, n256->values + *kb, kb + 1, ke, rv);
if (r && was_unset)
n256->nr_entries++;
n256->nr_entries++;
return r;
}
// FIXME: the tree should not be touched if insert fails (eg, OOM)
static bool _insert(struct radix_tree *rt, struct value *v, uint8_t *kb, uint8_t *ke, union radix_value rv)
static bool _insert(struct radix_tree *rt, struct value *v, const uint8_t *kb, const uint8_t *ke, union radix_value rv)
{
if (kb == ke) {
if (v->type == UNSET) {
@ -487,10 +488,10 @@ static bool _insert(struct radix_tree *rt, struct value *v, uint8_t *kb, uint8_t
struct lookup_result {
struct value *v;
uint8_t *kb;
const uint8_t *kb;
};
static struct lookup_result _lookup_prefix(struct value *v, uint8_t *kb, uint8_t *ke)
static struct lookup_result _lookup_prefix(struct value *v, const uint8_t *kb, const uint8_t *ke)
{
unsigned i;
struct value_chain *vc;
@ -500,7 +501,7 @@ static struct lookup_result _lookup_prefix(struct value *v, uint8_t *kb, uint8_t
struct node48 *n48;
struct node256 *n256;
if (kb == ke)
if (kb == ke || !kb) /* extra check for !kb for coverity */
return (struct lookup_result) {.v = v, .kb = kb};
switch (v->type) {
@ -555,8 +556,10 @@ static struct lookup_result _lookup_prefix(struct value *v, uint8_t *kb, uint8_t
return (struct lookup_result) {.v = v, .kb = kb};
}
bool radix_tree_insert(struct radix_tree *rt, uint8_t *kb, uint8_t *ke, union radix_value rv)
bool radix_tree_insert(struct radix_tree *rt, const void *key, size_t keylen, union radix_value rv)
{
const uint8_t *kb = key;
const uint8_t *ke = kb + keylen;
struct lookup_result lr = _lookup_prefix(&rt->root, kb, ke);
return _insert(rt, lr.v, lr.kb, ke, rv);
}
@ -564,14 +567,14 @@ bool radix_tree_insert(struct radix_tree *rt, uint8_t *kb, uint8_t *ke, union ra
// Note the degrade functions also free the original node.
static void _degrade_to_n4(struct node16 *n16, struct value *result)
{
struct node4 *n4 = zalloc(sizeof(*n4));
struct node4 *n4 = zalloc(sizeof(*n4));
assert(n4 != NULL);
n4->nr_entries = n16->nr_entries;
memcpy(n4->keys, n16->keys, n16->nr_entries * sizeof(*n4->keys));
memcpy(n4->values, n16->values, n16->nr_entries * sizeof(*n4->values));
free(n16);
n4->nr_entries = n16->nr_entries;
memcpy(n4->keys, n16->keys, n16->nr_entries * sizeof(*n4->keys));
memcpy(n4->values, n16->values, n16->nr_entries * sizeof(*n4->values));
free(n16);
result->type = NODE4;
result->value.ptr = n4;
@ -580,20 +583,20 @@ static void _degrade_to_n4(struct node16 *n16, struct value *result)
static void _degrade_to_n16(struct node48 *n48, struct value *result)
{
unsigned i, count = 0;
struct node16 *n16 = zalloc(sizeof(*n16));
struct node16 *n16 = zalloc(sizeof(*n16));
assert(n16 != NULL);
n16->nr_entries = n48->nr_entries;
for (i = 0; i < 256; i++) {
if (n48->keys[i] < 48) {
n16->keys[count] = i;
n16->values[count] = n48->values[n48->keys[i]];
count++;
}
}
n16->nr_entries = n48->nr_entries;
for (i = 0; i < 256; i++) {
if (n48->keys[i] < 48) {
n16->keys[count] = i;
n16->values[count] = n48->values[n48->keys[i]];
count++;
}
}
free(n48);
free(n48);
result->type = NODE16;
result->value.ptr = n16;
@ -601,13 +604,13 @@ static void _degrade_to_n16(struct node48 *n48, struct value *result)
static void _degrade_to_n48(struct node256 *n256, struct value *result)
{
unsigned i, count = 0;
struct node48 *n48 = zalloc(sizeof(*n48));
unsigned i, count = 0;
struct node48 *n48 = zalloc(sizeof(*n48));
assert(n48 != NULL);
n48->nr_entries = n256->nr_entries;
for (i = 0; i < 256; i++) {
n48->nr_entries = n256->nr_entries;
for (i = 0; i < 256; i++) {
if (n256->values[i].type == UNSET)
n48->keys[i] = 48;
@ -616,9 +619,9 @@ static void _degrade_to_n48(struct node256 *n256, struct value *result)
n48->values[count] = n256->values[i];
count++;
}
}
}
free(n256);
free(n256);
result->type = NODE48;
result->value.ptr = n48;
@ -632,14 +635,14 @@ static void _erase_elt(void *array, size_t obj_size, unsigned count, unsigned id
return;
memmove(((uint8_t *) array) + (obj_size * idx),
((uint8_t *) array) + (obj_size * (idx + 1)),
obj_size * (count - idx - 1));
((uint8_t *) array) + (obj_size * (idx + 1)),
obj_size * (count - idx - 1));
// Zero the now unused last elt (set's v.type to UNSET)
memset(((uint8_t *) array) + (count - 1) * obj_size, 0, obj_size);
}
static bool _remove(struct radix_tree *rt, struct value *root, uint8_t *kb, uint8_t *ke)
static bool _remove(struct radix_tree *rt, struct value *root, const uint8_t *kb, const uint8_t *ke)
{
bool r;
unsigned i, j;
@ -651,27 +654,27 @@ static bool _remove(struct radix_tree *rt, struct value *root, uint8_t *kb, uint
struct node256 *n256;
if (kb == ke) {
if (root->type == VALUE) {
root->type = UNSET;
_dtr(rt, root->value);
return true;
if (root->type == VALUE) {
root->type = UNSET;
_dtr(rt, root->value);
return true;
} else if (root->type == VALUE_CHAIN) {
} else if (root->type == VALUE_CHAIN) {
vc = root->value.ptr;
_dtr(rt, vc->value);
memcpy(root, &vc->child, sizeof(*root));
free(vc);
return true;
} else
} else
return false;
}
switch (root->type) {
case UNSET:
case VALUE:
// this is a value for a prefix of the key
return false;
// this is a value for a prefix of the key
return false;
case VALUE_CHAIN:
vc = root->value.ptr;
@ -686,11 +689,11 @@ static bool _remove(struct radix_tree *rt, struct value *root, uint8_t *kb, uint
case PREFIX_CHAIN:
pc = root->value.ptr;
if (ke - kb < pc->len)
return false;
return false;
for (i = 0; i < pc->len; i++)
if (kb[i] != pc->prefix[i])
return false;
return false;
r = _remove(rt, &pc->child, kb + pc->len, ke);
if (r && pc->child.type == UNSET) {
@ -705,12 +708,12 @@ static bool _remove(struct radix_tree *rt, struct value *root, uint8_t *kb, uint
if (n4->keys[i] == *kb) {
r = _remove(rt, n4->values + i, kb + 1, ke);
if (r && n4->values[i].type == UNSET) {
if (i < n4->nr_entries) {
_erase_elt(n4->keys, sizeof(*n4->keys), n4->nr_entries, i);
_erase_elt(n4->values, sizeof(*n4->values), n4->nr_entries, i);
}
if (i < n4->nr_entries) {
_erase_elt(n4->keys, sizeof(*n4->keys), n4->nr_entries, i);
_erase_elt(n4->values, sizeof(*n4->values), n4->nr_entries, i);
}
n4->nr_entries--;
n4->nr_entries--;
if (!n4->nr_entries) {
free(n4);
root->type = UNSET;
@ -722,19 +725,19 @@ static bool _remove(struct radix_tree *rt, struct value *root, uint8_t *kb, uint
return false;
case NODE16:
n16 = root->value.ptr;
n16 = root->value.ptr;
for (i = 0; i < n16->nr_entries; i++) {
if (n16->keys[i] == *kb) {
r = _remove(rt, n16->values + i, kb + 1, ke);
if (r && n16->values[i].type == UNSET) {
if (i < n16->nr_entries) {
_erase_elt(n16->keys, sizeof(*n16->keys), n16->nr_entries, i);
_erase_elt(n16->values, sizeof(*n16->values), n16->nr_entries, i);
}
if (i < n16->nr_entries) {
_erase_elt(n16->keys, sizeof(*n16->keys), n16->nr_entries, i);
_erase_elt(n16->values, sizeof(*n16->values), n16->nr_entries, i);
}
n16->nr_entries--;
n16->nr_entries--;
if (n16->nr_entries <= 4) {
_degrade_to_n4(n16, root);
_degrade_to_n4(n16, root);
}
}
return r;
@ -746,18 +749,18 @@ static bool _remove(struct radix_tree *rt, struct value *root, uint8_t *kb, uint
n48 = root->value.ptr;
i = n48->keys[*kb];
if (i < 48) {
r = _remove(rt, n48->values + i, kb + 1, ke);
if (r && n48->values[i].type == UNSET) {
n48->keys[*kb] = 48;
for (j = 0; j < 256; j++)
if (n48->keys[j] < 48 && n48->keys[j] > i)
n48->keys[j]--;
r = _remove(rt, n48->values + i, kb + 1, ke);
if (r && n48->values[i].type == UNSET) {
n48->keys[*kb] = 48;
for (j = 0; j < 256; j++)
if (n48->keys[j] < 48 && n48->keys[j] > i)
n48->keys[j]--;
_erase_elt(n48->values, sizeof(*n48->values), n48->nr_entries, i);
n48->nr_entries--;
if (n48->nr_entries <= 16)
_degrade_to_n16(n48, root);
}
return r;
_degrade_to_n16(n48, root);
}
return r;
}
return false;
@ -767,7 +770,7 @@ static bool _remove(struct radix_tree *rt, struct value *root, uint8_t *kb, uint
if (r && n256->values[*kb].type == UNSET) {
n256->nr_entries--;
if (n256->nr_entries <= 48)
_degrade_to_n48(n256, root);
_degrade_to_n48(n256, root);
}
return r;
}
@ -775,11 +778,14 @@ static bool _remove(struct radix_tree *rt, struct value *root, uint8_t *kb, uint
return false;
}
bool radix_tree_remove(struct radix_tree *rt, uint8_t *key_begin, uint8_t *key_end)
bool radix_tree_remove(struct radix_tree *rt, const void *key, size_t keylen)
{
if (_remove(rt, &rt->root, key_begin, key_end)) {
rt->nr_entries--;
return true;
const uint8_t *kb = key;
const uint8_t *ke = kb + keylen;
if (_remove(rt, &rt->root, kb, ke)) {
rt->nr_entries--;
return true;
}
return false;
@ -787,25 +793,25 @@ bool radix_tree_remove(struct radix_tree *rt, uint8_t *key_begin, uint8_t *key_e
//----------------------------------------------------------------
static bool _prefix_chain_matches(struct lookup_result *lr, uint8_t *ke)
static bool _prefix_chain_matches(const struct lookup_result *lr, const uint8_t *ke)
{
// It's possible the top node is a prefix chain, and
// the remaining key matches part of it.
if (lr->v->type == PREFIX_CHAIN) {
unsigned i, rlen = ke - lr->kb;
struct prefix_chain *pc = lr->v->value.ptr;
if (rlen < pc->len) {
for (i = 0; i < rlen; i++)
if (pc->prefix[i] != lr->kb[i])
return false;
return true;
// It's possible the top node is a prefix chain, and
// the remaining key matches part of it.
if (lr->v->type == PREFIX_CHAIN) {
unsigned i, rlen = ke - lr->kb;
const struct prefix_chain *pc = lr->v->value.ptr;
if (rlen < pc->len) {
for (i = 0; i < rlen; i++)
if (pc->prefix[i] != lr->kb[i])
return false;
return true;
}
}
}
return false;
return false;
}
static bool _remove_subtree(struct radix_tree *rt, struct value *root, uint8_t *kb, uint8_t *ke, unsigned *count)
static bool _remove_subtree(struct radix_tree *rt, struct value *root, const uint8_t *kb, const uint8_t *ke, unsigned *count)
{
bool r;
unsigned i, j, len;
@ -826,7 +832,7 @@ static bool _remove_subtree(struct radix_tree *rt, struct value *root, uint8_t *
case UNSET:
case VALUE:
// No entries with the given prefix
return true;
return true;
case VALUE_CHAIN:
vc = root->value.ptr;
@ -843,7 +849,7 @@ static bool _remove_subtree(struct radix_tree *rt, struct value *root, uint8_t *
len = min(pc->len, ke - kb);
for (i = 0; i < len; i++)
if (kb[i] != pc->prefix[i])
return true;
return true;
r = _remove_subtree(rt, &pc->child, len < pc->len ? ke : (kb + pc->len), ke, count);
if (r && pc->child.type == UNSET) {
@ -858,12 +864,12 @@ static bool _remove_subtree(struct radix_tree *rt, struct value *root, uint8_t *
if (n4->keys[i] == *kb) {
r = _remove_subtree(rt, n4->values + i, kb + 1, ke, count);
if (r && n4->values[i].type == UNSET) {
if (i < n4->nr_entries) {
_erase_elt(n4->keys, sizeof(*n4->keys), n4->nr_entries, i);
_erase_elt(n4->values, sizeof(*n4->values), n4->nr_entries, i);
}
if (i < n4->nr_entries) {
_erase_elt(n4->keys, sizeof(*n4->keys), n4->nr_entries, i);
_erase_elt(n4->values, sizeof(*n4->values), n4->nr_entries, i);
}
n4->nr_entries--;
n4->nr_entries--;
if (!n4->nr_entries) {
free(n4);
root->type = UNSET;
@ -875,19 +881,19 @@ static bool _remove_subtree(struct radix_tree *rt, struct value *root, uint8_t *
return true;
case NODE16:
n16 = root->value.ptr;
n16 = root->value.ptr;
for (i = 0; i < n16->nr_entries; i++) {
if (n16->keys[i] == *kb) {
r = _remove_subtree(rt, n16->values + i, kb + 1, ke, count);
if (r && n16->values[i].type == UNSET) {
if (i < n16->nr_entries) {
_erase_elt(n16->keys, sizeof(*n16->keys), n16->nr_entries, i);
_erase_elt(n16->values, sizeof(*n16->values), n16->nr_entries, i);
}
if (i < n16->nr_entries) {
_erase_elt(n16->keys, sizeof(*n16->keys), n16->nr_entries, i);
_erase_elt(n16->values, sizeof(*n16->values), n16->nr_entries, i);
}
n16->nr_entries--;
n16->nr_entries--;
if (n16->nr_entries <= 4)
_degrade_to_n4(n16, root);
_degrade_to_n4(n16, root);
}
return r;
}
@ -898,18 +904,18 @@ static bool _remove_subtree(struct radix_tree *rt, struct value *root, uint8_t *
n48 = root->value.ptr;
i = n48->keys[*kb];
if (i < 48) {
r = _remove_subtree(rt, n48->values + i, kb + 1, ke, count);
if (r && n48->values[i].type == UNSET) {
n48->keys[*kb] = 48;
for (j = 0; j < 256; j++)
if (n48->keys[j] < 48 && n48->keys[j] > i)
n48->keys[j]--;
r = _remove_subtree(rt, n48->values + i, kb + 1, ke, count);
if (r && n48->values[i].type == UNSET) {
n48->keys[*kb] = 48;
for (j = 0; j < 256; j++)
if (n48->keys[j] < 48 && n48->keys[j] > i)
n48->keys[j]--;
_erase_elt(n48->values, sizeof(*n48->values), n48->nr_entries, i);
n48->nr_entries--;
if (n48->nr_entries <= 16)
_degrade_to_n16(n48, root);
}
return r;
_degrade_to_n16(n48, root);
}
return r;
}
return true;
@ -922,7 +928,7 @@ static bool _remove_subtree(struct radix_tree *rt, struct value *root, uint8_t *
if (r && n256->values[*kb].type == UNSET) {
n256->nr_entries--;
if (n256->nr_entries <= 48)
_degrade_to_n48(n256, root);
_degrade_to_n48(n256, root);
}
return r;
}
@ -931,11 +937,13 @@ static bool _remove_subtree(struct radix_tree *rt, struct value *root, uint8_t *
return false;
}
unsigned radix_tree_remove_prefix(struct radix_tree *rt, uint8_t *kb, uint8_t *ke)
unsigned radix_tree_remove_prefix(struct radix_tree *rt, const void *prefix, size_t prefix_len)
{
unsigned count = 0;
const uint8_t *kb = prefix;
const uint8_t *ke = kb + prefix_len;
unsigned count = 0;
if (_remove_subtree(rt, &rt->root, kb, ke, &count))
if (_remove_subtree(rt, &rt->root, kb, ke, &count))
rt->nr_entries -= count;
return count;
@ -943,9 +951,11 @@ unsigned radix_tree_remove_prefix(struct radix_tree *rt, uint8_t *kb, uint8_t *k
//----------------------------------------------------------------
bool radix_tree_lookup(struct radix_tree *rt,
uint8_t *kb, uint8_t *ke, union radix_value *result)
bool radix_tree_lookup(struct radix_tree *rt, const void *key, size_t keylen,
union radix_value *result)
{
const uint8_t *kb = key;
const uint8_t *ke = kb + keylen;
struct value_chain *vc;
struct lookup_result lr = _lookup_prefix(&rt->root, kb, ke);
if (lr.kb == ke) {
@ -968,58 +978,58 @@ bool radix_tree_lookup(struct radix_tree *rt,
}
// FIXME: build up the keys too
static bool _iterate(struct value *v, struct radix_tree_iterator *it)
static bool _iterate(struct radix_tree_iterator *it, const struct value *v)
{
unsigned i;
struct value_chain *vc;
struct prefix_chain *pc;
struct node4 *n4;
struct node16 *n16;
struct node48 *n48;
struct node256 *n256;
const struct value_chain *vc;
const struct prefix_chain *pc;
const struct node4 *n4;
const struct node16 *n16;
const struct node48 *n48;
const struct node256 *n256;
switch (v->type) {
case UNSET:
// can't happen
// can't happen
break;
case VALUE:
return it->visit(it, NULL, NULL, v->value);
return it->visit(it, NULL, 0, v->value);
case VALUE_CHAIN:
vc = v->value.ptr;
return it->visit(it, NULL, NULL, vc->value) && _iterate(&vc->child, it);
return it->visit(it, NULL, 0, vc->value) && _iterate(it, &vc->child);
case PREFIX_CHAIN:
pc = v->value.ptr;
return _iterate(&pc->child, it);
return _iterate(it, &pc->child);
case NODE4:
n4 = (struct node4 *) v->value.ptr;
n4 = (const struct node4 *) v->value.ptr;
for (i = 0; i < n4->nr_entries; i++)
if (!_iterate(n4->values + i, it))
return false;
return true;
if (!_iterate(it, n4->values + i))
return false;
return true;
case NODE16:
n16 = (struct node16 *) v->value.ptr;
n16 = (const struct node16 *) v->value.ptr;
for (i = 0; i < n16->nr_entries; i++)
if (!_iterate(n16->values + i, it))
return false;
if (!_iterate(it, n16->values + i))
return false;
return true;
case NODE48:
n48 = (struct node48 *) v->value.ptr;
n48 = (const struct node48 *) v->value.ptr;
for (i = 0; i < n48->nr_entries; i++)
if (!_iterate(n48->values + i, it))
return false;
if (!_iterate(it, n48->values + i))
return false;
return true;
case NODE256:
n256 = (struct node256 *) v->value.ptr;
n256 = (const struct node256 *) v->value.ptr;
for (i = 0; i < 256; i++)
if (n256->values[i].type != UNSET && !_iterate(n256->values + i, it))
return false;
if (n256->values[i].type != UNSET && !_iterate(it, n256->values + i))
return false;
return true;
}
@ -1027,12 +1037,14 @@ static bool _iterate(struct value *v, struct radix_tree_iterator *it)
return false;
}
void radix_tree_iterate(struct radix_tree *rt, uint8_t *kb, uint8_t *ke,
struct radix_tree_iterator *it)
void radix_tree_iterate(struct radix_tree *rt, const void *key, size_t keylen,
struct radix_tree_iterator *it)
{
const uint8_t *kb = key;
const uint8_t *ke = kb + keylen;
struct lookup_result lr = _lookup_prefix(&rt->root, kb, ke);
if (lr.kb == ke || _prefix_chain_matches(&lr, ke))
(void) _iterate(lr.v, it);
(void) _iterate(it, lr.v);
}
//----------------------------------------------------------------
@ -1130,7 +1142,7 @@ static bool _check_nodes(struct value *v, unsigned *count)
if (ncount != n48->nr_entries) {
fprintf(stderr, "incorrect number of entries in n48, n48->nr_entries = %u, actual = %u\n",
n48->nr_entries, ncount);
n48->nr_entries, ncount);
return false;
}
@ -1166,7 +1178,7 @@ static bool _check_nodes(struct value *v, unsigned *count)
if (ncount != n256->nr_entries) {
fprintf(stderr, "incorrect number of entries in n256, n256->nr_entries = %u, actual = %u\n",
n256->nr_entries, ncount);
n256->nr_entries, ncount);
return false;
}
@ -1189,7 +1201,7 @@ bool radix_tree_is_well_formed(struct radix_tree *rt)
if (rt->nr_entries != count) {
fprintf(stderr, "incorrect entry count: rt->nr_entries = %u, actual = %u\n",
rt->nr_entries, count);
rt->nr_entries, count);
return false;
}
@ -1207,6 +1219,7 @@ static void _dump(FILE *out, struct value v, unsigned indent)
struct node16 *n16;
struct node48 *n48;
struct node256 *n256;
unsigned printable;
if (v.type == UNSET)
return;
@ -1231,9 +1244,22 @@ static void _dump(FILE *out, struct value v, unsigned indent)
case PREFIX_CHAIN:
pc = v.value.ptr;
fprintf(out, "<prefix: ");
fprintf(out, "<prefix(%u): ", pc->len);
printable = 1;
for (i = 0; i < pc->len; i++)
fprintf(out, "%x.", (unsigned) *(pc->prefix + i));
if (!isprint(pc->prefix[i])) {
printable = 0;
break;
}
if (printable)
fputc('"', out);
for (i = 0; i < pc->len; i++)
if (printable)
fprintf(out, "%c", pc->prefix[i]);
else
fprintf(out, "%02x.", (unsigned) *(pc->prefix + i));
if (printable)
fputc('"', out);
fprintf(out, ">\n");
_dump(out, pc->child, indent + 1);
break;
@ -1242,7 +1268,7 @@ static void _dump(FILE *out, struct value v, unsigned indent)
n4 = v.value.ptr;
fprintf(out, "<n4: ");
for (i = 0; i < n4->nr_entries; i++)
fprintf(out, "%x ", (unsigned) n4->keys[i]);
fprintf(out, "%02x ", (unsigned) n4->keys[i]);
fprintf(out, ">\n");
for (i = 0; i < n4->nr_entries; i++)
@ -1253,7 +1279,7 @@ static void _dump(FILE *out, struct value v, unsigned indent)
n16 = v.value.ptr;
fprintf(out, "<n16: ");
for (i = 0; i < n16->nr_entries; i++)
fprintf(out, "%x ", (unsigned) n16->keys[i]);
fprintf(out, "%02x ", (unsigned) n16->keys[i]);
fprintf(out, ">\n");
for (i = 0; i < n16->nr_entries; i++)
@ -1265,7 +1291,7 @@ static void _dump(FILE *out, struct value v, unsigned indent)
fprintf(out, "<n48: ");
for (i = 0; i < 256; i++)
if (n48->keys[i] < 48)
fprintf(out, "%x ", i);
fprintf(out, "%02x ", i);
fprintf(out, ">\n");
for (i = 0; i < n48->nr_entries; i++) {
@ -1279,7 +1305,7 @@ static void _dump(FILE *out, struct value v, unsigned indent)
fprintf(out, "<n256: ");
for (i = 0; i < 256; i++)
if (n256->values[i].type != UNSET)
fprintf(out, "%x ", i);
fprintf(out, "%02x ", i);
fprintf(out, ">\n");
for (i = 0; i < 256; i++)

View File

@ -1,5 +1,5 @@
// Copyright (C) 2018 Red Hat, Inc. All rights reserved.
//
//
// This file is part of LVM2.
//
// This copyrighted material is made available to anyone wishing to use,
@ -18,6 +18,7 @@
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
//----------------------------------------------------------------
// This implementation is based around nested binary trees. Very
@ -37,12 +38,12 @@ struct node {
struct radix_tree {
radix_value_dtr dtr;
void *dtr_context;
unsigned nr_entries;
struct node *root;
};
struct radix_tree *
radix_tree_create(radix_value_dtr dtr, void *dtr_context)
struct radix_tree *radix_tree_create(radix_value_dtr dtr, void *dtr_context)
{
struct radix_tree *rt = zalloc(sizeof(*rt));
@ -105,7 +106,7 @@ unsigned radix_tree_size(struct radix_tree *rt)
return _count(rt->root);
}
static struct node **_lookup(struct node **pn, uint8_t *kb, uint8_t *ke)
static struct node **_lookup(struct node **pn, const uint8_t *kb, const uint8_t *ke)
{
struct node *n = *pn;
@ -122,7 +123,7 @@ static struct node **_lookup(struct node **pn, uint8_t *kb, uint8_t *ke)
return _lookup(&n->center, kb + 1, ke);
}
static bool _insert(struct node **pn, uint8_t *kb, uint8_t *ke, union radix_value v)
static bool _insert(struct node **pn, const uint8_t *kb, const uint8_t *ke, union radix_value v)
{
struct node *n = *pn;
@ -151,39 +152,51 @@ static bool _insert(struct node **pn, uint8_t *kb, uint8_t *ke, union radix_valu
return _insert(&n->center, kb + 1, ke, v);
}
bool radix_tree_insert(struct radix_tree *rt, uint8_t *kb, uint8_t *ke, union radix_value v)
bool radix_tree_insert(struct radix_tree *rt, const void *key, size_t keylen,
union radix_value v)
{
return _insert(&rt->root, kb, ke, v);
const uint8_t *kb = key;
const uint8_t *ke = kb + keylen;
if (!_insert(&rt->root, kb, ke, v))
return false;
rt->nr_entries++;
return true;
}
bool radix_tree_remove(struct radix_tree *rt, uint8_t *kb, uint8_t *ke)
bool radix_tree_remove(struct radix_tree *rt, const void *key, size_t keylen)
{
const uint8_t *kb = key;
const uint8_t *ke = kb + keylen;
struct node **pn = _lookup(&rt->root, kb, ke);
struct node *n = *pn;
if (!n || !n->has_value)
return false;
else {
if (rt->dtr)
rt->dtr(rt->dtr_context, n->value);
rt->nr_entries--;
if (n->left || n->center || n->right) {
n->has_value = false;
return true;
if (rt->dtr)
rt->dtr(rt->dtr_context, n->value);
} else {
// FIXME: delete parent if this was the last entry
free(n);
*pn = NULL;
}
if (n->left || n->center || n->right) {
n->has_value = false;
return true;
return true;
}
// FIXME: delete parent if this was the last entry
free(n);
*pn = NULL;
return true;
}
unsigned radix_tree_remove_prefix(struct radix_tree *rt, uint8_t *kb, uint8_t *ke)
unsigned radix_tree_remove_prefix(struct radix_tree *rt, const void *key, size_t keylen)
{
const uint8_t *kb = key;
const uint8_t *ke = kb + keylen;
struct node **pn;
unsigned count;
@ -197,17 +210,20 @@ unsigned radix_tree_remove_prefix(struct radix_tree *rt, uint8_t *kb, uint8_t *k
return count;
}
bool
radix_tree_lookup(struct radix_tree *rt, uint8_t *kb, uint8_t *ke, union radix_value *result)
bool radix_tree_lookup(struct radix_tree *rt, const void *key, size_t keylen,
union radix_value *result)
{
const uint8_t *kb = key;
const uint8_t *ke = kb + keylen;
struct node **pn = _lookup(&rt->root, kb, ke);
struct node *n = *pn;
if (n && n->has_value) {
*result = n->value;
return true;
} else
return false;
}
return false;
}
static void _iterate(struct node *n, struct radix_tree_iterator *it)
@ -219,15 +235,18 @@ static void _iterate(struct node *n, struct radix_tree_iterator *it)
if (n->has_value)
// FIXME: fill out the key
it->visit(it, NULL, NULL, n->value);
it->visit(it, NULL, 0, n->value);
_iterate(n->center, it);
_iterate(n->right, it);
}
void radix_tree_iterate(struct radix_tree *rt, uint8_t *kb, uint8_t *ke,
void radix_tree_iterate(struct radix_tree *rt, const void *key, size_t keylen,
struct radix_tree_iterator *it)
{
const uint8_t *kb = key;
const uint8_t *ke = kb + keylen;
if (kb == ke)
_iterate(rt->root, it);
@ -237,7 +256,7 @@ void radix_tree_iterate(struct radix_tree *rt, uint8_t *kb, uint8_t *ke,
if (n) {
if (n->has_value)
it->visit(it, NULL, NULL, n->value);
it->visit(it, NULL, 0, n->value);
_iterate(n->center, it);
}
}
@ -248,8 +267,32 @@ bool radix_tree_is_well_formed(struct radix_tree *rt)
return true;
}
static void _dump(FILE *out, struct node *n, unsigned indent)
{
unsigned i;
if (!n)
return;
_dump(out, n->left, indent + 1);
for (i = 0; i < 2 * indent; i++)
fprintf(out, " ");
if (n->has_value) {
fprintf(out, "value: %llu\n", n->value.n);
} else {
fprintf(out, "key: '%c' [0x%02x] %u\n",
isprint(n->key) ? n->key : ' ', n->key, indent);
}
_dump(out, n->center, indent + 1);
_dump(out, n->right, indent + 1);
}
void radix_tree_dump(struct radix_tree *rt, FILE *out)
{
_dump(out, rt->root, 0);
}
//----------------------------------------------------------------

View File

@ -19,3 +19,45 @@
#endif
//----------------------------------------------------------------
struct visitor {
struct radix_tree_iterator it;
unsigned pos, nr_entries;
union radix_value *values;
};
static bool _visitor(struct radix_tree_iterator *it,
const void *key, size_t keylen,
union radix_value v)
{
struct visitor *vt = container_of(it, struct visitor, it);
if (vt->pos >= vt->nr_entries)
return false;
vt->values[vt->pos++] = v;
return true;
}
bool radix_tree_values(struct radix_tree *rt, const void *key, size_t keylen,
union radix_value **values, unsigned *nr_values)
{
struct visitor vt = {
.it.visit = _visitor,
.nr_entries = rt->nr_entries,
.values = calloc(rt->nr_entries + 1, sizeof(union radix_value)),
};
if (vt.values) {
// build set of all values in current radix tree
radix_tree_iterate(rt, key, keylen, &vt.it);
*nr_values = vt.pos;
*values = vt.values;
return true;
}
return false;
}
//----------------------------------------------------------------

View File

@ -33,32 +33,51 @@ struct radix_tree *radix_tree_create(radix_value_dtr dtr, void *dtr_context);
void radix_tree_destroy(struct radix_tree *rt);
unsigned radix_tree_size(struct radix_tree *rt);
bool radix_tree_insert(struct radix_tree *rt, uint8_t *kb, uint8_t *ke, union radix_value v);
bool radix_tree_remove(struct radix_tree *rt, uint8_t *kb, uint8_t *ke);
bool radix_tree_insert(struct radix_tree *rt, const void *key, size_t keylen, union radix_value v);
bool radix_tree_remove(struct radix_tree *rt, const void *key, size_t keylen);
// Returns the number of values removed
unsigned radix_tree_remove_prefix(struct radix_tree *rt, uint8_t *prefix_b, uint8_t *prefix_e);
unsigned radix_tree_remove_prefix(struct radix_tree *rt, const void *prefix, size_t prefix_len);
bool radix_tree_lookup(struct radix_tree *rt,
uint8_t *kb, uint8_t *ke, union radix_value *result);
bool radix_tree_lookup(struct radix_tree *rt, const void *key, size_t keylen,
union radix_value *result);
// The radix tree stores entries in lexicographical order. Which means
// we can iterate entries, in order. Or iterate entries with a particular
// prefix.
struct radix_tree_iterator {
// Returns false if the iteration should end.
// Returns false if the iteration should end.
bool (*visit)(struct radix_tree_iterator *it,
uint8_t *kb, uint8_t *ke, union radix_value v);
const void *key, size_t keylen, union radix_value v);
};
void radix_tree_iterate(struct radix_tree *rt, uint8_t *kb, uint8_t *ke,
struct radix_tree_iterator *it);
void radix_tree_iterate(struct radix_tree *rt, const void *key, size_t keylen,
struct radix_tree_iterator *it);
// Alternative traversing radix_tree.
// Builds whole set all radix_tree nr_values values.
// After use, free(values).
bool radix_tree_values(struct radix_tree *rt, const void *key, size_t keylen,
union radix_value **values, unsigned *nr_values);
// Checks that some constraints on the shape of the tree are
// being held. For debug only.
bool radix_tree_is_well_formed(struct radix_tree *rt);
void radix_tree_dump(struct radix_tree *rt, FILE *out);
// Shortcut for ptr value return
// Note: if value would be NULL, it's same result for not/found case.
static inline void *radix_tree_lookup_ptr(struct radix_tree *rt, const void *key, size_t keylen)
{
union radix_value v;
return radix_tree_lookup(rt, key, keylen, &v) ? v.ptr : NULL;
}
static inline bool radix_tree_insert_ptr(struct radix_tree *rt, const void *key, size_t keylen, void *ptr)
{
union radix_value v = { .ptr = ptr };
return radix_tree_insert(rt, key, keylen, v);
}
//----------------------------------------------------------------
#endif

View File

@ -49,7 +49,7 @@ install_localconf: $(CONFLOCAL)
fi
install_profiles: $(PROFILES)
@echo " [INSTALL] $<"
$(SHOW) " [INSTALL] $<"
$(Q) $(INSTALL_DIR) $(profiledir)
$(Q) $(INSTALL_DATA) $(PROFILES) $(profiledir)/

View File

@ -122,11 +122,11 @@ devices {
# Configuration option devices/use_devicesfile.
# Enable or disable the use of a devices file.
# When enabled, lvm will only use devices that
# are lised in the devices file. A devices file will
# are listed in the devices file. A devices file will
# be used, regardless of this setting, when the --devicesfile
# option is set to a specific file name.
# This configuration option has an automatic default value.
# use_devicesfile = 0
# use_devicesfile = @DEFAULT_USE_DEVICES_FILE@
# Configuration option devices/devicesfile.
# The name of the system devices file, listing devices that LVM should use.
@ -135,6 +135,16 @@ devices {
# This configuration option has an automatic default value.
# devicesfile = "system.devices"
# Configuration option devices/devicesfile_backup_limit.
# The max number of backup files to keep in /etc/lvm/devices/backup.
# LVM creates a backup of the devices file each time a new
# version is created, or each time a modification is detected.
# When the max number of backups is reached, the oldest are
# removed to remain at the limit. Set to 0 to disable backups.
# Only the system devices file is backed up.
# This configuration option has an automatic default value.
# devicesfile_backup_limit = 50
# Configuration option devices/search_for_devnames.
# Look outside of the devices file for missing devname entries.
# A devname entry is used for a device that does not have a stable
@ -149,7 +159,27 @@ devices {
# at other devices, but only those that are likely to have the PV.
# If "all", lvm will look at all devices on the system.
# This configuration option has an automatic default value.
# search_for_devnames = "auto"
# search_for_devnames = "all"
# Configuration option devices/device_ids_refresh.
# Find PVs on new devices and update the device IDs in the devices file.
# If PVs are restored or moved to a new system with new devices, but
# an old system.devices remains with old device IDs, then search for
# the PVIDs on new devices and update the device IDs in system.devices.
# The original device IDs must also not be found on the new system.
# See device_ids_refresh_check for conditions that trigger the refresh.
# This configuration option has an automatic default value.
# device_ids_refresh = 1
# Configuration option devices/device_ids_refresh_checks.
# Conditions that trigger device_ids_refresh to locate PVIDs on new devices.
# product_uuid: refresh if /sys/devices/virtual/dmi/id/product_uuid does not
# match the value saved in system.devices.
# hostname: refresh if hostname does not match the value saved in system.devices.
# (hostname is used if product_uuid is not available.)
# Remove values from this list to prevent lvm from using them.
# This configuration option has an automatic default value.
# device_ids_refresh_checks = [ "product_uuid", "hostname" ]
# Configuration option devices/filter.
# Limit the block devices that are used by LVM commands.
@ -211,17 +241,12 @@ devices {
# sysfs_scan = 1
# Configuration option devices/scan_lvs.
# Scan LVM LVs for layered PVs, allowing LVs to be used as PVs.
# When 1, LVM will detect PVs layered on LVs, and caution must be
# taken to avoid a host accessing a layered VG that may not belong
# to it, e.g. from a guest image. This generally requires excluding
# the LVs with device filters. Also, when this setting is enabled,
# every LVM command will scan every active LV on the system (unless
# filtered), which can cause performance problems on systems with
# many active LVs. When this setting is 0, LVM will not detect or
# use PVs that exist on LVs, and will not allow a PV to be created on
# an LV. The LVs are ignored using a built in device filter that
# identifies and excludes LVs.
# Allow LVM LVs to be used as PVs. When enabled, LVM commands will
# scan active LVs to look for other PVs. Caution is required to
# avoid using PVs that belong to guest images stored on LVs.
# When enabled, the LVs scanned should be restricted using the
# devices file or the filter. This option does not enable autoactivation
# of layered VGs, which requires editing LVM udev rules (see LVM_PVSCAN_ON_LVS.)
# This configuration option has an automatic default value.
# scan_lvs = 0
@ -537,7 +562,7 @@ allocation {
# Configuration option allocation/cache_pool_max_chunks.
# The maximum number of chunks in a cache pool.
# For cache target v1.9 the recommended maximumm is 1000000 chunks.
# For cache target v1.9 the recommended maximum is 1000000 chunks.
# Using cache pool with more chunks may degrade cache performance.
# This configuration option does not have a default value defined.
@ -621,17 +646,9 @@ allocation {
# This configuration option has an automatic default value.
# vdo_use_deduplication = 1
# Configuration option allocation/vdo_use_metadata_hints.
# Enables or disables whether VDO volume should tag its latency-critical
# writes with the REQ_SYNC flag. Some device mapper targets such as dm-raid5
# process writes with this flag at a higher priority.
# Default is enabled.
# This configuration option has an automatic default value.
# vdo_use_metadata_hints = 1
# Configuration option allocation/vdo_minimum_io_size.
# The minimum IO size for VDO volume to accept, in bytes.
# Valid values are 512 or 4096. The recommended and default value is 4096.
# Valid values are 512 or 4096. The recommended value is 4096.
# This configuration option has an automatic default value.
# vdo_minimum_io_size = 4096
@ -651,11 +668,6 @@ allocation {
# This configuration option has an automatic default value.
# vdo_block_map_period = 16380
# Configuration option allocation/vdo_check_point_frequency.
# The default check point frequency for VDO volume.
# This configuration option has an automatic default value.
# vdo_check_point_frequency = 0
# Configuration option allocation/vdo_use_sparse_index.
# Enables sparse indexing for VDO volume.
# This configuration option has an automatic default value.
@ -684,7 +696,7 @@ allocation {
# Configuration option allocation/vdo_bio_threads.
# Specifies the number of threads to use for submitting I/O
# operations to the storage device of VDO volume.
# The value must be in range [1..100]
# The value must be in range [1..100].
# Each additional thread after the first will use an additional 18MiB of RAM,
# plus 1.12 MiB of RAM per megabyte of configured read cache size.
# This configuration option has an automatic default value.
@ -698,7 +710,7 @@ allocation {
# Configuration option allocation/vdo_cpu_threads.
# Specifies the number of threads to use for CPU-intensive work such as
# hashing or compression for VDO volume. The value must be in range [1..100]
# hashing or compression for VDO volume. The value must be in range [1..100].
# This configuration option has an automatic default value.
# vdo_cpu_threads = 2
@ -716,7 +728,7 @@ allocation {
# processing based on the hash value computed from the block data.
# A logical thread count of 9 or more will require explicitly specifying
# a sufficiently large block map cache size, as well.
# The value must be in range [0..100].
# The value must be in range [0..60].
# vdo_hash_zone_threads, vdo_logical_threads and vdo_physical_threads must be
# either all zero or all non-zero.
# This configuration option has an automatic default value.
@ -732,19 +744,6 @@ allocation {
# This configuration option has an automatic default value.
# vdo_physical_threads = 1
# Configuration option allocation/vdo_write_policy.
# Specifies the write policy:
# auto - VDO will check the storage device and determine whether it supports flushes.
# If it does, VDO will run in async mode, otherwise it will run in sync mode.
# sync - Writes are acknowledged only after data is stably written.
# This policy is not supported if the underlying storage is not also synchronous.
# async - Writes are acknowledged after data has been cached for writing to stable storage.
# Data which has not been flushed is not guaranteed to persist in this mode.
# async-unsafe - Writes are handled like 'async' but there is no guarantee of the atomicity async provides.
# This mode should only be used for better performance when atomicity is not required.
# This configuration option has an automatic default value.
# vdo_write_policy = "auto"
# Configuration option allocation/vdo_max_discard.
# Specified the maximum size of discard bio accepted, in 4096 byte blocks.
# I/O requests to a VDO volume are normally split into 4096-byte blocks,
@ -758,7 +757,7 @@ allocation {
# vdo_max_discard = 1
# Configuration option allocation/vdo_pool_header_size.
# Specified the emptry header size in KiB at the front and end of vdo pool device.
# Specified the empty header size in KiB at the front and end of vdo pool device.
# This configuration option has an automatic default value.
# vdo_pool_header_size = 512
}
@ -782,6 +781,9 @@ log {
# to define fields to display and sort fields for the log report.
# You can also use log/command_log_selection to define selection
# criteria used each time the log is reported.
# Note that if report/output_format (or --reportformat command line
# option) is set to json or json_std, then log/report_command_log=1
# is default.
# This configuration option has an automatic default value.
# report_command_log = 0
@ -811,8 +813,9 @@ log {
# define selection criteria for log report on command line directly
# using <lvm command> --configreport log -S <selection criteria>
# which has precedence over log/command_log_selection setting.
# For more information about selection criteria in general, see
# lvm(8) man page.
# To make all the command log lines visible, use "all" value
# for the command log selection. For more information about selection
# criteria in general, see lvmreport(7) man page.
# This configuration option has an automatic default value.
# command_log_selection = "!(log_type=status && message=success)"
@ -937,7 +940,7 @@ backup {
# archive = 1
# Configuration option backup/archive_dir.
# Location of the metdata archive files.
# Location of the metadata archive files.
# Remember to back up this directory regularly!
# This configuration option has an automatic default value.
# archive_dir = "@DEFAULT_SYS_DIR@/@DEFAULT_ARCHIVE_SUBDIR@"
@ -1013,7 +1016,7 @@ global {
# Location of proc filesystem.
# This configuration option is advanced.
# This configuration option has an automatic default value.
# proc = "/proc"
# proc = "@DEFAULT_PROC_DIR@"
# Configuration option global/etc.
# Location of /etc system configuration directory.
@ -1151,18 +1154,13 @@ global {
# lvdisplay_shows_full_device_path = 0
# Configuration option global/event_activation.
# Activate LVs based on system-generated device events.
# When a PV appears on the system, a system-generated uevent triggers
# the lvm2-pvscan service which runs the pvscan --cache -aay command.
# If the new PV completes a VG, pvscan autoactivates LVs in the VG.
# When event_activation is disabled, the lvm2-activation services are
# generated and run at fixed points during system startup. These
# services run vgchange -aay to autoactivate LVs in VGs that happen
# to be present at that point in time.
# See the --setautoactivation option or the auto_activation_volume_list
# setting to configure autoactivation for specific VGs or LVs.
# Disable event based autoactivation commands.
# WARNING: setting this to zero may cause machine startup to fail.
# Previously, setting this to zero would enable static autoactivation
# services (via the lvm2-activation-generator), but the autoactivation
# services and generator have been removed.
# This configuration option has an automatic default value.
# event_activation = 1
# event_activation = @DEFAULT_EVENT_ACTIVATION@
# Configuration option global/use_aio.
# Use async I/O when reading and writing devices.
@ -1194,6 +1192,16 @@ global {
# This configuration option has an automatic default value.
# sanlock_lv_extend = 256
# Configuration option global/sanlock_align_size.
# The sanlock lease size in MiB to use on disks with a 4K sector size.
# Possible values are 1,2,4,8. The default is 8, which supports up to
# 2000 hosts (and max host_id 2000.) Smaller values support smaller
# numbers of max hosts (and max host_ids): 250, 500, 1000, 2000 for
# lease sizes 1,2,4,8. Disks with 512 byte sectors always use 1MiB
# leases and support 2000 hosts, and are not affected by this setting.
# This configuration option has an automatic default value.
# sanlock_align_size = 8
# Configuration option global/lvmlockctl_kill_command.
# The command that lvmlockctl --kill should use to force LVs offline.
# The lvmlockctl --kill command is run when a shared VG has lost
@ -1207,7 +1215,7 @@ global {
# Configuration option global/thin_check_executable.
# The full path to the thin_check command.
# LVM uses this command to check that a thin metadata device is in a
# LVM uses this command to check that a thin pool metadata device is in a
# usable state. When a thin pool is activated and after it is
# deactivated, this command is run. Activation will only proceed if
# the command has an exit status of 0. Set to "" to skip this check.
@ -1231,6 +1239,14 @@ global {
# This configuration option has an automatic default value.
# thin_repair_executable = "@THIN_REPAIR_CMD@"
# Configuration option global/thin_restore_executable.
# The full path to the thin_restore command.
# LVM uses this command to restore generated data for a thin pool metadata device.
# Also see thin_restore_options.
# (See package device-mapper-persistent-data or thin-provisioning-tools)
# This configuration option has an automatic default value.
# thin_restore_executable = "@THIN_RESTORE_CMD@"
# Configuration option global/thin_check_options.
# List of options passed to the thin_check command.
# With thin_check version 2.1 or newer you can add the option
@ -1245,6 +1261,11 @@ global {
# This configuration option has an automatic default value.
# thin_repair_options = [ "" ]
# Configuration option global/thin_restore_options.
# List of options passed to the thin_restore command.
# This configuration option has an automatic default value.
# thin_restore_options = [ "" ]
# Configuration option global/thin_disabled_features.
# Features to not use in the thin driver.
# This can be helpful for testing, or to avoid using a feature that is
@ -1293,6 +1314,14 @@ global {
# This configuration option has an automatic default value.
# cache_repair_executable = "@CACHE_REPAIR_CMD@"
# Configuration option global/cache_restore_executable.
# The full path to the cache_restore command.
# LVM uses this command to restore generated data for a cache metadata device.
# Also see cache_restore_options.
# (See package device-mapper-persistent-data or thin-provisioning-tools)
# This configuration option has an automatic default value.
# cache_restore_executable = "@CACHE_RESTORE_CMD@"
# Configuration option global/cache_check_options.
# List of options passed to the cache_check command.
# With cache_check version 5.0 or newer you should include the option
@ -1305,6 +1334,11 @@ global {
# This configuration option has an automatic default value.
# cache_repair_options = [ "" ]
# Configuration option global/cache_restore_options.
# List of options passed to the cache_restore command.
# This configuration option has an automatic default value.
# cache_restore_options = [ "" ]
# Configuration option global/vdo_format_executable.
# The full path to the vdoformat command.
# LVM uses this command to initial data volume for VDO type logical volume
@ -1319,10 +1353,10 @@ global {
# Configuration option global/vdo_disabled_features.
# Features to not use in the vdo driver.
# This can be helpful for testing, or to avoid using a feature that is
# causing problems. Features include: online_rename
# causing problems. Features include: online_rename, version4
#
# Example
# vdo_disabled_features = [ "online_rename" ]
# vdo_disabled_features = [ "online_rename", "version4" ]
#
# This configuration option does not have a default value defined.
@ -1352,8 +1386,9 @@ global {
# Use an LVM-specific derivation of the local machine-id as the
# system ID. See 'man machine-id'.
# machineid
# Use the contents of the machine-id file to set the system ID
# (appmachineid is recommended.)
# Use the contents of the machine-id file to set the system ID.
# (appmachineid is recommended to avoid exposing the confidential
# machine-id.)
# file
# Use the contents of another file (system_id_file) to set the
# system ID.
@ -1469,13 +1504,15 @@ activation {
# Configuration option activation/reserved_stack.
# Stack size in KiB to reserve for use while devices are suspended.
# Insufficent reserve risks I/O deadlock during device suspension.
# Insufficient reserve risks I/O deadlock during device suspension.
# Value 0 disables memory locking.
# This configuration option has an automatic default value.
# reserved_stack = 64
# Configuration option activation/reserved_memory.
# Memory size in KiB to reserve for use while devices are suspended.
# Insufficent reserve risks I/O deadlock during device suspension.
# Insufficient reserve risks I/O deadlock during device suspension.
# Value 0 disables memory locking.
# This configuration option has an automatic default value.
# reserved_memory = 8192
@ -1610,7 +1647,7 @@ activation {
# This includes LVs that have the following segment types:
# raid1, raid4, raid5*, and raid6*.
# If a device in the LV fails, the policy determines the steps
# performed by dmeventd automatically, and the steps perfomed by the
# performed by dmeventd automatically, and the steps performed by the
# manual command lvconvert --repair --use-policies.
# Automatic handling requires dmeventd to be monitoring the LV.
#
@ -1634,7 +1671,7 @@ activation {
# (copies) and a mirror log. A disk log ensures that a mirror LV does
# not need to be re-synced (all copies made the same) every time a
# machine reboots or crashes. If a device in the LV fails, this policy
# determines the steps perfomed by dmeventd automatically, and the steps
# determines the steps performed by dmeventd automatically, and the steps
# performed by the manual command lvconvert --repair --use-policies.
# Automatic handling requires dmeventd to be monitoring the LV.
#
@ -1796,7 +1833,7 @@ activation {
# Configuration option activation/polling_interval.
# Check pvmove or lvconvert progress at this interval (seconds).
# When pvmove or lvconvert must wait for the kernel to finish
# synchronising or merging data, they check and report progress at
# synchronizing or merging data, they check and report progress at
# intervals of this number of seconds. If this is set to 0 and there
# is only one thing to wait for, there are no progress reports, but
# the process is awoken immediately once the operation is complete.
@ -1824,7 +1861,7 @@ activation {
# uses are present. Other PVs in the Volume Group may be missing.
# degraded
# Like complete, but additionally RAID LVs of segment type raid1,
# raid4, raid5, radid6 and raid10 will be activated if there is no
# raid4, raid5, raid6 and raid10 will be activated if there is no
# data loss, i.e. they have sufficient redundancy to present the
# entire addressable range of the Logical Volume.
# partial
@ -1941,15 +1978,14 @@ activation {
# Configuration section report.
# LVM report command output formatting.
# This configuration section has an automatic default value.
# report {
report {
# Configuration option report/output_format.
# Format of LVM command's report output.
# If there is more than one report per command, then the format
# is applied for all reports. You can also change output format
# directly on command line using --reportformat option which
# has precedence over log/output_format setting.
# has precedence over report/output_format setting.
# Accepted values:
# basic
# Original format with columns and rows. If there is more than
@ -1957,6 +1993,13 @@ activation {
# name for identification.
# json
# JSON format.
# json_std
# JSON format that is more compliant with JSON standard.
# Compared to original "json" format:
# - it does not use double quotes around numeric values,
# - it uses 'null' for undefined numeric values,
# - it prints string list as proper JSON array of strings instead of a single string.
# Note that if json or json_std output format is used, then log/command_log_report=1 is default.
# This configuration option has an automatic default value.
# output_format = "basic"
@ -1996,7 +2039,11 @@ activation {
# buffered = 1
# Configuration option report/headings.
# Show headings for columns on report.
# Format of LVM command's report output headings.
# Accepted values:
# 0 no headings,
# 1 headings with column abbreviations,
# 2 headings with full column names.
# This configuration option has an automatic default value.
# headings = 1
@ -2075,7 +2122,7 @@ activation {
# %F
# Equivalent to %Y-%m-%d (the ISO 8601 date format).
# %G
# The ISO 8601 week-based year with century as adecimal number.
# The ISO 8601 week-based year with century as a decimal number.
# The 4-digit year corresponding to the ISO week number (see %V).
# This has the same format and value as %Y, except that if the
# ISO week number belongs to the previous or next year, that year
@ -2346,7 +2393,7 @@ activation {
# This is displayed when the device for a PV is not known.
# This configuration option has an automatic default value.
# two_word_unknown_device = 0
# }
}
# Configuration section dmeventd.
# Settings for the LVM event daemon.

View File

@ -49,9 +49,10 @@ local {
# This configuration option does not have a default value defined.
# Configuration option local/host_id.
# The lvmlockd sanlock host_id.
# This must be unique among all hosts, and must be between 1 and 2000.
# Applicable only if LVM is compiled with lockd support
# The sanlock host_id used by lvmlockd. This must be unique among all the hosts
# using shared VGs with sanlock. Accepted values are 1-2000, except when sanlock_align_size
# is configured to 1, 2 or 4, which correspond to max host_id values of 250, 500, or 1000.
# Applicable only if LVM is compiled with support for lvmlockd+sanlock.
# This configuration option has an automatic default value.
# host_id = 0
}

View File

@ -4,11 +4,9 @@
allocation {
vdo_use_compression=1
vdo_use_deduplication=1
vdo_use_metadata_hints=1
vdo_minimum_io_size=4096
vdo_block_map_cache_size_mb=128
vdo_block_map_period=16380
vdo_check_point_frequency=0
vdo_use_sparse_index=0
vdo_index_memory_size_mb=256
vdo_slab_size_mb=2048
@ -19,6 +17,5 @@ allocation {
vdo_hash_zone_threads=1
vdo_logical_threads=1
vdo_physical_threads=1
vdo_write_policy="auto"
vdo_max_discard=1
}

14166
configure vendored

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -21,7 +21,7 @@
* compile (using outdir 'cov'):
* cov-build --dir=cov make CC=gcc
*
* analyze (agressively, using 'cov')
* analyze (aggressively, using 'cov')
* cov-analyze --dir cov --wait-for-license --hfa --concurrency --enable-fnptr --enable-constraint-fpp --security --all --aggressiveness-level=high --field-offset-escape --user-model-file=coverity/coverity_model.xml
*
* generate html output (to 'html' from 'cov'):
@ -70,7 +70,7 @@ void *memccpy(void *dest, const void *src, int c, size_t n)
}
/*
* 2 lines bellow needs to be placed in coverity/config/user_nodefs.h
* 2 lines below needs to be placed in coverity/config/user_nodefs.h
* Not sure about any other way.
* Without them, coverity shows warning since x86 system header files
* are using inline assembly to reset fdset

View File

@ -32,12 +32,12 @@ CFLAGS += $(CPG_CFLAGS) $(EXTRA_EXEC_CFLAGS)
LDFLAGS += $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS)
cmirrord: $(OBJECTS)
@echo " [CC] $@"
$(SHOW) " [CC] $@"
$(Q) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJECTS) \
$(LMLIBS) -L$(top_builddir)/libdm -ldevmapper $(LIBS)
install_cluster: $(TARGETS)
@echo " [INSTALL] $<"
$(SHOW) " [INSTALL] $<"
$(Q) $(INSTALL_PROGRAM) -D $< $(usrsbindir)/$(<F)
install: install_cluster

View File

@ -43,14 +43,14 @@ static void usage (FILE *dest)
int main(int argc, char *argv[])
{
int foreground_mode = 0;
struct option longopts[] = {
static const struct option _long_options[] = {
{ "foreground", no_argument, NULL, 'f' },
{ "help" , no_argument, NULL, 'h' },
{ 0, 0, 0, 0 }
};
int opt;
while ((opt = getopt_long (argc, argv, "fh", longopts, NULL)) != -1) {
while ((opt = getopt_long (argc, argv, "fh", _long_options, NULL)) != -1) {
switch (opt) {
case 'f':
foreground_mode = 1;

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; \
@ -279,7 +279,7 @@ static int handle_cluster_request(struct clog_cpg *entry __attribute__((unused))
* With resumes, we only handle our own.
* Resume is a special case that requires
* local action (to set up CPG), followed by
* a cluster action to co-ordinate reading
* a cluster action to coordinate reading
* the disk and checkpointing
*/
if (tmp->u_rq.request_type == DM_ULOG_RESUME) {
@ -1091,6 +1091,7 @@ static void cpg_message_callback(cpg_handle_t handle, const struct cpg_name *gna
(rq->u_rq.request_type != DM_ULOG_RESUME) &&
(rq->u_rq.request_type != DM_ULOG_CLEAR_REGION) &&
(rq->u_rq.request_type != DM_ULOG_CHECKPOINT_READY)) {
/* coverity[suspicious_sizeof] allocation is using varargs data @end */
tmp_rq = malloc(DM_ULOG_REQUEST_SIZE);
if (!tmp_rq) {
/*
@ -1340,6 +1341,7 @@ static void cpg_join_callback(struct clog_cpg *match,
goto out;
}
/* coverity[suspicious_sizeof] allocation is using varargs data @end */
rq = malloc(DM_ULOG_REQUEST_SIZE);
if (!rq) {
LOG_ERROR("cpg_config_callback: "
@ -1632,7 +1634,7 @@ int create_cluster_cpg(char *uuid, uint64_t luid)
size = ((strlen(uuid) + 1) > CPG_MAX_NAME_LENGTH) ?
CPG_MAX_NAME_LENGTH : (strlen(uuid) + 1);
(void) dm_strncpy(new->name.value, uuid, size);
dm_strncpy(new->name.value, uuid, size);
new->name.length = (uint32_t)size;
new->luid = luid;

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 { \
@ -67,7 +67,7 @@ struct log_c {
uint32_t recoverer;
uint64_t recovering_region; /* -1 means not recovering */
uint64_t skip_bit_warning; /* used to warn if region skipped */
int sync_search;
unsigned sync_search;
int resume_override;
@ -220,7 +220,7 @@ static int rw_log(struct log_c *lc, int do_write)
if (r < 0)
LOG_ERROR("[%s] rw_log: read failure: %s",
SHORT_UUID(lc->uuid), strerror(errno));
if (r != lc->disk_size)
if ((unsigned) r != lc->disk_size)
return -EIO; /* Failed disk read */
return 0;
}
@ -254,7 +254,7 @@ static int read_log(struct log_c *lc)
bitset_size = lc->region_count / 8;
bitset_size += (lc->region_count % 8) ? 1 : 0;
/* 'lc->clean_bits + 1' becasue dm_bitset_t leads with a uint32_t */
/* 'lc->clean_bits + 1' because dm_bitset_t leads with a uint32_t */
memcpy(lc->clean_bits + 1, (char *)lc->disk_buffer + 1024, bitset_size);
return 0;
@ -281,7 +281,7 @@ static int write_log(struct log_c *lc)
bitset_size = lc->region_count / 8;
bitset_size += (lc->region_count % 8) ? 1 : 0;
/* 'lc->clean_bits + 1' becasue dm_bitset_t leads with a uint32_t */
/* 'lc->clean_bits + 1' because dm_bitset_t leads with a uint32_t */
memcpy((char *)lc->disk_buffer + 1024, lc->clean_bits + 1, bitset_size);
if (rw_log(lc, 1)) {
@ -292,13 +292,13 @@ static int write_log(struct log_c *lc)
}
/* FIXME Rewrite this function taking advantage of the udev changes (where in use) to improve its efficiency! */
static int find_disk_path(char *major_minor_str, char *path_rtn, int *unlink_path __attribute__((unused)))
static int find_disk_path(char *major_minor_str, char *path_rtn, size_t sz, int *unlink_path __attribute__((unused)))
{
int r;
DIR *dp;
struct dirent *dep;
struct stat statbuf;
int major, minor;
unsigned major, minor;
if (!strstr(major_minor_str, ":")) {
r = stat(major_minor_str, &statbuf);
@ -306,7 +306,7 @@ static int find_disk_path(char *major_minor_str, char *path_rtn, int *unlink_pat
return -errno;
if (!S_ISBLK(statbuf.st_mode))
return -EINVAL;
sprintf(path_rtn, "%s", major_minor_str);
dm_strncpy(path_rtn, major_minor_str, sz);
return 0;
}
@ -329,7 +329,7 @@ static int find_disk_path(char *major_minor_str, char *path_rtn, int *unlink_pat
* wanted.
*/
sprintf(path_rtn, "/dev/mapper/%s", dep->d_name);
snprintf(path_rtn, sz, "/dev/mapper/%s", dep->d_name);
if (stat(path_rtn, &statbuf) < 0) {
LOG_DBG("Unable to stat %s", path_rtn);
continue;
@ -394,7 +394,7 @@ static int _clog_ctr(char *uuid, uint64_t luid,
goto fail;
}
r = find_disk_path(argv[0], disk_path, &unlink_path);
r = find_disk_path(argv[0], disk_path, sizeof(disk_path), &unlink_path);
if (r) {
LOG_ERROR("Unable to find path to device %s", argv[0]);
goto fail;
@ -452,7 +452,7 @@ static int _clog_ctr(char *uuid, uint64_t luid,
lc->skip_bit_warning = region_count;
lc->disk_fd = -1;
lc->log_dev_failed = 0;
if (!dm_strncpy(lc->uuid, uuid, DM_UUID_LEN)) {
if (!_dm_strncpy(lc->uuid, uuid, DM_UUID_LEN)) {
LOG_ERROR("Cannot use too long UUID %s.", uuid);
r = -EINVAL;
goto fail;
@ -927,7 +927,7 @@ int local_resume(struct dm_ulog_request *rq)
*
* Since this value doesn't change, the kernel
* should not need to talk to server to get this
* The function is here for completness
* The function is here for completeness
*
* Returns: 0 on success, -EXXX on failure
*/
@ -1018,7 +1018,7 @@ static int clog_in_sync(struct dm_ulog_request *rq)
* happen for reads is that additional read attempts may be
* taken.
*
* Futher investigation may be required to determine if there are
* Further investigation may be required to determine if there are
* similar possible outcomes when the mirror is in the process of
* recovering. In that case, lc->in_sync would not have been set
* yet.

View File

@ -13,6 +13,7 @@
#define _LVM_CLOG_FUNCTIONS_H
#include "libdm/libdevmapper.h"
#include "libdm/dm-tools/util.h"
#include "libdm/misc/dm-log-userspace.h"
#include "cluster.h"

View File

@ -266,7 +266,7 @@ static int do_local_work(void *data __attribute__((unused)))
RQ_TYPE(u_rq->request_type));
break;
}
/* ELSE, fall through */
/* ELSE */ /* fall through */
case DM_ULOG_IS_CLEAN:
case DM_ULOG_FLUSH:
case DM_ULOG_MARK_REGION:

View File

@ -11,7 +11,7 @@
*/
#include "logging.h"
const char *__rq_types_off_by_one[] = {
const char * const __rq_types_off_by_one[] = {
"DM_ULOG_CTR",
"DM_ULOG_DTR",
"DM_ULOG_PRESUSPEND",

View File

@ -20,7 +20,7 @@
/* SHORT_UUID - print last 8 chars of a string */
#define SHORT_UUID(x) (strlen(x) > 8) ? ((x) + (strlen(x) - 8)) : (x)
extern const char *__rq_types_off_by_one[];
extern const char * const __rq_types_off_by_one[];
#define RQ_TYPE(x) __rq_types_off_by_one[(x) - 1]
extern int log_tabbing;

View File

@ -70,13 +70,13 @@ plugins.device-mapper: $(LIB_SHARED)
CFLAGS_dmeventd.o += $(EXTRA_EXEC_CFLAGS)
dmeventd: $(LIB_SHARED) dmeventd.o
@echo " [CC] $@"
$(SHOW) " [CC] $@"
$(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 dmeventd.o \
$(SHOW) " [CC] $@"
$(Q) $(CC) $(CFLAGS) $(LDFLAGS) $(STATIC_LDFLAGS) -static dmeventd.o \
-o $@ $(DL_LIBS) $(DMEVENT_LIBS) $(LIBS) $(STATIC_LIBS)
ifeq ("@PKGCONFIG@", "yes")
@ -84,27 +84,27 @@ ifeq ("@PKGCONFIG@", "yes")
endif
install_include: $(srcdir)/libdevmapper-event.h
@echo " [INSTALL] $(<F)"
$(SHOW) " [INSTALL] $(<F)"
$(Q) $(INSTALL_DATA) -D $< $(includedir)/$(<F)
install_pkgconfig: libdevmapper-event.pc
@echo " [INSTALL] $<"
$(SHOW) " [INSTALL] $<"
$(Q) $(INSTALL_DATA) -D $< $(pkgconfigdir)/devmapper-event.pc
install_lib_dynamic: install_lib_shared
install_lib_static: $(LIB_STATIC)
@echo " [INSTALL] $<"
$(SHOW) " [INSTALL] $<"
$(Q) $(INSTALL_DATA) -D $< $(usrlibdir)/$(<F)
install_lib: $(INSTALL_LIB_TARGETS)
install_dmeventd_dynamic: dmeventd
@echo " [INSTALL] $<"
$(SHOW) " [INSTALL] $<"
$(Q) $(INSTALL_PROGRAM) -D $< $(sbindir)/$(<F)
install_dmeventd_static: dmeventd.static
@echo " [INSTALL] $<"
$(SHOW) " [INSTALL] $<"
$(Q) $(INSTALL_PROGRAM) -D $< $(staticdir)/$(<F)
install_dmeventd: $(INSTALL_DMEVENTD_TARGETS)

View File

@ -23,12 +23,12 @@
#include "libdm/misc/dm-logging.h"
#include "base/memory/zalloc.h"
#include "libdaemon/server/daemon-stray.h"
#include <dlfcn.h>
#include <pthread.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <signal.h>
#include <arpa/inet.h> /* for htonl, ntohl */
@ -92,12 +92,10 @@ static const size_t THREAD_STACK_SIZE = 300 * 1024;
/* Default idle exit timeout 1 hour (in seconds) */
static const time_t DMEVENTD_IDLE_EXIT_TIMEOUT = 60 * 60;
static int _debug_level = 0;
static int _use_syslog = 1;
static int _systemd_activation = 0;
static int _foreground = 0;
static int _restart = 0;
static time_t _idle_since = 0;
static const char *_exit_on = DEFAULT_DMEVENTD_EXIT_ON_PATH;
static char **_initial_registrations = 0;
/* FIXME Make configurable at runtime */
@ -202,9 +200,9 @@ struct message_data {
char *dso_name; /* Name of DSO. */
char *device_uuid; /* Mapped device path. */
char *events_str; /* Events string as fetched from message. */
enum dm_event_mask events_field; /* Events bitfield. */
char *timeout_str;
unsigned events_field; /* Events bitfield. */
uint32_t timeout_secs;
char *timeout_str;
struct dm_event_daemon_message *msg; /* Pointer to message buffer. */
};
@ -238,7 +236,7 @@ struct thread_status {
int status; /* See DM_THREAD_{REGISTERING,RUNNING,DONE} */
int events; /* bitfield for event filter. */
int current_events; /* bitfield for occured events. */
int current_events; /* bitfield for occurred events. */
struct dm_task *wait_task;
int pending; /* Set when event filter change is pending */
time_t next_time;
@ -429,7 +427,7 @@ static struct thread_status *_alloc_thread_status(const struct message_data *dat
if (!(thread->device.name = strdup(data->device_uuid)))
goto_out;
/* runs ioctl and may register lvm2 pluging */
/* runs ioctl and may register lvm2 plugin */
thread->processing = 1;
thread->status = DM_THREAD_REGISTERING;
@ -522,7 +520,7 @@ static int _fetch_string(char **ptr, char **src, const int delimiter)
*p = delimiter;
*src = p;
}
(*src)++; /* Skip delmiter, next field */
(*src)++; /* Skip delimiter, next field */
} else if ((len = strlen(*src))) {
/* No delimiter, item ends with '\0' */
if (!(*ptr = strdup(*src))) {
@ -723,12 +721,18 @@ static int _get_status(struct message_data *message_data)
static int _get_parameters(struct message_data *message_data) {
struct dm_event_daemon_message *msg = message_data->msg;
int size;
char idle_buf[32] = "";
if (_idle_since)
(void)dm_snprintf(idle_buf, sizeof(idle_buf), " idle=%lu", (long unsigned) (time(NULL) - _idle_since));
free(msg->data);
if ((size = dm_asprintf(&msg->data, "%s pid=%d daemon=%s exec_method=%s",
if ((size = dm_asprintf(&msg->data, "%s pid=%d daemon=%s exec_method=%s exit_on=\"%s\"%s",
message_data->id, getpid(),
_foreground ? "no" : "yes",
_systemd_activation ? "systemd" : "direct")) < 0) {
_systemd_activation ? "systemd" : "direct",
_exit_on,
idle_buf)) < 0) {
stack;
return -ENOMEM;
}
@ -987,6 +991,7 @@ static void _monitor_unregister(void *arg)
DEBUGLOG("Unregistering monitor for %s.", thread->device.name);
_unregister_for_timeout(thread);
/* coverity[missing_lock] no missing lock here */
if ((thread->status != DM_THREAD_REGISTERING) &&
!_do_unregister_device(thread))
log_error("%s: %s unregister failed.", __func__,
@ -997,6 +1002,8 @@ static void _monitor_unregister(void *arg)
_lock_mutex();
thread->status = DM_THREAD_DONE; /* Last access to thread memory! */
_unlock_mutex();
if (_exit_now) /* Exit is already in-progress, wake-up sleeping select() */
kill(getpid(), SIGINT);
}
/* Device monitoring thread. */
@ -1043,9 +1050,9 @@ static void *_monitor_thread(void *arg)
_unlock_mutex();
_do_process_event(thread);
thread->current_events = 0; /* Current events processed */
_lock_mutex();
thread->current_events = 0; /* Current events processed */
thread->processing = 0;
/*
@ -1161,6 +1168,36 @@ static int _unregister_for_event(struct message_data *message_data)
return ret;
}
static void _unregister_all_threads(void)
{
struct thread_status *thread, *tmp;
_lock_mutex();
dm_list_iterate_items_safe(thread, tmp, &_thread_registry)
_update_events(thread, 0);
_unlock_mutex();
}
static void _wait_for_new_pid(void)
{
unsigned long st_ino = 0;
struct stat st;
int i;
for (i = 0; i < 400000; ++i) {
if (lstat(DMEVENTD_PIDFILE, &st) == 0) {
if (!st_ino)
st_ino = st.st_ino;
else if (st_ino != st.st_ino)
break; /* different pidfile */
} else if (errno == ENOENT)
break; /* pidfile is removed */
usleep(100);
}
}
/*
* Register for an event.
*
@ -1404,7 +1441,8 @@ static int _open_fifo(const char *path)
} else if (!S_ISFIFO(st.st_mode) || st.st_uid ||
(st.st_mode & (S_IEXEC | S_IRWXG | S_IRWXO))) {
log_warn("WARNING: %s has wrong attributes: Replacing.", path);
if (unlink(path)) {
/* coverity[toctou] don't care, path is going to be recreated */
if (unlink(path) && (errno != ENOENT)) {
log_sys_error("unlink", path);
return -1;
}
@ -1412,6 +1450,7 @@ static int _open_fifo(const char *path)
/* Create fifo. */
(void) dm_prepare_selinux_context(path, S_IFIFO);
/* coverity[toctou] revalidating things again */
if ((mkfifo(path, 0600) == -1) && errno != EEXIST) {
log_sys_error("mkfifo", path);
(void) dm_prepare_selinux_context(NULL, 0);
@ -1640,7 +1679,7 @@ static int _do_process_request(struct dm_event_daemon_message *msg)
} else
ret = _handle_request(msg, &message_data);
msg->cmd = ret;
msg->cmd = (uint32_t)ret;
if (!msg->data)
msg->size = dm_asprintf(&(msg->data), "%s %s", message_data.id, strerror(-ret));
@ -1677,9 +1716,9 @@ static void _process_request(struct dm_event_fifos *fifos)
free(msg.data);
if (cmd == DM_EVENT_CMD_DIE) {
if (unlink(DMEVENTD_PIDFILE))
log_sys_error("unlink", DMEVENTD_PIDFILE);
_exit(0);
_unregister_all_threads();
_exit_now = DM_SCHEDULED_EXIT;
log_info("dmeventd exiting for restart.");
}
}
@ -1726,7 +1765,7 @@ static void _cleanup_unused_threads(void)
DEBUGLOG("Destroying Thr %x.", (int)thread->thread);
if (pthread_join(thread->thread, NULL))
log_sys_error("pthread_join", "");
log_sys_debug("pthread_join", "");
_free_thread_status(thread);
_lock_mutex();
@ -1757,7 +1796,7 @@ static void _init_thread_signals(void)
sigdelset(&my_sigset, SIGQUIT);
if (pthread_sigmask(SIG_BLOCK, &my_sigset, NULL))
log_sys_error("pthread_sigmask", "SIG_BLOCK");
log_sys_debug("pthread_sigmask", "SIG_BLOCK");
}
/*
@ -1769,7 +1808,8 @@ static void _init_thread_signals(void)
*/
static void _exit_handler(int sig __attribute__((unused)))
{
_exit_now = DM_SIGNALED_EXIT;
if (!_exit_now)
_exit_now = DM_SIGNALED_EXIT;
}
#ifdef __linux__
@ -1785,7 +1825,7 @@ static int _set_oom_adj(const char *oom_adj_path, int val)
fprintf(fp, "%i", val);
if (dm_fclose(fp))
log_sys_error("fclose", oom_adj_path);
log_sys_debug("fclose", oom_adj_path);
return 1;
}
@ -1799,11 +1839,11 @@ static int _protect_against_oom_killer(void)
if (stat(OOM_ADJ_FILE, &st) == -1) {
if (errno != ENOENT)
log_sys_error("stat", OOM_ADJ_FILE);
log_sys_debug("stat", OOM_ADJ_FILE);
/* Try old oom_adj interface as a fallback */
if (stat(OOM_ADJ_FILE_OLD, &st) == -1) {
log_sys_error("stat", OOM_ADJ_FILE_OLD);
log_sys_debug("stat", OOM_ADJ_FILE_OLD);
return 1;
}
@ -1891,26 +1931,30 @@ out:
static void _remove_files_on_exit(void)
{
if (unlink(DMEVENTD_PIDFILE))
log_sys_error("unlink", DMEVENTD_PIDFILE);
if (unlink(DMEVENTD_PIDFILE) && (errno != ENOENT))
log_sys_debug("unlink", DMEVENTD_PIDFILE);
if (!_systemd_activation) {
if (unlink(DM_EVENT_FIFO_CLIENT))
log_sys_error("unlink", DM_EVENT_FIFO_CLIENT);
if (unlink(DM_EVENT_FIFO_CLIENT) && (errno != ENOENT))
log_sys_debug("unlink", DM_EVENT_FIFO_CLIENT);
if (unlink(DM_EVENT_FIFO_SERVER))
log_sys_error("unlink", DM_EVENT_FIFO_SERVER);
if (unlink(DM_EVENT_FIFO_SERVER) && (errno != ENOENT))
log_sys_debug("unlink", DM_EVENT_FIFO_SERVER);
}
}
static void _daemonize(void)
{
int child_status;
int fd;
int child_status, null_fd;
pid_t pid;
struct rlimit rlim;
struct timeval tval;
sigset_t my_sigset;
struct custom_fds custom_fds = {
/* Do not close fds preloaded by systemd! */
.out = (_systemd_activation) ? SD_FD_FIFO_SERVER : -1,
.err = -1,
.report = (_systemd_activation) ? SD_FD_FIFO_CLIENT : -1,
};
sigemptyset(&my_sigset);
if (sigprocmask(SIG_SETMASK, &my_sigset, NULL) < 0) {
@ -1954,33 +1998,28 @@ static void _daemonize(void)
if (chdir("/"))
exit(EXIT_CHDIR_FAILURE);
if (getrlimit(RLIMIT_NOFILE, &rlim) < 0)
fd = 256; /* just have to guess */
else
fd = rlim.rlim_cur;
daemon_close_stray_fds("dmeventd", 0, -1, &custom_fds);
for (--fd; fd >= 0; fd--) {
#ifdef __linux__
/* Do not close fds preloaded by systemd! */
if (_systemd_activation &&
(fd == SD_FD_FIFO_SERVER || fd == SD_FD_FIFO_CLIENT))
continue;
#endif
(void) close(fd);
}
if ((open("/dev/null", O_RDONLY) < 0) ||
(open("/dev/null", O_WRONLY) < 0) ||
(open("/dev/null", O_WRONLY) < 0))
if ((null_fd = open("/dev/null", O_RDWR)) < 0)
exit(EXIT_DESC_OPEN_FAILURE);
if ((dup2(null_fd, STDIN_FILENO) == -1) ||
(dup2(null_fd, STDOUT_FILENO) == -1) ||
(dup2(null_fd, STDERR_FILENO) == -1))
exit(EXIT_DESC_OPEN_FAILURE);
if ((null_fd > STDERR_FILENO) && close(null_fd))
exit(EXIT_DESC_CLOSE_FAILURE);
setsid();
/* coverity[leaked_handle] 'null_fd' handle is not leaking */
}
static int _reinstate_registrations(struct dm_event_fifos *fifos)
{
static const char _failed_parsing_msg[] = "Failed to parse existing event registration.\n";
static const char *_delim = " ";
static const char _delim[] = " ";
struct dm_event_daemon_message msg = { 0 };
char *endp, *dso_name, *dev_name, *mask, *timeout;
unsigned long mask_value, timeout_value;
@ -2030,28 +2069,94 @@ static int _reinstate_registrations(struct dm_event_fifos *fifos)
return 1;
}
static void _restart_dmeventd(void)
static int _info_dmeventd(const char *name, struct dm_event_fifos *fifos)
{
struct dm_event_daemon_message msg = { 0 };
int i, count = 0;
char *line;
int version;
int ret = 0;
if (!dm_daemon_is_running(DMEVENTD_PIDFILE)) {
fprintf(stderr, "No running dmeventd instance for status query.\n");
return 0;
}
/* Get the list of registrations from the running daemon. */
if (!init_fifos(fifos)) {
fprintf(stderr, "Could not initiate communication with existing dmeventd.\n");
return 0;
}
if (!dm_event_get_version(fifos, &version)) {
fprintf(stderr, "Could not communicate with existing dmeventd.\n");
goto out;
}
if (version < 1) {
fprintf(stderr, "The running dmeventd instance is too old.\n"
"Protocol version %d (required: 1). Action cancelled.\n", version);
goto out;
}
if (daemon_talk(fifos, &msg, DM_EVENT_CMD_GET_STATUS, "-", "-", 0, 0)) {
fprintf(stderr, "Failed to acquire status from existing dmeventd.\n");
goto out;
}
line = strchr(msg.data, ' ') + 1;
for (i = 0; msg.data[i]; ++i)
if (msg.data[i] == ';') {
msg.data[i] = 0;
if (!count)
printf("%s is monitoring:\n", name);
printf("%s\n", line);
line = msg.data + i + 1;
++count;
}
free(msg.data);
if (!count)
printf("%s does not monitor any device.\n", name);
if (version >= 2) {
if (daemon_talk(fifos, &msg, DM_EVENT_CMD_GET_PARAMETERS, "-", "-", 0, 0)) {
fprintf(stderr, "Failed to acquire parameters from existing dmeventd.\n");
goto out;
}
printf("%s internal status: %s\n", name, msg.data);
free(msg.data);
}
ret = 1;
out:
fini_fifos(fifos);
return ret;
}
/* Return 0 - fail, 1 - success, 2 - continue */
static int _restart_dmeventd(struct dm_event_fifos *fifos)
{
struct dm_event_fifos fifos = {
.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
};
struct dm_event_daemon_message msg = { 0 };
int i, count = 0;
char *message;
int version;
const char *e;
/* Get the list of registrations from the running daemon. */
if (!init_fifos(&fifos)) {
fprintf(stderr, "WARNING: Could not initiate communication with existing dmeventd.\n");
exit(EXIT_FAILURE);
if (!dm_daemon_is_running(DMEVENTD_PIDFILE)) {
fprintf(stderr, "WARNING: Could not find running dmeventd associated with pid file %s.\n", DMEVENTD_PIDFILE);
return 0;
}
if (!dm_event_get_version(&fifos, &version)) {
/* Get the list of registrations from the running daemon. */
if (!init_fifos(fifos)) {
fprintf(stderr, "WARNING: Could not initiate communication with existing dmeventd.\n");
return 0;
}
if (!dm_event_get_version(fifos, &version)) {
fprintf(stderr, "WARNING: Could not communicate with existing dmeventd.\n");
goto bad;
}
@ -2063,7 +2168,7 @@ static void _restart_dmeventd(void)
goto bad;
}
if (daemon_talk(&fifos, &msg, DM_EVENT_CMD_GET_STATUS, "-", "-", 0, 0))
if (daemon_talk(fifos, &msg, DM_EVENT_CMD_GET_STATUS, "-", "-", 0, 0))
goto bad;
message = strchr(msg.data, ' ') + 1;
@ -2087,7 +2192,7 @@ static void _restart_dmeventd(void)
}
if (version >= 2) {
if (daemon_talk(&fifos, &msg, DM_EVENT_CMD_GET_PARAMETERS, "-", "-", 0, 0)) {
if (daemon_talk(fifos, &msg, DM_EVENT_CMD_GET_PARAMETERS, "-", "-", 0, 0)) {
fprintf(stderr, "Failed to acquire parameters from old dmeventd.\n");
goto bad;
}
@ -2107,7 +2212,7 @@ static void _restart_dmeventd(void)
}
#endif
if (daemon_talk(&fifos, &msg, DM_EVENT_CMD_DIE, "-", "-", 0, 0)) {
if (daemon_talk(fifos, &msg, DM_EVENT_CMD_DIE, "-", "-", 0, 0)) {
fprintf(stderr, "Old dmeventd refused to die.\n");
goto bad;
}
@ -2116,43 +2221,41 @@ static void _restart_dmeventd(void)
((e = getenv(SD_ACTIVATION_ENV_VAR_NAME)) && strcmp(e, "1")))
_systemd_activation = 1;
for (i = 0; i < 10; ++i) {
if ((access(DMEVENTD_PIDFILE, F_OK) == -1) && (errno == ENOENT))
break;
usleep(10);
}
fini_fifos(fifos);
if (!_systemd_activation) {
fini_fifos(&fifos);
return;
}
/* Give a few seconds dmeventd to finish */
_wait_for_new_pid();
if (!_systemd_activation)
return 2; // continue with dmeventd start up
/* Reopen fifos. */
fini_fifos(&fifos);
if (!init_fifos(&fifos)) {
if (!init_fifos(fifos)) {
fprintf(stderr, "Could not initiate communication with new instance of dmeventd.\n");
exit(EXIT_FAILURE);
return 0;
}
if (!_reinstate_registrations(&fifos)) {
if (!_reinstate_registrations(fifos)) {
fprintf(stderr, "Failed to reinstate monitoring with new instance of dmeventd.\n");
goto bad;
}
fini_fifos(&fifos);
exit(EXIT_SUCCESS);
fini_fifos(fifos);
return 1;
bad:
fini_fifos(&fifos);
exit(EXIT_FAILURE);
fini_fifos(fifos);
return 0;
}
static void _usage(char *prog, FILE *file)
{
fprintf(file, "Usage:\n"
"%s [-d [-d [-d]]] [-f] [-h] [-l] [-R] [-V] [-?]\n\n"
"%s [-d [-d [-d]]] [-e path] [-f] [-h] [i] [-l] [-R] [-V] [-?]\n\n"
" -d Log debug messages to syslog (-d, -dd, -ddd)\n"
" -e Select a file path checked on exit\n"
" -f Don't fork, run in the foreground\n"
" -h Show this help information\n"
" -i Query running instance of dmeventd for info\n"
" -l Log to stdout,stderr instead of syslog\n"
" -? Show this help information on stderr\n"
" -R Restart dmeventd\n"
@ -2162,6 +2265,10 @@ static void _usage(char *prog, FILE *file)
int main(int argc, char *argv[])
{
signed char opt;
int debug_level = 0;
int info = 0;
int restart = 0;
int use_syslog = 1;
struct dm_event_fifos fifos = {
.client = -1,
.server = -1,
@ -2169,39 +2276,58 @@ int main(int argc, char *argv[])
.server_path = DM_EVENT_FIFO_SERVER
};
time_t now, idle_exit_timeout = DMEVENTD_IDLE_EXIT_TIMEOUT;
opterr = 0;
optind = 0;
while ((opt = getopt(argc, argv, "?fhVdlR")) != EOF) {
optopt = optind = opterr = 0;
optarg = (char*) "";
while ((opt = getopt(argc, argv, ":?e:fhiVdlR")) != EOF) {
switch (opt) {
case 'h':
_usage(argv[0], stdout);
exit(EXIT_SUCCESS);
return EXIT_SUCCESS;
case '?':
_usage(argv[0], stderr);
exit(EXIT_SUCCESS);
return EXIT_SUCCESS;
case 'i':
info++;
break;
case 'R':
_restart++;
restart++;
break;
case 'e':
if (strchr(optarg, '"')) {
fprintf(stderr, "dmeventd: option -e does not accept path \"%s\" with '\"' character.\n", optarg);
return EXIT_FAILURE;
}
_exit_on=optarg;
break;
case 'f':
_foreground++;
break;
case 'd':
_debug_level++;
debug_level++;
break;
case 'l':
_use_syslog = 0;
use_syslog = 0;
break;
case 'V':
printf("dmeventd version: %s\n", DM_LIB_VERSION);
exit(EXIT_SUCCESS);
return EXIT_SUCCESS;
case ':':
fprintf(stderr, "dmeventd: option -%c requires an argument.\n", optopt);
return EXIT_FAILURE;
}
}
if (!_foreground && !_use_syslog) {
printf("WARNING: Ignoring logging to stdout, needs options -f\n");
_use_syslog = 1;
if (info) {
_foreground = 1;
use_syslog = 0;
}
if (!_foreground && !use_syslog) {
printf("WARNING: Ignoring logging to stdout, needs options -f\n");
use_syslog = 1;
}
/*
* Switch to C locale to avoid reading large locale-archive file
* used by some glibc (on some distributions it takes over 100MB).
@ -2210,21 +2336,29 @@ int main(int argc, char *argv[])
if (setenv("LC_ALL", "C", 1))
perror("Cannot set LC_ALL to C");
if (_restart)
_restart_dmeventd();
if (info)
return _info_dmeventd(argv[0], &fifos) ? EXIT_SUCCESS : EXIT_FAILURE;
#ifdef __linux__
_systemd_activation = _systemd_handover(&fifos);
#endif
dm_log_with_errno_init(_libdm_log);
if (restart) {
dm_event_log_set(debug_level, 0);
if ((restart = _restart_dmeventd(&fifos)) < 2)
return restart ? EXIT_SUCCESS : EXIT_FAILURE;
}
if (!_foreground)
_daemonize();
if (_use_syslog)
if (use_syslog)
openlog("dmeventd", LOG_PID, LOG_DAEMON);
dm_event_log_set(_debug_level, _use_syslog);
dm_log_with_errno_init(_libdm_log);
dm_event_log_set(debug_level, use_syslog);
(void) dm_prepare_selinux_context(DMEVENTD_PIDFILE, S_IFREG);
if (dm_create_lockfile(DMEVENTD_PIDFILE) == 0)
@ -2285,15 +2419,28 @@ int main(int argc, char *argv[])
break;
}
}
} else if (_exit_now == DM_SIGNALED_EXIT) {
_exit_now = DM_SCHEDULED_EXIT;
/*
* When '_exit_now' is set, signal has been received,
* but can not simply exit unless all
* threads are done processing.
*/
log_info("dmeventd received break, scheduling exit.");
}
} else
switch (_exit_now) {
case DM_SIGNALED_EXIT:
_exit_now = DM_SCHEDULED_EXIT;
/*
* When '_exit_now' is set, signal has been received,
* but can not simply exit unless all
* threads are done processing.
*/
log_info("dmeventd received break, scheduling exit.");
/* fall through */
case DM_SCHEDULED_EXIT:
/* While exit is scheduled, check for exit_on file */
DEBUGLOG("Checking exit on file \"%s\".", _exit_on);
if (_exit_on[0] && (access(_exit_on, F_OK) == 0)) {
log_info("dmeventd detected exit on file %s, unregistering all monitored devices.",
_exit_on);
_unregister_all_threads();
}
break;
}
_process_request(&fifos);
_cleanup_unused_threads();
}
@ -2303,11 +2450,11 @@ int main(int argc, char *argv[])
log_notice("dmeventd shutting down.");
if (fifos.client >= 0 && close(fifos.client))
log_sys_error("client close", fifos.client_path);
log_sys_debug("client close", fifos.client_path);
if (fifos.server >= 0 && close(fifos.server))
log_sys_error("server close", fifos.server_path);
log_sys_debug("server close", fifos.server_path);
if (_use_syslog)
if (use_syslog)
closelog();
_exit_dm_lib();

View File

@ -68,7 +68,7 @@ struct dm_event_fifos {
int daemon_talk(struct dm_event_fifos *fifos,
struct dm_event_daemon_message *msg, int cmd,
const char *dso_name, const char *dev_name,
enum dm_event_mask evmask, uint32_t timeout);
unsigned evmask, uint32_t timeout);
int init_fifos(struct dm_event_fifos *fifos);
void fini_fifos(struct dm_event_fifos *fifos);
int dm_event_get_version(struct dm_event_fifos *fifos, int *version);

View File

@ -352,7 +352,7 @@ static int _daemon_write(struct dm_event_fifos *fifos,
int daemon_talk(struct dm_event_fifos *fifos,
struct dm_event_daemon_message *msg, int cmd,
const char *dso_name, const char *dev_name,
enum dm_event_mask evmask, uint32_t timeout)
unsigned evmask, uint32_t timeout)
{
int msg_size;
memset(msg, 0, sizeof(*msg));
@ -400,25 +400,16 @@ int daemon_talk(struct dm_event_fifos *fifos,
return (int32_t) msg->cmd;
}
/*
* start_daemon
* Check for usable client fifo file
*
* This function forks off a process (dmeventd) that will handle
* the events. I am currently test opening one of the fifos to
* ensure that the daemon is running and listening... I thought
* this would be less expensive than fork/exec'ing every time.
* Perhaps there is an even quicker/better way (no, checking the
* lock file is _not_ a better way).
*
* Returns: 1 on success, 0 otherwise
* Returns: 2 client path does not exists, dmeventd should be restarted
* 1 on success, 0 otherwise
*/
static int _start_daemon(char *dmeventd_path, struct dm_event_fifos *fifos)
static int _check_for_usable_fifos(char *dmeventd_path, struct dm_event_fifos *fifos)
{
int pid, ret = 0;
int status;
struct stat statbuf;
char default_dmeventd_path[] = DMEVENTD_PATH;
char *args[] = { dmeventd_path ? : default_dmeventd_path, NULL };
/*
* FIXME Explicitly verify the code's requirement that client_path is secure:
@ -429,7 +420,7 @@ static int _start_daemon(char *dmeventd_path, struct dm_event_fifos *fifos)
if ((lstat(fifos->client_path, &statbuf) < 0)) {
if (errno == ENOENT)
/* Jump ahead if fifo does not already exist. */
goto start_server;
return 2;
else {
log_sys_error("stat", fifos->client_path);
return 0;
@ -455,12 +446,14 @@ static int _start_daemon(char *dmeventd_path, struct dm_event_fifos *fifos)
log_error("%s is no longer a secure root-owned fifo with mode 0600.", fifos->client_path);
if (close(fifos->client))
log_sys_debug("close", fifos->client_path);
fifos->client = -1;
return 0;
}
/* server is running and listening */
if (close(fifos->client))
log_sys_debug("close", fifos->client_path);
fifos->client = -1;
return 1;
}
if (errno != ENXIO && errno != ENOENT) {
@ -469,9 +462,36 @@ static int _start_daemon(char *dmeventd_path, struct dm_event_fifos *fifos)
return 0;
}
start_server:
/* server is not running */
return 2;
}
/*
* start_daemon
*
* This function forks off a process (dmeventd) that will handle
* the events. I am currently test opening one of the fifos to
* ensure that the daemon is running and listening... I thought
* this would be less expensive than fork/exec'ing every time.
* Perhaps there is an even quicker/better way (no, checking the
* lock file is _not_ a better way).
*
* Returns: 1 on success, 0 otherwise
*/
static int _start_daemon(char *dmeventd_path, struct dm_event_fifos *fifos)
{
struct stat statbuf;
char default_dmeventd_path[] = DMEVENTD_PATH;
char *args[] = { dmeventd_path ? : default_dmeventd_path, NULL };
int pid, ret = 0;
int status;
switch (_check_for_usable_fifos(dmeventd_path, fifos)) {
case 0: return_0;
case 1: return 1; /* Already running dmeventd */
}
/* server is not running */
if ((args[0][0] == '/') && stat(args[0], &statbuf)) {
log_sys_error("stat", args[0]);
return 0;
@ -492,8 +512,17 @@ start_server:
strerror(errno));
else if (WEXITSTATUS(status))
log_error("Unable to start dmeventd.");
else
ret = 1;
else {
/* Loop here till forked dmeventd is serving fifos */
for (ret = 100; ret > 0; --ret)
switch (_check_for_usable_fifos(dmeventd_path, fifos)) {
case 0: return_0;
case 1: return 1;
case 2: usleep(1000); break;
}
/* ret == 0 */
log_error("Dmeventd is not serving fifos.");
}
}
return ret;
@ -513,7 +542,7 @@ int init_fifos(struct dm_event_fifos *fifos)
/* Lock out anyone else trying to do communication with the daemon. */
if (flock(fifos->server, LOCK_EX) < 0) {
log_sys_error("flock", fifos->server_path);
goto bad;
goto bad_no_unlock;
}
/* if ((fifos->client = open(fifos->client_path, O_WRONLY | O_NONBLOCK)) < 0) {*/
@ -524,6 +553,9 @@ int init_fifos(struct dm_event_fifos *fifos)
return 1;
bad:
if (flock(fifos->server, LOCK_UN))
log_sys_debug("flock unlock", fifos->server_path);
bad_no_unlock:
if (close(fifos->server))
log_sys_debug("close", fifos->server_path);
fifos->server = -1;
@ -552,6 +584,8 @@ void fini_fifos(struct dm_event_fifos *fifos)
if (close(fifos->server))
log_sys_debug("close", fifos->server_path);
}
fifos->client = fifos->server = -1;
}
/* Get uuid of a device */
@ -720,7 +754,7 @@ static char *_fetch_string(char **src, const int delimiter)
/* Parse a device message from the daemon. */
static int _parse_message(struct dm_event_daemon_message *msg, char **dso_name,
char **uuid, enum dm_event_mask *evmask)
char **uuid, unsigned *evmask)
{
char *id;
char *p = msg->data;
@ -745,7 +779,7 @@ int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next)
int ret = 0;
const char *uuid = NULL;
char *reply_dso = NULL, *reply_uuid = NULL;
enum dm_event_mask reply_mask = 0;
unsigned reply_mask = 0;
struct dm_task *dmt = NULL;
struct dm_event_daemon_message msg = { 0 };
struct dm_info info;
@ -844,6 +878,7 @@ int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next)
int dm_event_get_version(struct dm_event_fifos *fifos, int *version) {
char *p;
struct dm_event_daemon_message msg = { 0 };
int ret = 0;
if (daemon_talk(fifos, &msg, DM_EVENT_CMD_HELLO, NULL, NULL, 0, 0))
return 0;
@ -851,13 +886,17 @@ int dm_event_get_version(struct dm_event_fifos *fifos, int *version) {
*version = 0;
if (!p || !(p = strchr(p, ' '))) /* Message ID */
return 0;
goto out;
if (!(p = strchr(p + 1, ' '))) /* HELLO */
return 0;
goto out;
if ((p = strchr(p + 1, ' '))) /* HELLO, once more */
*version = atoi(p);
return 1;
ret = 1;
out:
free(msg.data);
return ret;
}
void dm_event_log_set(int debug_log_level, int use_syslog)
@ -872,11 +911,11 @@ void dm_event_log(const char *subsys, int level, const char *file,
{
static int _abort_on_internal_errors = -1;
static pthread_mutex_t _log_mutex = PTHREAD_MUTEX_INITIALIZER;
static time_t start = 0;
static long long _start = 0;
const char *indent = "";
FILE *stream = log_stderr(level) ? stderr : stdout;
int prio;
time_t now;
long long now, now_nsec;
int log_with_debug = 0;
if (subsys[0] == '#') {
@ -923,17 +962,28 @@ void dm_event_log(const char *subsys, int level, const char *file,
if (_use_syslog) {
vsyslog(prio, format, ap);
} else {
now = time(NULL);
if (!start)
start = now;
now -= start;
if (_debug_level)
fprintf(stream, "[%2d:%02d] %8x:%-6s%s",
(int)now / 60, (int)now % 60,
if (_debug_level) {
#define _NSEC_PER_SEC (1000000000LL)
#ifdef HAVE_REALTIME
struct timespec mono_time = { 0 };
if (clock_gettime(CLOCK_MONOTONIC, &mono_time) == 0)
now = mono_time.tv_sec * _NSEC_PER_SEC + mono_time.tv_nsec;
else
#endif
now = time(NULL) * _NSEC_PER_SEC;
if (!_start)
_start = now;
now -= _start;
now_nsec = now %_NSEC_PER_SEC;
now /= _NSEC_PER_SEC;
fprintf(stream, "[%2lld:%02lld.%06lld] %8x:%-6s%s",
now / 60, now % 60, now_nsec / 1000,
// TODO: Maybe use shorter ID
// ((int)(pthread_self()) >> 6) & 0xffff,
(int)pthread_self(), subsys,
(_debug_level > 3) ? "" : indent);
}
if (_debug_level > 3)
fprintf(stream, "%28s:%4d %s", file, line, indent);
vfprintf(stream, _(format), ap);
@ -957,7 +1007,7 @@ void dm_event_log(const char *subsys, int level, const char *file,
static char *_skip_string(char *src, const int delimiter)
{
src = srtchr(src, delimiter);
src = strchr(src, delimiter);
if (src && *(src + 1))
return src + 1;
return NULL;

View File

@ -41,7 +41,7 @@ enum dm_event_mask {
DM_EVENT_STATUS_MASK = 0xFF0000,
DM_EVENT_SYNC_STATUS = 0x010000, /* Mirror synchronization completed/failed. */
DM_EVENT_TIMEOUT = 0x020000, /* Timeout has occured */
DM_EVENT_TIMEOUT = 0x020000, /* Timeout has occurred */
DM_EVENT_REGISTRATION_PENDING = 0x1000000, /* Monitor thread is setting-up/shutting-down */
};
@ -109,7 +109,7 @@ int dm_event_unregister_handler(const struct dm_event_handler *dmevh);
/* Set debug level for logging, and whether to log on stdout/stderr or syslog */
void dm_event_log_set(int debug_log_level, int use_syslog);
/* Log messages acroding to current debug level */
/* Log messages according to current debug level */
__attribute__((format(printf, 6, 0)))
void dm_event_log(const char *subsys, int level, const char *file,
int line, int dm_errno_or_class,

View File

@ -87,7 +87,7 @@ int dmeventd_lvm2_init(void)
lvm2_disable_dmeventd_monitoring(_lvm_handle);
/* FIXME Temporary: move to dmeventd core */
lvm2_run(_lvm_handle, "_memlock_inc");
log_debug("lvm plugin initilized.");
log_debug("lvm plugin initialized.");
}
_register_count++;
@ -103,7 +103,7 @@ void dmeventd_lvm2_exit(void)
pthread_mutex_lock(&_register_mutex);
if (!--_register_count) {
log_debug("lvm plugin shuting down.");
log_debug("lvm plugin shutting down.");
lvm2_run(_lvm_handle, "_memlock_dec");
dm_pool_destroy(_mem_pool);
_mem_pool = NULL;
@ -123,6 +123,7 @@ struct dm_pool *dmeventd_lvm2_pool(void)
int dmeventd_lvm2_run(const char *cmdline)
{
/* coverity[missing_lock] no locking for run part */
return (lvm2_run(_lvm_handle, cmdline) == LVM2_COMMAND_SUCCEEDED);
}

View File

@ -38,7 +38,7 @@ static void _process_status_code(dm_status_mirror_health_t health,
* A => Alive - No failures
* D => Dead - A write failure occurred leaving mirror out-of-sync
* F => Flush failed.
* S => Sync - A sychronization failure occurred, mirror out-of-sync
* S => Sync - A synchronization failure occurred, mirror out-of-sync
* R => Read - A read failure occurred, mirror data unaffected
* U => Unclassified failure (bug)
*/

View File

@ -17,7 +17,7 @@
#include "daemons/dmeventd/libdevmapper-event.h"
#include "lib/config/defaults.h"
/* Hold enough elements for the mximum number of RAID images */
/* Hold enough elements for the maximum number of RAID images */
#define RAID_DEVS_ELEMS ((DEFAULT_RAID_MAX_IMAGES + 63) / 64)
struct dso_state {

View File

@ -87,7 +87,7 @@ static int _run_command(struct dso_state *state)
log_verbose("Executing command: %s", state->cmd_str);
/* TODO:
* Support parallel run of 'task' and it's waitpid maintainence
* Support parallel run of 'task' and it's waitpid maintenance
* ATM we can't handle signaling of SIGALRM
* as signalling is not allowed while 'process_event()' is running
*/
@ -245,7 +245,7 @@ void process_event(struct dm_task *dmt,
/*
* Trigger action when threshold boundary is exceeded.
* Report 80% threshold warning when it's used above 80%.
* Only 100% is exception as it cannot be surpased so policy
* Only 100% is exception as it cannot be surpassed so policy
* action is called for: >50%, >55% ... >95%, 100%
*/
state->metadata_percent = dm_make_percent(tps->used_metadata_blocks, tps->total_metadata_blocks);
@ -379,7 +379,7 @@ int register_device(const char *device,
state->argv[1] = str + 1; /* 1 argument - vg/lv */
_init_thread_signals(state);
} else /* Unuspported command format */
} else /* Unsupported command format */
goto inval;
state->pid = -1;

View File

@ -19,7 +19,7 @@
/*
* Use parser from new device_mapper library.
* Although during compilation we can see dm_vdo_status_parse()
* in runtime we are linked agains systems libdm 'older' library
* in runtime we are linked against systems libdm 'older' library
* which does not provide this symbol and plugin fails to load
*/
/* coverity[unnecessary_header] used for parsing */
@ -78,7 +78,7 @@ static int _run_command(struct dso_state *state)
log_verbose("Executing command: %s", state->cmd_str);
/* TODO:
* Support parallel run of 'task' and it's waitpid maintainence
* Support parallel run of 'task' and it's waitpid maintenance
* ATM we can't handle signaling of SIGALRM
* as signalling is not allowed while 'process_event()' is running
*/
@ -227,7 +227,7 @@ void process_event(struct dm_task *dmt,
/*
* Trigger action when threshold boundary is exceeded.
* Report 80% threshold warning when it's used above 80%.
* Only 100% is exception as it cannot be surpased so policy
* Only 100% is exception as it cannot be surpassed so policy
* action is called for: >50%, >55% ... >95%, 100%
*/
if ((state->percent > WARNING_THRESH) &&
@ -354,7 +354,7 @@ int register_device(const char *device,
_init_thread_signals(state);
} else if (cmd[0] == 0) {
state->name = "volume"; /* What to use with 'others?' */
} else/* Unuspported command format */
} else/* Unsupported command format */
goto inval;
state->pid = -1;

View File

@ -51,18 +51,14 @@ include $(top_builddir)/make.tmpl
.PHONY: install_lvmdbusd
all:
$(Q) test -x $(LVMDBUSD) || chmod 755 $(LVMDBUSD)
install_lvmdbusd: $(LVMDBUSD)
@echo " [INSTALL] $<"
$(SHOW) " [INSTALL] $<"
$(Q) $(INSTALL_DIR) $(sbindir)
$(Q) $(INSTALL_SCRIPT) $(LVMDBUSD) $(sbindir)
$(Q) $(INSTALL_DIR) $(lvmdbusdir)
$(Q) $(INSTALL_DIR) $(lvmdbusdir) $(lvmdbusdir)/__pycache__
$(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

@ -44,10 +44,10 @@ class AutomatedProperties(dbus.service.Object):
def set_interface(self, interface):
"""
With inheritance we can't easily tell what interfaces a class provides
With inheritance, we can't easily tell what interfaces a class provides,
so we will have each class that implements an interface tell the
base AutomatedProperties what it is they do provide. This is kind of
clunky and perhaps we can figure out a better way to do this later.
clunky, and perhaps we can figure out a better way to do this later.
:param interface: An interface the object supports
:return:
"""
@ -88,7 +88,6 @@ class AutomatedProperties(dbus.service.Object):
cb, cbe, False)
cfg.worker_q.put(r)
@staticmethod
def _get_all_prop(obj, interface_name):
if interface_name in obj.interface(True):

View File

@ -7,16 +7,13 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import subprocess
from . import cfg
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,\
mt_async_call
from .utils import pv_range_append, pv_dest_ranges, log_error, log_debug
from .request import RequestEntry
import threading
import time
import traceback
def pv_move_lv_cmd(move_options, lv_full_name,
@ -65,18 +62,15 @@ def _move_callback(job_state, 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.
# the status of the long-running operation.
meta = LvmExecutionMeta(time.time(), 0, command, -1000, None, None)
cfg.blackbox.add(meta)
meta = LvmExecutionMeta(time.time(), 0, command)
cfg.flightrecorder.add(meta)
ec, stdout, stderr = call_lvm(command, line_cb=_move_callback,
cb_data=job_state)
with meta.lock:
meta.ended = time.time()
meta.ec = ec
meta.stderr_txt = stderr
ended = time.time()
meta.completed(ended, ec, stdout, stderr)
if ec == 0:
job_state.Percent = 100

View File

@ -11,11 +11,18 @@ import os
import multiprocessing
import queue
import itertools
from lvmdbusd.utils import LvmDebugData
from lvmdbusd import path
LVM_CMD = os.getenv('LVM_BINARY', path.LVM_BINARY)
LOCK_FILE = os.getenv("LVM_DBUSD_LOCKFILE", "/var/lock/lvm/lvmdbusd")
# Save off the debug data needed for lvm team to debug issues
# only used for 'fullreport' at this time.
lvmdebug = LvmDebugData(os.getenv('LVM_DBUSD_COLLECT_LVM_DEBUG', False))
# This is the global object manager
om = None
@ -25,13 +32,13 @@ bus = None
# Command line args
args = None
# Set to true if we are depending on external events for updates
# Set to true if we depend on external events for updates
got_external_event = False
# Shared state variable across all processes
run = multiprocessing.Value('i', 1)
# If this is set to true, the current setup support lvm shell and we are
# If this is set to true, the current setup support lvm shell, and we are
# running in that mode of operation
SHELL_IN_USE = None
@ -43,6 +50,11 @@ worker_q = queue.Queue()
# Main event loop
loop = None
G_LOOP_TMO = 0.5
# Used to instruct the daemon if we should ignore SIGTERM
ignore_sigterm = False
BUS_NAME = os.getenv('LVM_DBUS_NAME', 'com.redhat.lvmdbus1')
BASE_INTERFACE = 'com.redhat.lvmdbus1'
PV_INTERFACE = BASE_INTERFACE + '.Pv'
@ -90,11 +102,14 @@ vdo_support = False
db = None
# lvm flight recorder
blackbox = None
flightrecorder = None
# RequestEntry ctor
create_request_entry = None
# Circular debug log
debug = None
def exit_daemon():
"""
@ -104,3 +119,6 @@ def exit_daemon():
if run and loop:
run.value = 0
loop.quit()
systemd = False

View File

@ -6,19 +6,18 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import errno
from subprocess import Popen, PIPE
import select
import time
import threading
from itertools import chain
import collections
import traceback
import os
from lvmdbusd import cfg
from lvmdbusd.utils import pv_dest_ranges, log_debug, log_error, add_no_notify,\
make_non_block, read_decoded
make_non_block, read_decoded, extract_stack_trace, LvmBug, add_config_option, get_error_msg
from lvmdbusd.lvm_shell_proxy import LVMShellProxy
try:
@ -26,7 +25,6 @@ try:
except ImportError:
import json
SEP = '{|}'
total_time = 0.0
total_count = 0
@ -38,7 +36,7 @@ cmd_lock = threading.RLock()
class LvmExecutionMeta(object):
def __init__(self, start, ended, cmd, ec, stdout_txt, stderr_txt):
def __init__(self, start, ended, cmd, ec=-1000, stdout_txt=None, stderr_txt=None):
self.lock = threading.RLock()
self.start = start
self.ended = ended
@ -49,32 +47,49 @@ class LvmExecutionMeta(object):
def __str__(self):
with self.lock:
return "EC= %d for %s\n" \
"STARTED: %f, ENDED: %f\n" \
if self.ended == 0:
ended_txt = "still running"
self.ended = time.time()
else:
ended_txt = str(time.ctime(self.ended))
return 'EC= %d for "%s"\n' \
"STARTED: %s, ENDED: %s, DURATION: %f\n" \
"STDOUT=%s\n" \
"STDERR=%s\n" % \
(self.ec, str(self.cmd), self.start, self.ended, self.stdout_txt,
self.stderr_txt)
(self.ec, " ".join(self.cmd), time.ctime(self.start), ended_txt, float(self.ended) - self.start,
self.stdout_txt,
self.stderr_txt)
def completed(self, end_time, ec, stdout_txt, stderr_txt):
with self.lock:
self.ended = end_time
self.ec = ec
self.stdout_txt = stdout_txt
self.stderr_txt = stderr_txt
class LvmFlightRecorder(object):
def __init__(self, size=16):
self.queue = collections.deque(maxlen=size)
self.lock = threading.RLock()
def add(self, lvm_exec_meta):
self.queue.append(lvm_exec_meta)
with self.lock:
self.queue.append(lvm_exec_meta)
def dump(self):
with cmd_lock:
with self.lock:
if len(self.queue):
log_error("LVM dbus flight recorder START")
log_error("LVM dbus flight recorder START (in order of newest to oldest)")
for c in reversed(self.queue):
log_error(str(c))
log_error("LVM dbus flight recorder END")
self.queue.clear()
cfg.blackbox = LvmFlightRecorder()
cfg.flightrecorder = LvmFlightRecorder()
def _debug_c(cmd, exit_code, out):
@ -94,7 +109,7 @@ def call_lvm(command, debug=False, line_cb=None,
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
:param cb_data: Supplied to call back to allow caller access to
its own data
# Callback signature
@ -106,6 +121,9 @@ def call_lvm(command, debug=False, line_cb=None,
command.insert(0, cfg.LVM_CMD)
command = add_no_notify(command)
# Ensure we get an error message when we fork & exec the lvm command line
command = add_config_option(command, "--config", 'log/command_log_selection="log_context!=''"')
process = Popen(command, stdout=PIPE, stderr=PIPE, close_fds=True,
env=os.environ)
@ -115,10 +133,10 @@ def call_lvm(command, debug=False, line_cb=None,
make_non_block(process.stdout)
make_non_block(process.stderr)
while True:
while True and cfg.run.value != 0:
try:
rd_fd = [process.stdout.fileno(), process.stderr.fileno()]
ready = select.select(rd_fd, [], [], 2)
ready = select.select(rd_fd, [], [], cfg.G_LOOP_TMO)
for r in ready[0]:
if r == process.stdout.fileno():
@ -133,8 +151,8 @@ def call_lvm(command, debug=False, line_cb=None,
if i != -1:
try:
line_cb(cb_data, stdout_text[stdout_index:i])
except:
st = traceback.format_exc()
except BaseException as be:
st = extract_stack_trace(be)
log_error("call_lvm: line_cb exception: \n %s" % st)
stdout_index = i + 1
else:
@ -145,12 +163,31 @@ def call_lvm(command, debug=False, line_cb=None,
break
except IOError as ioe:
log_debug("call_lvm:" + str(ioe))
pass
break
if debug or process.returncode != 0:
_debug_c(command, process.returncode, (stdout_text, stderr_text))
if process.returncode is not None:
cfg.lvmdebug.lvm_complete()
if debug or (process.returncode != 0 and (process.returncode != 5 and "fullreport" in command)):
_debug_c(command, process.returncode, (stdout_text, stderr_text))
try:
report_json = json.loads(stdout_text)
except json.decoder.JSONDecodeError:
# Some lvm commands don't return json even though we are asking for it to do so.
return process.returncode, stdout_text, stderr_text
error_msg = get_error_msg(report_json)
if error_msg:
stderr_text += error_msg
return process.returncode, report_json, stderr_text
else:
if cfg.run.value == 0:
raise SystemExit
# We can bail out before the lvm command finished when we get a signal
# which is requesting we exit
return -errno.EINTR, "", "operation interrupted"
return process.returncode, stdout_text, stderr_text
# The actual method which gets called to invoke the lvm command, can vary
# from forking a new process to using lvm shell
@ -165,18 +202,18 @@ def _shell_cfg():
_t_call = lvm_shell.call_lvm
cfg.SHELL_IN_USE = lvm_shell
return True
except Exception:
except Exception as e:
_t_call = call_lvm
cfg.SHELL_IN_USE = None
log_error(traceback.format_exc())
log_error("Unable to utilize lvm shell, dropping back to fork & exec")
log_error("Unable to utilize lvm shell, dropping "
"back to fork & exec\n%s" % extract_stack_trace(e))
return False
def set_execution(shell):
global _t_call
with cmd_lock:
# If the user requested lvm shell and we are currently setup that
# If the user requested lvm shell, and we are currently setup that
# way, just return
if cfg.SHELL_IN_USE and shell:
return True
@ -200,11 +237,15 @@ def time_wrapper(command, debug=False):
with cmd_lock:
start = time.time()
meta = LvmExecutionMeta(start, 0, command)
# Add the partial metadata to flight recorder, so if the command hangs
# we will see what it was.
cfg.flightrecorder.add(meta)
results = _t_call(command, debug)
ended = time.time()
total_time += (ended - start)
total_count += 1
cfg.blackbox.add(LvmExecutionMeta(start, ended, command, *results))
meta.completed(ended, *results)
return results
@ -214,44 +255,11 @@ call = time_wrapper
# Default cmd
# Place default arguments for every command here.
def _dc(cmd, args):
c = [cmd, '--noheading', '--separator', '%s' % SEP, '--nosuffix',
'--unbuffered', '--units', 'b']
c = [cmd, '--nosuffix', '--unbuffered', '--units', 'b']
c.extend(args)
return c
def parse(out):
rc = []
for line in out.split('\n'):
# This line includes separators, so process them
if SEP in line:
elem = line.split(SEP)
cleaned_elem = []
for e in elem:
e = e.strip()
cleaned_elem.append(e)
if len(cleaned_elem) > 1:
rc.append(cleaned_elem)
else:
t = line.strip()
if len(t) > 0:
rc.append(t)
return rc
def parse_column_names(out, column_names):
lines = parse(out)
rc = []
for i in range(0, len(lines)):
d = dict(list(zip(column_names, lines[i])))
rc.append(d)
return rc
def options_to_cli_args(options):
rc = []
for k, v in list(dict(options).items()):
@ -316,10 +324,12 @@ def vg_rename(vg_uuid, new_name, rename_options):
return call(cmd)
def vg_remove(vg_name, remove_options):
def vg_remove(vg_id, remove_options):
cmd = ['vgremove']
cmd.extend(options_to_cli_args(remove_options))
cmd.extend(['-f', vg_name])
cmd.extend(['-f', vg_id])
# https://bugzilla.redhat.com/show_bug.cgi?id=2175220 is preventing us from doing the following
# cmd.extend(['-f', "--select", "vg_uuid=%s" % vg_id])
return call(cmd)
@ -613,68 +623,25 @@ def lvm_full_report_json():
'--configreport', 'vg', '-o', ','.join(vg_columns),
'--configreport', 'lv', '-o', ','.join(lv_columns),
'--configreport', 'seg', '-o', ','.join(lv_seg_columns),
'--configreport', 'pvseg', '-o', ','.join(pv_seg_columns),
'--reportformat', 'json'
'--configreport', 'pvseg', '-o', ','.join(pv_seg_columns)
])
# We are running the fullreport command, we will ask lvm to output the debug
# data, so we can have the required information for lvm to debug the fullreport failures.
# Note: this is disabled by default and can be enabled with env. var.
# LVM_DBUSD_COLLECT_LVM_DEBUG=True
fn = cfg.lvmdebug.setup()
if fn is not None:
add_config_option(cmd, "--config", "log {level=7 file=%s syslog=0}" % fn)
rc, out, err = call(cmd)
# When we have an exported vg the exit code of lvs or fullreport will be 5
if rc == 0 or rc == 5:
# With the current implementation, if we are using the shell then we
# are using JSON and JSON is returned back to us as it was parsed to
# figure out if we completed OK or not
if cfg.SHELL_IN_USE:
assert(type(out) == dict)
return out
else:
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
def pv_retrieve_with_segs(device=None):
d = []
err = ""
out = ""
rc = 0
columns = ['pv_name', 'pv_uuid', 'pv_fmt', 'pv_size', 'pv_free',
'pv_used', 'dev_size', 'pv_mda_size', 'pv_mda_free',
'pv_ba_start', 'pv_ba_size', 'pe_start', 'pv_pe_count',
'pv_pe_alloc_count', 'pv_attr', 'pv_tags', 'vg_name',
'vg_uuid', 'pvseg_start', 'pvseg_size', 'segtype', 'pv_missing']
# Lvm has some issues where it returns failure when querying pvs when other
# operations are in process, see:
# https://bugzilla.redhat.com/show_bug.cgi?id=1274085
for i in range(0, 10):
cmd = _dc('pvs', ['-o', ','.join(columns)])
if device:
cmd.extend(device)
rc, out, err = call(cmd)
if rc == 0:
d = parse_column_names(out, columns)
break
else:
time.sleep(0.2)
log_debug("LVM Bug workaround, retrying pvs command...")
if rc != 0:
msg = "We were unable to get pvs to return without error after " \
"trying 10 times, RC=%d, STDERR=(%s), STDOUT=(%s)" % \
(rc, err, out)
log_error(msg)
raise RuntimeError(msg)
return d
if type(out) != dict:
raise LvmBug("lvm likely returned invalid JSON, lvm exit code = %d, output = %s, err= %s" %
(rc, str(out), str(err)))
return out
raise LvmBug("'fullreport' exited with code '%d'" % rc)
def pv_resize(device, size_bytes, create_options):
@ -820,6 +787,10 @@ def activate_deactivate(op, name, activate, control_flags, options):
if (1 << 5) & control_flags:
cmd.append('--ignoreactivationskip')
# Shared locking (Cluster)
if (1 << 6) & control_flags:
op += 's'
if activate:
op += 'y'
else:
@ -831,53 +802,6 @@ def activate_deactivate(op, name, activate, control_flags, options):
return call(cmd)
def vg_retrieve(vg_specific):
if vg_specific:
assert isinstance(vg_specific, list)
columns = ['vg_name', 'vg_uuid', 'vg_fmt', 'vg_size', 'vg_free',
'vg_sysid', 'vg_extent_size', 'vg_extent_count',
'vg_free_count', 'vg_profile', 'max_lv', 'max_pv',
'pv_count', 'lv_count', 'snap_count', 'vg_seqno',
'vg_mda_count', 'vg_mda_free', 'vg_mda_size',
'vg_mda_used_count', 'vg_attr', 'vg_tags']
cmd = _dc('vgs', ['-o', ','.join(columns)])
if vg_specific:
cmd.extend(vg_specific)
d = []
rc, out, err = call(cmd)
if rc == 0:
d = parse_column_names(out, columns)
return d
def lv_retrieve_with_segments():
columns = ['lv_uuid', 'lv_name', 'lv_path', 'lv_size',
'vg_name', 'pool_lv_uuid', 'pool_lv', 'origin_uuid',
'origin', 'data_percent',
'lv_attr', 'lv_tags', 'vg_uuid', 'lv_active', 'data_lv',
'metadata_lv', 'seg_pe_ranges', 'segtype', 'lv_parent',
'lv_role', 'lv_layout',
'snap_percent', 'metadata_percent', 'copy_percent',
'sync_percent', 'lv_metadata_size', 'move_pv', 'move_pv_uuid']
cmd = _dc('lvs', ['-a', '-o', ','.join(columns)])
rc, out, err = call(cmd)
d = []
if rc == 0:
d = parse_column_names(out, columns)
return d
if __name__ == '__main__':
pv_data = pv_retrieve_with_segs()
for p in pv_data:
print(str(p))
# Leave this for future debug as needed
pass

View File

@ -6,16 +6,16 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import errno
from .pv import load_pvs
from .vg import load_vgs
from .lv import load_lvs
from . import cfg
from .utils import MThreadRunner, log_debug, log_error
from .utils import MThreadRunner, log_debug, log_error, LvmBug, extract_stack_trace
import threading
import queue
import time
import traceback
def _main_thread_load(refresh=True, emit_signal=True):
@ -120,89 +120,125 @@ class StateUpdate(object):
@staticmethod
def update_thread(obj):
exception_count = 0
queued_requests = []
def set_results(val):
nonlocal queued_requests
for idx in queued_requests:
idx.set_result(val)
# Only clear out the requests after we have given them a result
# otherwise we can orphan the waiting threads, and they never
# wake up if we get an exception
queued_requests = []
def bailing(rv):
set_results(rv)
try:
while True:
item = obj.queue.get(False)
item.set_result(rv)
except queue.Empty:
pass
def _load_args(requests):
"""
If we have multiple requests in the queue, they might not all have the same options. If any of the requests
have an option set we need to honor it.
"""
refresh = any([r.refresh for r in requests])
emit_signal = any([r.emit_signal for r in requests])
cache_refresh = any([r.cache_refresh for r in requests])
log = any([r.log for r in requests])
need_main_thread = any([r.need_main_thread for r in requests])
return refresh, emit_signal, cache_refresh, log, need_main_thread
def _drain_queue(queued, incoming):
try:
while True:
queued.append(incoming.get(block=False))
except queue.Empty:
pass
def _handle_error():
nonlocal exception_count
exception_count += 1
if exception_count >= 5:
log_error("Too many errors in update_thread, exiting daemon")
cfg.debug.dump()
cfg.flightrecorder.dump()
bailing(errno.EFAULT)
cfg.exit_daemon()
else:
# Slow things down when encountering errors
cfg.lvmdebug.complete()
time.sleep(1)
while cfg.run.value != 0:
# noinspection PyBroadException
try:
refresh = True
emit_signal = True
cache_refresh = True
log = True
need_main_thread = True
with obj.lock:
wait = not obj.deferred
obj.deferred = False
if len(queued_requests) == 0 and wait:
queued_requests.append(obj.queue.get(True, 2))
# Note: If we don't have anything for N seconds we will
# get a queue.Empty exception raised here
queued_requests.append(obj.queue.get(block=True, timeout=cfg.G_LOOP_TMO))
# Ok we have one or the deferred queue has some,
# check if any others
try:
while True:
queued_requests.append(obj.queue.get(False))
except queue.Empty:
pass
# check if any others and grab them too
_drain_queue(queued_requests, obj.queue)
if len(queued_requests) > 1:
log_debug("Processing %d updates!" % len(queued_requests),
'bg_black', 'fg_light_green')
# We have what we can, run the update with the needed options
for i in queued_requests:
if not i.refresh:
refresh = False
if not i.emit_signal:
emit_signal = False
if not i.cache_refresh:
cache_refresh = False
if not i.log:
log = False
if not i.need_main_thread:
need_main_thread = False
num_changes = load(refresh, emit_signal, cache_refresh, log,
need_main_thread)
num_changes = load(*_load_args(queued_requests))
# Update is done, let everyone know!
for i in queued_requests:
i.set_result(num_changes)
# Only clear out the requests after we have given them a result
# otherwise we can orphan the waiting threads and they never
# wake up if we get an exception
queued_requests = []
set_results(num_changes)
# We retrieved OK, clear exception count
exception_count = 0
except queue.Empty:
pass
except SystemExit:
break
except LvmBug as bug:
# If a lvm bug occurred, we will dump the lvm debug data if
# we have it.
cfg.lvmdebug.dump()
log_error(str(bug))
_handle_error()
except Exception as e:
st = traceback.format_exc()
log_error("update_thread exception: \n%s" % st)
cfg.blackbox.dump()
exception_count += 1
if exception_count >= 5:
for i in queued_requests:
i.set_result(e)
log_error("update_thread: \n%s" % extract_stack_trace(e))
_handle_error()
finally:
cfg.lvmdebug.complete()
log_error("Too many errors in update_thread, exiting daemon")
cfg.exit_daemon()
else:
# Slow things down when encountering errors
time.sleep(1)
# Make sure to unblock any that may be waiting before we exit this thread
# otherwise they hang forever ...
bailing(Exception("update thread exiting"))
log_debug("update thread exiting!")
def __init__(self):
self.lock = threading.RLock()
self.queue = queue.Queue()
self.deferred = False
# Do initial load
load(refresh=False, emit_signal=False, need_main_thread=False)
# Do initial load, with retries. During error injection testing we can and do fail here.
count = 0
need_refresh = False # First attempt we are building from new, any subsequent will be true
while count < 5:
try:
load(refresh=need_refresh, emit_signal=False, need_main_thread=False)
break
except LvmBug as bug:
count += 1
need_refresh = True
log_error("We encountered an lvm bug on initial load, trying again %s" % str(bug))
self.thread = threading.Thread(target=StateUpdate.update_thread,
args=(self,),

View File

@ -44,7 +44,7 @@ class WaitingClient(object):
self.timer_id = GLib.timeout_add_seconds(
tmo, WaitingClient._timeout, self)
# The job finished before the timer popped and we are being notified that
# The job finished before the timer popped, and we are being notified that
# it's done
def notify(self):
with self.rlock:
@ -71,7 +71,7 @@ class JobState(object):
self._stderr = ''
self._waiting_clients = []
# This is an lvm command that is just taking too long and doesn't
# This is a lvm command that is just taking too long and doesn't
# support background operation
if self._request:
# Faking the percentage when we don't have one
@ -138,7 +138,7 @@ class JobState(object):
# If a waiting client timer pops before the job is done we will allow
# the client to remove themselves from the list. As we have a lock
# here and a lock in the waiting client too, and they can be obtained
# in different orders, a dead lock can occur.
# in different orders, a deadlock can occur.
# As this remove is really optional, we will try to acquire the lock
# and remove. If we are unsuccessful it's not fatal, we just delay
# the time when the objects can be garbage collected by python
@ -226,3 +226,21 @@ class Job(AutomatedProperties):
def Uuid(self):
import uuid
return uuid.uuid1()
# Override the property "getters" implementation for the job interface, so a user can query a job while the queue
# is processing items. Originally all the property get methods were this way, but we changed this in
# e53454d6de07de56736303dd2157c3859f6fa848
# Properties
# noinspection PyUnusedLocal
@dbus.service.method(dbus_interface=dbus.PROPERTIES_IFACE,
in_signature='ss', out_signature='v')
def Get(self, interface_name, property_name):
# Note: If we get an exception in this handler we won't know about it,
# only the side effect of no returned value!
return AutomatedProperties._get_prop(self, interface_name, property_name)
@dbus.service.method(dbus_interface=dbus.PROPERTIES_IFACE,
in_signature='s', out_signature='a{sv}')
def GetAll(self, interface_name):
return AutomatedProperties._get_all_prop(self, interface_name)

View File

@ -42,7 +42,7 @@ def common(retrieve, o_type, search_keys,
existing_paths = cfg.om.object_paths_by_type(o_type)
for o in objects:
# Assume we need to add this one to dbus, unless we are refreshing
# Assume we need to add this one to dbus, unless we are refreshing,
# and it's already present
return_object = True

View File

@ -10,7 +10,7 @@
from .automatedproperties import AutomatedProperties
from . import utils
from .utils import vg_obj_path_generate, log_error, _handle_execute
from .utils import vg_obj_path_generate, log_error, _handle_execute, LvmBug
import dbus
from . import cmdhandler
from . import cfg
@ -21,14 +21,12 @@ from .utils import n, n32, d
from .loader import common
from .state import State
from . import background
from .utils import round_size, mt_remove_dbus_objects
from .utils import round_size, mt_remove_dbus_objects, lvm_column_key
from .job import JobState
import traceback
# Try and build a key for a LV, so that we sort the LVs with least dependencies
# first. This may be error prone because of the flexibility LVM
# Try and build a key for a LV, so that we sort the LVs with the least dependencies
# first. This may be error-prone because of the flexibility LVM
# provides and what you can stack.
def get_key(i):
@ -67,73 +65,80 @@ def lvs_state_retrieve(selection, cache_refresh=True):
if cache_refresh:
cfg.db.refresh()
# When building up the model, it's best to process LVs with the least
# dependencies to those that are dependant upon other LVs. Otherwise, when
# we are trying to gather information we could be in a position where we
# don't have information available yet.
lvs = sorted(cfg.db.fetch_lvs(selection), key=get_key)
try:
# When building up the model, it's best to process LVs with the least
# dependencies to those that are dependent upon other LVs. Otherwise, when
# we are trying to gather information we could be in a position where we
# don't have information available yet.
lvs = sorted(cfg.db.fetch_lvs(selection), key=get_key)
for l in lvs:
if cfg.vdo_support:
rc.append(LvStateVdo(
l['lv_uuid'], l['lv_name'],
l['lv_path'], n(l['lv_size']),
l['vg_name'],
l['vg_uuid'], l['pool_lv_uuid'],
l['pool_lv'], l['origin_uuid'], l['origin'],
n32(l['data_percent']), l['lv_attr'],
l['lv_tags'], l['lv_active'], l['data_lv'],
l['metadata_lv'], l['segtype'], l['lv_role'],
l['lv_layout'],
n32(l['snap_percent']),
n32(l['metadata_percent']),
n32(l['copy_percent']),
n32(l['sync_percent']),
n(l['lv_metadata_size']),
l['move_pv'],
l['move_pv_uuid'],
l['vdo_operating_mode'],
l['vdo_compression_state'],
l['vdo_index_state'],
n(l['vdo_used_size']),
d(l['vdo_saving_percent']),
l['vdo_compression'],
l['vdo_deduplication'],
l['vdo_use_metadata_hints'],
n32(l['vdo_minimum_io_size']),
n(l['vdo_block_map_cache_size']),
n32(l['vdo_block_map_era_length']),
l['vdo_use_sparse_index'],
n(l['vdo_index_memory_size']),
n(l['vdo_slab_size']),
n32(l['vdo_ack_threads']),
n32(l['vdo_bio_threads']),
n32(l['vdo_bio_rotation']),
n32(l['vdo_cpu_threads']),
n32(l['vdo_hash_zone_threads']),
n32(l['vdo_logical_threads']),
n32(l['vdo_physical_threads']),
n32(l['vdo_max_discard']),
l['vdo_write_policy'],
n32(l['vdo_header_size'])))
else:
rc.append(LvState(
l['lv_uuid'], l['lv_name'],
l['lv_path'], n(l['lv_size']),
l['vg_name'],
l['vg_uuid'], l['pool_lv_uuid'],
l['pool_lv'], l['origin_uuid'], l['origin'],
n32(l['data_percent']), l['lv_attr'],
l['lv_tags'], l['lv_active'], l['data_lv'],
l['metadata_lv'], l['segtype'], l['lv_role'],
l['lv_layout'],
n32(l['snap_percent']),
n32(l['metadata_percent']),
n32(l['copy_percent']),
n32(l['sync_percent']),
n(l['lv_metadata_size']),
l['move_pv'],
l['move_pv_uuid']))
for l in lvs:
if cfg.vdo_support:
rc.append(LvStateVdo(
l['lv_uuid'], l['lv_name'],
l['lv_path'], n(l['lv_size']),
l['vg_name'],
l['vg_uuid'], l['pool_lv_uuid'],
l['pool_lv'], l['origin_uuid'], l['origin'],
n32(l['data_percent']), l['lv_attr'],
l['lv_tags'], l['lv_active'], l['data_lv'],
l['metadata_lv'], l['segtype'], l['lv_role'],
l['lv_layout'],
n32(l['snap_percent']),
n32(l['metadata_percent']),
n32(l['copy_percent']),
n32(l['sync_percent']),
n(l['lv_metadata_size']),
l['move_pv'],
l['move_pv_uuid'],
l['vdo_operating_mode'],
l['vdo_compression_state'],
l['vdo_index_state'],
n(l['vdo_used_size']),
d(l['vdo_saving_percent']),
l['vdo_compression'],
l['vdo_deduplication'],
l['vdo_use_metadata_hints'],
n32(l['vdo_minimum_io_size']),
n(l['vdo_block_map_cache_size']),
n32(l['vdo_block_map_era_length']),
l['vdo_use_sparse_index'],
n(l['vdo_index_memory_size']),
n(l['vdo_slab_size']),
n32(l['vdo_ack_threads']),
n32(l['vdo_bio_threads']),
n32(l['vdo_bio_rotation']),
n32(l['vdo_cpu_threads']),
n32(l['vdo_hash_zone_threads']),
n32(l['vdo_logical_threads']),
n32(l['vdo_physical_threads']),
n32(l['vdo_max_discard']),
l['vdo_write_policy'],
n32(l['vdo_header_size'])))
else:
rc.append(LvState(
l['lv_uuid'], l['lv_name'],
l['lv_path'], n(l['lv_size']),
l['vg_name'],
l['vg_uuid'], l['pool_lv_uuid'],
l['pool_lv'], l['origin_uuid'], l['origin'],
n32(l['data_percent']), l['lv_attr'],
l['lv_tags'], l['lv_active'], l['data_lv'],
l['metadata_lv'], l['segtype'], l['lv_role'],
l['lv_layout'],
n32(l['snap_percent']),
n32(l['metadata_percent']),
n32(l['copy_percent']),
n32(l['sync_percent']),
n(l['lv_metadata_size']),
l['move_pv'],
l['move_pv_uuid']))
except KeyError as ke:
# Sometimes lvm omits returning one of the keys we requested.
key = ke.args[0]
if lvm_column_key(key):
raise LvmBug("missing JSON key: '%s'" % key)
raise ke
return rc
@ -274,15 +279,15 @@ class LvStateVdo(LvState):
MetaDataPercent, CopyPercent, SyncPercent,
MetaDataSizeBytes, move_pv, move_pv_uuid,
vdo_operating_mode, vdo_compression_state, vdo_index_state,
vdo_used_size,vdo_saving_percent,vdo_compression,
vdo_deduplication,vdo_use_metadata_hints,
vdo_minimum_io_size,vdo_block_map_cache_size,
vdo_block_map_era_length,vdo_use_sparse_index,
vdo_index_memory_size,vdo_slab_size,vdo_ack_threads,
vdo_bio_threads,vdo_bio_rotation,vdo_cpu_threads,
vdo_hash_zone_threads,vdo_logical_threads,
vdo_physical_threads,vdo_max_discard,
vdo_write_policy,vdo_header_size):
vdo_used_size, vdo_saving_percent, vdo_compression,
vdo_deduplication, vdo_use_metadata_hints,
vdo_minimum_io_size, vdo_block_map_cache_size,
vdo_block_map_era_length, vdo_use_sparse_index,
vdo_index_memory_size, vdo_slab_size, vdo_ack_threads,
vdo_bio_threads, vdo_bio_rotation, vdo_cpu_threads,
vdo_hash_zone_threads, vdo_logical_threads,
vdo_physical_threads, vdo_max_discard,
vdo_write_policy, vdo_header_size):
super(LvStateVdo, self).__init__(Uuid, Name, Path, SizeBytes,
vg_name, vg_uuid, pool_lv_uuid, PoolLv,
origin_uuid, OriginLv, DataPercent, Attr, Tags, active,
@ -371,8 +376,8 @@ class LvCommon(AutomatedProperties):
return dbus.Struct((self.state.Attr[index],
type_map.get(self.state.Attr[index], default)),
signature="(ss)")
except BaseException:
st = traceback.format_exc()
except BaseException as b:
st = utils.extract_stack_trace(b)
log_error("attr_struct: \n%s" % st)
return dbus.Struct(('?', 'Unavailable'), signature="(ss)")
@ -595,7 +600,7 @@ class Lv(LvCommon):
optional_size = space + 512 - remainder
LvCommon.handle_execute(*cmdhandler.vg_lv_snapshot(
lv_name, snapshot_options,name, optional_size))
lv_name, snapshot_options, name, optional_size))
full_name = "%s/%s" % (dbo.vg_name_lookup(), name)
return cfg.om.get_object_path_by_lvm_id(full_name)
@ -635,7 +640,7 @@ class Lv(LvCommon):
size_change = new_size_bytes - dbo.SizeBytes
LvCommon.handle_execute(*cmdhandler.lv_resize(
dbo.lvm_id, size_change,pv_dests, resize_options))
dbo.lvm_id, size_change, pv_dests, resize_options))
return "/"
@dbus.service.method(
@ -744,7 +749,7 @@ class Lv(LvCommon):
cfg.worker_q.put(r)
@staticmethod
def _writecache_lv(lv_uuid, lv_name, lv_object_path, cache_options):
def _caching_common(method, 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)
@ -753,7 +758,7 @@ class Lv(LvCommon):
if lv_to_cache:
fcn = lv_to_cache.lv_full_name()
rc, out, err = cmdhandler.lv_writecache_lv(
rc, out, err = method(
dbo.lv_full_name(), fcn, cache_options)
if rc == 0:
# When we cache an LV, the cache pool and the lv that is getting
@ -770,9 +775,14 @@ class Lv(LvCommon):
else:
raise dbus.exceptions.DBusException(
LV_INTERFACE, 'LV to cache with object path %s not present!' %
lv_object_path)
lv_object_path)
return lv_converted
@staticmethod
def _writecache_lv(lv_uuid, lv_name, lv_object_path, cache_options):
return Lv._caching_common(cmdhandler.lv_writecache_lv, lv_uuid,
lv_name, lv_object_path, cache_options)
@dbus.service.method(
dbus_interface=LV_INTERFACE,
in_signature='oia{sv}',
@ -845,10 +855,10 @@ class LvVdoPool(Lv):
cfg.worker_q.put(r)
@dbus.service.method(
dbus_interface=VDO_POOL_INTERFACE,
in_signature='ia{sv}',
out_signature='o',
async_callbacks=('cb', 'cbe'))
dbus_interface=VDO_POOL_INTERFACE,
in_signature='ia{sv}',
out_signature='o',
async_callbacks=('cb', 'cbe'))
def DisableCompression(self, tmo, comp_options, cb, cbe):
r = RequestEntry(
tmo, LvVdoPool._enable_disable_compression,
@ -878,10 +888,10 @@ class LvVdoPool(Lv):
cfg.worker_q.put(r)
@dbus.service.method(
dbus_interface=VDO_POOL_INTERFACE,
in_signature='ia{sv}',
out_signature='o',
async_callbacks=('cb', 'cbe'))
dbus_interface=VDO_POOL_INTERFACE,
in_signature='ia{sv}',
out_signature='o',
async_callbacks=('cb', 'cbe'))
def DisableDeduplication(self, tmo, dedup_options, cb, cbe):
r = RequestEntry(
tmo, LvVdoPool._enable_disable_deduplication,
@ -952,33 +962,8 @@ class LvCachePool(Lv):
@staticmethod
def _cache_lv(lv_uuid, lv_name, lv_object_path, cache_options):
# Make sure we have a dbus object representing cache pool
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_cache_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
return Lv._caching_common(cmdhandler.lv_cache_lv, lv_uuid, lv_name,
lv_object_path, cache_options)
@dbus.service.method(
dbus_interface=CACHE_POOL_INTERFACE,

View File

@ -14,12 +14,12 @@
import subprocess
import shlex
import os
import traceback
import pty
import sys
import tempfile
import time
import threading
import select
import copy
try:
import simplejson as json
@ -27,9 +27,9 @@ except ImportError:
import json
from lvmdbusd.cfg import LVM_CMD
import lvmdbusd.cfg as cfg
from lvmdbusd.utils import log_debug, log_error, add_no_notify, make_non_block,\
read_decoded
read_decoded, extract_stack_trace, LvmBug, get_error_msg
SHELL_PROMPT = "lvm> "
@ -43,10 +43,11 @@ def _quote_arg(arg):
class LVMShellProxy(object):
# 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!)
def _read_until_prompt(self, no_output=False):
# Read REPORT FD until we have a complete and valid JSON record or give
# up trying to get one.
#
# Returns stdout, report (JSON), stderr
def _read_response(self, no_output=False):
stdout = ""
report = ""
stderr = ""
@ -58,24 +59,27 @@ class LVMShellProxy(object):
# Try reading from all FDs to prevent one from filling up and causing
# a hang. Keep reading until we get the prompt back and the report
# FD does not contain valid JSON
while keep_reading:
while keep_reading and cfg.run.value != 0:
try:
rd_fd = [
self.lvm_shell.stdout.fileno(),
self.parent_stdout_fd,
self.report_stream.fileno(),
self.lvm_shell.stderr.fileno()]
ready = select.select(rd_fd, [], [], 2)
self.parent_stderr_fd]
ready = select.select(rd_fd, [], [], cfg.G_LOOP_TMO)
for r in ready[0]:
if r == self.lvm_shell.stdout.fileno():
stdout += read_decoded(self.lvm_shell.stdout)
if r == self.parent_stdout_fd:
for line in self.parent_stdout.readlines():
stdout += line
elif r == self.report_stream.fileno():
report += read_decoded(self.report_stream)
elif r == self.lvm_shell.stderr.fileno():
stderr += read_decoded(self.lvm_shell.stderr)
elif r == self.parent_stderr_fd:
for line in self.parent_stderr.readlines():
stderr += line
# Check to see if the lvm process died on us
if self.lvm_shell.poll():
if self.lvm_shell.poll() is not None:
raise Exception(self.lvm_shell.returncode, "%s" % stderr)
if stdout.endswith(SHELL_PROMPT):
@ -99,91 +103,106 @@ class LVMShellProxy(object):
extra_passes -= 1
if extra_passes <= 0:
if len(report):
raise ValueError("Invalid json: %s" %
raise LvmBug("Invalid json: %s" %
report)
else:
raise ValueError(
raise LvmBug(
"lvm returned no JSON output!")
except Exception as e:
log_error("While reading from lvm shell we encountered an error %s" % str(e))
log_error("stdout= %s\nstderr= %s\n" % (stdout, stderr))
if self.lvm_shell.poll() is not None:
log_error("Underlying lvm shell process unexpectedly exited: %d" % self.lvm_shell.returncode)
else:
log_error("Underlying lvm shell process is still present!")
raise e
except IOError as ioe:
log_debug(str(ioe))
pass
if keep_reading and cfg.run.value == 0:
# We didn't complete as we are shutting down
# Try to clean up lvm shell process
log_debug("exiting lvm shell as we are shutting down")
self.exit_shell()
raise SystemExit
return stdout, report_json, stderr
def _write_cmd(self, cmd):
cmd_bytes = bytes(cmd, "utf-8")
num_written = self.lvm_shell.stdin.write(cmd_bytes)
assert (num_written == len(cmd_bytes))
self.lvm_shell.stdin.flush()
self.parent_stdin.write(cmd)
self.parent_stdin.flush()
def __init__(self):
# Create a temp directory
tmp_dir = tempfile.mkdtemp(prefix="lvmdbus_")
tmp_file = "%s/lvmdbus_report" % (tmp_dir)
try:
# Lets create fifo for the report output
os.mkfifo(tmp_file, 0o600)
except FileExistsError:
pass
# Create a lock so that we don't step on each other when we are waiting for a command
# to finish and some other request comes in concurrently, like to exit the shell.
self.shell_lock = threading.RLock()
# We have to open non-blocking as the other side isn't open until
# we actually fork the process.
# Create a fifo for the report output
os.mkfifo(tmp_file, 0o600)
# Open the fifo for use to read and for lvm child process to write to.
self.report_fd = os.open(tmp_file, os.O_NONBLOCK)
self.report_stream = os.fdopen(self.report_fd, 'rb', 0)
lvm_fd = os.open(tmp_file, os.O_WRONLY)
# Setup the environment for using our own socket for reporting
local_env = copy.deepcopy(os.environ)
local_env["LVM_REPORT_FD"] = "32"
local_env["LVM_COMMAND_PROFILE"] = "lvmdbusd"
# Set up the environment for using our own socket for reporting and disable the abort
# logic if lvm logs too much, which easily happens when utilizing the lvm shell.
local_env = {"LC_ALL": "C", "LVM_REPORT_FD": "%s" % lvm_fd, "LVM_COMMAND_PROFILE": "lvmdbusd",
"LVM_LOG_FILE_MAX_LINES": "0"}
# Disable the abort logic if lvm logs too much, which easily happens
# when utilizing the lvm shell.
local_env["LVM_LOG_FILE_MAX_LINES"] = "0"
# If any env variables contain LVM we will propagate them too
for k, v in os.environ.items():
if "PATH" in k:
local_env[k] = v
if "LVM" in k:
local_env[k] = v
self.parent_stdin_fd, child_stdin_fd = pty.openpty()
self.parent_stdout_fd, child_stdout_fd = pty.openpty()
self.parent_stderr_fd, child_stderr_fd = pty.openpty()
self.parent_stdin = os.fdopen(self.parent_stdin_fd, "w")
self.parent_stdout = os.fdopen(self.parent_stdout_fd, "r")
self.parent_stderr = os.fdopen(self.parent_stderr_fd, "r")
# run the lvm shell
self.lvm_shell = subprocess.Popen(
[LVM_CMD + " 32>%s" % tmp_file],
stdin=subprocess.PIPE, stdout=subprocess.PIPE, env=local_env,
stderr=subprocess.PIPE, close_fds=True, shell=True)
[cfg.LVM_CMD],
stdin=child_stdin_fd,
stdout=child_stdout_fd, env=local_env,
stderr=child_stderr_fd, close_fds=True,
pass_fds=(lvm_fd,), shell=False)
try:
make_non_block(self.lvm_shell.stdout)
make_non_block(self.lvm_shell.stderr)
make_non_block(self.parent_stdout_fd)
make_non_block(self.parent_stderr_fd)
# Close our copies of the child FDs there were created with the fork, we don't need them open.
os.close(lvm_fd)
os.close(child_stdin_fd)
os.close(child_stdout_fd)
os.close(child_stderr_fd)
# wait for the first prompt
errors = self._read_until_prompt(no_output=True)[2]
log_debug("waiting for first prompt...")
errors = self._read_response(no_output=True)[2]
if errors and len(errors):
raise RuntimeError(errors)
raise LvmBug(errors)
log_debug("lvm prompt read!!!")
except:
raise
finally:
# These will get deleted when the FD count goes to zero so we
# These will get deleted when the FD count goes to zero, so we
# can be sure to clean up correctly no matter how we finish
os.unlink(tmp_file)
os.rmdir(tmp_dir)
def get_error_msg(self):
# We got an error, lets go fetch the error message
def _get_last_log(self):
# Precondition, lock is held
self._write_cmd('lastlog\n')
# read everything from the STDOUT to the next prompt
stdout, report_json, stderr = self._read_until_prompt()
if 'log' in report_json:
error_msg = ""
# Walk the entire log array and build an error string
for log_entry in report_json['log']:
if log_entry['log_type'] == "error":
if error_msg:
error_msg += ', ' + log_entry['log_message']
else:
error_msg = log_entry['log_message']
return error_msg
return 'No error reason provided! (missing "log" section)'
report_json = self._read_response()[1]
return get_error_msg(report_json)
def call_lvm(self, argv, debug=False):
rc = 1
@ -201,60 +220,94 @@ class LVMShellProxy(object):
cmd += "\n"
# run the command by writing it to the shell's STDIN
self._write_cmd(cmd)
with self.shell_lock:
self._write_cmd(cmd)
# read everything from the STDOUT to the next prompt
stdout, report_json, stderr = self._read_until_prompt()
# read everything from the STDOUT to the next prompt
stdout, report_json, stderr = self._read_response()
# Parse the report to see what happened
if 'log' in report_json:
ret_code = int(report_json['log'][-1:][0]['log_ret_code'])
# If we have an exported vg we get a log_ret_code == 5 when
# we do a 'fullreport'
if (ret_code == 1) or (ret_code == 5 and argv[0] == 'fullreport'):
rc = 0
else:
error_msg = self.get_error_msg()
# Parse the report to see what happened
if 'log' in report_json:
ret_code = int(report_json['log'][-1:][0]['log_ret_code'])
# If we have an exported vg we get a log_ret_code == 5 when
# we do a 'fullreport'
# Note: 0 == error
if (ret_code == 1) or (ret_code == 5 and argv[0] == 'fullreport'):
rc = 0
else:
# Depending on where lvm fails the command, it may not have anything
# to report for "lastlog", so we need to check for a message in the
# report json too.
error_msg = self._get_last_log()
if error_msg is None:
error_msg = get_error_msg(report_json)
if error_msg is None:
error_msg = 'No error reason provided! (missing "log" section)'
if debug or rc != 0:
log_error(('CMD: %s' % cmd))
log_error(("EC = %d" % rc))
log_error(("CMD= %s" % cmd))
log_error(("EC= %d" % rc))
log_error(("ERROR_MSG=\n %s\n" % error_msg))
return rc, report_json, error_msg
def exit_shell(self):
try:
self._write_cmd('exit\n')
except Exception as e:
log_error(str(e))
with self.shell_lock:
try:
if self.lvm_shell is not None:
self._write_cmd('exit\n')
self.lvm_shell.wait(1)
self.lvm_shell = None
except Exception as _e:
log_error("exit_shell: %s" % (str(_e)))
def __del__(self):
try:
self.lvm_shell.terminate()
except:
pass
# Note: When we are shutting down the daemon and the main process has already exited
# and this gets called we have a limited set of things we can do, like we cannot call
# log_error as _common_log is None!!!
if self.lvm_shell is not None:
try:
self.lvm_shell.wait(1)
except subprocess.TimeoutExpired:
print("lvm shell child process did not exit as instructed, sending SIGTERM")
cfg.ignore_sigterm = True
self.lvm_shell.terminate()
child_exit_code = self.lvm_shell.wait(1)
print("lvm shell process exited with %d" % child_exit_code)
if __name__ == "__main__":
shell = LVMShellProxy()
in_line = "start"
print("USING LVM BINARY: %s " % cfg.LVM_CMD)
try:
while in_line:
in_line = input("lvm> ")
if in_line:
start = time.time()
ret, out, err = shell.call_lvm(in_line.split())
end = time.time()
if len(sys.argv) > 1 and sys.argv[1] == "bisect":
shell = LVMShellProxy()
shell.exit_shell()
else:
shell = LVMShellProxy()
in_line = "start"
try:
while in_line:
in_line = input("lvm> ")
if in_line:
if in_line == "exit":
shell.exit_shell()
sys.exit(0)
start = time.time()
ret, out, err = shell.call_lvm(in_line.split())
end = time.time()
print(("RC: %d" % ret))
print(("OUT:\n%s" % out))
print(("ERR:\n%s" % err))
print(("RC: %d" % ret))
print(("OUT:\n%s" % out))
print(("ERR:\n%s" % err))
print("Command = %f seconds" % (end - start))
except KeyboardInterrupt:
pass
except EOFError:
pass
except Exception:
traceback.print_exc(file=sys.stdout)
print("Command = %f seconds" % (end - start))
except KeyboardInterrupt:
pass
except EOFError:
pass
except Exception as e:
log_error("main process exiting on exception!\n%s" % extract_stack_trace(e))
sys.exit(1)
sys.exit(0)

View File

@ -13,14 +13,13 @@ from collections import OrderedDict
import pprint as prettyprint
import os
import sys
from lvmdbusd import cmdhandler
from lvmdbusd.utils import log_debug, log_error
from lvmdbusd.utils import log_debug, log_error, lvm_column_key, LvmBug
class DataStore(object):
def __init__(self, usejson=True, vdo_support=False):
def __init__(self, vdo_support=False):
self.pvs = {}
self.vgs = {}
self.lvs = {}
@ -35,41 +34,9 @@ class DataStore(object):
self.lvs_in_vgs = {}
self.pvs_in_vgs = {}
# self.refresh()
self.num_refreshes = 0
if usejson:
self.json = cmdhandler.supports_json()
else:
self.json = usejson
self.vdo_support = vdo_support
@staticmethod
def _insert_record(table, key, record, allowed_multiple):
if key in table:
existing = table[key]
for rec_k, rec_v in record.items():
if rec_k in allowed_multiple:
# This column name allows us to store multiple value for
# each type
if not isinstance(existing[rec_k], list):
existing_value = existing[rec_k]
existing[rec_k] = [existing_value, rec_v]
else:
existing[rec_k].append(rec_v)
else:
# If something is not expected to have changing values
# lets ensure that
if existing[rec_k] != rec_v:
raise RuntimeError(
"existing[%s]=%s != %s" %
(rec_k, str(existing[rec_k]),
str(rec_v)))
else:
table[key] = record
@staticmethod
def _pvs_parse_common(c_pvs, c_pvs_in_vgs, c_lookup):
for p in c_pvs.values():
@ -84,22 +51,6 @@ class DataStore(object):
# Lookup for translating between /dev/<name> and pv uuid
c_lookup[p['pv_name']] = p['pv_uuid']
@staticmethod
def _parse_pvs(_pvs):
pvs = sorted(_pvs, key=lambda pk: pk['pv_name'])
c_pvs = OrderedDict()
c_lookup = {}
c_pvs_in_vgs = {}
for p in pvs:
DataStore._insert_record(
c_pvs, p['pv_uuid'], p,
['pvseg_start', 'pvseg_size', 'segtype'])
DataStore._pvs_parse_common(c_pvs, c_pvs_in_vgs, c_lookup)
return c_pvs, c_lookup, c_pvs_in_vgs
@staticmethod
def _parse_pvs_json(_all):
@ -107,7 +58,7 @@ class DataStore(object):
c_lookup = {}
c_pvs_in_vgs = {}
# Each item item in the report is a collection of information pertaining
# Each item in the report is a collection of information pertaining
# to the vg
for r in _all['report']:
tmp_pv = []
@ -141,28 +92,6 @@ class DataStore(object):
return c_pvs, c_lookup, c_pvs_in_vgs
@staticmethod
def _parse_vgs(_vgs):
vgs = sorted(_vgs, key=lambda vk: vk['vg_uuid'])
c_vgs = OrderedDict()
c_lookup = {}
for i in vgs:
vg_name = i['vg_name']
# Lvm allows duplicate vg names. When this occurs, each subsequent
# matching VG name will be called vg_name:vg_uuid. Note: ':' is an
# invalid character for lvm VG names
if vg_name in c_lookup:
vg_name = "%s:%s" % (vg_name, i['vg_uuid'])
i['vg_name'] = vg_name
c_lookup[vg_name] = i['vg_uuid']
DataStore._insert_record(c_vgs, i['vg_uuid'], i, [])
return c_vgs, c_lookup
@staticmethod
def _parse_vgs_json(_all):
@ -227,28 +156,12 @@ class DataStore(object):
return c_lvs, c_lvs_in_vgs, c_lvs_hidden, c_lv_full_lookup
@staticmethod
def _parse_lvs(_lvs):
lvs = sorted(_lvs, key=lambda vk: vk['lv_name'])
c_lvs = OrderedDict()
c_lv_full_lookup = OrderedDict()
for i in lvs:
full_name = "%s/%s" % (i['vg_name'], i['lv_name'])
c_lv_full_lookup[full_name] = i['lv_uuid']
DataStore._insert_record(
c_lvs, i['lv_uuid'], i,
['seg_pe_ranges', 'segtype'])
return DataStore._parse_lvs_common(c_lvs, c_lv_full_lookup)
def _parse_lvs_json(self, _all):
c_lvs = OrderedDict()
c_lv_full_lookup = {}
# Each item item in the report is a collection of information pertaining
# Each item in the report is a collection of information pertaining
# to the vg
for r in _all['report']:
# Get the lv data for this VG.
@ -396,12 +309,12 @@ class DataStore(object):
:param log Add debug log entry/exit messages
:return: None
"""
self.num_refreshes += 1
if log:
log_debug("lvmdb - refresh entry")
try:
self.num_refreshes += 1
if log:
log_debug("lvmdb - refresh entry")
# Grab everything first then parse it
if self.json:
# Grab everything first then parse it
# Do a single lvm retrieve for everything in json
a = cmdhandler.lvm_full_report_json()
@ -409,29 +322,25 @@ class DataStore(object):
_vgs, _vgs_lookup = self._parse_vgs_json(a)
_lvs, _lvs_in_vgs, _lvs_hidden, _lvs_lookup = self._parse_lvs_json(a)
else:
_raw_pvs = cmdhandler.pv_retrieve_with_segs()
_raw_vgs = cmdhandler.vg_retrieve(None)
_raw_lvs = cmdhandler.lv_retrieve_with_segments()
# Set all
self.pvs = _pvs
self.pv_path_to_uuid = _pvs_lookup
self.vg_name_to_uuid = _vgs_lookup
self.lv_full_name_to_uuid = _lvs_lookup
_pvs, _pvs_lookup, _pvs_in_vgs = self._parse_pvs(_raw_pvs)
_vgs, _vgs_lookup = self._parse_vgs(_raw_vgs)
_lvs, _lvs_in_vgs, _lvs_hidden, _lvs_lookup = self._parse_lvs(_raw_lvs)
self.vgs = _vgs
self.lvs = _lvs
self.lvs_in_vgs = _lvs_in_vgs
self.pvs_in_vgs = _pvs_in_vgs
self.lvs_hidden = _lvs_hidden
# Set all
self.pvs = _pvs
self.pv_path_to_uuid = _pvs_lookup
self.vg_name_to_uuid = _vgs_lookup
self.lv_full_name_to_uuid = _lvs_lookup
self.vgs = _vgs
self.lvs = _lvs
self.lvs_in_vgs = _lvs_in_vgs
self.pvs_in_vgs = _pvs_in_vgs
self.lvs_hidden = _lvs_hidden
# Create lookup table for which LV and segments are on each PV
self.pv_lvs, self.lv_pvs = self._parse_pv_in_lvs()
# Create lookup table for which LV and segments are on each PV
self.pv_lvs, self.lv_pvs = self._parse_pv_in_lvs()
except KeyError as ke:
key = ke.args[0]
if lvm_column_key(key):
raise LvmBug("missing JSON key: '%s'" % key)
raise ke
if log:
log_debug("lvmdb - refresh exit")
@ -442,7 +351,7 @@ class DataStore(object):
else:
rc = []
for s in pv_name:
# Ths user could be using a symlink instead of the actual
# The user could be using a symlink instead of the actual
# block device, make sure we are using actual block device file
# if the pv name isn't in the lookup
if s not in self.pv_path_to_uuid:
@ -451,10 +360,13 @@ class DataStore(object):
return rc
def pv_missing(self, pv_uuid):
# The uuid might not be a PV, default to false
if pv_uuid in self.pvs:
if self.pvs[pv_uuid]['pv_missing'] == '':
return False
return True
else:
return True
return False
def fetch_vgs(self, vg_name):
if not vg_name:
@ -525,15 +437,11 @@ class DataStore(object):
if __name__ == "__main__":
os.environ["LC_ALL"] = "C"
os.environ["LVM_COMMAND_PROFILE"] = "lvmdbusd"
pp = prettyprint.PrettyPrinter(indent=4)
use_json = False
if len(sys.argv) != 1:
print(len(sys.argv))
use_json = True
ds = DataStore(use_json)
ds = DataStore()
ds.refresh()
print("PVS")

View File

@ -22,14 +22,13 @@ from . import lvmdb
from gi.repository import GLib
from .fetch import StateUpdate
from .manager import Manager
import traceback
import queue
from . import udevwatch
from .utils import log_debug, log_error
from .utils import log_debug, log_error, log_msg, DebugMessages
import argparse
import os
import sys
from .cmdhandler import LvmFlightRecorder, supports_vdo
from .cmdhandler import LvmFlightRecorder, supports_vdo, supports_json
from .request import RequestEntry
@ -42,7 +41,7 @@ def process_request():
while cfg.run.value != 0:
# noinspection PyBroadException
try:
req = cfg.worker_q.get(True, 5)
req = cfg.worker_q.get(True, cfg.G_LOOP_TMO)
log_debug(
"Method start: %s with args %s (callback = %s)" %
(str(req.method), str(req.arguments), str(req.cb)))
@ -50,12 +49,15 @@ def process_request():
log_debug("Method complete: %s" % str(req.method))
except queue.Empty:
pass
except Exception:
st = traceback.format_exc()
except SystemExit:
break
except Exception as e:
st = utils.extract_stack_trace(e)
utils.log_error("process_request exception: \n%s" % st)
log_debug("process_request thread exiting!")
def check_bb_size(value):
def check_fr_size(value):
v = int(value)
if v < 0:
raise argparse.ArgumentTypeError(
@ -65,7 +67,7 @@ def check_bb_size(value):
def install_signal_handlers():
# Because of the glib main loop stuff the python signal handler code is
# apparently not usable and we need to use the glib calls instead
# apparently not usable, and we need to use the glib calls instead
signal_add = None
if hasattr(GLib, 'unix_signal_add'):
@ -77,13 +79,13 @@ def install_signal_handlers():
signal_add(GLib.PRIORITY_HIGH, signal.SIGHUP, utils.handler, signal.SIGHUP)
signal_add(GLib.PRIORITY_HIGH, signal.SIGINT, utils.handler, signal.SIGINT)
signal_add(GLib.PRIORITY_HIGH, signal.SIGUSR1, utils.handler, signal.SIGUSR1)
signal_add(GLib.PRIORITY_HIGH, signal.SIGUSR2, utils.handler, signal.SIGUSR2)
signal_add(GLib.PRIORITY_HIGH, signal.SIGTERM, utils.handler, signal.SIGTERM)
else:
log_error("GLib.unix_signal_[add|add_full] are NOT available!")
def main():
start = time.time()
# Add simple command line handling
def process_args():
parser = argparse.ArgumentParser()
parser.add_argument(
"--udev", action='store_true',
@ -104,101 +106,137 @@ def main():
default=False,
dest='use_lvm_shell')
parser.add_argument(
"--blackboxsize",
help="Size of the black box flight recorder, 0 to disable",
"--frsize",
help="Size of the flight recorder (num. entries), 0 to disable (signal 12 to dump)",
default=10,
type=check_bb_size,
dest='bb_size')
type=check_fr_size,
dest='fr_size')
use_session = os.getenv('LVMDBUSD_USE_SESSION', False)
args = parser.parse_args()
# Ensure that we get consistent output for parsing stdout/stderr
if not args.use_json:
log_error("Daemon no longer supports lvm without JSON support, exiting!")
sys.exit(1)
else:
if not supports_json():
log_error("Un-supported version of LVM, daemon requires JSON output, exiting!")
sys.exit(1)
# Add udev watching
if args.use_udev:
# Make sure this msg ends up in the journal, so we know
log_msg('The --udev option is no longer supported,'
'the daemon always uses a combination of dbus notify from lvm tools and udev')
return args
def running_under_systemd():
""""
Checks to see if we are running under systemd, by checking daemon fd 0, 1
systemd sets stdin to /dev/null and 1 & 2 are a socket
"""
base = "/proc/self/fd"
stdout = os.readlink("%s/0" % base)
if stdout == "/dev/null":
stdout = os.readlink("%s/1" % base)
if "socket" in stdout:
return True
return False
def main():
start = time.time()
use_session = os.getenv('LVM_DBUSD_USE_SESSION', False)
# Ensure that we get consistent output for parsing stdout/stderr and that we
# are using the lvmdbusd profile.
os.environ["LC_ALL"] = "C"
os.environ["LVM_COMMAND_PROFILE"] = "lvmdbusd"
# Indicator if we are running under systemd
cfg.systemd = running_under_systemd()
# Add simple command line handling
cfg.args = process_args()
cfg.args = parser.parse_args()
cfg.create_request_entry = RequestEntry
# We create a flight recorder in cmdhandler too, but we replace it here
# as the user may be specifying a different size. The default one in
# cmdhandler is for when we are running other code with a different main.
cfg.blackbox = LvmFlightRecorder(cfg.args.bb_size)
cfg.flightrecorder = LvmFlightRecorder(cfg.args.fr_size)
if cfg.args.use_lvm_shell and not cfg.args.use_json:
log_error("You cannot specify --lvmshell and --nojson")
sys.exit(1)
# Create a circular buffer for debug logs
cfg.debug = DebugMessages()
log_debug("Using lvm binary: %s" % cfg.LVM_CMD)
# We will dynamically add interfaces which support vdo if it
# exists.
cfg.vdo_support = supports_vdo()
if cfg.vdo_support and not cfg.args.use_json:
log_error("You cannot specify --nojson when lvm has VDO support")
sys.exit(1)
# List of threads that we start up
thread_list = []
install_signal_handlers()
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
dbus.mainloop.glib.threads_init()
with utils.LockFile(cfg.LOCK_FILE):
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
dbus.mainloop.glib.threads_init()
cmdhandler.set_execution(cfg.args.use_lvm_shell)
cmdhandler.set_execution(cfg.args.use_lvm_shell)
if use_session:
cfg.bus = dbus.SessionBus()
else:
cfg.bus = dbus.SystemBus()
# The base name variable needs to exist for things to work.
# noinspection PyUnusedLocal
base_name = dbus.service.BusName(BUS_NAME, cfg.bus)
cfg.om = Lvm(BASE_OBJ_PATH)
cfg.om.register_object(Manager(MANAGER_OBJ_PATH))
if use_session:
cfg.bus = dbus.SessionBus()
else:
cfg.bus = dbus.SystemBus()
# The base name variable needs to exist for things to work.
# noinspection PyUnusedLocal
base_name = dbus.service.BusName(BUS_NAME, cfg.bus)
cfg.om = Lvm(BASE_OBJ_PATH)
cfg.om.register_object(Manager(MANAGER_OBJ_PATH))
cfg.db = lvmdb.DataStore(cfg.args.use_json, cfg.vdo_support)
cfg.db = lvmdb.DataStore(vdo_support=cfg.vdo_support)
# Using a thread to process requests, we cannot hang the dbus library
# thread that is handling the dbus interface
thread_list.append(
threading.Thread(target=process_request, name='process_request'))
# Using a thread to process requests, we cannot hang the dbus library
# thread that is handling the dbus interface
thread_list.append(
threading.Thread(target=process_request, name='process_request'))
# Have a single thread handling updating lvm and the dbus model so we
# don't have multiple threads doing this as the same time
updater = StateUpdate()
thread_list.append(updater.thread)
# Have a single thread handling updating lvm and the dbus model, so we
# don't have multiple threads doing this as the same time
updater = StateUpdate()
thread_list.append(updater.thread)
cfg.load = updater.load
cfg.load = updater.load
cfg.loop = GLib.MainLoop()
cfg.loop = GLib.MainLoop()
for thread in thread_list:
thread.damon = True
thread.start()
for thread in thread_list:
thread.daemon = True
thread.start()
# Add udev watching
if cfg.args.use_udev:
log_debug('Utilizing udev to trigger updates')
# In all cases we are going to monitor for udev until we get an
# ExternalEvent. In the case where we get an external event and the user
# didn't specify --udev we will stop monitoring udev
udevwatch.add()
# In all cases we are going to monitor for udev until we get an
# ExternalEvent. In the case where we get an external event and the user
# didn't specify --udev we will stop monitoring udev
udevwatch.add()
end = time.time()
log_debug(
'Service ready! total time= %.4f, lvm time= %.4f count= %d' %
(end - start, cmdhandler.total_time, cmdhandler.total_count),
'bg_black', 'fg_light_green')
end = time.time()
log_debug(
'Service ready! total time= %.4f, lvm time= %.4f count= %d' %
(end - start, cmdhandler.total_time, cmdhandler.total_count),
'bg_black', 'fg_light_green')
try:
if cfg.run.value != 0:
cfg.loop.run()
udevwatch.remove()
try:
if cfg.run.value != 0:
cfg.loop.run()
udevwatch.remove()
for thread in thread_list:
thread.join()
except KeyboardInterrupt:
# If we are unable to register signal handler, we will end up here when
# the service gets a ^C or a kill -2 <parent pid>
utils.handler(signal.SIGINT)
for thread in thread_list:
thread.join()
except KeyboardInterrupt:
# If we are unable to register signal handler, we will end up here when
# the service gets a ^C or a kill -2 <parent pid>
utils.handler(signal.SIGINT)
return 0

View File

@ -137,7 +137,8 @@ class Manager(AutomatedProperties):
"""
Dump the flight recorder to syslog
"""
cfg.blackbox.dump()
cfg.debug.dump()
cfg.flightrecorder.dump()
@staticmethod
def _lookup_by_lvm_id(key):
@ -194,6 +195,7 @@ class Manager(AutomatedProperties):
def _external_event(command):
utils.log_debug("Processing _external_event= %s" % command,
'bg_black', 'fg_orange')
cfg.got_external_event = True
cfg.load()
@dbus.service.method(
@ -201,14 +203,6 @@ class Manager(AutomatedProperties):
in_signature='s', out_signature='i')
def ExternalEvent(self, command):
utils.log_debug("ExternalEvent %s" % command)
# If a user didn't explicitly specify udev, we will turn it off now.
if not cfg.args.use_udev:
if udevwatch.remove():
utils.log_debug("ExternalEvent received, disabling "
"udev monitoring")
# We are dependent on external events now to stay current!
cfg.got_external_event = True
r = RequestEntry(
-1, Manager._external_event, (command,), None, None, False)
cfg.worker_q.put(r)

View File

@ -9,12 +9,11 @@
import sys
import threading
import traceback
import dbus
import os
import copy
from . import cfg
from .utils import log_debug, pv_obj_path_generate, log_error
from .utils import log_debug, log_error, extract_stack_trace
from .automatedproperties import AutomatedProperties
@ -40,8 +39,8 @@ class ObjectManager(AutomatedProperties):
for k, v in list(obj._objects.items()):
path, props = v[0].emit_data()
rc[path] = props
except Exception:
traceback.print_exc(file=sys.stdout)
except Exception as e:
log_error("_get_managed_objects exception, bailing: \n%s" % extract_stack_trace(e))
sys.exit(1)
return rc
@ -53,15 +52,6 @@ class ObjectManager(AutomatedProperties):
(self, ), cb, cbe, False)
cfg.worker_q.put(r)
def locked(self):
"""
If some external code need to run across a number of different
calls into ObjectManager while blocking others they can use this method
to lock others out.
:return:
"""
return ObjectManagerLock(self.rlock)
@dbus.service.signal(
dbus_interface="org.freedesktop.DBus.ObjectManager",
signature='oa{sa{sv}}')
@ -169,8 +159,8 @@ class ObjectManager(AutomatedProperties):
# print('Registering object path %s for %s' %
# (path, dbus_object.lvm_id))
# We want fast access to the object by a number of different ways
# so we use multiple hashs with different keys
# We want fast access to the object by a number of different ways,
# so we use multiple hashes with different keys
self._lookup_add(dbus_object, path, dbus_object.lvm_id,
dbus_object.Uuid)
@ -219,7 +209,7 @@ class ObjectManager(AutomatedProperties):
def get_object_by_lvm_id(self, lvm_id):
"""
Given an lvm identifier, return the object registered for it
Given a lvm identifier, return the object registered for it
:param lvm_id: The lvm identifier
"""
with self.rlock:
@ -230,7 +220,7 @@ class ObjectManager(AutomatedProperties):
def get_object_path_by_lvm_id(self, lvm_id):
"""
Given an lvm identifier, return the object path for it
Given a lvm identifier, return the object path for it
:param lvm_id: The lvm identifier
:return: Object path or '/' if not found
"""
@ -287,7 +277,7 @@ class ObjectManager(AutomatedProperties):
register it with the object manager for the specified uuid & lvm_id.
Note: If path create is not None, uuid and lvm_id cannot be equal
:param uuid: The uuid for the lvm object we are searching for
:param lvm_id: The lvm name (eg. pv device path, vg name, lv full name)
:param lvm_id: The lvm name (e.g. pv device path, vg name, lv full name)
:param path_create: If not None, create the path using this function if
we fail to find the object by uuid or lvm_id.
:returns None if lvm asset not found and path_create == None otherwise
@ -305,18 +295,17 @@ class ObjectManager(AutomatedProperties):
if uuid == lvm_id:
path = self._id_lookup(lvm_id)
else:
# We have a uuid and a lvm_id we can do sanity checks to ensure
# We have an uuid and a lvm_id we can do sanity checks to ensure
# that they are consistent
# If a PV is missing it's device path is '[unknown]' or some
# If a PV is missing its device path is '[unknown]' or some
# other text derivation of unknown. When we find that a PV is
# missing we will clear out the lvm_id as it's likely not unique
# and thus not useful and potentially harmful for lookups.
if path_create == pv_obj_path_generate and \
cfg.db.pv_missing(uuid):
# missing we will clear out the lvm_id as it's not unique
# and thus not useful and harmful for lookups.
if cfg.db.pv_missing(uuid):
lvm_id = None
# Lets check for the uuid first
# Let's check for the uuid first
path = self._id_lookup(uuid)
if path:
# Ensure table lookups are correct
@ -337,29 +326,3 @@ class ObjectManager(AutomatedProperties):
# (uuid, lvm_id, str(path_create), path))
return path
class ObjectManagerLock(object):
"""
The sole purpose of this class is to allow other code the ability to
lock the object manager using a `with` statement, eg.
with cfg.om.locked():
# Do stuff with object manager
This will ensure that the lock is always released (assuming this is done
correctly)
"""
def __init__(self, recursive_lock):
self._lock = recursive_lock
def __enter__(self):
# Acquire lock
self._lock.acquire()
# noinspection PyUnusedLocal
def __exit__(self, e_type, e_value, e_traceback):
# Release lock
self._lock.release()
self._lock = None

View File

@ -14,11 +14,11 @@ import dbus
from .cfg import PV_INTERFACE
from . import cmdhandler
from .utils import vg_obj_path_generate, n, pv_obj_path_generate, \
lv_object_path_method, _handle_execute
lv_object_path_method, _handle_execute, lvm_column_key
from .loader import common
from .request import RequestEntry
from .state import State
from .utils import round_size
from .utils import round_size, LvmBug
# noinspection PyUnusedLocal
@ -28,16 +28,23 @@ def pvs_state_retrieve(selection, cache_refresh=True):
if cache_refresh:
cfg.db.refresh()
for p in cfg.db.fetch_pvs(selection):
rc.append(
PvState(
p["pv_name"], p["pv_uuid"], p["pv_name"],
p["pv_fmt"], n(p["pv_size"]), n(p["pv_free"]),
n(p["pv_used"]), n(p["dev_size"]), n(p["pv_mda_size"]),
n(p["pv_mda_free"]), int(p["pv_ba_start"]),
n(p["pv_ba_size"]), n(p["pe_start"]),
int(p["pv_pe_count"]), int(p["pv_pe_alloc_count"]),
p["pv_attr"], p["pv_tags"], p["vg_name"], p["vg_uuid"]))
try:
for p in cfg.db.fetch_pvs(selection):
rc.append(
PvState(
p["pv_name"], p["pv_uuid"], p["pv_name"],
p["pv_fmt"], n(p["pv_size"]), n(p["pv_free"]),
n(p["pv_used"]), n(p["dev_size"]), n(p["pv_mda_size"]),
n(p["pv_mda_free"]), int(p["pv_ba_start"]),
n(p["pv_ba_size"]), n(p["pe_start"]),
int(p["pv_pe_count"]), int(p["pv_pe_alloc_count"]),
p["pv_attr"], p["pv_tags"], p["vg_name"], p["vg_uuid"]))
except KeyError as ke:
# Sometimes lvm omits returning one of the keys we requested.
key = ke.args[0]
if lvm_column_key(key):
raise LvmBug("missing JSON key: '%s'" % key)
raise ke
return rc

View File

@ -7,13 +7,13 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import dbus
import threading
# noinspection PyUnresolvedReferences
from gi.repository import GLib
from .job import Job
from . import cfg
import traceback
from .utils import log_error, mt_async_call
from .utils import log_error, mt_async_call, extract_stack_trace
class RequestEntry(object):
@ -71,13 +71,23 @@ class RequestEntry(object):
try:
result = self.method(*self.arguments)
self.register_result(result)
except SystemExit as se:
self.register_error(-1, str(se), se)
raise se
except dbus.exceptions.DBusException as dbe:
# This is an expected error path when something goes awry that
# we handled
self.register_error(-1, str(dbe), dbe)
except Exception as e:
# Use the request entry to return the result as the client may
# have gotten a job by the time we hit an error
# Lets get the stacktrace and set that to the error message
st = traceback.format_exc()
cfg.blackbox.dump()
log_error("Exception returned to client: \n%s" % st)
# Lets set the exception text as the error message and log the
# exception in the journal for figuring out what went wrong.
cfg.debug.dump()
cfg.flightrecorder.dump()
tb = extract_stack_trace(e)
log_error("While processing %s: we encountered\n%s" % (str(self.method), tb))
log_error("Error returned to client: %s" % str(e))
self.register_error(-1, str(e), e)
def is_done(self):
@ -131,7 +141,7 @@ class RequestEntry(object):
mt_async_call(self.cb_error, error_exception)
else:
# We have a job and it's complete, indicate that it's done.
# We have a job, and it's complete, indicate that it's done.
self._job.Complete = True
self._job = None

View File

@ -52,20 +52,30 @@ def filter_event(action, device):
# when appropriate.
refresh = False
# Ignore everything but change
if action != 'change':
return
if 'ID_FS_TYPE' in device:
fs_type_new = device['ID_FS_TYPE']
if 'LVM' in fs_type_new:
refresh = True
# If we get a lvm related udev event for a block device
# we don't know about, it's either a pvcreate which we
# would handle with the dbus notification or something
# copied a pv signature onto a block device, this is
# required to catch the latter.
if not cfg.om.get_object_by_lvm_id(device['DEVNAME']):
refresh = True
elif fs_type_new == '':
# Check to see if the device was one we knew about
if 'DEVNAME' in device:
found = cfg.om.get_object_by_lvm_id(device['DEVNAME'])
if found:
if cfg.om.get_object_by_lvm_id(device['DEVNAME']):
refresh = True
if 'DM_LV_NAME' in device:
refresh = True
else:
# This handles the wipefs -a path
if not refresh and 'DEVNAME' in device:
if cfg.om.get_object_by_lvm_id(device['DEVNAME']):
refresh = True
if refresh:
udev_add()

View File

@ -10,11 +10,14 @@
import xml.etree.ElementTree as Et
import sys
import inspect
import ctypes
import collections
import errno
import fcntl
import os
import stat
import string
import datetime
from fcntl import fcntl, F_GETFL, F_SETFL
import tempfile
import dbus
from lvmdbusd import cfg
@ -86,7 +89,7 @@ def init_class_from_arguments(
nt = k
# If the current attribute has a value, but the incoming does
# not, don't overwrite it. Otherwise the default values on the
# not, don't overwrite it. Otherwise, the default values on the
# property decorator don't work as expected.
cur = getattr(obj_instance, nt, v)
@ -106,7 +109,7 @@ def init_class_from_arguments(
def get_properties(f):
"""
Walks through an object instance or it's parent class(es) and determines
Walks through an object instance, or it's parent class(es) and determines
which attributes are properties and if they were created to be used for
dbus.
:param f: Object to inspect
@ -190,7 +193,7 @@ def add_properties(xml, interface, props):
interface_element = c
break
# Interface is not present, lets create it so we have something to
# Interface is not present, lets create it, so we have something to
# attach the properties too
if interface_element is None:
interface_element = Et.Element("interface", name=interface)
@ -280,25 +283,64 @@ def parse_tags(tags):
return dbus.Array([], signature='s')
def _common_log(msg, *attributes):
cfg.stdout_lock.acquire()
tid = ctypes.CDLL('libc.so.6').syscall(186)
class DebugMessages(object):
if STDOUT_TTY:
def __init__(self, size=5000):
self.queue = collections.deque(maxlen=size)
self.lock = threading.RLock()
def add(self, message):
with self.lock:
self.queue.append(message)
def dump(self):
if cfg.args and not cfg.args.debug:
with self.lock:
if len(self.queue):
log_error("LVM dbus debug messages START last (%d max) messages" % self.queue.maxlen)
for m in self.queue:
print(m)
log_error("LVM dbus debug messages END")
self.queue.clear()
def _get_tid():
try:
# Only 3.8 and later have this
return threading.get_native_id()
except:
return -1
def _format_log_entry(msg):
tid = _get_tid()
if not cfg.systemd and STDOUT_TTY:
msg = "%s: %d:%d - %s" % \
(datetime.datetime.now().strftime("%b %d %H:%M:%S.%f"),
os.getpid(), tid, msg)
else:
msg = "%d:%d - %s" % (os.getpid(), tid, msg)
if cfg.systemd:
# Systemd already puts the daemon pid in the log, we'll just add the tid
msg = "[%d]: %s" % (tid, msg)
else:
msg = "[%d:%d]: %s" % (os.getpid(), tid, msg)
return msg
def _common_log(msg, *attributes):
msg = _format_log_entry(msg)
cfg.stdout_lock.acquire()
if STDOUT_TTY and attributes:
print(color(msg, *attributes))
else:
print(msg)
cfg.stdout_lock.release()
sys.stdout.flush()
cfg.stdout_lock.release()
# Serializes access to stdout to prevent interleaved output
@ -307,12 +349,19 @@ def _common_log(msg, *attributes):
def log_debug(msg, *attributes):
if cfg.args and cfg.args.debug:
_common_log(msg, *attributes)
else:
if cfg.debug:
cfg.debug.add(_format_log_entry(msg))
def log_error(msg, *attributes):
_common_log(msg, *attributes)
def log_msg(msg, *attributes):
_common_log(msg, *attributes)
def dump_threads_stackframe():
ident_to_name = {}
@ -340,15 +389,32 @@ def dump_threads_stackframe():
# noinspection PyUnusedLocal
def handler(signum):
try:
# signal 10
if signum == signal.SIGUSR1:
cfg.debug.dump()
dump_threads_stackframe()
# signal 12
elif signum == signal.SIGUSR2:
cfg.debug.dump()
cfg.flightrecorder.dump()
else:
# If we are getting a SIGTERM, and we sent one to the lvm shell we
# will ignore this and keep running.
if signum == signal.SIGTERM and cfg.ignore_sigterm:
# Clear the flag, so we will exit on SIGTERM if we didn't
# send it.
cfg.ignore_sigterm = False
return True
# If lvm shell is in use, tell it to exit
if cfg.SHELL_IN_USE is not None:
cfg.SHELL_IN_USE.exit_shell()
cfg.run.value = 0
log_debug('Exiting daemon with signal %d' % signum)
log_error('Exiting daemon with signal %d' % signum)
if cfg.loop is not None:
cfg.loop.quit()
except:
st = traceback.format_exc()
except BaseException as be:
st = extract_stack_trace(be)
log_error("signal handler: exception (logged, not reported!) \n %s" % st)
# It's important we report that we handled the exception for the exception
@ -477,7 +543,7 @@ def round_size(size_bytes):
return size_bytes + bs - remainder
_ALLOWABLE_CH = string.ascii_letters + string.digits + '#+-.:=@_\/%'
_ALLOWABLE_CH = string.ascii_letters + string.digits + '#+-.:=@_/%'
_ALLOWABLE_CH_SET = set(_ALLOWABLE_CH)
_ALLOWABLE_VG_LV_CH = string.ascii_letters + string.digits + '.-_+'
@ -572,6 +638,23 @@ def validate_tag(interface, tag):
% (tag, _ALLOWABLE_TAG_CH))
def add_config_option(cmdline, key, value):
if 'help' in cmdline:
return cmdline
if key in cmdline:
for i, arg in enumerate(cmdline):
if arg == key:
if len(cmdline) <= i + 1:
raise dbus.exceptions.DBusException("Missing value for --config option.")
cmdline[i + 1] += " %s" % value
break
else:
cmdline.extend([key, value])
return cmdline
def add_no_notify(cmdline):
"""
Given a command line to execute we will see if `--config` is present, if it
@ -583,27 +666,18 @@ def add_no_notify(cmdline):
:rtype: list
"""
# Only after we have seen an external event will be disable lvm from sending
# Only after we have seen an external event will we disable lvm from sending
# us one when we call lvm
rv = cmdline
if cfg.got_external_event:
if 'help' in cmdline:
return cmdline
rv = add_config_option(rv, "--config", "global/notify_dbus=0")
if '--config' in cmdline:
for i, arg in enumerate(cmdline):
if arg == '--config':
if len(cmdline) <= i+1:
raise dbus.exceptions.DBusException("Missing value for --config option.")
cmdline[i+1] += " global/notify_dbus=0"
break
else:
cmdline.extend(['--config', 'global/notify_dbus=0'])
return cmdline
return rv
# The methods below which start with mt_* are used to execute the desired code
# on the the main thread of execution to alleviate any issues the dbus-python
# library with regards to multi-threaded access. Essentially, we are trying to
# on the main thread of execution to alleviate any issues the dbus-python
# library with regard to multithreaded access. Essentially, we are trying to
# ensure all dbus library interaction is done from the same thread!
@ -617,9 +691,8 @@ def _async_handler(call_back, parameters):
call_back(*parameters)
else:
call_back()
except:
st = traceback.format_exc()
log_error("mt_async_call: exception (logged, not reported!) \n %s" % st)
except BaseException as be:
log_error("mt_async_call: exception (logged, not reported!) \n %s" % extract_stack_trace(be))
# Execute the function on the main thread with the provided parameters, do
@ -669,9 +742,6 @@ class MThreadRunner(object):
self.rc = self.f()
except BaseException as be:
self.exception = be
st = traceback.format_exc()
log_error("MThreadRunner: exception \n %s" % st)
log_error("Exception will be raised in calling thread!")
def _remove_objects(dbus_objects_rm):
@ -686,8 +756,8 @@ def mt_remove_dbus_objects(objs):
# Make stream non-blocking
def make_non_block(stream):
flags = fcntl(stream, F_GETFL)
fcntl(stream, F_SETFL, flags | os.O_NONBLOCK)
flags = fcntl.fcntl(stream, fcntl.F_GETFL)
fcntl.fcntl(stream, fcntl.F_SETFL, flags | os.O_NONBLOCK)
def read_decoded(stream):
@ -695,3 +765,128 @@ def read_decoded(stream):
if tmp:
return tmp.decode("utf-8")
return ''
class LockFile(object):
"""
Simple lock file class
Based on Pg.1144 "The Linux Programming Interface" by Michael Kerrisk
"""
def __init__(self, lock_file):
self.fd = 0
self.lock_file = lock_file
def __enter__(self):
try:
os.makedirs(os.path.dirname(self.lock_file), exist_ok=True)
self.fd = os.open(self.lock_file, os.O_CREAT | os.O_RDWR, stat.S_IRUSR | stat.S_IWUSR)
# Get and set the close on exec and lock the file
flags = fcntl.fcntl(self.fd, fcntl.F_GETFD)
flags |= fcntl.FD_CLOEXEC
fcntl.fcntl(self.fd, fcntl.F_SETFL, flags)
fcntl.lockf(self.fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
except OSError as e:
if e.errno == errno.EAGAIN:
log_error("Daemon already running, exiting!")
else:
log_error("Error during creation of lock file(%s): errno(%d), exiting!" % (self.lock_file, e.errno))
sys.exit(114)
def __exit__(self, _type, _value, _traceback):
os.close(self.fd)
def extract_stack_trace(exception):
return ''.join(traceback.format_exception(None, exception, exception.__traceback__))
def lvm_column_key(key):
# Check LV
if key.startswith("lv_") or key.startswith("vg_") or key.startswith("pool_") or \
key.endswith("_percent") or key.startswith("move_") or key.startswith("vdo_") or \
key in ["origin_uuid", "segtype", "origin", "data_lv", "metadata_lv"]:
return True
# Check VG
if key.startswith("vg_") or key.startswith("lv_") or key.startswith("pv_") or \
key in ["max_lv", "max_pv", "snap_count"]:
return True
# Check PV
if key.startswith("pv") or key.startswith("vg") or (key in ['dev_size', 'pe_start']):
return True
return False
class LvmBug(RuntimeError):
"""
Things that are clearly a bug with lvm itself.
"""
def __init__(self, msg):
super().__init__(msg)
def __str__(self):
return "lvm bug encountered: %s" % ' '.join(self.args)
class LvmDebugData:
def __init__(self, do_collection):
self.fd = -1
self.fn = None
self.collect = do_collection
if self.collect:
log_msg("Collecting lvm debug data!")
def _remove_file(self):
if self.fn is not None:
os.unlink(self.fn)
self.fn = None
def _close_fd(self):
if self.fd != -1:
os.close(self.fd)
self.fd = -1
def setup(self):
# Create a secure filename
if self.collect:
self.fd, self.fn = tempfile.mkstemp(suffix=".log", prefix="lvmdbusd.lvm.debug.")
return self.fn
return None
def lvm_complete(self):
# Remove the file ASAP, so we decrease our odds of leaving it
# around if the daemon gets killed by a signal -9
self._remove_file()
def dump(self):
# Read the file and log it to log_err
if self.fd != -1:
# How big could the verbose debug get?
debug = os.read(self.fd, 1024*1024*5)
debug_txt = debug.decode("utf-8")
for line in debug_txt.split("\n"):
log_error("lvm debug >>> %s" % line)
self._close_fd()
# In case lvm_complete doesn't get called.
self._remove_file()
def complete(self):
self._close_fd()
# In case lvm_complete doesn't get called.
self._remove_file()
def get_error_msg(report_json):
# Get the error message from the returned JSON
if 'log' in report_json:
error_msg = ""
# Walk the entire log array and build an error string
for log_entry in report_json['log']:
if log_entry['log_type'] == "error":
if error_msg:
error_msg += ', ' + log_entry['log_message']
else:
error_msg = log_entry['log_message']
return error_msg
return None

View File

@ -20,7 +20,7 @@ from .request import RequestEntry
from .loader import common
from .state import State
from . import background
from .utils import round_size, mt_remove_dbus_objects
from .utils import round_size, mt_remove_dbus_objects, LvmBug, lvm_column_key
from .job import JobState
@ -31,17 +31,24 @@ def vgs_state_retrieve(selection, cache_refresh=True):
if cache_refresh:
cfg.db.refresh()
for v in cfg.db.fetch_vgs(selection):
rc.append(
VgState(
v['vg_uuid'], v['vg_name'], v['vg_fmt'], n(v['vg_size']),
n(v['vg_free']), v['vg_sysid'], n(v['vg_extent_size']),
n(v['vg_extent_count']), n(v['vg_free_count']),
v['vg_profile'], n(v['max_lv']), n(v['max_pv']),
n(v['pv_count']), n(v['lv_count']), n(v['snap_count']),
n(v['vg_seqno']), n(v['vg_mda_count']),
n(v['vg_mda_free']), n(v['vg_mda_size']),
n(v['vg_mda_used_count']), v['vg_attr'], v['vg_tags']))
try:
for v in cfg.db.fetch_vgs(selection):
rc.append(
VgState(
v['vg_uuid'], v['vg_name'], v['vg_fmt'], n(v['vg_size']),
n(v['vg_free']), v['vg_sysid'], n(v['vg_extent_size']),
n(v['vg_extent_count']), n(v['vg_free_count']),
v['vg_profile'], n(v['max_lv']), n(v['max_pv']),
n(v['pv_count']), n(v['lv_count']), n(v['snap_count']),
n(v['vg_seqno']), n(v['vg_mda_count']),
n(v['vg_mda_free']), n(v['vg_mda_size']),
n(v['vg_mda_used_count']), v['vg_attr'], v['vg_tags']))
except KeyError as ke:
# Sometimes lvm omits returning one of the keys we requested.
key = ke.args[0]
if lvm_column_key(key):
raise LvmBug("missing JSON key: '%s'" % key)
raise ke
return rc
@ -144,6 +151,7 @@ class Vg(AutomatedProperties):
_AllocNormal_meta = ('b', VG_INTERFACE)
_AllocAnywhere_meta = ('b', VG_INTERFACE)
_Clustered_meta = ('b', VG_INTERFACE)
_Shared_meta = ('b', VG_INTERFACE)
_Name_meta = ('s', VG_INTERFACE)
# noinspection PyUnusedLocal,PyPep8Naming
@ -778,6 +786,10 @@ class Vg(AutomatedProperties):
def Clustered(self):
return self._attribute(5, 'c')
@property
def Shared(self):
return self._attribute(5, 's')
class VgVdo(Vg):

View File

@ -15,61 +15,61 @@ srcdir = @srcdir@
top_srcdir = @top_srcdir@
top_builddir = @top_builddir@
USE_SD_NOTIFY=yes
SOURCES = lvmlockd-core.c
SOURCES2 = lvmlockctl.c
TARGETS = lvmlockd lvmlockctl
include $(top_builddir)/make.tmpl
ifeq ("@BUILD_LOCKDSANLOCK@", "yes")
SOURCES += lvmlockd-sanlock.c
LOCK_LIBS += -lsanlock_client
CFLAGS += $(LIBSANLOCKCLIENT_CFLAGS)
LOCK_LIBS += $(LIBSANLOCKCLIENT_LIBS)
endif
ifeq ("@BUILD_LOCKDDLM@", "yes")
SOURCES += lvmlockd-dlm.c
LOCK_LIBS += -ldlm_lt
LOCK_LIBS += -ldlmcontrol
CFLAGS += $(LIBDLM) $(LIBDLMCONTROL_CFLAGS)
# LOCK_LIBS += $(LIBDLM_LIBS) $(LIBDLMCONTROL_LIBS)
LOCK_LIBS += -ldlm_lt $(LIBDLMCONTROL_LIBS)
endif
ifeq ("@BUILD_LOCKDIDM@", "yes")
SOURCES += lvmlockd-idm.c
LOCK_LIBS += -lseagate_ilm -lblkid
LOCK_LIBS += $(LIBSEAGATEILM_LIBS) $(BLKID_LIBS)
endif
SOURCES2 = lvmlockctl.c
TARGETS = lvmlockd lvmlockctl
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 += $(DAEMON_LIBS) $(PTHREAD_LIBS)
ifeq ($(USE_SD_NOTIFY),yes)
CFLAGS += $(shell pkg-config --cflags libsystemd) -DUSE_SD_NOTIFY
LIBS += $(shell pkg-config --libs libsystemd)
ifneq (,$(firstword $(LIBSYSTEMD_LIBS)))
DEFS += -DUSE_SD_NOTIFY
CFLAGS += $(LIBSYSTEMD_CFLAGS)
LIBS += $(LIBSYSTEMD_LIBS)
endif
lvmlockd: $(OBJECTS) $(top_builddir)/libdaemon/server/libdaemonserver.a $(INTERNAL_LIBS)
@echo " [CC] $@"
$(SHOW) " [CC] $@"
$(Q) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $+ $(LOCK_LIBS) $(LIBS)
lvmlockctl: lvmlockctl.o $(INTERNAL_LIBS)
@echo " [CC] $@"
$(SHOW) " [CC] $@"
$(Q) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $+ $(LIBS)
install_lvmlockd: lvmlockd
@echo " [INSTALL] $<"
$(SHOW) " [INSTALL] $<"
$(Q) $(INSTALL_PROGRAM) -D $< $(sbindir)/$(<F)
install_lvmlockctl: lvmlockctl
@echo " [INSTALL] $<"
$(SHOW) " [INSTALL] $<"
$(Q) $(INSTALL_PROGRAM) -D $< $(sbindir)/$(<F)
install_lvm2: install_lvmlockd install_lvmlockctl

View File

@ -38,7 +38,7 @@ static int stop_lockspaces = 0;
static char *arg_vg_name = NULL;
#define DUMP_SOCKET_NAME "lvmlockd-dump.sock"
#define DUMP_BUF_SIZE (1024 * 1024)
#define DUMP_BUF_SIZE (4 * 1024 * 1024)
static char dump_buf[DUMP_BUF_SIZE+1];
static int dump_len;
static struct sockaddr_un dump_addr;
@ -264,19 +264,19 @@ static void format_info_r_action(char *line, char *r_name, char *r_type)
static void format_info_line(char *line, char *r_name, char *r_type)
{
if (!strncmp(line, "info=structs ", strlen("info=structs "))) {
if (!strncmp(line, "info=structs ", sizeof("info=structs ") - 1)) {
/* only print this in the raw info dump */
} else if (!strncmp(line, "info=client ", strlen("info=client "))) {
} else if (!strncmp(line, "info=client ", sizeof("info=client ") - 1)) {
save_client_info(line);
} else if (!strncmp(line, "info=ls ", strlen("info=ls "))) {
} else if (!strncmp(line, "info=ls ", sizeof("info=ls ") - 1)) {
format_info_ls(line);
} else if (!strncmp(line, "info=ls_action ", strlen("info=ls_action "))) {
} else if (!strncmp(line, "info=ls_action ", sizeof("info=ls_action ") - 1)) {
format_info_ls_action(line);
} else if (!strncmp(line, "info=r ", strlen("info=r "))) {
} else if (!strncmp(line, "info=r ", sizeof("info=r ") - 1)) {
/*
* r_name/r_type are reset when a new resource is found.
* They are reused for the lock and action lines that
@ -286,11 +286,11 @@ static void format_info_line(char *line, char *r_name, char *r_type)
memset(r_type, 0, MAX_NAME+1);
format_info_r(line, r_name, r_type);
} else if (!strncmp(line, "info=lk ", strlen("info=lk "))) {
} else if (!strncmp(line, "info=lk ", sizeof("info=lk ") - 1)) {
/* will use info from previous r */
format_info_lk(line, r_name, r_type);
} else if (!strncmp(line, "info=r_action ", strlen("info=r_action "))) {
} else if (!strncmp(line, "info=r_action ", sizeof("info=r_action ") - 1)) {
/* will use info from previous r */
format_info_r_action(line, r_name, r_type);
} else {
@ -940,7 +940,7 @@ static int read_options(int argc, char *argv[])
int option_index = 0;
int c;
static struct option long_options[] = {
static const struct option _long_options[] = {
{"help", no_argument, 0, 'h' },
{"quit", no_argument, 0, 'q' },
{"info", no_argument, 0, 'i' },
@ -962,7 +962,7 @@ static int read_options(int argc, char *argv[])
}
while (1) {
c = getopt_long(argc, argv, "hqidE:D:w:k:r:Se", long_options, &option_index);
c = getopt_long(argc, argv, "hqidE:D:w:k:r:Se", _long_options, &option_index);
if (c == -1)
break;

View File

@ -16,9 +16,12 @@
#define LVMLOCKD_SOCKET DEFAULT_RUN_DIR "/lvmlockd.socket"
#define LVMLOCKD_ADOPT_FILE DEFAULT_RUN_DIR "/lvmlockd.adopt"
#define LVMLOCKD_USE_SANLOCK_LVB 0
/* Wrappers to open/close connection */
static inline daemon_handle lvmlockd_open(const char *sock)
static inline __attribute__((always_inline))
daemon_handle lvmlockd_open(const char *sock)
{
daemon_info lvmlockd_info = {
.path = "lvmlockd",
@ -51,5 +54,8 @@ static inline void lvmlockd_close(daemon_handle h)
#define EREMOVED 219
#define EDEVOPEN 220 /* sanlock failed to open lvmlock LV */
#define ELMERR 221
#define EORPHAN 222
#define EADOPT_NONE 223
#define EADOPT_RETRY 224
#endif /* _LVM_LVMLOCKD_CLIENT_H */

File diff suppressed because it is too large Load Diff

View File

@ -96,7 +96,6 @@ static int check_args_version(char *vg_args)
static int read_cluster_name(char *clustername)
{
static const char close_error_msg[] = "read_cluster_name: close_error %d";
char *n;
int fd;
int rv;
@ -115,18 +114,19 @@ static int read_cluster_name(char *clustername)
rv = read(fd, clustername, MAX_ARGS);
if (rv < 0) {
log_error("read_cluster_name: cluster name read error %d, check dlm_controld", fd);
if (close(fd))
log_error(close_error_msg, fd);
return rv;
goto out;
}
clustername[rv] = 0;
n = strstr(clustername, "\n");
if (n)
*n = '\0';
rv = 0;
out:
if (close(fd))
log_error(close_error_msg, fd);
return 0;
log_error("read_cluster_name: close_error %d", fd);
return rv;
}
#define MAX_VERSION 16
@ -220,20 +220,112 @@ int lm_prepare_lockspace_dlm(struct lockspace *ls)
return 0;
}
int lm_add_lockspace_dlm(struct lockspace *ls, int adopt)
#define DLM_COMMS_PATH "/sys/kernel/config/dlm/cluster/comms"
#define LOCK_LINE_MAX 1024
static int get_local_nodeid(void)
{
struct dirent *de;
DIR *ls_dir;
char ls_comms_path[PATH_MAX] = { 0 };
char path[PATH_MAX] = { 0 };
FILE *file;
char line[LOCK_LINE_MAX];
char *str1, *str2;
int rv = -1, val;
snprintf(ls_comms_path, sizeof(ls_comms_path), "%s", DLM_COMMS_PATH);
if (!(ls_dir = opendir(ls_comms_path)))
return -ECONNREFUSED;
while ((de = readdir(ls_dir))) {
if (de->d_name[0] == '.')
continue;
snprintf(path, sizeof(path), "%s/%s/local",
DLM_COMMS_PATH, de->d_name);
if (!(file = fopen(ls_comms_path, "r")))
continue;
str1 = fgets(line, sizeof(line), file);
if (fclose(file))
log_sys_debug("fclose", path);
if (str1) {
rv = sscanf(line, "%d", &val);
if ((rv == 1) && (val == 1 )) {
snprintf(path, sizeof(path), "%s/%s/nodeid",
DLM_COMMS_PATH, de->d_name);
if (!(file = fopen(path, "r")))
continue;
str2 = fgets(line, sizeof(line), file);
if (fclose(file))
log_sys_debug("fclose", path);
if (str2) {
rv = sscanf(line, "%d", &val);
if (rv == 1) {
if (closedir(ls_dir))
log_sys_debug("closedir", ls_comms_path);
return val;
}
}
}
}
}
if (closedir(ls_dir))
log_sys_debug("closedir", ls_comms_path);
return rv;
}
int lm_purge_locks_dlm(struct lockspace *ls)
{
struct lm_dlm *lmd = (struct lm_dlm *)ls->lm_data;
int nodeid;
int rv = -1;
if (!lmd || !lmd->dh) {
log_error("purge_locks_dlm %s no dlm_handle_t error", ls->name);
goto fail;
}
nodeid = get_local_nodeid();
if (nodeid < 0) {
log_error("failed to get local nodeid");
goto fail;
}
if (dlm_ls_purge(lmd->dh, nodeid, 0)) {
log_error("purge_locks_dlm %s error", ls->name);
goto fail;
}
rv = 0;
fail:
return rv;
}
int lm_add_lockspace_dlm(struct lockspace *ls, int adopt_only, int adopt_ok)
{
struct lm_dlm *lmd = (struct lm_dlm *)ls->lm_data;
if (daemon_test)
return 0;
if (adopt)
if (adopt_only || adopt_ok) {
lmd->dh = dlm_open_lockspace(ls->name);
else
if (!lmd->dh && adopt_ok)
lmd->dh = dlm_new_lockspace(ls->name, 0600, DLM_LSFL_NEWEXCL);
if (!lmd->dh)
log_error("add_lockspace_dlm adopt_only %d adopt_ok %d %s error",
adopt_only, adopt_ok, ls->name);
} else {
lmd->dh = dlm_new_lockspace(ls->name, 0600, DLM_LSFL_NEWEXCL);
if (!lmd->dh)
log_error("add_lockspace_dlm %s error", ls->name);
}
if (!lmd->dh) {
log_error("add_lockspace_dlm %s adopt %d error", ls->name, adopt);
free(lmd);
ls->lm_data = NULL;
return -1;
@ -301,7 +393,7 @@ static int lm_add_resource_dlm(struct lockspace *ls, struct resource *r, int wit
r->name, strlen(r->name),
0, NULL, NULL, NULL);
if (rv < 0) {
log_error("S %s R %s add_resource_dlm lock error %d", ls->name, r->name, rv);
log_error("%s:%s add_resource_dlm lock error %d", ls->name, r->name, rv);
return rv;
}
out:
@ -325,7 +417,7 @@ int lm_rem_resource_dlm(struct lockspace *ls, struct resource *r)
rv = dlm_ls_unlock_wait(lmd->dh, lksb->sb_lkid, 0, lksb);
if (rv < 0) {
log_error("S %s R %s rem_resource_dlm unlock error %d", ls->name, r->name, rv);
log_error("%s:%s rem_resource_dlm unlock error %d", ls->name, r->name, rv);
}
out:
free(rdd->vb);
@ -380,7 +472,7 @@ static int lm_adopt_dlm(struct lockspace *ls, struct resource *r, int ld_mode,
goto fail;
}
log_debug("S %s R %s adopt_dlm", ls->name, r->name);
log_debug("%s:%s adopt_dlm", ls->name, r->name);
if (daemon_test)
return 0;
@ -389,29 +481,29 @@ static int lm_adopt_dlm(struct lockspace *ls, struct resource *r, int ld_mode,
* dlm returns 0 for success, -EAGAIN if an orphan is
* found with another mode, and -ENOENT if no orphan.
*
* cast/bast/param are (void *)1 because the kernel
* cast/bast/param are (void (*)(void*))1 because the kernel
* returns errors if some are null.
*/
rv = dlm_ls_lockx(lmd->dh, mode, lksb, flags,
r->name, strlen(r->name), 0,
(void *)1, (void *)1, (void *)1,
(void (*)(void*))1, (void (*)(void*))1, (void (*)(void*))1,
NULL, NULL);
if (rv == -1 && (errno == EAGAIN)) {
log_debug("S %s R %s adopt_dlm adopt mode %d try other mode",
log_debug("%s:%s adopt_dlm adopt mode %d try other mode",
ls->name, r->name, ld_mode);
rv = -EUCLEAN;
rv = -EADOPT_RETRY;
goto fail;
}
if (rv == -1 && (errno == ENOENT)) {
log_debug("S %s R %s adopt_dlm adopt mode %d no lock",
log_debug("%s:%s adopt_dlm adopt mode %d no lock",
ls->name, r->name, ld_mode);
rv = -ENOENT;
rv = -EADOPT_NONE;
goto fail;
}
if (rv < 0) {
log_debug("S %s R %s adopt_dlm mode %d flags %x error %d errno %d",
log_debug("%s:%s adopt_dlm mode %d flags %x error %d errno %d",
ls->name, r->name, mode, flags, rv, errno);
goto fail;
}
@ -441,7 +533,7 @@ static int lm_adopt_dlm(struct lockspace *ls, struct resource *r, int ld_mode,
*/
int lm_lock_dlm(struct lockspace *ls, struct resource *r, int ld_mode,
struct val_blk *vb_out, int adopt)
struct val_blk *vb_out, int adopt_only, int adopt_ok)
{
struct lm_dlm *lmd = (struct lm_dlm *)ls->lm_data;
struct rd_dlm *rdd = (struct rd_dlm *)r->lm_data;
@ -451,7 +543,13 @@ int lm_lock_dlm(struct lockspace *ls, struct resource *r, int ld_mode,
int mode;
int rv;
if (adopt) {
if (adopt_ok) {
log_debug("%s:%s lock_dlm adopt_ok not supported", ls->name, r->name);
return -1;
}
if (adopt_only) {
log_debug("%s:%s lock_dlm adopt_only", ls->name, r->name);
/* When adopting, we don't follow the normal method
of acquiring a NL lock then converting it to the
desired mode. */
@ -480,7 +578,7 @@ int lm_lock_dlm(struct lockspace *ls, struct resource *r, int ld_mode,
return -EINVAL;
}
log_debug("S %s R %s lock_dlm", ls->name, r->name);
log_debug("%s:%s lock_dlm", ls->name, r->name);
if (daemon_test) {
if (rdd->vb) {
@ -500,7 +598,7 @@ int lm_lock_dlm(struct lockspace *ls, struct resource *r, int ld_mode,
r->name, strlen(r->name),
0, NULL, NULL, NULL);
if (rv == -1) {
log_debug("S %s R %s lock_dlm acquire mode PR for %d rv %d",
log_debug("%s:%s lock_dlm acquire mode PR for %d rv %d",
ls->name, r->name, mode, rv);
goto lockrv;
}
@ -513,17 +611,17 @@ int lm_lock_dlm(struct lockspace *ls, struct resource *r, int ld_mode,
0, NULL, NULL, NULL);
lockrv:
if (rv == -1 && errno == EAGAIN) {
log_debug("S %s R %s lock_dlm acquire mode %d rv EAGAIN", ls->name, r->name, mode);
log_debug("%s:%s lock_dlm acquire mode %d rv EAGAIN", ls->name, r->name, mode);
return -EAGAIN;
}
if (rv < 0) {
log_error("S %s R %s lock_dlm acquire error %d errno %d", ls->name, r->name, rv, errno);
log_error("%s:%s lock_dlm acquire error %d errno %d", ls->name, r->name, rv, errno);
return -ELMERR;
}
if (rdd->vb) {
if (lksb->sb_flags & DLM_SBF_VALNOTVALID) {
log_debug("S %s R %s lock_dlm VALNOTVALID", ls->name, r->name);
log_debug("%s:%s lock_dlm VALNOTVALID", ls->name, r->name);
memset(rdd->vb, 0, sizeof(struct val_blk));
memset(vb_out, 0, sizeof(struct val_blk));
goto out;
@ -552,11 +650,11 @@ int lm_convert_dlm(struct lockspace *ls, struct resource *r,
struct lm_dlm *lmd = (struct lm_dlm *)ls->lm_data;
struct rd_dlm *rdd = (struct rd_dlm *)r->lm_data;
struct dlm_lksb *lksb = &rdd->lksb;
uint32_t mode;
int mode;
uint32_t flags = 0;
int rv;
log_debug("S %s R %s convert_dlm", ls->name, r->name);
log_debug("%s:%s convert_dlm", ls->name, r->name);
flags |= LKF_CONVERT;
flags |= LKF_NOQUEUE;
@ -570,14 +668,16 @@ int lm_convert_dlm(struct lockspace *ls, struct resource *r,
rdd->vb->r_version = cpu_to_le32(r_version);
memcpy(lksb->sb_lvbptr, rdd->vb, sizeof(struct val_blk));
log_debug("S %s R %s convert_dlm set r_version %u",
log_debug("%s:%s convert_dlm set r_version %u",
ls->name, r->name, r_version);
flags |= LKF_VALBLK;
}
mode = to_dlm_mode(ld_mode);
if ((mode = to_dlm_mode(ld_mode)) < 0) {
log_error("lm_convert_dlm invalid mode %d", ld_mode);
return -EINVAL;
}
if (daemon_test)
return 0;
@ -586,11 +686,11 @@ int lm_convert_dlm(struct lockspace *ls, struct resource *r,
0, NULL, NULL, NULL);
if (rv == -1 && errno == EAGAIN) {
/* FIXME: When does this happen? Should something different be done? */
log_error("S %s R %s convert_dlm mode %d rv EAGAIN", ls->name, r->name, mode);
log_error("%s:%s convert_dlm mode %d rv EAGAIN", ls->name, r->name, mode);
return -EAGAIN;
}
if (rv < 0) {
log_error("S %s R %s convert_dlm error %d", ls->name, r->name, rv);
log_error("%s:%s convert_dlm error %d", ls->name, r->name, rv);
rv = -ELMERR;
}
return rv;
@ -640,7 +740,7 @@ int lm_unlock_dlm(struct lockspace *ls, struct resource *r,
memcpy(rdd->vb, &vb_next, sizeof(struct val_blk));
memcpy(lksb->sb_lvbptr, &vb_next, sizeof(struct val_blk));
log_debug("S %s R %s unlock_dlm vb old %x %x %u new %x %x %u",
log_debug("%s:%s unlock_dlm vb old %x %x %u new %x %x %u",
ls->name, r->name,
le16_to_cpu(vb_prev.version),
le16_to_cpu(vb_prev.flags),
@ -649,12 +749,12 @@ int lm_unlock_dlm(struct lockspace *ls, struct resource *r,
le16_to_cpu(vb_next.flags),
le32_to_cpu(vb_next.r_version));
} else {
log_debug("S %s R %s unlock_dlm vb unchanged", ls->name, r->name);
log_debug("%s:%s unlock_dlm vb unchanged", ls->name, r->name);
}
flags |= LKF_VALBLK;
} else {
log_debug("S %s R %s unlock_dlm", ls->name, r->name);
log_debug("%s:%s unlock_dlm", ls->name, r->name);
}
if (daemon_test)
@ -664,7 +764,7 @@ int lm_unlock_dlm(struct lockspace *ls, struct resource *r,
r->name, strlen(r->name),
0, NULL, NULL, NULL);
if (rv < 0) {
log_error("S %s R %s unlock_dlm error %d", ls->name, r->name, rv);
log_error("%s:%s unlock_dlm error %d", ls->name, r->name, rv);
rv = -ELMERR;
}
@ -699,7 +799,6 @@ int lm_unlock_dlm(struct lockspace *ls, struct resource *r,
int lm_hosts_dlm(struct lockspace *ls, int notify)
{
static const char closedir_err_msg[] = "lm_hosts_dlm: closedir failed";
char ls_nodes_path[PATH_MAX];
struct dirent *de;
DIR *ls_dir;
@ -722,7 +821,7 @@ int lm_hosts_dlm(struct lockspace *ls, int notify)
}
if (closedir(ls_dir))
log_error(closedir_err_msg);
log_error("lm_hosts_dlm: closedir failed");
if (!count) {
log_error("lm_hosts_dlm found no nodes in %s", ls_nodes_path);
@ -739,10 +838,10 @@ int lm_hosts_dlm(struct lockspace *ls, int notify)
int lm_get_lockspaces_dlm(struct list_head *ls_rejoin)
{
static const char closedir_err_msg[] = "lm_get_lockspace_dlm: closedir failed";
struct lockspace *ls;
struct dirent *de;
DIR *ls_dir;
int ret = 0;
if (!(ls_dir = opendir(DLM_LOCKSPACES_PATH)))
return -ECONNREFUSED;
@ -755,20 +854,20 @@ int lm_get_lockspaces_dlm(struct list_head *ls_rejoin)
continue;
if (!(ls = alloc_lockspace())) {
if (closedir(ls_dir))
log_error(closedir_err_msg);
return -ENOMEM;
ret = -ENOMEM;
goto out;
}
ls->lm_type = LD_LM_DLM;
strncpy(ls->name, de->d_name, MAX_NAME);
strncpy(ls->vg_name, ls->name + strlen(LVM_LS_PREFIX), MAX_NAME);
dm_strncpy(ls->name, de->d_name, sizeof(ls->name));
dm_strncpy(ls->vg_name, ls->name + strlen(LVM_LS_PREFIX), sizeof(ls->vg_name));
list_add_tail(&ls->list, ls_rejoin);
}
out:
if (closedir(ls_dir))
log_error(closedir_err_msg);
return 0;
log_error("lm_get_lockspace_dlm: closedir failed");
return ret;
}
int lm_is_running_dlm(void)
@ -798,7 +897,7 @@ int lm_refresh_lv_start_dlm(struct action *act)
int rv;
/* split /dev/vgname/lvname into vgname and lvname strings */
strncpy(path, act->path, PATH_MAX-1);
dm_strncpy(path, act->path, sizeof(path));
/* skip past dev */
if (!(p = strchr(path + 1, '/')))

View File

@ -136,7 +136,7 @@ static int lm_idm_scsi_directory_select(const struct dirent *s)
return 0;
}
static int lm_idm_scsi_find_block_dirctory(const char *block_path)
static int lm_idm_scsi_find_block_directory(const char *block_path)
{
struct stat stats;
@ -252,7 +252,7 @@ static char *lm_idm_scsi_get_block_device_node(const char *scsi_path)
goto fail;
}
ret = lm_idm_scsi_find_block_dirctory(blk_path);
ret = lm_idm_scsi_find_block_directory(blk_path);
if (ret < 0) {
log_error("Fail to find block path %s", blk_path);
goto fail;
@ -364,7 +364,7 @@ static void lm_idm_update_vb_timestamp(uint64_t *vb_timestamp)
/*
* It's possible that the multiple nodes have no clock
* synchronization with microsecond prcision and the time
* synchronization with microsecond precision and the time
* is going backward. For this case, simply increment the
* existing timestamp and write out to drive.
*/
@ -391,7 +391,7 @@ int lm_prepare_lockspace_idm(struct lockspace *ls)
return 0;
}
int lm_add_lockspace_idm(struct lockspace *ls, int adopt)
int lm_add_lockspace_idm(struct lockspace *ls, int adopt_only, int adopt_ok)
{
char killpath[IDM_FAILURE_PATH_LEN];
char killargs[IDM_FAILURE_ARGS_LEN];
@ -530,7 +530,7 @@ static int to_idm_mode(int ld_mode)
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 adopt_only, int adopt_ok)
{
struct lm_idm *lmi = (struct lm_idm *)ls->lm_data;
struct rd_idm *rdi = (struct rd_idm *)r->lm_data;

View File

@ -107,11 +107,12 @@ struct client {
#define LD_AF_SEARCH_LS 0x00000200
#define LD_AF_WAIT_STARTING 0x00001000
#define LD_AF_DUP_GL_LS 0x00002000
#define LD_AF_ADOPT 0x00010000
#define LD_AF_ADOPT 0x00010000 /* adopt ok but not required */
#define LD_AF_WARN_GL_REMOVED 0x00020000
#define LD_AF_LV_LOCK 0x00040000
#define LD_AF_LV_UNLOCK 0x00080000
#define LD_AF_SH_EXISTS 0x00100000
#define LD_AF_ADOPT_ONLY 0x00200000 /* adopt orphan or fail */
/*
* Number of times to repeat a lock request after
@ -131,6 +132,7 @@ struct action {
uint32_t flags; /* LD_AF_ */
uint32_t version;
uint64_t host_id;
uint64_t lv_size_bytes;
int8_t op; /* operation type LD_OP_ */
int8_t rt; /* resource type LD_RT_ */
int8_t mode; /* lock mode LD_LK_ */
@ -139,6 +141,7 @@ struct action {
int max_retries;
int result;
int lm_rv; /* return value from lm_ function */
int align_mb;
char *path;
char vg_uuid[64];
char vg_name[MAX_NAME+1];
@ -190,8 +193,6 @@ struct lockspace {
void *lm_data;
uint64_t host_id;
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 */
@ -363,6 +364,8 @@ void log_level(int level, const char *fmt, ...) __attribute__((format(printf, 2
#define log_debug(fmt, args...) log_level(LOG_DEBUG, fmt, ##args)
#define log_error(fmt, args...) log_level(LOG_ERR, fmt, ##args)
#define log_warn(fmt, args...) log_level(LOG_WARNING, fmt, ##args)
#define log_sys_debug(x, y) \
log_debug("%s: %s failed: %s", y, x, strerror(errno))
struct lockspace *alloc_lockspace(void);
int lockspaces_empty(void);
@ -391,10 +394,11 @@ static inline const char *mode_str(int x)
int lm_init_vg_dlm(char *ls_name, char *vg_name, uint32_t flags, char *vg_args);
int lm_prepare_lockspace_dlm(struct lockspace *ls);
int lm_add_lockspace_dlm(struct lockspace *ls, int adopt);
int lm_add_lockspace_dlm(struct lockspace *ls, int adopt_only, int adopt_ok);
int lm_purge_locks_dlm(struct lockspace *ls);
int lm_rem_lockspace_dlm(struct lockspace *ls, int free_vg);
int lm_lock_dlm(struct lockspace *ls, struct resource *r, int ld_mode,
struct val_blk *vb_out, int adopt);
struct val_blk *vb_out, int adopt_only, int adopt_ok);
int lm_convert_dlm(struct lockspace *ls, struct resource *r,
int ld_mode, uint32_t r_version);
int lm_unlock_dlm(struct lockspace *ls, struct resource *r,
@ -424,7 +428,12 @@ static inline int lm_prepare_lockspace_dlm(struct lockspace *ls)
return -1;
}
static inline int lm_add_lockspace_dlm(struct lockspace *ls, int adopt)
static inline int lm_add_lockspace_dlm(struct lockspace *ls, int adopt_only, int adopt_ok)
{
return -1;
}
static inline int lm_purge_locks_dlm(struct lockspace *ls)
{
return -1;
}
@ -435,7 +444,7 @@ static inline int lm_rem_lockspace_dlm(struct lockspace *ls, int free_vg)
}
static inline int lm_lock_dlm(struct lockspace *ls, struct resource *r, int ld_mode,
struct val_blk *vb_out, int adopt)
struct val_blk *vb_out, int adopt_only, int adopt_ok)
{
return -1;
}
@ -496,15 +505,16 @@ static inline int lm_refresh_lv_check_dlm(struct action *act)
#ifdef LOCKDSANLOCK_SUPPORT
int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_args);
int lm_init_lv_sanlock(char *ls_name, char *vg_name, char *lv_name, char *vg_args, char *lv_args, int sector_size, int align_size, uint64_t free_offset);
int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_args, int opt_align_mb);
int lm_init_lv_sanlock(struct lockspace *ls, char *lv_name, char *vg_args, char *lv_args);
int lm_free_lv_sanlock(struct lockspace *ls, struct resource *r);
int lm_rename_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_args);
int lm_prepare_lockspace_sanlock(struct lockspace *ls);
int lm_add_lockspace_sanlock(struct lockspace *ls, int adopt);
int lm_add_lockspace_sanlock(struct lockspace *ls, int adopt_only, int adopt_ok);
int lm_rem_lockspace_sanlock(struct lockspace *ls, int free_vg);
int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode,
struct val_blk *vb_out, int *retry, int adopt);
struct val_blk *vb_out, int *retry,
int adopt_only, int adopt_ok);
int lm_convert_sanlock(struct lockspace *ls, struct resource *r,
int ld_mode, uint32_t r_version);
int lm_unlock_sanlock(struct lockspace *ls, struct resource *r,
@ -517,7 +527,7 @@ int lm_gl_is_enabled(struct lockspace *ls);
int lm_get_lockspaces_sanlock(struct list_head *ls_rejoin);
int lm_data_size_sanlock(void);
int lm_is_running_sanlock(void);
int lm_find_free_lock_sanlock(struct lockspace *ls, uint64_t *free_offset, int *sector_size, int *align_size);
int lm_find_free_lock_sanlock(struct lockspace *ls, uint64_t lv_size_bytes);
static inline int lm_support_sanlock(void)
{
@ -526,12 +536,12 @@ static inline int lm_support_sanlock(void)
#else
static inline int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_args)
static inline int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_args, int opt_align_mb)
{
return -1;
}
static inline int lm_init_lv_sanlock(char *ls_name, char *vg_name, char *lv_name, char *vg_args, char *lv_args, int sector_size, int align_size, uint64_t free_offset)
static inline int lm_init_lv_sanlock(struct lockspace *ls, char *lv_name, char *vg_args, char *lv_args)
{
return -1;
}
@ -551,7 +561,7 @@ static inline int lm_prepare_lockspace_sanlock(struct lockspace *ls)
return -1;
}
static inline int lm_add_lockspace_sanlock(struct lockspace *ls, int adopt)
static inline int lm_add_lockspace_sanlock(struct lockspace *ls, int adopt_only, int adopt_ok)
{
return -1;
}
@ -562,7 +572,8 @@ static inline int lm_rem_lockspace_sanlock(struct lockspace *ls, int free_vg)
}
static inline int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode,
struct val_blk *vb_out, int *retry, int adopt)
struct val_blk *vb_out, int *retry,
int adopt_only, int adopt_ok)
{
return -1;
}
@ -619,7 +630,7 @@ static inline int lm_is_running_sanlock(void)
return 0;
}
static inline int lm_find_free_lock_sanlock(struct lockspace *ls, uint64_t *free_offset, int *sector_size, int *align_size)
static inline int lm_find_free_lock_sanlock(struct lockspace *ls, uint64_t lv_size_bytes);
{
return -1;
}
@ -636,11 +647,11 @@ static inline int lm_support_sanlock(void)
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_add_lockspace_idm(struct lockspace *ls, int adopt_only, int adopt_ok);
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 adopt_only, int adopt_ok);
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,
@ -673,7 +684,7 @@ static inline int lm_prepare_lockspace_idm(struct lockspace *ls)
return -1;
}
static inline int lm_add_lockspace_idm(struct lockspace *ls, int adopt)
static inline int lm_add_lockspace_idm(struct lockspace *ls, int adopt_only, int adopt_ok)
{
return -1;
}
@ -685,7 +696,7 @@ static inline int lm_rem_lockspace_idm(struct lockspace *ls, int free_vg)
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)
int adopt_only, int adopt_ok)
{
return -1;
}

File diff suppressed because it is too large Load Diff

View File

@ -32,11 +32,11 @@ LDFLAGS += $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS)
LIBS += $(DAEMON_LIBS) $(PTHREAD_LIBS)
lvmpolld: $(OBJECTS) $(top_builddir)/libdaemon/server/libdaemonserver.a $(INTERNAL_LIBS)
@echo " [CC] $@"
$(SHOW) " [CC] $@"
$(Q) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $+ $(LIBS)
install_lvmpolld: lvmpolld
@echo " [INSTALL] $<"
$(SHOW) " [INSTALL] $<"
$(Q) $(INSTALL_PROGRAM) -D $< $(sbindir)/$(<F)
install_lvm2: install_lvmpolld

View File

@ -19,7 +19,7 @@
#define MIN_ARGV_SIZE 8
static const char *const polling_ops[] = {
static const char *const _polling_ops[] = {
[PVMOVE] = LVMPD_REQ_PVMOVE,
[CONVERT] = LVMPD_REQ_CONVERT,
[MERGE] = LVMPD_REQ_MERGE,
@ -28,7 +28,7 @@ static const char *const polling_ops[] = {
const char *polling_op(enum poll_type type)
{
return type < POLL_TYPE_MAX ? polling_ops[type] : "<undefined>";
return type < POLL_TYPE_MAX ? _polling_ops[type] : "<undefined>";
}
static int add_to_cmd_arr(const char ***cmdargv, const char *str, unsigned *ind)
@ -81,7 +81,7 @@ const char **cmdargv_ctr(const struct lvmpolld_lv *pdlv, const char *lvm_binary,
/* one of: "convert", "pvmove", "merge", "merge_thin" */
if (!add_to_cmd_arr(&cmd_argv, "--polloperation", &i) ||
!add_to_cmd_arr(&cmd_argv, polling_ops[pdlv->type], &i))
!add_to_cmd_arr(&cmd_argv, _polling_ops[pdlv->type], &i))
goto err;
/* vg/lv name */

View File

@ -52,7 +52,7 @@ static pthread_key_t key;
static const char *_strerror_r(int errnum, struct lvmpolld_thread_data *data)
{
#ifdef _GNU_SOURCE
#if defined(_GNU_SOURCE) && defined(STRERROR_R_CHAR_P)
return strerror_r(errnum, data->buf, sizeof(data->buf)); /* never returns NULL */
#elif (_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600)
return strerror_r(errnum, data->buf, sizeof(data->buf)) ? "" : data->buf;
@ -75,7 +75,7 @@ static void _usage(const char *prog, FILE *file)
" -p|--pidfile Set path to the pidfile\n"
" -s|--socket Set path to the communication socket\n"
" -B|--binary Path to lvm2 binary\n"
" -t|--timeout Time to wait in seconds before shutdown on idle (missing or 0 = inifinite)\n\n", prog, prog);
" -t|--timeout Time to wait in seconds before shutdown on idle (missing or 0 = infinite)\n\n", prog, prog);
}
static int _init(struct daemon_state *s)
@ -781,7 +781,7 @@ struct log_line_baton {
const char *prefix;
};
daemon_handle _lvmpolld = { .error = 0 };
static daemon_handle _lvmpolld = { .error = 0 };
static daemon_handle _lvmpolld_open(const char *socket)
{
@ -867,14 +867,14 @@ enum action_index {
ACTION_MAX /* keep at the end */
};
static const action_fn_t actions[ACTION_MAX] = { [ACTION_DUMP] = action_dump };
static int _make_action(enum action_index idx, void *args)
{
return idx < ACTION_MAX ? actions[idx](args) : 0;
static const action_fn_t _actions[ACTION_MAX] = { [ACTION_DUMP] = action_dump };
return idx < ACTION_MAX ? _actions[idx](args) : 0;
}
static int _lvmpolld_client(const char *socket, unsigned action)
static int _lvmpolld_client(const char *socket, enum action_index action)
{
int r;
@ -892,10 +892,9 @@ static int _lvmpolld_client(const char *socket, unsigned action)
return r ? EXIT_SUCCESS : EXIT_FAILURE;
}
static int action_idx = ACTION_MAX;
static struct option long_options[] = {
static const struct option _long_options[] = {
/* Have actions always at the beginning of the array. */
{"dump", no_argument, &action_idx, ACTION_DUMP }, /* or an option_index ? */
{"dump", no_argument, 0, ACTION_DUMP }, /* or an option_index ? */
/* other options */
{"binary", required_argument, 0, 'B' },
@ -914,7 +913,7 @@ int main(int argc, char *argv[])
int opt;
int option_index = 0;
int client = 0, server = 0;
unsigned action = ACTION_MAX;
enum action_index action = ACTION_MAX;
struct timespec timeout;
daemon_idle di = { .ptimeout = &timeout };
struct lvmpolld_state ls = { .log_config = "" };
@ -930,16 +929,16 @@ int main(int argc, char *argv[])
.socket_path = getenv("LVM_LVMPOLLD_SOCKET") ?: LVMPOLLD_SOCKET,
};
while ((opt = getopt_long(argc, argv, "fhVl:p:s:B:t:", long_options, &option_index)) != -1) {
while ((opt = getopt_long(argc, argv, "fhVl:p:s:B:t:", _long_options, &option_index)) != -1) {
switch (opt) {
case 0 :
if (action < ACTION_MAX) {
if (action != ACTION_MAX) {
fprintf(stderr, "Can't perform more actions. Action already requested: %s\n",
long_options[action].name);
_long_options[action].name);
_usage(argv[0], stderr);
exit(EXIT_FAILURE);
}
action = action_idx;
action = ACTION_DUMP;
client = 1;
break;
case '?':

View File

@ -273,12 +273,12 @@ static void _pdlv_locked_dump(struct buffer *buff, const struct lvmpolld_lv *pdl
buffer_append(buff, tmp);
if (dm_snprintf(tmp, sizeof(tmp), "\t\tpolling_finished=%d\n", pdlv->polling_finished) > 0)
buffer_append(buff, tmp);
if (dm_snprintf(tmp, sizeof(tmp), "\t\terror_occured=%d\n", pdlv->error) > 0)
if (dm_snprintf(tmp, sizeof(tmp), "\t\terror_occurred=%d\n", pdlv->error) > 0)
buffer_append(buff, tmp);
if (dm_snprintf(tmp, sizeof(tmp), "\t\tinit_requests_count=%d\n", pdlv->init_rq_count) > 0)
buffer_append(buff, tmp);
/* lvm_commmand-section { */
/* lvm_command-section { */
buffer_append(buff, "\t\tlvm_command {\n");
if (cmd_state->retcode == -1 && !cmd_state->signal)
buffer_append(buff, "\t\t\tstate=\"" LVMPD_RESP_IN_PROGRESS "\"\n");
@ -290,7 +290,7 @@ static void _pdlv_locked_dump(struct buffer *buff, const struct lvmpolld_lv *pdl
buffer_append(buff, tmp);
}
buffer_append(buff, "\t\t}\n");
/* } lvm_commmand-section */
/* } lvm_command-section */
buffer_append(buff, "\t}\n");
/* } pdlv-section */

View File

@ -45,18 +45,18 @@ struct lvmpolld_lv {
* accessing following vars doesn't
* require struct lvmpolld_lv lock
*/
struct lvmpolld_state *const ls;
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;
const char *const lvm_system_dir_env;
struct lvmpolld_store *const pdst;
const char *const *cmdargv;
const char *const *cmdenvp;
struct lvmpolld_state *ls;
enum poll_type type;
const char *lvid;
const char *lvmpolld_id;
const char *devicesfile;
const char *lvname; /* full vg/lv name */
unsigned pdtimeout; /* in seconds */
const char *sinterval;
const char *lvm_system_dir_env;
struct lvmpolld_store *pdst;
const char **cmdargv;
const char **cmdenvp;
/* only used by write */
pid_t cmd_pid;
@ -66,9 +66,9 @@ struct lvmpolld_lv {
/* block of shared variables protected by lock */
struct lvmpolld_cmd_stat cmd_state;
unsigned init_rq_count; /* for debuging purposes only */
unsigned init_rq_count; /* for debugging purposes only */
unsigned polling_finished:1; /* no more updates */
unsigned error:1; /* unrecoverable error occured in lvmpolld */
unsigned error:1; /* unrecoverable error occurred in lvmpolld */
};
typedef void (*lvmpolld_parse_output_fn_t) (struct lvmpolld_lv *pdlv, const char *line);

View File

@ -45,7 +45,7 @@
#define LVMPD_RESP_OK "OK"
#define LVMPD_REAS_RETCODE "retcode" /* lvm cmd ret code */
#define LVMPD_REAS_SIGNAL "signal" /* lvm cmd terminating singal */
#define LVMPD_REAS_SIGNAL "signal" /* lvm cmd terminating signal */
#define LVMPD_RET_DUP_FAILED 100
#define LVMPD_RET_EXC_FAILED 101

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018 Red Hat, Inc. All rights reserved.
# Copyright (C) 2018 - 2022 Red Hat, Inc. All rights reserved.
#
# This file is part of the device-mapper userspace tools.
#
@ -29,6 +29,7 @@ DEVICE_MAPPER_SOURCE=\
device_mapper/regex/parse_rx.c \
device_mapper/regex/ttree.c \
device_mapper/vdo/status.c \
device_mapper/vdo/vdo_reader.c \
device_mapper/vdo/vdo_target.c
DEVICE_MAPPER_TARGET = device_mapper/libdevice-mapper.a
@ -43,10 +44,10 @@ CLEAN_TARGETS += $(DEVICE_MAPPER_DEPENDS) $(DEVICE_MAPPER_OBJECTS) \
#$(DEVICE_MAPPER_OBJECTS): INCLUDES+=$(VDO_INCLUDES)
$(DEVICE_MAPPER_TARGET): $(DEVICE_MAPPER_OBJECTS)
@echo " [AR] $@"
$(SHOW) " [AR] $@"
$(Q) $(RM) $@
$(Q) $(AR) rsv $@ $(DEVICE_MAPPER_OBJECTS) > /dev/null
ifeq ("$(DEPENDS)","yes")
ifeq ("$(USE_TRACKING)","yes")
-include $(DEVICE_MAPPER_DEPENDS)
endif

View File

@ -173,6 +173,15 @@ struct dm_names {
char name[];
};
struct dm_active_device {
struct dm_list list;
dev_t devno;
const char *name; /* device name */
uint32_t event_nr; /* valid when DM_DEVICE_LIST_HAS_EVENT_NR is set */
const 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];
@ -210,6 +219,18 @@ 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);
/* 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);
@ -283,15 +304,15 @@ int dm_task_add_target(struct dm_task *dmt,
#define DM_FORMAT_DEV_BUFSIZE 13 /* Minimum bufsize to handle worst case. */
int dm_format_dev(char *buf, int bufsize, uint32_t dev_major, uint32_t dev_minor);
/* Use this to retrive target information returned from a STATUS call */
/* Use this to retrieve target information returned from a STATUS call */
void *dm_get_next_target(struct dm_task *dmt,
void *next, uint64_t *start, uint64_t *length,
char **target_type, char **params);
/*
* Following dm_get_status_* functions will allocate approriate status structure
* Following dm_get_status_* functions will allocate appropriate status structure
* from passed mempool together with the necessary character arrays.
* Destroying the mempool will release all asociated allocation.
* Destroying the mempool will release all associated allocation.
*/
/* Parse params from STATUS call for mirror target */
@ -520,7 +541,7 @@ const char *dm_sysfs_dir(void);
/*
* Configure default UUID prefix string.
* Conventionally this is a short capitalised prefix indicating the subsystem
* Conventionally this is a short capitalized prefix indicating the subsystem
* that is managing the devices, e.g. "LVM-" or "MPATH-".
* To support stacks of devices from different subsystems, recursive functions
* stop recursing if they reach a device with a different prefix.
@ -563,7 +584,7 @@ int dm_device_has_mounted_fs(uint32_t major, uint32_t minor);
/*
* Callback is invoked for individal mountinfo lines,
* Callback is invoked for individual mountinfo lines,
* minor, major and mount target are parsed and unmangled.
*/
typedef int (*dm_mountinfo_line_callback_fn) (char *line, unsigned maj, unsigned min,
@ -677,7 +698,7 @@ void *dm_tree_node_get_context(const struct dm_tree_node *node);
/*
* Returns 0 when node size and its children is unchanged.
* Returns 1 when node or any of its children has increased size.
* Rerurns -1 when node or any of its children has reduced size.
* Returns -1 when node or any of its children has reduced size.
*/
int dm_tree_node_size_changed(const struct dm_tree_node *dnode);
@ -864,7 +885,7 @@ struct dm_tree_node_raid_params {
};
/*
* Version 2 of above node raid params struct to keeep API compatibility.
* Version 2 of above node raid params struct to keep API compatibility.
*
* Extended for more than 64 legs (max 253 in the MD kernel runtime!),
* delta_disks for disk add/remove reshaping,
@ -887,7 +908,7 @@ struct dm_tree_node_raid_params_v2 {
* 'rebuilds' and 'writemostly' are bitfields that signify
* which devices in the array are to be rebuilt or marked
* writemostly. The kernel supports up to 253 legs.
* We limit ourselvs by choosing a lower value
* We limit ourselves by choosing a lower value
* for DEFAULT_RAID_MAX_IMAGES.
*/
uint64_t rebuilds[RAID_BITMAP_SIZE];
@ -924,7 +945,7 @@ struct dm_config_node;
*
* policy_settings {
* migration_threshold=2048
* sequention_threashold=100
* sequential_threshold=100
* ...
* }
*
@ -953,7 +974,9 @@ struct writecache_settings {
uint32_t fua;
uint32_t nofua;
uint32_t cleaner;
uint32_t max_age;
uint32_t max_age; /* in milliseconds */
uint32_t metadata_only;
uint32_t pause_writeback; /* in milliseconds */
/*
* Allow an unrecognized key and its val to be passed to the kernel for
@ -975,6 +998,8 @@ struct writecache_settings {
unsigned nofua_set:1;
unsigned cleaner_set:1;
unsigned max_age_set:1;
unsigned metadata_only_set:1;
unsigned pause_writeback_set:1;
};
int dm_tree_node_add_writecache_target(struct dm_tree_node *node,
@ -998,6 +1023,7 @@ struct integrity_settings {
uint32_t commit_time;
uint32_t bitmap_flush_interval;
uint64_t sectors_per_bit;
uint32_t allow_discards;
unsigned journal_sectors_set:1;
unsigned interleave_sectors_set:1;
@ -1006,6 +1032,7 @@ struct integrity_settings {
unsigned commit_time_set:1;
unsigned bitmap_flush_interval_set:1;
unsigned sectors_per_bit_set:1;
unsigned allow_discards_set:1;
};
int dm_tree_node_add_integrity_target(struct dm_tree_node *node,
@ -1020,6 +1047,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,
uint32_t vdo_version,
const char *vdo_pool_name,
const char *data_uuid,
uint64_t data_size,
@ -1066,7 +1094,7 @@ int dm_tree_node_add_replicator_dev_target(struct dm_tree_node *node,
/* End of Replicator API */
/*
* FIXME: Defines bellow are based on kernel's dm-thin.c defines
* FIXME: Defines below are based on kernel's dm-thin.c defines
* DATA_DEV_BLOCK_SIZE_MIN_SECTORS (64 * 1024 >> SECTOR_SHIFT)
* DATA_DEV_BLOCK_SIZE_MAX_SECTORS (1024 * 1024 * 1024 >> SECTOR_SHIFT)
*/
@ -1132,7 +1160,7 @@ int dm_tree_node_set_thin_pool_error_if_no_space(struct dm_tree_node *node,
int dm_tree_node_set_thin_pool_read_only(struct dm_tree_node *node,
unsigned read_only);
/*
* FIXME: Defines bellow are based on kernel's dm-thin.c defines
* FIXME: Defines below are based on kernel's dm-thin.c defines
* MAX_DEV_ID ((1 << 24) - 1)
*/
#define DM_THIN_MAX_DEVICE_ID (UINT32_C((1 << 24) - 1))
@ -1841,6 +1869,7 @@ const void *dm_report_value_cache_get(struct dm_report *rh, const char *name);
#define DM_REPORT_OUTPUT_FIELD_UNQUOTED 0x00000010
#define DM_REPORT_OUTPUT_COLUMNS_AS_ROWS 0x00000020
#define DM_REPORT_OUTPUT_MULTIPLE_TIMES 0x00000040
#define DM_REPORT_OUTPUT_FIELD_IDS_IN_HEADINGS 0x00000080
struct dm_report *dm_report_init(uint32_t *report_types,
const struct dm_report_object_type *types,
@ -1953,7 +1982,8 @@ struct dm_report_group;
typedef enum {
DM_REPORT_GROUP_SINGLE,
DM_REPORT_GROUP_BASIC,
DM_REPORT_GROUP_JSON
DM_REPORT_GROUP_JSON,
DM_REPORT_GROUP_JSON_STD
} dm_report_group_type_t;
struct dm_report_group *dm_report_group_create(dm_report_group_type_t type, void *data);
@ -2028,7 +2058,7 @@ void dm_config_destroy(struct dm_config_tree *cft);
/* Simple output line by line. */
typedef int (*dm_putline_fn)(const char *line, void *baton);
/* More advaced output with config node reference. */
/* More advanced output with config node reference. */
typedef int (*dm_config_node_out_fn)(const struct dm_config_node *cn, const char *line, void *baton);
/*
@ -2091,7 +2121,7 @@ struct dm_config_node *dm_config_clone_node(struct dm_config_tree *cft, const st
* Common formatting flags applicable to all config node types (lower 16 bits).
*/
#define DM_CONFIG_VALUE_FMT_COMMON_ARRAY 0x00000001 /* value is array */
#define DM_CONFIG_VALUE_FMT_COMMON_EXTRA_SPACES 0x00000002 /* add spaces in "key = value" pairs in constrast to "key=value" for better readability */
#define DM_CONFIG_VALUE_FMT_COMMON_EXTRA_SPACES 0x00000002 /* add spaces in "key = value" pairs in contrast to "key=value" for better readability */
/*
* Type-related config node formatting flags (higher 16 bits).
@ -2137,7 +2167,7 @@ struct dm_pool *dm_config_memory(struct dm_config_tree *cft);
*/
#define DM_UDEV_DISABLE_DM_RULES_FLAG 0x0001
/*
* DM_UDEV_DISABLE_SUBSYTEM_RULES_FLAG is set in case we need to disable
* DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG is set in case we need to disable
* subsystem udev rules, but still we need the general DM udev rules to
* be applied (to create the nodes and symlinks under /dev and /dev/disk).
*/
@ -2208,7 +2238,7 @@ struct dm_pool *dm_config_memory(struct dm_config_tree *cft);
int dm_cookie_supported(void);
/*
* Udev synchronisation functions.
* Udev synchronization functions.
*/
void dm_udev_set_sync_support(int sync_with_udev);
int dm_udev_get_sync_support(void);

View File

@ -87,10 +87,8 @@ static int _version_checked = 0;
static int _version_ok = 1;
static unsigned _ioctl_buffer_double_factor = 0;
const int _dm_compat = 0;
/* *INDENT-OFF* */
static struct cmd_data _cmd_data_v4[] = {
static const struct cmd_data _cmd_data_v4[] = {
{"create", DM_DEV_CREATE, {4, 0, 0}},
{"reload", DM_TABLE_LOAD, {4, 0, 0}},
{"remove", DM_DEV_REMOVE, {4, 0, 0}},
@ -139,7 +137,6 @@ static char *_align(char *ptr, unsigned int a)
return (char *) (((unsigned long) ptr + agn) & ~agn);
}
#ifdef DM_IOCTLS
static unsigned _kernel_major = 0;
static unsigned _kernel_minor = 0;
static unsigned _kernel_release = 0;
@ -182,6 +179,9 @@ int get_uname_version(unsigned *major, unsigned *minor, unsigned *release)
return 1;
}
#ifdef DM_IOCTLS
/*
* Set number to NULL to populate _dm_bitset - otherwise first
* match is returned.
@ -198,6 +198,7 @@ static int _get_proc_number(const char *file, const char *name,
char *line = NULL;
size_t len;
uint32_t num;
unsigned blocksection = (strcmp(file, PROC_DEVICES) == 0) ? 0 : 1;
if (!(fl = fopen(file, "r"))) {
log_sys_error("fopen", file);
@ -205,7 +206,9 @@ static int _get_proc_number(const char *file, const char *name,
}
while (getline(&line, &len, fl) != -1) {
if (sscanf(line, "%u %255s\n", &num, &nm[0]) == 2) {
if (!blocksection && (line[0] == 'B'))
blocksection = 1;
else if (sscanf(line, "%u %255s\n", &num, &nm[0]) == 2) {
if (!strcmp(name, nm)) {
if (number) {
*number = num;
@ -245,6 +248,16 @@ static int _control_device_number(uint32_t *major, uint32_t *minor)
return 1;
}
static int _control_unlink(const char *control)
{
if (unlink(control) && (errno != ENOENT)) {
log_sys_error("unlink", control);
return -1;
}
return 0;
}
/*
* Returns 1 if it exists on returning; 0 if it doesn't; -1 if it's wrong.
*/
@ -260,10 +273,7 @@ static int _control_exists(const char *control, uint32_t major, uint32_t minor)
if (!S_ISCHR(buf.st_mode)) {
log_verbose("%s: Wrong inode type", control);
if (!unlink(control))
return 0;
log_sys_error("unlink", control);
return -1;
return _control_unlink(control);
}
if (major && buf.st_rdev != MKDEV(major, minor)) {
@ -271,10 +281,7 @@ static int _control_exists(const char *control, uint32_t major, uint32_t minor)
"(%u, %u)", control,
MAJOR(buf.st_mode), MINOR(buf.st_mode),
major, minor);
if (!unlink(control))
return 0;
log_sys_error("unlink", control);
return -1;
return _control_unlink(control);
}
return 1;
@ -310,8 +317,13 @@ static int _create_control(const char *control, uint32_t major, uint32_t minor)
old_umask = umask(DM_CONTROL_NODE_UMASK);
if (mknod(control, S_IFCHR | S_IRUSR | S_IWUSR,
MKDEV(major, minor)) < 0) {
log_sys_error("mknod", control);
ret = 0;
if (errno != EEXIST) {
log_sys_error("mknod", control);
ret = 0;
} else if (_control_exists(control, major, minor) != 1) {
stack; /* Invalid control node created by parallel command ? */
ret = 0;
}
}
umask(old_umask);
(void) dm_prepare_selinux_context(NULL, 0);
@ -397,7 +409,7 @@ static void _close_control_fd(void)
{
if (_control_fd != -1) {
if (close(_control_fd) < 0)
log_sys_error("close", "_control_fd");
log_sys_debug("close", "_control_fd");
_control_fd = -1;
}
}
@ -586,23 +598,9 @@ int dm_check_version(void)
_version_checked = 1;
if (_check_version(dmversion, sizeof(dmversion), _dm_compat))
if (_check_version(dmversion, sizeof(dmversion), 0))
return 1;
if (!_dm_compat)
goto_bad;
log_verbose("device-mapper ioctl protocol version %u failed. "
"Trying protocol version 1.", _dm_version);
_dm_version = 1;
if (_check_version(dmversion, sizeof(dmversion), 0)) {
log_verbose("Using device-mapper ioctl protocol version 1");
return 1;
}
compat = "(compat)";
bad:
dm_get_library_version(libversion, sizeof(libversion));
log_error("Incompatible libdevmapper %s%s and kernel driver %s.",
@ -616,8 +614,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)
@ -662,7 +659,7 @@ void *dm_get_next_target(struct dm_task *dmt, void *next,
return t->next;
}
/* Unmarshall the target info returned from a status call */
/* Unmarshal the target info returned from a status call */
static int _unmarshal_status(struct dm_task *dmt, struct dm_ioctl *dmi)
{
char *outbuf = (char *) dmi + dmi->data_start;
@ -751,10 +748,131 @@ uint32_t dm_task_get_read_ahead(const struct dm_task *dmt, uint32_t *read_ahead)
struct dm_deps *dm_task_get_deps(struct dm_task *dmt)
{
if (!dmt) {
log_error(INTERNAL_ERROR "Missing dm_task.");
return NULL;
}
return (struct dm_deps *) (((char *) dmt->dmi.v4) +
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;
}
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_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);
}
/* buffer for devs + sorted ptrs + dm_devs + aligned strings */
if (!(devs = malloc(sizeof(*devs) + cnt * (2 * sizeof(void*) + sizeof(*dm_dev)) +
(cnt ? (char*)names1 - (char*)names + 256 : 0))))
return_0;
dm_list_init(devs);
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 */
}
/* Shift position where to store individual dm_devs */
dm_dev = (struct dm_active_device *) ((long*) (devs + 1) + cnt);
do {
names = (struct dm_names *)((char *) names + next);
dm_dev->devno = (dev_t) names->dev;
dm_dev->name = (const char *)(dm_dev + 1);
dm_dev->event_nr = 0;
dm_dev->uuid = "";
len = strlen(names->name) + 1;
memcpy((char*)dm_dev->name, names->name, len);
dm_new_dev = _align_ptr((char*)(dm_dev + 1) + len);
if (_check_has_event_nr()) {
*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);
len = strlen(uuid_ptr) + 1;
memcpy(dm_new_dev, uuid_ptr, len);
dm_dev->uuid = (const char *) dm_new_dev;
dm_new_dev = _align_ptr((char*)dm_new_dev + len);
}
}
dm_list_add(devs, &dm_dev->list);
dm_dev = dm_new_dev;
next = names->next;
} while (next);
out:
*devs_list = devs;
return 1;
}
void dm_device_list_destroy(struct dm_list **devs_list)
{
struct dm_device_list *devs = (struct dm_device_list *) *devs_list;
if (devs) {
free(devs);
*devs_list = NULL;
}
}
struct dm_names *dm_task_get_names(struct dm_task *dmt)
{
return (struct dm_names *) (((char *) dmt->dmi.v4) +
@ -1042,9 +1160,10 @@ static char *_add_target(struct target *t, char *out, char *end)
while (*pt)
if (*pt++ == '\\')
backslash_count++;
len = strlen(t->params) + backslash_count;
if ((out >= end) || (out + len + 1) >= end) {
len = strlen(t->params) + 1;
if ((out >= end) || (out + len + backslash_count) >= end) {
log_error("Ran out of memory building ioctl parameter");
return NULL;
}
@ -1060,8 +1179,8 @@ static char *_add_target(struct target *t, char *out, char *end)
*out++ = '\0';
}
else {
strcpy(out, t->params);
out += len + 1;
memcpy(out, t->params, len);
out += len + backslash_count;
}
/* align next block */
@ -1095,7 +1214,7 @@ static int _lookup_dev_name(uint64_t dev, char *buf, size_t len)
do {
names = (struct dm_names *)((char *) names + next);
if (names->dev == dev) {
strncpy(buf, names->name, len);
memccpy(buf, names->name, 0, len);
r = 1;
break;
}
@ -1132,6 +1251,7 @@ static struct dm_ioctl *_flatten(struct dm_task *dmt, unsigned repeat_count)
struct target *t;
struct dm_target_msg *tmsg;
size_t len = sizeof(struct dm_ioctl);
size_t message_len = 0, newname_len = 0, geometry_len = 0;
char *b, *e;
int count = 0;
@ -1192,14 +1312,20 @@ static struct dm_ioctl *_flatten(struct dm_task *dmt, unsigned repeat_count)
return NULL;
}
if (dmt->newname)
len += strlen(dmt->newname) + 1;
if (dmt->newname) {
newname_len = strlen(dmt->newname) + 1;
len += newname_len;
}
if (dmt->message)
len += sizeof(struct dm_target_msg) + strlen(dmt->message) + 1;
if (dmt->message) {
message_len = strlen(dmt->message) + 1;
len += sizeof(struct dm_target_msg) + message_len;
}
if (dmt->geometry)
len += strlen(dmt->geometry) + 1;
if (dmt->geometry) {
geometry_len = strlen(dmt->geometry) + 1;
len += geometry_len;
}
/*
* Give len a minimum size so that we have space to store
@ -1257,12 +1383,10 @@ 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));
memccpy(dmi->name, DEV_NAME(dmt), 0, sizeof(dmi->name));
if (DEV_UUID(dmt))
/* coverity[buffer_size_warning] */
strncpy(dmi->uuid, DEV_UUID(dmt), sizeof(dmi->uuid));
memccpy(dmi->uuid, DEV_UUID(dmt), 0, sizeof(dmi->uuid));
if (dmt->type == DM_DEVICE_SUSPEND)
dmi->flags |= DM_SUSPEND_FLAG;
@ -1321,16 +1445,16 @@ static struct dm_ioctl *_flatten(struct dm_task *dmt, unsigned repeat_count)
goto_bad;
if (dmt->newname)
strcpy(b, dmt->newname);
memcpy(b, dmt->newname, newname_len);
if (dmt->message) {
tmsg = (struct dm_target_msg *) b;
tmsg->sector = dmt->sector;
strcpy(tmsg->message, dmt->message);
memcpy(tmsg->message, dmt->message, message_len);
}
if (dmt->geometry)
strcpy(b, dmt->geometry);
memcpy(b, dmt->geometry, geometry_len);
return dmi;
@ -1441,8 +1565,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;
@ -1453,7 +1576,7 @@ static int _check_uevent_generated(struct dm_ioctl *dmi)
static int _create_and_load_v4(struct dm_task *dmt)
{
struct dm_task *task;
int r;
int r, ioctl_errno = 0;
uint32_t cookie;
/* Use new task struct to create the device */
@ -1479,8 +1602,10 @@ static int _create_and_load_v4(struct dm_task *dmt)
task->cookie_set = dmt->cookie_set;
task->add_node = dmt->add_node;
if (!dm_task_run(task))
if (!dm_task_run(task)) {
ioctl_errno = task->ioctl_errno;
goto_bad;
}
dm_task_destroy(task);
@ -1506,6 +1631,8 @@ static int _create_and_load_v4(struct dm_task *dmt)
task->ima_measurement = dmt->ima_measurement;
r = dm_task_run(task);
if (!r)
ioctl_errno = task->ioctl_errno;
task->head = NULL;
task->tail = NULL;
@ -1523,6 +1650,7 @@ static int _create_and_load_v4(struct dm_task *dmt)
dmt->uuid = NULL;
free(dmt->mangled_uuid);
dmt->mangled_uuid = NULL;
/* coverity[double_free] recursive function call */
_dm_task_free_targets(dmt);
if (dm_task_run(dmt))
@ -1534,6 +1662,7 @@ static int _create_and_load_v4(struct dm_task *dmt)
dmt->uuid = NULL;
free(dmt->mangled_uuid);
dmt->mangled_uuid = NULL;
/* coverity[double_free] recursive function call */
_dm_task_free_targets(dmt);
/*
@ -1552,12 +1681,18 @@ static int _create_and_load_v4(struct dm_task *dmt)
if (!dm_task_run(dmt))
log_error("Failed to revert device creation.");
if (ioctl_errno != 0)
dmt->ioctl_errno = ioctl_errno;
return 0;
bad:
dm_task_destroy(task);
_udev_complete(dmt);
if (ioctl_errno != 0)
dmt->ioctl_errno = ioctl_errno;
return 0;
}
@ -1808,23 +1943,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);
}
@ -1888,7 +2034,7 @@ static struct dm_ioctl *_do_dm_ioctl(struct dm_task *dmt, unsigned command,
/*
* Prevent udev vs. libdevmapper race when processing nodes
* and symlinks. This can happen when the udev rules are
* installed and udev synchronisation code is enabled in
* installed and udev synchronization code is enabled in
* libdevmapper but the software using libdevmapper does not
* make use of it (by not calling dm_task_set_cookie before).
* We need to instruct the udev rules not to be applied at
@ -1898,7 +2044,7 @@ static struct dm_ioctl *_do_dm_ioctl(struct dm_task *dmt, unsigned command,
if (!dmt->cookie_set && dm_udev_get_sync_support()) {
log_debug_activation("Cookie value is not set while trying to call %s "
"ioctl. Please, consider using libdevmapper's udev "
"synchronisation interface or disable it explicitly "
"synchronization interface or disable it explicitly "
"by calling dm_udev_set_sync_support(0).",
dmt->type == DM_DEVICE_RESUME ? "DM_DEVICE_RESUME" :
dmt->type == DM_DEVICE_REMOVE ? "DM_DEVICE_REMOVE" :

View File

@ -79,7 +79,7 @@ struct dm_task {
};
struct cmd_data {
const char *name;
const char name[16];
const unsigned cmd;
const int version[3];
};

View File

@ -537,7 +537,8 @@ int unmangle_string(const char *str, const char *str_name, size_t len,
}
if (str[i] == '\\' && str[i+1] == 'x') {
if (!sscanf(&str[i+2], "%2x%s", &code, str_rest)) {
if (!sscanf(&str[i+2], "%2x%" DM_TO_STRING(DM_NAME_LEN) "s",
&code, str_rest)) {
log_debug_activation("Hex encoding mismatch detected in %s \"%s\" "
"while trying to unmangle it.", str_name, str);
goto out;
@ -1060,9 +1061,8 @@ static int _add_dev_node(const char *dev_name, uint32_t major, uint32_t minor,
if (info.st_rdev == dev)
return 1;
if (unlink(path) < 0) {
log_error("Unable to unlink device node for '%s'",
dev_name);
if (unlink(path) && (errno != ENOENT)) {
log_sys_error("unlink", path);
return 0;
}
} else if (_warn_if_op_needed(warn_if_udev_failed))
@ -1106,8 +1106,8 @@ static int _rm_dev_node(const char *dev_name, int warn_if_udev_failed)
"Falling back to direct node removal.", path);
/* udev may already have deleted the node. Ignore ENOENT. */
if (unlink(path) < 0 && errno != ENOENT) {
log_error("Unable to unlink device node for '%s'", dev_name);
if (unlink(path) && (errno != ENOENT)) {
log_sys_error("unlink", path);
return 0;
}
@ -1451,9 +1451,10 @@ struct node_op_parms {
static void _store_str(char **pos, char **ptr, const char *str)
{
strcpy(*pos, str);
size_t len = strlen(str) + 1;
memcpy(*pos, str, len);
*ptr = *pos;
*pos += strlen(*ptr) + 1;
*pos += len;
}
static void _del_node_op(struct node_op_parms *nop)
@ -1703,15 +1704,17 @@ const char *dm_sysfs_dir(void)
*/
int dm_set_uuid_prefix(const char *uuid_prefix)
{
size_t len;
if (!uuid_prefix)
return_0;
if (strlen(uuid_prefix) > DM_MAX_UUID_PREFIX_LEN) {
if ((len = strlen(uuid_prefix)) > DM_MAX_UUID_PREFIX_LEN) {
log_error("New uuid prefix %s too long.", uuid_prefix);
return 0;
}
strcpy(_default_uuid_prefix, uuid_prefix);
memcpy(_default_uuid_prefix, uuid_prefix, len + 1);
return 1;
}
@ -1740,6 +1743,9 @@ static void _unmangle_mountinfo_string(const char *src, char *buf)
*buf = '\0';
}
/* coverity[+tainted_string_sanitize_content:arg-0] */
static int _sanitize_line(const char *line) { return 1; }
/* Parse one line of mountinfo and unmangled target line */
static int _mountinfo_parse_line(const char *line, unsigned *maj, unsigned *min, char *buf)
{
@ -1790,7 +1796,7 @@ static int _mountinfo_parse_line(const char *line, unsigned *maj, unsigned *min,
}
/*
* Function to operate on individal mountinfo line,
* Function to operate on individual mountinfo line,
* minor, major and mount target are parsed and unmangled
*/
int dm_mountinfo_read(dm_mountinfo_line_callback_fn read_fn, void *cb_data)
@ -1810,7 +1816,8 @@ int dm_mountinfo_read(dm_mountinfo_line_callback_fn read_fn, void *cb_data)
}
while (!feof(minfo) && fgets(buffer, sizeof(buffer), minfo))
if (!_mountinfo_parse_line(buffer, &maj, &min, target) ||
if (!_sanitize_line(buffer) ||
!_mountinfo_parse_line(buffer, &maj, &min, target) ||
!read_fn(buffer, maj, min, target, cb_data)) {
stack;
r = 0;
@ -1954,7 +1961,7 @@ static int _sysfs_find_kernel_name(uint32_t major, uint32_t minor, char *buf, si
!strcmp(name_dev, "holders") ||
!strcmp(name_dev, "integrity") ||
!strcmp(name_dev, "loop") ||
!strcmp(name_dev, "queueu") ||
!strcmp(name_dev, "queue") ||
!strcmp(name_dev, "md") ||
!strcmp(name_dev, "mq") ||
!strcmp(name_dev, "power") ||
@ -2311,7 +2318,7 @@ static int _check_semaphore_is_supported(void)
if (maxid < 0) {
log_warn("Kernel not configured for semaphores (System V IPC). "
"Not using udev synchronisation code.");
"Not using udev synchronization code.");
return 0;
}
@ -2334,7 +2341,7 @@ static int _check_udev_is_running(void)
if (!(r = udev_queue_get_udev_is_active(udev_queue)))
log_debug_activation("Udev is not running. "
"Not using udev synchronisation code.");
"Not using udev synchronization code.");
udev_queue_unref(udev_queue);
udev_unref(udev);
@ -2409,7 +2416,7 @@ static int _get_cookie_sem(uint32_t cookie, int *semid)
break;
case EACCES:
log_error("No permission to access "
"notificaton semaphore identified "
"notification semaphore identified "
"by cookie value %" PRIu32 " (0x%x)",
cookie, cookie);
break;
@ -2430,20 +2437,20 @@ static int _udev_notify_sem_inc(uint32_t cookie, int semid)
int val;
if (semop(semid, &sb, 1) < 0) {
log_error("semid %d: semop failed for cookie 0x%" PRIx32 ": %s",
log_error("cookie inc: semid %d: semop failed for cookie 0x%" PRIx32 ": %s",
semid, cookie, strerror(errno));
return 0;
}
if ((val = semctl(semid, 0, GETVAL)) < 0) {
log_error("semid %d: sem_ctl GETVAL failed for "
log_warn("cookie inc: semid %d: sem_ctl GETVAL failed for "
"cookie 0x%" PRIx32 ": %s",
semid, cookie, strerror(errno));
return 0;
}
log_debug_activation("Udev cookie 0x%" PRIx32 " (semid %d) incremented to %d",
cookie, semid, val);
log_debug_activation("Udev cookie 0x%" PRIx32 " (semid %d) incremented.",
cookie, semid);
} else
log_debug_activation("Udev cookie 0x%" PRIx32 " (semid %d) incremented to %d",
cookie, semid, val);
return 1;
}
@ -2453,23 +2460,21 @@ static int _udev_notify_sem_dec(uint32_t cookie, int semid)
struct sembuf sb = {0, -1, IPC_NOWAIT};
int val;
if ((val = semctl(semid, 0, GETVAL)) < 0) {
log_error("semid %d: sem_ctl GETVAL failed for "
"cookie 0x%" PRIx32 ": %s",
semid, cookie, strerror(errno));
return 0;
}
if ((val = semctl(semid, 0, GETVAL)) < 0)
log_warn("cookie dec: semid %d: sem_ctl GETVAL failed for "
"cookie 0x%" PRIx32 ": %s",
semid, cookie, strerror(errno));
if (semop(semid, &sb, 1) < 0) {
switch (errno) {
case EAGAIN:
log_error("semid %d: semop failed for cookie "
log_error("cookie dec: semid %d: semop failed for cookie "
"0x%" PRIx32 ": "
"incorrect semaphore state",
semid, cookie);
break;
default:
log_error("semid %d: semop failed for cookie "
log_error("cookie dec: semid %d: semop failed for cookie "
"0x%" PRIx32 ": %s",
semid, cookie, strerror(errno));
break;
@ -2477,9 +2482,12 @@ static int _udev_notify_sem_dec(uint32_t cookie, int semid)
return 0;
}
log_debug_activation("Udev cookie 0x%" PRIx32 " (semid %d) decremented to %d",
cookie, semid, val - 1);
if (val < 0)
log_debug_activation("Udev cookie 0x%" PRIx32 " (semid %d) decremented.",
cookie, semid);
else
log_debug_activation("Udev cookie 0x%" PRIx32 " (semid %d) decremented to %d",
cookie, semid, val - 1);
return 1;
}
@ -2556,7 +2564,7 @@ static int _udev_notify_sem_create(uint32_t *cookie, int *semid)
sem_arg.val = 1;
if (semctl(gen_semid, 0, SETVAL, sem_arg) < 0) {
log_error("semid %d: semctl failed: %s", gen_semid, strerror(errno));
log_error("cookie create: semid %d: semctl failed: %s", gen_semid, strerror(errno));
/* We have to destroy just created semaphore
* so it won't stay in the system. */
(void) _udev_notify_sem_destroy(gen_cookie, gen_semid);
@ -2564,9 +2572,10 @@ static int _udev_notify_sem_create(uint32_t *cookie, int *semid)
}
if ((val = semctl(gen_semid, 0, GETVAL)) < 0) {
log_error("semid %d: sem_ctl GETVAL failed for "
log_error("cookie create: semid %d: sem_ctl GETVAL failed for "
"cookie 0x%" PRIx32 ": %s",
gen_semid, gen_cookie, strerror(errno));
(void) _udev_notify_sem_destroy(gen_cookie, gen_semid);
goto bad;
}

View File

@ -70,12 +70,11 @@ static struct dm_config_value *_value(struct parser *p);
static struct dm_config_value *_type(struct parser *p);
static int _match_aux(struct parser *p, int t);
static struct dm_config_value *_create_value(struct dm_pool *mem);
static struct dm_config_node *_create_node(struct dm_pool *mem);
static struct dm_config_value *_create_str_value(struct dm_pool *mem, const char *str, size_t str_len);
static struct dm_config_node *_create_node(struct dm_pool *mem, const char *key, size_t key_len);
static char *_dup_tok(struct parser *p);
static char *_dup_token(struct dm_pool *mem, const char *b, const char *e);
static const int _sep = '/';
#define MAX_INDENT 32
#define match(t) do {\
@ -86,14 +85,19 @@ static const int _sep = '/';
} \
} while(0)
/* match token */
static int _tok_match(const char *str, const char *b, const char *e)
{
while (*str && (b != e)) {
if (*str++ != *b++)
while (b < e) {
if (*str != *b)
return 0;
if (!*str)
return 0;
++str;
++b;
}
return !(*str || (b != e));
return !*str; /* token is matching for \0 end */
}
struct dm_config_tree *dm_config_create(void)
@ -177,19 +181,18 @@ static int _do_dm_config_parse(struct dm_config_tree *cft, const char *start, co
{
/* TODO? if (start == end) return 1; */
struct parser *p;
if (!(p = dm_pool_zalloc(cft->mem, sizeof(*p))))
return_0;
struct parser p = {
.mem = cft->mem,
.tb = start,
.te = start,
.fb = start,
.fe = end,
.line = 1,
.no_dup_node_check = no_dup_node_check
};
p->mem = cft->mem;
p->fb = start;
p->fe = end;
p->tb = p->te = p->fb;
p->line = 1;
p->no_dup_node_check = no_dup_node_check;
_get_token(p, TOK_SECTION_E);
if (!(cft->root = _file(p)))
_get_token(&p, TOK_SECTION_E);
if (!(cft->root = _file(&p)))
return_0;
cft->root = _config_reverse(cft->root);
@ -470,23 +473,33 @@ int dm_config_write_node_out(const struct dm_config_node *cn,
/*
* parser
*/
static char *_dup_string_tok(struct parser *p)
static const char *_string_tok(struct parser *p, size_t *len)
{
char *str;
ptrdiff_t d = p->te - p->tb;
p->tb++, p->te--; /* strip "'s */
if (p->te < p->tb) {
if (d < 2) {
log_error("Parse error at byte %" PRIptrdiff_t " (line %d): "
"expected a string token.",
p->tb - p->fb + 1, p->line);
return NULL;
}
if (!(str = _dup_tok(p)))
*len = (size_t)(d - 2); /* strip "'s */
return p->tb + 1;
}
static char *_dup_string_tok(struct parser *p)
{
const char *tok;
size_t len;
char *str;
if (!(tok = _string_tok(p, &len)))
return_NULL;
p->te++;
if (!(str = _dup_token(p->mem, tok, tok + len)))
return_NULL;
return str;
}
@ -508,10 +521,9 @@ static struct dm_config_node *_make_node(struct dm_pool *mem,
{
struct dm_config_node *n;
if (!(n = _create_node(mem)))
if (!(n = _create_node(mem, key_b, key_e - key_b)))
return_NULL;
n->key = _dup_token(mem, key_b, key_e);
if (parent) {
n->parent = parent;
n->sib = parent->child;
@ -526,17 +538,18 @@ static struct dm_config_node *_find_or_make_node(struct dm_pool *mem,
const char *path,
int no_dup_node_check)
{
const int sep = '/';
const char *e;
struct dm_config_node *cn = parent ? parent->child : NULL;
struct dm_config_node *cn_found = NULL;
while (cn || mem) {
/* trim any leading slashes */
while (*path && (*path == _sep))
while (*path && (*path == sep))
path++;
/* find the end of this segment */
for (e = path; *e && (*e != _sep); e++) ;
for (e = path; *e && (*e != sep); e++) ;
/* hunt for the node */
cn_found = NULL;
@ -671,16 +684,14 @@ static struct dm_config_value *_value(struct parser *p)
static struct dm_config_value *_type(struct parser *p)
{
/* [+-]{0,1}[0-9]+ | [0-9]*\.[0-9]* | ".*" */
struct dm_config_value *v = _create_value(p->mem);
char *str;
if (!v) {
log_error("Failed to allocate type value");
return NULL;
}
struct dm_config_value *v;
const char *str;
size_t len;
switch (p->t) {
case TOK_INT:
if (!(v = _create_value(p->mem)))
break;
v->type = DM_CFG_INT;
errno = 0;
v->v.i = strtoll(p->tb, NULL, 0); /* FIXME: check error */
@ -701,6 +712,8 @@ static struct dm_config_value *_type(struct parser *p)
break;
case TOK_FLOAT:
if (!(v = _create_value(p->mem)))
break;
v->type = DM_CFG_FLOAT;
errno = 0;
v->v.f = strtod(p->tb, NULL); /* FIXME: check error */
@ -712,31 +725,31 @@ static struct dm_config_value *_type(struct parser *p)
break;
case TOK_STRING:
v->type = DM_CFG_STRING;
if (!(v->v.str = _dup_string_tok(p)))
if (!(str = _string_tok(p, &len)))
return_NULL;
match(TOK_STRING);
if ((v = _create_str_value(p->mem, str, len))) {
v->type = DM_CFG_STRING;
match(TOK_STRING);
}
break;
case TOK_STRING_BARE:
v->type = DM_CFG_STRING;
if (!(v->v.str = _dup_tok(p)))
return_NULL;
match(TOK_STRING_BARE);
if ((v = _create_str_value(p->mem, p->tb, p->te - p->tb))) {
v->type = DM_CFG_STRING;
match(TOK_STRING_BARE);
}
break;
case TOK_STRING_ESCAPED:
v->type = DM_CFG_STRING;
if (!(str = _dup_string_tok(p)))
if (!(str = _string_tok(p, &len)))
return_NULL;
dm_unescape_double_quotes(str);
v->v.str = str;
match(TOK_STRING_ESCAPED);
if ((v = _create_str_value(p->mem, str, len))) {
v->type = DM_CFG_STRING;
dm_unescape_double_quotes((char*)v->v.str);
match(TOK_STRING_ESCAPED);
}
break;
default:
@ -744,6 +757,12 @@ static struct dm_config_value *_type(struct parser *p)
p->tb - p->fb + 1, p->line);
return NULL;
}
if (!v) {
log_error("Failed to allocate type value.");
return NULL;
}
return v;
}
@ -885,16 +904,19 @@ static void _get_token(struct parser *p, int tok_prev)
static void _eat_space(struct parser *p)
{
while (p->tb != p->fe) {
if (*p->te == '#')
if (!isspace(*p->te)) {
if (*p->te != '#')
break;
while ((p->te != p->fe) && (*p->te != '\n') && (*p->te))
++p->te;
}
else if (!isspace(*p->te))
break;
while ((p->te != p->fe) && isspace(*p->te)) {
while (p->te != p->fe) {
if (*p->te == '\n')
++p->line;
else if (!isspace(*p->te))
break;
++p->te;
}
@ -910,9 +932,46 @@ static struct dm_config_value *_create_value(struct dm_pool *mem)
return dm_pool_zalloc(mem, sizeof(struct dm_config_value));
}
static struct dm_config_node *_create_node(struct dm_pool *mem)
static struct dm_config_value *_create_str_value(struct dm_pool *mem, const char *str, size_t str_len)
{
return dm_pool_zalloc(mem, sizeof(struct dm_config_node));
struct dm_config_value *cv;
char *str_buf;
if (!(cv = dm_pool_alloc(mem, sizeof(struct dm_config_value) + str_len + 1)))
return_NULL;
memset(cv, 0, sizeof(*cv));
if (str) {
str_buf = (char *)(cv + 1);
if (str_len)
memcpy(str_buf, str, str_len);
str_buf[str_len] = '\0';
cv->v.str = str_buf;
}
return cv;
}
static struct dm_config_node *_create_node(struct dm_pool *mem, const char *key, size_t key_len)
{
struct dm_config_node *cn;
char *key_buf;
if (!(cn = dm_pool_alloc(mem, sizeof(struct dm_config_node) + key_len + 1)))
return_NULL;
memset(cn, 0, sizeof(*cn));
if (key) {
key_buf = (char *)(cn + 1);
if (key_len)
memcpy(key_buf, key, key_len);
key_buf[key_len] = '\0';
cn->key = key_buf;
}
return cn;
}
static char *_dup_token(struct dm_pool *mem, const char *b, const char *e)
@ -1329,19 +1388,19 @@ static struct dm_config_value *_clone_config_value(struct dm_pool *mem,
{
struct dm_config_value *new_cv;
if (!(new_cv = _create_value(mem))) {
log_error("Failed to clone config value.");
return NULL;
if (v->type == DM_CFG_STRING) {
if (!(new_cv = _create_str_value(mem, v->v.str, strlen(v->v.str)))) {
}
} else {
if (!(new_cv = _create_value(mem))) {
log_error("Failed to clone config value.");
return NULL;
}
new_cv->v = v->v;
}
new_cv->type = v->type;
if (v->type == DM_CFG_STRING) {
if (!(new_cv->v.str = dm_pool_strdup(mem, v->v.str))) {
log_error("Failed to clone config string value.");
return NULL;
}
} else
new_cv->v = v->v;
if (v->next && !(new_cv->next = _clone_config_value(mem, v->next)))
return_NULL;
@ -1358,16 +1417,11 @@ struct dm_config_node *dm_config_clone_node_with_mem(struct dm_pool *mem, const
return NULL;
}
if (!(new_cn = _create_node(mem))) {
if (!(new_cn = _create_node(mem, cn->key, cn->key ? strlen(cn->key) : 0))) {
log_error("Failed to clone config node.");
return NULL;
}
if ((cn->key && !(new_cn->key = dm_pool_strdup(mem, cn->key)))) {
log_error("Failed to clone config node key.");
return NULL;
}
new_cn->id = cn->id;
if ((cn->v && !(new_cn->v = _clone_config_value(mem, cn->v))) ||
@ -1387,14 +1441,11 @@ struct dm_config_node *dm_config_create_node(struct dm_config_tree *cft, const c
{
struct dm_config_node *cn;
if (!(cn = _create_node(cft->mem))) {
if (!(cn = _create_node(cft->mem, key, strlen(key)))) {
log_error("Failed to create config node.");
return NULL;
}
if (!(cn->key = dm_pool_strdup(cft->mem, key))) {
log_error("Failed to create config node's key.");
return NULL;
}
cn->parent = NULL;
cn->v = NULL;

View File

@ -171,7 +171,7 @@ struct load_segment {
uint32_t region_size; /* Mirror + raid */
unsigned clustered; /* Mirror */
unsigned mirror_area_count; /* Mirror */
uint32_t flags; /* Mirror + raid + Cache */
uint64_t flags; /* Mirror + Raid + Cache */
char *uuid; /* Clustered mirror log */
const char *policy_name; /* Cache */
@ -214,6 +214,7 @@ struct load_segment {
uint32_t device_id; /* Thin */
// VDO params
uint32_t vdo_version; /* VDO - version of target table line */
struct dm_tree_node *vdo_data; /* VDO */
struct dm_vdo_target_params vdo_params; /* VDO */
const char *vdo_name; /* VDO - device name is ALSO passed as table arg */
@ -264,7 +265,7 @@ struct load_properties {
/*
* Preload tree normally only loads and not resume, but there is
* automatic resume when target is extended, as it's believed
* there can be no i/o flying to this 'new' extedend space
* there can be no i/o flying to this 'new' extended space
* from any device above. Reason is that preloaded target above
* may actually need to see its bigger subdevice before it
* gets suspended. As long as devices are simple linears
@ -276,7 +277,7 @@ struct load_properties {
/*
* When comparing table lines to decide if a reload is
* needed, ignore any differences betwen the lvm device
* needed, ignore any differences between 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,
@ -287,12 +288,16 @@ struct load_properties {
/*
* Call node_send_messages(), set to 2 if there are messages
* When != 0, it validates matching transaction id, thus thin-pools
* where transation_id is passed as 0 are never validated, this
* allows external managment of thin-pool TID.
* where transaction_id is passed as 0 are never validated, this
* allows external management of thin-pool TID.
*/
unsigned send_messages;
/* Skip suspending node's children, used when sending messages to thin-pool */
int skip_suspend;
/* Suspend and Resume siblings after node activation with udev flags*/
unsigned reactivate_siblings;
uint16_t reactivate_udev_flags;
};
/* Two of these used to join two nodes with uses and used_by. */
@ -343,7 +348,7 @@ struct dm_tree {
int retry_remove; /* 1 retries remove if not successful */
uint32_t cookie;
char buf[DM_NAME_LEN + 32]; /* print buffer for device_name (major:minor) */
const char **optional_uuid_suffixes; /* uuid suffixes ignored when matching */
const char * const *optional_uuid_suffixes; /* uuid suffixes ignored when matching */
};
/*
@ -585,6 +590,7 @@ void dm_tree_set_optional_uuid_suffixes(struct dm_tree *dtree, const char **opti
dtree->optional_uuid_suffixes = optional_uuid_suffixes;
}
static const char *_node_name(struct dm_tree_node *dnode);
static struct dm_tree_node *_find_dm_tree_node_by_uuid(struct dm_tree *dtree,
const char *uuid)
{
@ -592,28 +598,26 @@ static struct dm_tree_node *_find_dm_tree_node_by_uuid(struct dm_tree *dtree,
const char *default_uuid_prefix;
size_t default_uuid_prefix_len;
const char *suffix, *suffix_position;
char uuid_without_suffix[DM_UUID_LEN];
char uuid_without_suffix[DM_UUID_LEN + 1];
unsigned i = 0;
const char **suffix_list = dtree->optional_uuid_suffixes;
const char * const *suffix_list = dtree->optional_uuid_suffixes;
if ((node = dm_hash_lookup(dtree->uuids, uuid))) {
log_debug("Matched uuid %s in deptree.", uuid);
log_debug_activation("Matched uuid %s %s in deptree.", uuid, _node_name(node));
return node;
}
default_uuid_prefix = dm_uuid_prefix();
default_uuid_prefix_len = strlen(default_uuid_prefix);
if (suffix_list && (suffix_position = strrchr(uuid, '-'))) {
while ((suffix = suffix_list[i++])) {
if (strcmp(suffix_position + 1, suffix))
continue;
(void) strncpy(uuid_without_suffix, uuid, sizeof(uuid_without_suffix));
dm_strncpy(uuid_without_suffix, uuid, sizeof(uuid_without_suffix));
uuid_without_suffix[suffix_position - uuid] = '\0';
if ((node = dm_hash_lookup(dtree->uuids, uuid_without_suffix))) {
log_debug("Matched uuid %s (missing suffix -%s) in deptree.", uuid_without_suffix, suffix);
log_debug_activation("Matched uuid %s %s (missing suffix -%s) in deptree.",
uuid_without_suffix, _node_name(node), suffix);
return node;
}
@ -621,15 +625,17 @@ static struct dm_tree_node *_find_dm_tree_node_by_uuid(struct dm_tree *dtree,
};
}
if (strncmp(uuid, default_uuid_prefix, default_uuid_prefix_len))
return NULL;
default_uuid_prefix = dm_uuid_prefix();
default_uuid_prefix_len = strlen(default_uuid_prefix);
if ((node = dm_hash_lookup(dtree->uuids, uuid + default_uuid_prefix_len))) {
log_debug("Matched uuid %s (missing prefix) in deptree.", uuid + default_uuid_prefix_len);
if ((strncmp(uuid, default_uuid_prefix, default_uuid_prefix_len) == 0) &&
(node = dm_hash_lookup(dtree->uuids, uuid + default_uuid_prefix_len))) {
log_debug_activation("Matched uuid %s %s (missing prefix) in deptree.",
uuid + default_uuid_prefix_len, _node_name(node));
return node;
}
log_debug("Not matched uuid %s in deptree.", uuid);
log_debug_activation("Not matched uuid %s in deptree.", uuid);
return NULL;
}
@ -962,7 +968,7 @@ static int _check_device_not_in_use(const char *name, struct dm_info *info)
} else if (dm_device_has_holders(info->major, info->minor))
reason = "is used by another device";
else if (dm_device_has_mounted_fs(info->major, info->minor))
reason = "constains a filesystem in use";
reason = "contains a filesystem in use";
else
return 1;
@ -1810,7 +1816,7 @@ static int _dm_tree_deactivate_children(struct dm_tree_node *dnode,
if (info.open_count) {
/* Skip internal non-toplevel opened nodes */
/* On some old udev systems without corrrect udev rules
/* On some old udev systems without correct udev rules
* this hack avoids 'leaking' active _mimageX legs after
* deactivation of mirror LV. Other suffixes are not added
* since it's expected newer systems with wider range of
@ -2029,6 +2035,68 @@ static int _rename_conflict_exists(struct dm_tree_node *parent,
return 0;
}
/*
* Reactivation of sibling nodes
*
* Function is used when activating origin and its thick snapshots
* to ensure udev is processing first the origin LV and all the
* snapshot LVs are processed afterwards.
*/
static int _reactivate_siblings(struct dm_tree_node *dnode,
const char *uuid_prefix,
size_t uuid_prefix_len)
{
struct dm_tree_node *child;
const char *uuid;
void *handle = NULL;
int r = 1;
/* Wait for udev before reactivating siblings */
if (!dm_udev_wait(dm_tree_get_cookie(dnode)))
stack;
dm_tree_set_cookie(dnode, 0);
while ((child = dm_tree_next_child(&handle, dnode, 0))) {
if (child->props.reactivate_siblings) {
/* Skip 'leading' device in this group, marked with flag */
child->props.reactivate_siblings = 0;
continue;
}
if (!(uuid = dm_tree_node_get_uuid(child))) {
stack;
continue;
}
if (!_uuid_prefix_matches(uuid, uuid_prefix, uuid_prefix_len))
continue;
if (!_suspend_node(child->name, child->info.major, child->info.minor,
child->dtree->skip_lockfs,
child->dtree->no_flush, &child->info)) {
log_error("Unable to suspend %s (" FMTu32
":" FMTu32 ")", child->name,
child->info.major, child->info.minor);
r = 0;
continue;
}
if (!_resume_node(child->name, child->info.major, child->info.minor,
child->props.read_ahead, child->props.read_ahead_flags,
&child->info, &child->dtree->cookie,
child->props.reactivate_udev_flags, // use these flags
child->info.suspended)) {
log_error("Failed to suspend %s (" FMTu32
":" FMTu32 ")", child->name,
child->info.major, child->info.minor);
r = 0;
continue;
}
}
return r;
}
int dm_tree_activate_children(struct dm_tree_node *dnode,
const char *uuid_prefix,
size_t uuid_prefix_len)
@ -2039,7 +2107,7 @@ int dm_tree_activate_children(struct dm_tree_node *dnode,
struct dm_tree_node *child = dnode;
const char *name;
const char *uuid;
int priority;
int priority, next_priority;
/* Activate children first */
while ((child = dm_tree_next_child(&handle, dnode, 0))) {
@ -2057,12 +2125,16 @@ int dm_tree_activate_children(struct dm_tree_node *dnode,
}
handle = NULL;
for (priority = 0; priority < 3; priority++) {
awaiting_peer_rename = 0;
next_priority = 0;
while ((child = dm_tree_next_child(&handle, dnode, 0))) {
if (priority != child->activation_priority)
if (priority != child->activation_priority) {
if ((next_priority < child->activation_priority) &&
(child->activation_priority > priority))
next_priority = child->activation_priority;
continue;
}
if (!(uuid = dm_tree_node_get_uuid(child))) {
stack;
@ -2110,16 +2182,23 @@ int dm_tree_activate_children(struct dm_tree_node *dnode,
/*
* FIXME: Implement delayed error reporting
* activation should be stopped only in the case,
* the submission of transation_id message fails,
* the submission of transaction_id message fails,
* resume should continue further, just whole command
* has to report failure.
*/
if (r && (child->props.send_messages > 1) &&
!(r = _node_send_messages(child, uuid_prefix, uuid_prefix_len, 1)))
stack;
/* Reactivate only for fresh activated origin */
if (r && child->props.reactivate_siblings &&
(!(r = _reactivate_siblings(dnode, uuid_prefix, uuid_prefix_len))))
stack;
}
if (awaiting_peer_rename)
priority--; /* redo priority level */
else if (!next_priority)
break; /* no more work, higher priority was not found in the chain */
}
return r;
@ -2195,7 +2274,7 @@ static int _build_dev_string(char *devbuf, size_t bufsize, struct dm_tree_node *
return 1;
}
/* simplify string emiting code */
/* simplify string emitting code */
#define EMIT_PARAMS(p, str...)\
do {\
int w;\
@ -2678,6 +2757,10 @@ static int _writecache_emit_segment_line(struct dm_task *dmt,
count += 1;
if (seg->writecache_settings.max_age_set)
count += 2;
if (seg->writecache_settings.metadata_only_set)
count += 1;
if (seg->writecache_settings.pause_writeback_set)
count += 2;
if (seg->writecache_settings.new_key)
count += 2;
@ -2729,6 +2812,14 @@ static int _writecache_emit_segment_line(struct dm_task *dmt,
EMIT_PARAMS(pos, " max_age %u", seg->writecache_settings.max_age);
}
if (seg->writecache_settings.metadata_only_set) {
EMIT_PARAMS(pos, " metadata_only");
}
if (seg->writecache_settings.pause_writeback_set) {
EMIT_PARAMS(pos, " pause_writeback %u", seg->writecache_settings.pause_writeback);
}
if (seg->writecache_settings.new_key) {
EMIT_PARAMS(pos, " %s %s",
seg->writecache_settings.new_key,
@ -2777,6 +2868,8 @@ static int _integrity_emit_segment_line(struct dm_task *dmt,
count++;
if (set->sectors_per_bit_set)
count++;
if (set->allow_discards_set && set->allow_discards)
count++;
EMIT_PARAMS(pos, "%s 0 %u %s %d fix_padding block_size:%u internal_hash:%s",
origin_dev,
@ -2796,7 +2889,7 @@ static int _integrity_emit_segment_line(struct dm_task *dmt,
EMIT_PARAMS(pos, " journal_sectors:%u", set->journal_sectors);
if (set->interleave_sectors_set)
EMIT_PARAMS(pos, " ineterleave_sectors:%u", set->interleave_sectors);
EMIT_PARAMS(pos, " interleave_sectors:%u", set->interleave_sectors);
if (set->buffer_sectors_set)
EMIT_PARAMS(pos, " buffer_sectors:%u", set->buffer_sectors);
@ -2813,6 +2906,9 @@ static int _integrity_emit_segment_line(struct dm_task *dmt,
if (set->sectors_per_bit_set)
EMIT_PARAMS(pos, " sectors_per_bit:%llu", (unsigned long long)set->sectors_per_bit);
if (set->allow_discards_set && set->allow_discards)
EMIT_PARAMS(pos, " allow_discards");
if (!dm_task_secure_data(dmt))
stack;
@ -2849,13 +2945,18 @@ static int _thin_pool_emit_segment_line(struct dm_task *dmt,
return 1;
}
static int _vdo_emit_segment_line(struct dm_task *dmt,
static int _vdo_emit_segment_line(struct dm_task *dmt, uint32_t major, uint32_t minor,
struct load_segment *seg,
char *params, size_t paramsize)
{
int pos = 0;
char data[DM_FORMAT_DEV_BUFSIZE];
char data_dev[128]; // for /dev/dm-XXXX
uint64_t logical_blocks;
struct dm_task *vdo_dmt;
uint64_t start, length = 0;
char *type = NULL;
char *vdo_params = NULL;
if (!_build_dev_string(data, sizeof(data), seg->vdo_data))
return_0;
@ -2865,18 +2966,59 @@ static int _vdo_emit_segment_line(struct dm_task *dmt,
return 0;
}
EMIT_PARAMS(pos, "V2 %s " FMTu64 " %u " FMTu64 " %u %s %s %s "
"maxDiscard %u ack %u bio %u bioRotationInterval %u cpu %u hash %u logical %u physical %u",
data_dev,
seg->vdo_data_size / 8, // this parameter is in 4K units
seg->vdo_params.minimum_io_size * UINT32_C(512), // sector to byte units
seg->vdo_params.block_map_cache_size_mb * UINT64_C(256), // 1MiB -> 4KiB units
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" :
(seg->vdo_params.write_policy == DM_VDO_WRITE_POLICY_ASYNC_UNSAFE) ? "async-unsafe" : "auto", // policy
seg->vdo_name,
/*
* If there is already running VDO target, read 'existing' virtual size out of table line
* and avoid reading it them from VDO metadata device
*
* NOTE: ATM VDO virtual size can be ONLY extended thus it's simple to recognize 'right' size.
* However if there would be supported also reduction, this check would need to check range.
*/
if ((vdo_dmt = dm_task_create(DM_DEVICE_TABLE))) {
if (dm_task_set_major(vdo_dmt, major) &&
dm_task_set_minor(vdo_dmt, minor) &&
dm_task_run(vdo_dmt)) {
(void) dm_get_next_target(vdo_dmt, NULL, &start, &length, &type, &vdo_params);
if (!type || strcmp(type, "vdo"))
length = 0;
}
dm_task_destroy(vdo_dmt);
}
if (!length && dm_vdo_parse_logical_size(data_dev, &logical_blocks))
length = logical_blocks * 8;
if (seg->size < length) {
log_debug_activation("Correcting VDO virtual volume size from " FMTu64 " to " FMTu64 ".",
seg->size, length);
seg->size = length;
}
if (seg->vdo_version < 4) {
EMIT_PARAMS(pos, "V2 %s " FMTu64 " %u " FMTu64 " %u %s %s %s ",
data_dev,
seg->vdo_data_size / 8, // this parameter is in 4K units
seg->vdo_params.minimum_io_size * UINT32_C(512), // sector to byte units
seg->vdo_params.block_map_cache_size_mb * UINT64_C(256), // 1MiB -> 4KiB units
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" :
(seg->vdo_params.write_policy == DM_VDO_WRITE_POLICY_ASYNC_UNSAFE) ? "async-unsafe" : "auto", // policy
seg->vdo_name);
} else {
EMIT_PARAMS(pos, "V4 %s " FMTu64 " %u " FMTu64 " %u "
"deduplication %s compression %s ",
data_dev,
seg->vdo_data_size / 8, // this parameter is in 4K units
seg->vdo_params.minimum_io_size * UINT32_C(512), // sector to byte units
seg->vdo_params.block_map_cache_size_mb * UINT64_C(256), // 1MiB -> 4KiB units
seg->vdo_params.block_map_era_length,
seg->vdo_params.use_deduplication ? "on" : "off",
seg->vdo_params.use_compression ? "on" : "off");
}
EMIT_PARAMS(pos, "maxDiscard %u ack %u bio %u bioRotationInterval %u cpu %u hash %u logical %u physical %u",
seg->vdo_params.max_discard,
seg->vdo_params.ack_threads,
seg->vdo_params.bio_threads,
@ -2951,7 +3093,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 (!_vdo_emit_segment_line(dmt, seg, params, paramsize))
if (!_vdo_emit_segment_line(dmt, major, minor, seg, params, paramsize))
return_0;
break;
case SEG_CRYPT:
@ -3240,7 +3382,7 @@ int dm_tree_preload_children(struct dm_tree_node *dnode,
if (!child->info.exists && !(node_created = _create_node(child, dnode)))
return_0;
/* Propagate delayed resume from exteded child node */
/* Propagate delayed resume from extended child node */
if (child->props.delay_resume_if_extended)
dnode->props.delay_resume_if_extended = 1;
@ -3390,6 +3532,10 @@ int dm_tree_node_add_snapshot_origin_target(struct dm_tree_node *dnode,
/* Resume snapshot origins after new snapshots */
dnode->activation_priority = 1;
if (!dnode->info.exists)
/* Reactivate siblings for this origin after being resumed */
dnode->props.reactivate_siblings = 1;
/*
* Don't resume the origin immediately in case it is a non-trivial
* target that must not be active more than once concurrently!
@ -3452,6 +3598,20 @@ static int _add_snapshot_target(struct dm_tree_node *node,
/* Resume merging snapshot after snapshot-merge */
seg->merge->activation_priority = 2;
}
} else if (!origin_node->info.exists) {
/* Keep original udev_flags for reactivation. */
node->props.reactivate_udev_flags = node->udev_flags;
/* Reactivation is needed if the origin's -real device is not in DM table.
* For this case after the resume of its origin LV we resume its snapshots
* with updated udev_flags to completely avoid udev scanning for the first resume.
* Reactivation then resumes snapshots with original udev_flags.
*/
node->udev_flags |= DM_SUBSYSTEM_UDEV_FLAG0 |
DM_UDEV_DISABLE_DISK_RULES_FLAG |
DM_UDEV_DISABLE_OTHER_RULES_FLAG;
log_debug_activation("Using udev_flags 0x%x for activation of %s.",
node->udev_flags, node->name);
}
return 1;
@ -3658,7 +3818,7 @@ int dm_tree_node_add_raid_target(struct dm_tree_node *node,
* - maximum 253 legs in a raid set (MD kernel limitation)
* - delta_disks for disk add/remove reshaping
* - data_offset for out-of-place reshaping
* - data_copies to cope witth odd numbers of raid10 disks
* - data_copies to cope with odd numbers of raid10 disks
*/
int dm_tree_node_add_raid_target_with_params_v2(struct dm_tree_node *node,
uint64_t size,
@ -3709,7 +3869,7 @@ int dm_tree_node_add_cache_target(struct dm_tree_node *node,
{
struct dm_config_node *cn;
struct load_segment *seg;
static const uint64_t _modemask =
const uint64_t modemask =
DM_CACHE_FEATURE_PASSTHROUGH |
DM_CACHE_FEATURE_WRITETHROUGH |
DM_CACHE_FEATURE_WRITEBACK;
@ -3721,12 +3881,12 @@ int dm_tree_node_add_cache_target(struct dm_tree_node *node,
return 0;
}
switch (feature_flags & _modemask) {
switch (feature_flags & modemask) {
case DM_CACHE_FEATURE_PASSTHROUGH:
case DM_CACHE_FEATURE_WRITEBACK:
if (strcmp(policy_name, "cleaner") == 0) {
/* Enforce writethrough mode for cleaner policy */
feature_flags = ~_modemask;
feature_flags = ~modemask;
feature_flags |= DM_CACHE_FEATURE_WRITETHROUGH;
}
/* Fall through */
@ -3922,7 +4082,7 @@ int dm_tree_node_add_replicator_dev_target(struct dm_tree_node *node,
uint32_t slog_flags,
uint32_t slog_region_size)
{
log_error("Replicator targer is unsupported.");
log_error("Replicator target is unsupported.");
return 0;
}
@ -4209,6 +4369,12 @@ int dm_tree_node_set_thin_external_origin(struct dm_tree_node *node,
seg->external = external;
if (!external->info.minor) {
log_debug_activation("Delaying resume for new external origin %s.",
external->name);
external->props.delay_resume_if_new = 1;
}
return 1;
}
@ -4323,6 +4489,7 @@ void dm_tree_node_set_callback(struct dm_tree_node *dnode,
int dm_tree_node_add_vdo_target(struct dm_tree_node *node,
uint64_t size,
uint32_t vdo_version,
const char *vdo_pool_name,
const char *data_uuid,
uint64_t data_size,
@ -4344,11 +4511,13 @@ int dm_tree_node_add_vdo_target(struct dm_tree_node *node,
if (!_link_tree_nodes(node, seg->vdo_data))
return_0;
seg->vdo_version = vdo_version;
seg->vdo_params = *vtp;
seg->vdo_name = vdo_pool_name;
seg->vdo_data_size = data_size;
node->props.send_messages = 2;
if (seg->vdo_version < 4)
node->props.send_messages = 2;
return 1;
}

View File

@ -223,7 +223,6 @@ retry_fcntl:
}
/* coverity[leaked_handle] intentional leak of fd handle here */
return 1;
fail_close_unlink:

File diff suppressed because it is too large Load Diff

View File

@ -192,7 +192,7 @@ int dm_asprintf(char **result, const char *format, ...)
}
/*
* Count occurences of 'c' in 'str' until we reach a null char.
* Count occurrences of 'c' in 'str' until we reach a null char.
*
* Returns:
* len - incremented for each char we encounter.
@ -385,7 +385,7 @@ char *dm_build_dm_uuid(struct dm_pool *mem, const char *uuid_prefix, const char
return NULL;
}
sprintf(dmuuid, "%s%s%s%s", uuid_prefix, lvid, (*layer) ? "-" : "", layer);
snprintf(dmuuid, len, "%s%s%s%s", uuid_prefix, lvid, (*layer) ? "-" : "", layer);
return dmuuid;
}
@ -552,7 +552,7 @@ const char *dm_size_to_string(struct dm_pool *mem, uint64_t size,
if (size == UINT64_C(0)) {
if (base == BASE_UNKNOWN)
s = 0;
sprintf(size_buf, "0%s", include_suffix ? size_str[base + s][suffix_type] : "");
snprintf(size_buf, SIZE_BUF, "0%s", include_suffix ? size_str[base + s][suffix_type] : "");
return size_buf;
}

View File

@ -106,26 +106,31 @@ int dm_get_status_raid(struct dm_pool *mem, const char *params,
/* Second field holds the device count */
msg_fields = "<#devs> ";
if (!(p = _skip_fields(params, 1)) || (sscanf(p, "%d", &i) != 1))
if (!(pp = _skip_fields(params, 1)) || (sscanf(pp, "%d", &i) != 1) || !(p = _skip_fields(pp, 1)))
goto_bad;
msg_fields = "";
if (!(s = dm_pool_zalloc(mem, sizeof(struct dm_status_raid))))
goto_bad;
if (!(s->raid_type = dm_pool_zalloc(mem, p - params)))
msg_fields = "<raid_type> <#devices> <health_chars> and <sync_ratio> ";
if (!(s->raid_type = dm_pool_strndup(mem, params, pp - params - 1)))
goto_bad; /* memory is freed when pool is destroyed */
if (!(s->dev_health = dm_pool_zalloc(mem, i + 1))) /* Space for health chars */
if (!(pp = _skip_fields(p, 1)))
goto_bad;
msg_fields = "<raid_type> <#devices> <health_chars> and <sync_ratio> ";
if (sscanf(params, "%s %u %s " FMTu64 "/" FMTu64,
s->raid_type,
&s->dev_count,
s->dev_health,
&s->insync_regions,
&s->total_regions) != 5)
/* Raid target can actually report more then real number of legs in a case
* raid legs have been removed during initial raid array resynchronization */
if (i > (pp - p - 1))
i = pp - p - 1;
if (!(s->dev_health = dm_pool_strndup(mem, p, i))) /* health chars */
goto_bad;
p = pp;
s->dev_count = i;
if (sscanf(p, FMTu64 "/" FMTu64, &s->insync_regions, &s->total_regions) != 2)
goto_bad;
/*
@ -141,13 +146,13 @@ int dm_get_status_raid(struct dm_pool *mem, const char *params,
msg_fields = "<sync_action> and <mismatch_cnt> ";
/* Skip pre-1.5.0 params */
if (!(p = _skip_fields(params, 4)) || !(pp = _skip_fields(p, 1)))
if (!(pp = _skip_fields(params, 4)) || !(p = _skip_fields(pp, 1)))
goto_bad;
if (!(s->sync_action = dm_pool_zalloc(mem, pp - p)))
if (!(s->sync_action = dm_pool_strndup(mem, pp, p - pp - 1)))
goto_bad;
if (sscanf(p, "%s " FMTu64, s->sync_action, &s->mismatch_count) != 2)
if (sscanf(p, FMTu64, &s->mismatch_count) != 1)
goto_bad;
if (num_fields < 7)
@ -166,23 +171,35 @@ int dm_get_status_raid(struct dm_pool *mem, const char *params,
if (sscanf(p, FMTu64, &s->data_offset) != 1)
goto bad;
/* <journal_char> - 'A' - active write-through journal device.
* - 'a' - active write-back journal device.
* - 'D' - dead journal device.
* - '-' - no journal device.
*/
out:
*status = s;
if (s->insync_regions == s->total_regions) {
/* FIXME: kernel gives misleading info here
* Trying to recognize a true state */
while (i-- > 0)
if (s->dev_health[i] == 'a')
a++; /* Count number of 'a' */
while (i-- > 0)
if (s->dev_health[i] == 'a')
a++; /* Count number of 'a' */
if (a && a < s->dev_count) {
/* SOME legs are in 'a' */
if (!strcasecmp(s->sync_action, "recover")
|| !strcasecmp(s->sync_action, "idle"))
/* Kernel may possibly start some action
* in near-by future, do not report 100% */
s->insync_regions--;
if (a) {
if ((a < s->dev_count) && /* SOME legs are in 'a' */
/* FIXME: kernel gives misleading info here
* Trying to recognize a true state */
(s->insync_regions == s->total_regions) &&
(!strcasecmp(s->sync_action, "recover") ||
!strcasecmp(s->sync_action, "idle"))) {
/* Kernel may possibly start some action
* in near-by future, do not report 100% */
s->insync_regions--;
}
if ((a == s->dev_count) && /* all legs are in 'a' */
(!strcasecmp(s->sync_action, "resync") ||
!strcasecmp(s->sync_action, "idle"))) {
/* Mark 1st. leg in sync */
s->dev_health[0] = 'A';
}
}
@ -511,6 +528,21 @@ int dm_get_status_thin(struct dm_pool *mem, const char *params,
return 1;
}
static dm_status_mirror_health_t _get_health(char c)
{
switch (c) {
case 'A': return DM_STATUS_MIRROR_ALIVE;
case 'F': return DM_STATUS_MIRROR_FLUSH_FAILED;
case 'D': return DM_STATUS_MIRROR_WRITE_FAILED;
case 'S': return DM_STATUS_MIRROR_SYNC_FAILED;
case 'R': return DM_STATUS_MIRROR_READ_FAILED;
default:
log_warn("WARNING: Unknown mirror health status char: %c", c);
/* fall through */
case 'U': return DM_STATUS_MIRROR_UNCLASSIFIED;
}
}
/*
* dm core parms: 0 409600 mirror
* Mirror core parms: 2 253:4 253:5 400/400
@ -564,7 +596,7 @@ int dm_get_status_mirror(struct dm_pool *mem, const char *params,
pos += used;
for (i = 0; i < num_devs ; ++i)
s->devs[i].health = pos[i];
s->devs[i].health = _get_health(pos[i]);
if (!(pos = _skip_fields(pos, argc)))
goto_out;
@ -609,7 +641,7 @@ int dm_get_status_mirror(struct dm_pool *mem, const char *params,
goto_out;
for (i = 0; i < s->log_count; ++i)
s->logs[i].health = pos[i];
s->logs[i].health = _get_health(pos[i]);
}
}

View File

@ -209,7 +209,7 @@ struct dm_name_list {
};
#define DM_NAME_LIST_FLAG_HAS_UUID 1
#define DM_NAME_LIST_FLAG_DOESNT_HAVE_UUID 2
#define DM_NAME_LIST_FLAG_DOES_NOT_HAVE_UUID 2
/*
* Used to retrieve the target versions

View File

@ -62,7 +62,7 @@
*
* The UUID contained in the dm_ulog_request structure is the reference that
* will be used by all request types to a specific log. The constructor must
* record this assotiation with the instance created.
* record this association with the instance created.
*
* When the request has been processed, user-space must return the
* dm_ulog_request to the kernel - setting the 'error' field, filling the

View File

@ -129,7 +129,7 @@ int dm_pool_locked(struct dm_pool *p)
* Bool specifies whether to store the pool crc/hash checksum.
*
* \return
* 1 (success) when the pool was preperly locked, 0 otherwise.
* 1 (success) when the pool was properly locked, 0 otherwise.
*/
int dm_pool_lock(struct dm_pool *p, int crc)
{

View File

@ -77,9 +77,10 @@ enum dm_vdo_write_policy {
struct dm_vdo_target_params {
uint32_t minimum_io_size; // in sectors
uint32_t block_map_cache_size_mb;
uint32_t block_map_era_length; // format period
uint32_t check_point_frequency;
union {
uint32_t block_map_era_length; // format period
uint32_t block_map_period; // supported alias
};
uint32_t index_memory_size_mb; // format
uint32_t slab_size_mb; // format
@ -106,6 +107,8 @@ struct dm_vdo_target_params {
bool dm_vdo_validate_target_params(const struct dm_vdo_target_params *vtp,
uint64_t vdo_size);
bool dm_vdo_parse_logical_size(const char *vdo_path, uint64_t *logical_blocks);
//----------------------------------------------------------------
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2018 Red Hat, Inc. All rights reserved.
* Copyright (C) 2018-2022 Red Hat, Inc. All rights reserved.
*
* This file is part of the device-mapper userspace tools.
*
@ -15,49 +15,52 @@
#ifndef DEVICE_MAPPER_VDO_LIMITS_H
#define DEVICE_MAPPER_VDO_LIMITS_H
#ifndef SECTOR_SHIFT
#define SECTOR_SHIFT 9L
#endif
#define DM_VDO_BLOCK_SIZE UINT64_C(8) // 4KiB in sectors
#define DM_VDO_BLOCK_SIZE_KB (DM_VDO_BLOCK_SIZE << SECTOR_SHIFT)
#define DM_VDO_BLOCK_MAP_CACHE_SIZE_MINIMUM_MB (128) // 128MiB
#define DM_VDO_BLOCK_MAP_CACHE_SIZE_MAXIMUM_MB (16 * 1024 * 1024 - 1) // 16TiB - 1
#define DM_VDO_BLOCK_MAP_CACHE_SIZE_MINIMUM_PER_LOGICAL_THREAD (4096 * DM_VDO_BLOCK_SIZE_KB)
#define DM_VDO_BLOCK_MAP_ERA_LENGTH_MINIMUM (1)
#define DM_VDO_BLOCK_MAP_ERA_LENGTH_MAXIMUM (16380)
#define DM_VDO_BLOCK_MAP_ERA_LENGTH_MINIMUM 1
#define DM_VDO_BLOCK_MAP_ERA_LENGTH_MAXIMUM 16380
#define DM_VDO_INDEX_MEMORY_SIZE_MINIMUM_MB (256) // 0.25 GiB
#define DM_VDO_INDEX_MEMORY_SIZE_MINIMUM_MB 256 // 0.25 GiB
#define DM_VDO_INDEX_MEMORY_SIZE_MAXIMUM_MB (1024 * 1024 * 1024) // 1TiB
//#define DM_VDO_READ_CACHE_SIZE_MINIMUM_MB (0)
#define DM_VDO_READ_CACHE_SIZE_MAXIMUM_MB (16 * 1024 * 1024 - 1) // 16TiB - 1
#define DM_VDO_SLAB_SIZE_MINIMUM_MB (128) // 128MiB
#define DM_VDO_SLAB_SIZE_MINIMUM_MB 128 // 128MiB
#define DM_VDO_SLAB_SIZE_MAXIMUM_MB (32 * 1024) // 32GiB
#define DM_VDO_SLABS_MAXIMUM 8192
//#define DM_VDO_LOGICAL_SIZE_MINIMUM_MB (0)
#define DM_VDO_LOGICAL_SIZE_MAXIMUM_MB (UINT64_C(4) * 1024 * 1024 * 1024) // 4PiB
#define DM_VDO_LOGICAL_SIZE_MAXIMUM (UINT64_C(4) * 1024 * 1024 * 1024 * 1024 * 1024 >> SECTOR_SHIFT) // 4PiB
#define DM_VDO_PHYSICAL_SIZE_MAXIMUM (UINT64_C(64) * DM_VDO_BLOCK_SIZE_KB * 1024 * 1024 * 1024 >> SECTOR_SHIFT) // 256TiB
//#define DM_VDO_ACK_THREADS_MINIMUM (0)
#define DM_VDO_ACK_THREADS_MAXIMUM (100)
#define DM_VDO_ACK_THREADS_MINIMUM 0
#define DM_VDO_ACK_THREADS_MAXIMUM 100
#define DM_VDO_BIO_THREADS_MINIMUM (1)
#define DM_VDO_BIO_THREADS_MAXIMUM (100)
#define DM_VDO_BIO_THREADS_MINIMUM 1
#define DM_VDO_BIO_THREADS_MAXIMUM 100
#define DM_VDO_BIO_ROTATION_MINIMUM (1)
#define DM_VDO_BIO_ROTATION_MAXIMUM (1024)
#define DM_VDO_BIO_ROTATION_MINIMUM 1
#define DM_VDO_BIO_ROTATION_MAXIMUM 1024
#define DM_VDO_CPU_THREADS_MINIMUM (1)
#define DM_VDO_CPU_THREADS_MAXIMUM (100)
#define DM_VDO_CPU_THREADS_MINIMUM 1
#define DM_VDO_CPU_THREADS_MAXIMUM 100
//#define DM_VDO_HASH_ZONE_THREADS_MINIMUM (0)
#define DM_VDO_HASH_ZONE_THREADS_MAXIMUM (100)
#define DM_VDO_HASH_ZONE_THREADS_MINIMUM 0
#define DM_VDO_HASH_ZONE_THREADS_MAXIMUM 100
//#define DM_VDO_LOGICAL_THREADS_MINIMUM (0)
#define DM_VDO_LOGICAL_THREADS_MAXIMUM (100)
#define DM_VDO_LOGICAL_THREADS_MINIMUM 0
#define DM_VDO_LOGICAL_THREADS_MAXIMUM 60
//#define DM_VDO_PHYSICAL_THREADS_MINIMUM (0)
#define DM_VDO_PHYSICAL_THREADS_MAXIMUM (16)
#define DM_VDO_PHYSICAL_THREADS_MINIMUM 0
#define DM_VDO_PHYSICAL_THREADS_MAXIMUM 16
#define DM_VDO_MAX_DISCARD_MINIMUM (1)
#define DM_VDO_MAX_DISCARD_MAXIMUM (UINT32_MAX / 4096)
#define DM_VDO_MAX_DISCARD_MINIMUM 1
#define DM_VDO_MAX_DISCARD_MAXIMUM (UINT32_MAX / (uint32_t)(DM_VDO_BLOCK_SIZE_KB))
#endif // DEVICE_MAPPER_VDO_LIMITS_H

View File

@ -0,0 +1,308 @@
/*
* Copyright (C) 2022 Red Hat, Inc. All rights reserved.
*
* This file is part of the device-mapper userspace tools.
*
* 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
*/
/*
* Based on VDO sources: https://github.com/dm-vdo/vdo
*
* Simplified parser of VDO superblock to obtain basic VDO parameteers
*
* TODO: maybe switch to some library in the future
*/
//#define _GNU_SOURCE 1
//#define _LARGEFILE64_SOURCE 1
#include "device_mapper/misc/dmlib.h"
#include "target.h"
#include "lib/mm/xlate.h"
//#include "linux/byteorder/big_endian.h"
//#include "linux/byteorder/little_endian.h"
//#define le32_to_cpu __le32_to_cpu
//#define le64_to_cpu __le64_to_cpu
#include <errno.h>
#include <fcntl.h>
#include <linux/fs.h> /* For block ioctl definitions */
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <unistd.h>
typedef unsigned char uuid_t[16];
#define __packed __attribute__((packed))
static const char _MAGIC_NUMBER[] = "dmvdo001";
#define MAGIC_NUMBER_SIZE (sizeof(_MAGIC_NUMBER) - 1)
struct vdo_version_number {
uint32_t major_version;
uint32_t minor_version;
} __packed;
/*
* The registry of component ids for use in headers
*/
enum {
SUPER_BLOCK = 0,
FIXED_LAYOUT = 1,
RECOVERY_JOURNAL = 2,
SLAB_DEPOT = 3,
BLOCK_MAP = 4,
GEOMETRY_BLOCK = 5,
}; /* ComponentID */
struct vdo_header {
uint32_t id; /* The component this is a header for */
struct vdo_version_number version; /* The version of the data format */
size_t size; /* The size of the data following this header */
} __packed;
struct vdo_geometry_block {
char magic_number[MAGIC_NUMBER_SIZE];
struct vdo_header header;
uint32_t checksum;
} __packed;
struct vdo_config {
uint64_t logical_blocks; /* number of logical blocks */
uint64_t physical_blocks; /* number of physical blocks */
uint64_t slab_size; /* number of blocks in a slab */
uint64_t recovery_journal_size; /* number of recovery journal blocks */
uint64_t slab_journal_blocks; /* number of slab journal blocks */
} __packed;
struct vdo_component_41_0 {
uint32_t state;
uint64_t complete_recoveries;
uint64_t read_only_recoveries;
struct vdo_config config; /* packed */
uint64_t nonce;
} __packed;
enum vdo_volume_region_id {
VDO_INDEX_REGION = 0,
VDO_DATA_REGION = 1,
VDO_VOLUME_REGION_COUNT,
};
struct vdo_volume_region {
/* The ID of the region */
enum vdo_volume_region_id id;
/*
* The absolute starting offset on the device. The region continues
* until the next region begins.
*/
uint64_t start_block;
} __packed;
struct vdo_index_config {
uint32_t mem;
uint32_t unused;
uint8_t sparse;
} __packed;
struct vdo_volume_geometry {
uint32_t release_version;
uint64_t nonce;
uuid_t uuid;
uint64_t bio_offset;
struct vdo_volume_region regions[VDO_VOLUME_REGION_COUNT];
struct vdo_index_config index_config;
} __packed;
struct vdo_volume_geometry_4 {
uint32_t release_version;
uint64_t nonce;
uuid_t uuid;
struct vdo_volume_region regions[VDO_VOLUME_REGION_COUNT];
struct vdo_index_config index_config;
} __packed;
/* Decoding mostly only some used structure members */
static void _vdo_decode_version(struct vdo_version_number *v)
{
v->major_version = le32_to_cpu(v->major_version);
v->minor_version = le32_to_cpu(v->minor_version);
}
static void _vdo_decode_header(struct vdo_header *h)
{
h->id = le32_to_cpu(h->id);
_vdo_decode_version(&h->version);
h->size = le64_to_cpu(h->size);
}
static void _vdo_decode_geometry_region(struct vdo_volume_region *vr)
{
vr->id = le32_to_cpu(vr->id);
vr->start_block = le64_to_cpu(vr->start_block);
}
static void _vdo_decode_volume_geometry(struct vdo_volume_geometry *vg)
{
vg->release_version = le32_to_cpu(vg->release_version);
vg->nonce = le64_to_cpu(vg->nonce);
vg->bio_offset = le64_to_cpu(vg->bio_offset);
_vdo_decode_geometry_region(&vg->regions[VDO_DATA_REGION]);
}
static void _vdo_decode_volume_geometry_4(struct vdo_volume_geometry *vg,
struct vdo_volume_geometry_4 *vg_4)
{
vg->release_version = le32_to_cpu(vg_4->release_version);
vg->nonce = le64_to_cpu(vg_4->nonce);
vg->bio_offset = 0;
vg->regions[VDO_DATA_REGION] = vg_4->regions[VDO_DATA_REGION];
_vdo_decode_geometry_region(&vg->regions[VDO_DATA_REGION]);
}
static void _vdo_decode_config(struct vdo_config *vc)
{
vc->logical_blocks = le64_to_cpu(vc->logical_blocks);
vc->physical_blocks = le64_to_cpu(vc->physical_blocks);
vc->slab_size = le64_to_cpu(vc->slab_size);
vc->recovery_journal_size = le64_to_cpu(vc->recovery_journal_size);
vc->slab_journal_blocks = le64_to_cpu(vc->slab_journal_blocks);
}
static void _vdo_decode_pvc(struct vdo_component_41_0 *pvc)
{
_vdo_decode_config(&pvc->config);
pvc->nonce = le64_to_cpu(pvc->nonce);
}
bool dm_vdo_parse_logical_size(const char *vdo_path, uint64_t *logical_blocks)
{
char buffer[4096];
int fh;
bool r = false;
struct stat st;
uint64_t size;
uint64_t regpos;
struct vdo_header h;
struct vdo_version_number vn;
struct vdo_volume_geometry vg;
struct vdo_volume_geometry_4 vg_4;
struct vdo_component_41_0 pvc;
*logical_blocks = 0;
if ((fh = open(vdo_path, O_RDONLY)) == -1) {
log_sys_debug("Failed to open VDO backend %s.", vdo_path);
return false;
}
if (ioctl(fh, BLKGETSIZE64, &size) == -1) {
if (errno != ENOTTY) {
log_sys_debug("ioctl", vdo_path);
goto err;
}
/* lets retry for file sizes */
if (fstat(fh, &st) < 0) {
log_sys_debug("fstat", vdo_path);
goto err;
}
size = st.st_size;
}
if (read(fh, buffer, sizeof(buffer)) < 0) {
log_sys_debug("read", vdo_path);
goto err;
}
if (strncmp(buffer, _MAGIC_NUMBER, MAGIC_NUMBER_SIZE)) {
log_debug_activation("Found mismatching VDO magic header in %s.", vdo_path);
goto err;
}
memcpy(&h, buffer + MAGIC_NUMBER_SIZE, sizeof(h));
_vdo_decode_header(&h);
if (h.id != 5) {
log_debug_activation("Expected geometry VDO block instead of block %u.", h.id);
goto err;
}
switch (h.version.major_version) {
case 4:
memcpy(&vg_4, buffer + MAGIC_NUMBER_SIZE + sizeof(h), sizeof(vg_4));
_vdo_decode_volume_geometry_4(&vg, &vg_4);
break;
case 5:
memcpy(&vg, buffer + MAGIC_NUMBER_SIZE + sizeof(h), sizeof(vg));
_vdo_decode_volume_geometry(&vg);
break;
default:
log_debug_activation("Unsupported VDO version %u.%u.", h.version.major_version, h.version.minor_version);
goto err;
}
regpos = (vg.regions[VDO_DATA_REGION].start_block - vg.bio_offset) * 4096;
if ((regpos + sizeof(buffer)) > size) {
log_debug_activation("File/Device is shorter and can't provide requested VDO volume region at " FMTu64 " > " FMTu64 ".", regpos, size);
goto err;
}
if (lseek(fh, regpos, SEEK_SET) < 0) {
log_sys_debug("lseek", vdo_path);
goto err;
}
if (read(fh, buffer, sizeof(buffer)) < 0) {
log_sys_debug("read", vdo_path);
goto err;
}
memcpy(&vn, buffer + sizeof(struct vdo_geometry_block), sizeof(vn));
_vdo_decode_version(&vn);
if (vn.major_version > 41) {
log_debug_activation("Unknown VDO component version %u.", vn.major_version); // should be 41!
goto err;
}
memcpy(&pvc, buffer + sizeof(struct vdo_geometry_block) + sizeof(vn), sizeof(pvc));
_vdo_decode_pvc(&pvc);
if (pvc.nonce != vg.nonce) {
log_debug_activation("VDO metadata has mismatching VDO nonces " FMTu64 " != " FMTu64 ".", pvc.nonce, vg.nonce);
goto err;
}
#if 0
log_debug_activation("LogBlocks " FMTu64 ".", pvc.config.logical_blocks);
log_debug_activation("PhyBlocks " FMTu64 ".", pvc.config.physical_blocks);
log_debug_activation("SlabSize " FMTu64 ".", pvc.config.slab_size);
log_debug_activation("RecJourSize " FMTu64 ".", pvc.config.recovery_journal_size);
log_debug_activation("SlabJouSize " FMTu64 ".", pvc.config.slab_journal_blocks);
#endif
*logical_blocks = pvc.config.logical_blocks;
r = true;
err:
(void) close(fh);
return r;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2018 Red Hat, Inc. All rights reserved.
* Copyright (C) 2018-2022 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
@ -18,82 +18,117 @@
#include "vdo_limits.h"
#include "target.h"
/* validate vdo target parameters and 'vdo_size' in sectors */
bool dm_vdo_validate_target_params(const struct dm_vdo_target_params *vtp,
uint64_t vdo_size)
{
bool valid = true;
/* 512 or 4096 bytes only ATM */
if ((vtp->minimum_io_size != 1) &&
(vtp->minimum_io_size != 8)) {
log_error("VDO minimum io size %u is unsupported.",
if ((vtp->minimum_io_size != (512 >> SECTOR_SHIFT)) &&
(vtp->minimum_io_size != (4096 >> SECTOR_SHIFT))) {
log_error("VDO minimum io size %u is unsupported [512, 4096].",
vtp->minimum_io_size);
valid = false;
}
if ((vtp->block_map_cache_size_mb < DM_VDO_BLOCK_MAP_CACHE_SIZE_MINIMUM_MB) ||
(vtp->block_map_cache_size_mb > DM_VDO_BLOCK_MAP_CACHE_SIZE_MAXIMUM_MB)) {
log_error("VDO block map cache size %u out of range.",
vtp->block_map_cache_size_mb);
log_error("VDO block map cache size %u MiB is out of range [%u..%u].",
vtp->block_map_cache_size_mb,
DM_VDO_BLOCK_MAP_CACHE_SIZE_MINIMUM_MB,
DM_VDO_BLOCK_MAP_CACHE_SIZE_MAXIMUM_MB);
valid = false;
}
if ((vtp->block_map_era_length < DM_VDO_BLOCK_MAP_ERA_LENGTH_MINIMUM) ||
(vtp->block_map_era_length > DM_VDO_BLOCK_MAP_ERA_LENGTH_MAXIMUM)) {
log_error("VDO block map era length %u is out of range [%u..%u].",
vtp->block_map_era_length,
DM_VDO_BLOCK_MAP_ERA_LENGTH_MINIMUM,
DM_VDO_BLOCK_MAP_ERA_LENGTH_MAXIMUM);
valid = false;
}
if ((vtp->index_memory_size_mb < DM_VDO_INDEX_MEMORY_SIZE_MINIMUM_MB) ||
(vtp->index_memory_size_mb > DM_VDO_INDEX_MEMORY_SIZE_MAXIMUM_MB)) {
log_error("VDO index memory size %u out of range.",
vtp->index_memory_size_mb);
log_error("VDO index memory size %u MiB is out of range [%u..%u].",
vtp->index_memory_size_mb,
DM_VDO_INDEX_MEMORY_SIZE_MINIMUM_MB,
DM_VDO_INDEX_MEMORY_SIZE_MAXIMUM_MB);
valid = false;
}
if ((vtp->slab_size_mb < DM_VDO_SLAB_SIZE_MINIMUM_MB) ||
(vtp->slab_size_mb > DM_VDO_SLAB_SIZE_MAXIMUM_MB)) {
log_error("VDO slab size %u out of range.",
vtp->slab_size_mb);
log_error("VDO slab size %u MiB is out of range [%u..%u].",
vtp->slab_size_mb,
DM_VDO_SLAB_SIZE_MINIMUM_MB,
DM_VDO_SLAB_SIZE_MAXIMUM_MB);
valid = false;
}
if ((vtp->max_discard < DM_VDO_MAX_DISCARD_MINIMUM) ||
(vtp->max_discard > DM_VDO_MAX_DISCARD_MAXIMUM)) {
log_error("VDO max discard %u out of range.",
vtp->max_discard);
log_error("VDO max discard %u is out of range [%u..%u].",
vtp->max_discard,
DM_VDO_MAX_DISCARD_MINIMUM,
DM_VDO_MAX_DISCARD_MAXIMUM);
valid = false;
}
if (vtp->ack_threads > DM_VDO_ACK_THREADS_MAXIMUM) {
log_error("VDO ack threads %u out of range.", vtp->ack_threads);
log_error("VDO ack threads %u is out of range [0..%u].",
vtp->ack_threads,
DM_VDO_ACK_THREADS_MAXIMUM);
valid = false;
}
if ((vtp->bio_threads < DM_VDO_BIO_THREADS_MINIMUM) ||
(vtp->bio_threads > DM_VDO_BIO_THREADS_MAXIMUM)) {
log_error("VDO bio threads %u out of range.", vtp->bio_threads);
log_error("VDO bio threads %u is out of range [%u..%u].",
vtp->bio_threads,
DM_VDO_BIO_THREADS_MINIMUM,
DM_VDO_BIO_THREADS_MAXIMUM);
valid = false;
}
if ((vtp->bio_rotation < DM_VDO_BIO_ROTATION_MINIMUM) ||
(vtp->bio_rotation > DM_VDO_BIO_ROTATION_MAXIMUM)) {
log_error("VDO bio rotation %u out of range.", vtp->bio_rotation);
log_error("VDO bio rotation %u is out of range [%u..%u].",
vtp->bio_rotation,
DM_VDO_BIO_ROTATION_MINIMUM,
DM_VDO_BIO_ROTATION_MAXIMUM);
valid = false;
}
if ((vtp->cpu_threads < DM_VDO_CPU_THREADS_MINIMUM) ||
(vtp->cpu_threads > DM_VDO_CPU_THREADS_MAXIMUM)) {
log_error("VDO cpu threads %u out of range.", vtp->cpu_threads);
log_error("VDO cpu threads %u is out of range [%u..%u].",
vtp->cpu_threads,
DM_VDO_CPU_THREADS_MINIMUM,
DM_VDO_CPU_THREADS_MAXIMUM);
valid = false;
}
if (vtp->hash_zone_threads > DM_VDO_HASH_ZONE_THREADS_MAXIMUM) {
log_error("VDO hash zone threads %u out of range.", vtp->hash_zone_threads);
log_error("VDO hash zone threads %u is out of range [0..%u].",
vtp->hash_zone_threads,
DM_VDO_HASH_ZONE_THREADS_MAXIMUM);
valid = false;
}
if (vtp->logical_threads > DM_VDO_LOGICAL_THREADS_MAXIMUM) {
log_error("VDO logical threads %u out of range.", vtp->logical_threads);
log_error("VDO logical threads %u is out of range [0..%u].",
vtp->logical_threads,
DM_VDO_LOGICAL_THREADS_MAXIMUM);
valid = false;
}
if (vtp->physical_threads > DM_VDO_PHYSICAL_THREADS_MAXIMUM) {
log_error("VDO physical threads %u out of range.", vtp->physical_threads);
log_error("VDO physical threads %u is out of range [0..%u].",
vtp->physical_threads,
DM_VDO_PHYSICAL_THREADS_MAXIMUM);
valid = false;
}
@ -120,10 +155,10 @@ bool dm_vdo_validate_target_params(const struct dm_vdo_target_params *vtp,
valid = false;
}
if (vdo_size >= (DM_VDO_LOGICAL_SIZE_MAXIMUM_MB * UINT64_C(1024 * 2))) {
log_error("VDO logical size is by " FMTu64 "KiB bigger then limit " FMTu64 "TiB.",
(vdo_size - (DM_VDO_LOGICAL_SIZE_MAXIMUM_MB * UINT64_C(1024 * 2))) / 2,
DM_VDO_LOGICAL_SIZE_MAXIMUM_MB / UINT64_C(1024) / UINT64_C(1024));
if (vdo_size > DM_VDO_LOGICAL_SIZE_MAXIMUM) {
log_error("VDO logical size is larger than limit " FMTu64 " TiB by " FMTu64 " KiB.",
DM_VDO_LOGICAL_SIZE_MAXIMUM / (UINT64_C(1024) * 1024 * 1024 * 1024 >> SECTOR_SHIFT),
(vdo_size - DM_VDO_LOGICAL_SIZE_MAXIMUM) / 2);
valid = false;
}

24
doc/Problems.mdwn Normal file
View File

@ -0,0 +1,24 @@
# Common problems
## Duplicate PVs in the system
LVM tries to detect the common sources of duplicates, mdadm RAID and multipath,
there are cases where duplicate PV appears on the system.
There are two solutions to this problem:
* Setting a *global_filter* configuration option.
* Using of *devices_file* (See [lvmdevices(8)](https://man7.org/linux/man-pages/man8/lvmdevices.8.html))
## Device Filtering
*filter* and *global_filter* are meant to be used in two ways:
* as an allow list, listing patterns for devices which will be accepted
* `a|/dev/sdX|`, and rejecting the rest `r|.*|`,
* as a reject list, listing only patterns for devices which will be rejected
* `r|/dev/sdX|`,
Even though there are situations where it works, mixing reject and accept
patterns is not recommended.

34
doc/README.mdwn Normal file
View File

@ -0,0 +1,34 @@
LVM2 Wiki Documentation
=======================
If you are looking for information about LVM2 visit the [[Index]] page,
There are only some notes about writing stuff under *./doc* here:
* If possible use [[MarkDown]] for formatting, use *.md* (or *.mdwn*) suffix.
* For linking between files, use [[IkiWiki]] syntax `[[FileName]]` or
`[[FileName#Anchor]]`, or `[[link text|FileName]]`
Markdown
--------
* Use `<!-- comment -->` to keep notes, which will not be rendered.
* Use `[[TODO]]` for anything what needs attention. This will be accessible
through the linked [[TODO]] page.
IkiWiki
-------
* Install ikiwiki:
yum install ikiwiki
* To generate the content, run following in the LVM2 top directory:
ikiwiki --setup ikiwiki.setup
Internal Stuff:
---------------
* [[TODO]] Can we have a section which is hidden by default? Like this one?
* [[TODO]] Add basic IkiWiki and MarkDown How To.

152
doc/index.mdwn Normal file
View File

@ -0,0 +1,152 @@
# LVM - Logical Volume Manager for Linux
<!--
* TODO: Add banner for Important News: Critical Bugs, Important Announcements,...
-->
<!--
* TODO: Add a feed for latest articles/release-notes on the right
-->
<!--
## About LVM2
-->
LVM aka LVM2 refers to the userspace toolset that provide logical volume
management facilities on linux.
<!--
It is reasonably backwards-compatible with the
original LVM1 toolset.
* TODO: Add information about LVM1 metadata format conversion!
-->
LVM offers more flexibility than using partitions, allowing one to
* grow and, where supported by filesystem, shrink volumes,
* create snapshots of existing volumes,
* mirror data on multiple disks including RAID levels 5 or 6,
* striping data on multiple disks,
* create a read or write cache.
To use LVM2 you need 3 things:
* [device-mapper](https://sourceware.org/dm/) in your kernel (upstream since long ago)
* the userspace device-mapper support library (*libdevmapper*) (part of lvm2)
* and the userspace LVM2 tools.
## Getting LVM
Most of linux distribution offer packaged LVM tools.
Depending on your distribution use
# RPM based distributions (Fedora):
yum install lvm2
# DEB based distributions (Debian, Ubuntu):
apt-get install lvm2
Tarballs of the userspace LVM2 source code releases are available from [sourceware.org](https://sourceware.org/pub/lvm2/) [ftp](ftp://sourceware.org/pub/lvm2/).
List of official [mirror sites](https://sourceware.org/mirrors.html) (including http and rsync protocols).
### LVM Releases
[[!inline pages="release-notes/2.03.* and !*/template and !*/Discussion and !tagged(draft) and !tagged(pending)" limit=2 rootpage="release-notes"]]
[[More releases|release-notes/index]]
## Getting Started
<!--
TODO: We are missing a lvm(7) man page explaining this, I think it would be a nic addition!
And perhaps so would be a lvmtroubleshooting(7) guide.
-->
Word of warning first! Even though LVM errs on the side of data safety it is a
tool with low level access and one may seriously harm their data when used
incorrectly!
* Physical Volume (PV) is underlying disk, local or remote, encrypted or even
a mdadm RAID volume. PV is divided into so called Physical Extents (PE) which
are a basic allocation unit.
List PVs using [pvs(8)](https://man7.org/linux/man-pages/man8/pvs.8.html) or
[pvdisplay(8)](https://man7.org/linux/man-pages/man8/pvdisplay.8.html).
Make one by running `pvcreate /dev/sdX`.
See [pvcreate(8)](https://man7.org/linux/man-pages/man8/pvcreate.8.html). This step is optional.
* Volume Group (VG) consisting of one or more PVs is used as a pool from which LVs are allocated.
List VGs using [vgs(8)](https://man7.org/linux/man-pages/man8/vgs.8.html) or
[vgdisplay(8)](https://man7.org/linux/man-pages/man8/vgdisplay.8.html).
Make one by running `vgcreate VGNAME /dev/sdX...`, add PVs to existing one by `vgextend VGNAME /dev/sdX`.
To use LVM at least one Volume Group must be present on the system.
See [vgcreate(8)](https://man7.org/linux/man-pages/man8/vgcreate.8.html), and
[vgextend(8)](https://man7.org/linux/man-pages/man8/vgextend.8.html).
* Logical Volume (LV) is the block device usually visible to user to be used for file system.
List PVs using [lvs(8)](https://man7.org/linux/man-pages/man8/lvs.8.html) or
[lvdisplay(8)](https://man7.org/linux/man-pages/man8/lvdisplay.8.html).
Make one by running `lvcreate [-n LVNAME] -L SIZE VGNAME`, and you are done!
See [vgcreate(8)](https://man7.org/linux/man-pages/man8/vgcreate.8.html).
## Avoiding Problems
Good start is to avoid using `{--force|-f}` and `{--yes|-y}` options which are
often seen on internet discussions.
there is a possibility of data loss, LVM tools usually ask, so read the prompts
carefully! Using `--yes` removes these safety.
Also in some cases where it is too dangerous to proceed, e.g. device is used,
LVM refuses to do so, which can be overridden by `--force`.
Second, when resizing and especially when shrinking LVs it is always a good
idea to use `--resizefs` option which ensures the devices are resized in
correct order.
Third, if you still make a mess, never ever run fsck on damaged LV/FS, this is
usually the final blow to your data. It is always better to ask first!
## Documentation
## Resolving Problems
* Backup if possible!
* Search the problem first, check the list of [[common problems|Problems]]
* Never run `fsck` on damaged LV, LV must be recovered first!
* When asking for help describe exactly how the system got corrupted. It really
does not help trying to cover one's mistakes in such situation, it takes
longer to get help and also you are likely to get wrong answer making repair
impossible.
## Reporting Bugs
* When you find a problem there is often something specific about your system.
If the problem is reproducible run the failing command(s) with verbose flag
`-vvvv` which gives developers clue where the problem might be.
There is a [lvmdump(8)](https://man7.org/linux/man-pages/man8/lvmdump.8.html)
tool to help collect data about your system, block devices and LVM setup.
* Please report upstream bugs or request features in [Red Hat Bugzilla](https://bugzilla.redhat.com/enter_bug.cgi?product=LVM%20and%20device-mapper)
<!--
TODO:
* Add links to other documentation
* Add links to git
* Add links to mailing lists
* Resolving problems
* Backup if possible!
* Newer run fsck! Do the research first!
* List of Common issues
* Resizing in wrong order
* Thin pool running out of space
* Configuration - duplicates
* Mailing list
* IRC?
* Reporting Bugs
* sosreport/lvmdump
* BZ
* Contributing
* gitlab MR
* Add latest articles
-->

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