1
0
mirror of git://sourceware.org/git/lvm2.git synced 2026-01-04 00:32:47 +03:00

Compare commits

..

681 Commits

Author SHA1 Message Date
David Teigland
37a628db52 lvmlockd: use persistent reservations for lock recovery in sanlock 2025-09-18 14:02:06 -05:00
David Teigland
687b1a780f persist: support --setpersist in vgcreate
Previously, setpersist was only supported in vgchange
on an existing VG.  The PR is acquired exclusively before
the devices are modified, and in the case of a shared
VG the PR is subsequently changed to a shared mode.
2025-09-17 15:46:54 -05:00
David Teigland
57bf48c058 persist: use vgid in the key file name
adding a new helper function to create key file path.

Including vgid protects against cases of reading a
stale key file that was left over from a previous VG
with the same name.
2025-09-17 12:28:30 -05:00
David Teigland
ab1405034d persist: vgremove should check for other keys
vgremove should check for keys registered by other hosts
before removing the VG to avoid leaving dangling PR keys
on devices.  This involves refactoring the related commit
ca6fe99162 "lvmpersist: fix vgremove when another key is registered"
that separated persist_stop into before and after parts.
2025-09-17 11:38:08 -05:00
Peter Rajnoha
1f18ee1388 scripts: lvresize-fs-helper.sh: logmsg and not fail if unable to get XFS mount options for remount 2025-09-17 14:36:48 +02:00
Peter Rajnoha
f5852f2c9e WHATS_NEW: update 2025-09-17 12:16:26 +02:00
Peter Rajnoha
b6df5bf9d6 tests: lvresize-xfs: test quota mount options are preserved 2025-09-17 11:57:12 +02:00
Peter Rajnoha
55fda3afa5 scripts: lvresize-fs-helper.sh: detect and use proper quota mount options for XFS
When an XFS file system was previously mounted with quota mount options
(combination of -o uquota,gquota,pgquota) and then we are mounting the
file system as part of the lvresize/lvextend operation (through the fs
resize helper script), we need to preserve the quota mount options.

Otherwise, the XFS would need to recheck quotas - in that case the kernel
log contains:

  XFS (<device>): Quotacheck needed: Please wait.

This may take a long time, depending on the file system size.

Related issue: https://github.com/lvmteam/lvm2/issues/182
2025-09-17 11:57:02 +02:00
Arnout Engelen
6013977043 man: simplify vmautoactivation(7)
Previously this was hard-coded to: "Autoactivation commands use a number
of temp files in /run/lvm (with the expectation that /run is cleared
between boots.)"

Since c1bfc8737f it was made more generic,
but on some systems this logic leads to "Autoactivation commands use a
number of temp files in /run/lvm (with the expectation that /var/run
is cleared between boots)." which I'd say adds more confusion than it
solves.
2025-09-16 15:31:26 +00:00
David Teigland
b4a49811cd persist: fix start/stop with vgchange ay/an
vgchange -ay --persist start
	wasn't working, and should exclude shared VGs.
vgchange -an --persist stop
	code was missing for this case.
2025-09-12 15:20:42 -05:00
Zdenek Kabelac
09ceb425b7 make: generate 2025-09-12 14:23:35 +02:00
Zdenek Kabelac
fb708004fe man: print better arg for persist
As man pages now tend to print options as man macro reference,
we may still need some local 'specialization'.

ATM --persist option is known expection where command may accept only
certain argument to be recognized/allowed - so generic String printed
in Italic can be replaced with just specific argument printed in Bold.

TODO: recognize only cases where the 'generic' String is NOT used and
for rest of them use the common O_persist macro reference.
2025-09-12 14:23:14 +02:00
Zdenek Kabelac
b9e6337f04 codespell: typos 2025-09-11 16:18:19 +02:00
Marian Csontos
edd8b52967 doc: Few fixes and additions in pages
(cherry picked from commit 4561756bda8a0b5417c7cf5df269bb37af6eaec5)
2025-09-11 16:12:39 +02:00
David Teigland
58c534ba57 lvmpersist: fix remove exit code if an invalid local key is specified
Exit with an error if the wrong local key is specified.
2025-09-10 15:56:45 -05:00
Marian Csontos
5e6ff6f446 post-release 2025-09-09 14:22:01 +02:00
Marian Csontos
38c1124a47 pre-release 2.03.35 2025-09-09 14:19:37 +02:00
Marian Csontos
f83ad85b16 doc: Update WHATS_NEW and release-notes 2025-09-09 14:17:35 +02:00
Marian Csontos
cf2b027d47 spec: Install /var/lib/lvm directory 2025-09-09 14:16:55 +02:00
Zdenek Kabelac
ba16339bc4 test: update with unresizable kernels
These kernels do miss fixing commit for mdraid resize to work.
2025-09-08 14:35:55 +02:00
Zdenek Kabelac
6db8e63996 test: thin monitoring optimization 2025-09-08 14:35:55 +02:00
David Teigland
5b410e589c lvmlockd: always free ls struct after ls thread exits
The ls struct was being freed after ls thread exit for common stop,
but was missing when the ls thread was stopped for drop and rename.
Also free ls->actions structs in case any still exist.
2025-09-05 13:22:14 -05:00
David Teigland
a93729b004 lvmpersist: fix key file for vgrename and vgremove 2025-09-05 13:22:11 -05:00
David Teigland
ce5d7d11b3 lvmpersist: print other key blocking start 2025-09-02 16:10:08 -05:00
David Teigland
cb72f6217e lvmpersist: fix check for no keys on mpath device 2025-09-02 12:55:46 -05:00
David Teigland
59fb9f5d3a lvmpersist: allow deactivation without PR 2025-09-02 12:44:59 -05:00
Zdenek Kabelac
be3224b3f5 dmstats: fix parsing of list regions
Replace %4095c sscanf format specifier with position-based copying.

The _stats_parse_list_region() function previously used %4095c to read
the remaining part of the input buffer. Recent glibc versions
(2.42.9000-3.fc44) have changed the behavior of this format
specifier to align with C standard specifications, which affects
parsing when the buffer contains fewer than 4095 characters.

To ensure compatibility across different glibc versions, switch to
using %n to track the parsing position and manually copy the string
data using dm_strncpy().

Note: Binaries compiled with the previous implementation may experience
compatibility issues with newer glibc versions.
2025-09-02 00:05:33 +02:00
Zdenek Kabelac
5f8b2e0e53 dmeventd: ignore result of pthread_cond_timedwait()
Used just for some sleep....
2025-09-01 13:40:34 +02:00
Zdenek Kabelac
ed8d913c78 dmeventd: simplify grace period synchronization
Remove per-thread grace_mutex and use existing global_mutex
with per-thread condition variables.

We separate take of grace mutex there was slight race chance
of hitting wait condition while 2nd. thread already signaled wakeup.

With the use of global mutex (which must be held before and after
anyway), there is no such race chance even possible.
2025-09-01 13:34:10 +02:00
Zdenek Kabelac
b2cd886a12 dmeventd: handle case for missing udev link
With old systems we cannot always check /dev/mapper/vg-lv name,
as those might be symlinks managed by udev. However monitoring
is not 'synchronized' with udev as dmventd API is major:minor
based and does not needed symlinks. So to 'compensate' this
and make just 'old system' working - just check also for
presence of /dev/dm-X device.
2025-08-31 21:35:01 +02:00
Zdenek Kabelac
279d3feaae dmeventd: simplify _grace_period
Use plain 'int' time - so it doesn't make problems
on some archs (x32) printing time_t.
Also drop ret asign from pthread_cond_timedwait().
2025-08-29 22:03:09 +02:00
Zdenek Kabelac
ee32cabd0f dmeventd: fix inode check for old kernels <3.x
Improve _get_device_inode() function with kernel version check

For kernel >=3: Use sysfs path format (/sys/dev/block/major:minor).
For kernel <3: Use /dev/mapper device path format.

Add explicit handling for very old kernels (<3.x) that don't change
inode numbers for /sys  device-mapper devices.
2025-08-29 21:45:22 +02:00
David Teigland
ca6fe99162 lvmpersist: fix vgremove when another key is registered
For vgremove, split persist stop steps into:
1. prepare, which gets the pr key and VG devices,
   and happens before the normal vgremove.
2. run, which removes pr key from the VG devices,
   and happens after the normal vgremove.

This is necessary if another PR key is registered on the device
(which likely doesn't happen in the normal usage pattern, but is
still possible.)

When another key exists, removing the local PR key will cause the
machine to lose the ability to write VG metadata to the device.
So, the removal of the local PR key must happen after the VG metadata
is written for vgremove.  The prepare step must remain at the beginning
of the command, while the list of PVs in the VG still exists.
2025-08-29 13:59:28 -05:00
Peter Rajnoha
d89869f17e tools: pvchange: unlock devices file at the end of cmd processing
Remove the line, not just comment out.
2025-08-29 13:50:20 +02:00
Peter Rajnoha
16d3195a69 tools: pvchange: unlock devices file at the end of cmd processing
Unlock devices file at the end of cmd processing, after all the PVs are
processed, not after the first processed PV.

Before this patch:

❯  pvchange -u /dev/sda /dev/sdb
  Physical volume "/dev/sda" changed
  WARNING: Devices file unlock no fd.
  Physical volume "/dev/sdb" changed
  2 physical volumes changed / 0 physical volumes not changed

With this patch applied:

❯  pvchange -u /dev/sda /dev/sdb
  Physical volume "/dev/sda" changed
  Physical volume "/dev/sdb" changed
  2 physical volumes changed / 0 physical volumes not changed

The lvm_run_command/devices_file_exit/unlock_devices_file will
do the unlock at the very end of cmd processing.
2025-08-29 13:47:53 +02:00
Zdenek Kabelac
63250dfe8d dmeventd: fixes for grace period timer
Fix several problems in recent dmeventd grace period enhancement:

1. **Timer reset bug**: Threads exiting grace period were starting
   time period with rather random time 'offset' causing change
   in behavior and firing monitor action in non-deterministic time.
   Reset timer (next_time = current_time + timeout) AFTER grace
   period wait.

2. **Device identity verification**: Add inode tracking to prevent
   incorrect thread reuse when device UUID is recycled. Grace period
   thread lookup now verifies device inode matches to ensure same
   physical device. This avoid reusing of monitored values for
   a different device.
   'diskseq' was also considered as unique identifier, but inode
   check seems to be easier to check and is not 'so new'.
   Also another solution could have been to change dmeventd protocol,
   and introduce supend/resume calls - but this could be another source
   of problem.

3. **Signal handling order**: Move SIGALRM reset to occur BEFORE
   entering grace period instead of after. This prevents potential
   error path trouble that may have shutdown reused thread causing
   the actual monitoring to be silently lost.

4. **Event state cleanup**: Clear current_events before grace period
   to prevent stale event processing after thread reuse.

Note: wondering if there can be any problem with inode check....
2025-08-28 15:17:19 +02:00
David Teigland
47118a45bd man lvmpersist: shared VGs with locktype dlm work with PR 2025-08-25 12:39:39 -05:00
David Teigland
7086da4335 vgchange persist stop: use lockopt force to skip lockstop check
vgchange --persist stop requires locking to first be stopped
(vgchange --lockstop).  Allow setting --lockopt force to bypass
this check so that PR can be forcibly stopped.
2025-08-25 12:33:24 -05:00
David Teigland
4d8819218e lvmpersist: fix device support check
Fix commit b2bc06caf8
"lvmpersist: check devices support PR before certain commands"

which broke clear and read commands.  Change to skip individual
devices in clear/read if they don't support PR.
2025-08-25 12:16:41 -05:00
David Teigland
8dcdcc54b4 man lvmpersist: improve description 2025-08-25 10:55:09 -05:00
Marian Csontos
436778f6df toollib: proper error path handling 2025-08-19 15:56:21 +02:00
Peter Rajnoha
881df5e071 tools: allow --reportformat for pv/vg/lvdisplay log report
The pv/vg/lvdisplay (without -C|--columns) does not use the reporting
mode for the output. However, we can still allow the --reportformat
option for these commands, but it will affect only the log report,
like we have for other non-reporting lvm commands
(e.g. lvchange,vgchange...).
2025-08-19 10:54:21 +02:00
David Teigland
e61aab7049 lvmdevices: do not create system.devices when deleting entries
When using "lvmdevices --deldev" or "lvmdevices --delpvid" and no
system.devices file exists, the commands should not create the file.
2025-08-14 16:30:34 -05:00
David Teigland
b2bc06caf8 lvmpersist: check devices support PR before certain commands
Produce a proper error message, avoiding an ugly jq null list
error when handling nvme devs that do not support PR.
2025-08-14 16:27:09 -05:00
David Teigland
95e7e48d86 vgchange: setpersist enabling should check if PR works on devs
attempt to read PR keys from VG devs before enabling PR on the VG
to ensure PR works.
2025-08-14 16:03:32 -05:00
Peter Rajnoha
4380986053 tests: update listings.sh
Test further reporting options that can be used only with -C|--columns
for pv/vg/lvdisplay.
2025-08-13 13:58:37 +02:00
Peter Rajnoha
bada07d267 WHATS_NEW: update 2025-08-13 13:43:20 +02:00
Peter Rajnoha
ae75b70e5b toollib: also initialize processing handle in process_each_pv
Just like process_each_vg and process_each_lv, the top-level process_each_pv
should also initialize the processing handle (if the handle not already passed
as argument for use). This is mainly important, among others, for proper
log_report tracking and proper output formatting.

For example:

Before this patch - there are two "log" sections as the processing handle is
initialized dynamically more times if not passed explicitly from the top-level
process_each_pv function:

❯  pvdisplay --config 'log/report_command_log=1 report/output_format=json'
  {
      "log": [
          ...
      ]
  }
  {
      "log": [
         ...
      ]
  }

❯  pvdisplay --config 'log/report_command_log=1 report/output_format=json' | jsonlint
<stdin>:17:2: Error: Unexpected text after end of JSON value
   |  At line 17, column 2, offset 4463
<stdin>: has errors

With this patch applied:

❯  pvdisplay --config 'log/report_command_log=1 report/output_format=json'
  {
      "log": [
          ...
       ]
  }

❯  pvdisplay --config 'log/report_command_log=1 report/output_format=json' | jsonlint
<stdin>: ok
2025-08-13 13:10:11 +02:00
Peter Rajnoha
e04e784575 make: generate 2025-08-13 13:10:11 +02:00
Peter Rajnoha
b1462ea09b tools: allow report options only with pv/vg/lvdisplay -C|--columns
--configreport, --logonly, --reportformat and --select options can be
used only if -C|--columns is used at the same time. These options are
only to control the reporting infrastructure. We switch to reporting
mode using that -C|--columns switch.

Using the options for reporting mode if reporting is not initiated
(using the -C|--columns switch) can cause various issues and
inconsistencies in the output.

See also https://github.com/lvmteam/lvm2/issues/144.
2025-08-13 13:07:35 +02:00
Peter Rajnoha
6d8585c249 dmeventd: fix error with older compilers 2025-08-12 14:14:00 +02:00
Peter Rajnoha
9b95252a94 dmeventd: fix error with older compilers
dmeventd.c:97: error: initializer element is not constant
2025-08-12 14:11:24 +02:00
Peter Rajnoha
01fda7092a tests: vgsplit-cache: remove the splitted VG 2025-08-12 13:25:03 +02:00
Peter Rajnoha
8a8660107e WHATS_NEW: update 2025-08-12 13:23:28 +02:00
Peter Rajnoha
d75361f445 tests: vgsplit-cache: also test splitting a PV not used for cachevol LV 2025-08-12 13:00:26 +02:00
Peter Rajnoha
3fe57cc892 vgsplit: fix check for not splitting an LV between two VGs for cachevol
When cachevol was used for the cache LV, the check for not splitting an
LV between two VGs was incorrect, not allowing to split the VG in cases
it should have been possible.

For example, splitting a VG which contains the cache LV with cachevol
only on two devices (sda and sdb here) and leaving third device completely
unused (sdc here) should clearly allow us to split it into a new VG:

❯  vgcreate vg /dev/sd{a..c}
  Physical volume "/dev/sda" successfully created.
  Physical volume "/dev/sdb" successfully created.
  Physical volume "/dev/sdc" successfully created.
  Volume group "vg" successfully created

❯  lvcreate -l2 -n main vg /dev/sda
  Logical volume "main" created.

❯  lvcreate -l2 -n fast vg /dev/sdb
  Logical volume "fast" created.

❯  lvconvert -y --type cache --cachevol fast vg/main
  Logical volume vg/main is now cached.

❯  lvs -a -o name,devices vg
  lv_name      devices
  [fast_cvol]  /dev/sdb(0)
  main         main_corig(0)
  [main_corig] /dev/sda(0)

❯  lsblk -o name /dev/sd{a..c}
NAME
sda
└─vg-main_corig
  └─vg-main
sdb
└─vg-fast_cvol
  ├─vg-fast_cvol-cdata
  │ └─vg-main
  └─vg-fast_cvol-cmeta
    └─vg-main
sdc

Before this patch:

❯  vgsplit vg vg2 /dev/sdc
  Logical volume vg/main must be inactive.

❯  vgchange -an vg
  0 logical volume(s) in volume group "vg" now active

❯  vgsplit vg vg2 /dev/sdc
  Can't split LV main between two Volume Groups

With this patch applied:

❯  vgsplit vg vg2 /dev/sdc
  New volume group "vg2" successfully split from "vg"
2025-08-12 13:00:17 +02:00
Mikulas Patocka
77f1809ddf test integrity.sh use writemostly to reliably detect mismatches
The test shell/integrity.sh creates raid arrays, corrupts one of the
legs, then reads the array and verifies that the corruption was
corrected. Finally, the test tests that the number of mismatches on the
corrupted leg is non-zero.

The problem is that the raid1 implementation may freely choose which leg
to read from. If it chooses to read the non-corrupted leg, the corruption
is not detected, the number of mismatches is not incremented and the test
reports this as failure.

Fix this failure by marking the non-corrupted leg as "writemostly", so
that the kernel doesn't try to read it (it reads it only if it finds
corruption on the other leg).

Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
2025-08-11 11:35:37 -05:00
David Teigland
b32b830f95 Revert "test integrity.sh cannot rely on mismatches being detected for raid1"
This reverts commit e50e59ae42.
2025-08-11 11:27:06 -05:00
David Teigland
3dc5c3fc9e lvmlockd: --lockopt was mistakenly ignored when --nolocking was set 2025-08-08 14:06:24 -05:00
Mikulas Patocka
e50e59ae42 test integrity.sh cannot rely on mismatches being detected for raid1
The test shell/integrity.sh creates raid arrays, corrupts one of the
legs, then reads the array and verifies that the corruption was
corrected. Finally, the test tests that the number of mismatches on the
corrupted leg is non-zero.

The problem is that the raid1 implementation may freely choose which leg
to read from. If it chooses to read from the non-corrupted leg, the
corruption is not detected, the number of mismatches is not incremented
and the test reports this as a failure.

Fix the test by not checking the number of integrity mismatches for
raid1.
2025-08-07 10:56:45 -05:00
Peter Rajnoha
5fe7d1150d test: vgsplit-raid: also test RAID LVs with integrity 2025-08-04 13:20:54 +02:00
Peter Rajnoha
1854556593 vgsplit: fix check for not splitting an LV between two VGs
Fix check for not splitting an LV between two VGs in case
where the LVs contains an internal layer.

For example, integrity layer for RAIDs and splitting a PV that
is not part of the RAID LV at all (sdc here):

❯  vgcreate vg /dev/sda /dev/sdb /dev/sdc
  Volume group "vg" successfully created

❯  lvcreate -l1 -m1 --type raid1 --raidintegrity y vg /dev/sda /dev/sdb
  Logical volume "lvol0" created.

Before this patch:

❯  vgsplit vg vg2 /dev/sdc
  Logical volume vg/lvol0_rimage_0 (part of lvol0) must be inactive.

❯  vgchange -an vg
  0 logical volume(s) in volume group "vg" now active

❯  vgsplit vg vg2 /dev/sdc
  Can't split LV lvol0_rimage_0 between two Volume Groups

With this patch applied:

❯  vgsplit vg vg2 /dev/sdc
  New volume group "vg2" successfully split from "vg"
2025-08-04 13:00:15 +02:00
Zdenek Kabelac
36a0b26054 test: aux starts dmeventd with small grace period
For our tests we expect very fast reaction.
So to keep i.e. reporting for the test 'lvextend-thin-metadata-dmeventd'
fast use just 2 seconds grace period (thread reuse).
2025-07-31 00:56:08 +02:00
Zdenek Kabelac
d9063048cb dmeventd: add thread grace period for monitoring
Add thread reuse mechanism to reduce overhead when devices are frequently
registered/unregistered by introducing a configurable grace period where
monitoring threads wait for potential reuse before termination.

Key changes:
- Add -g option to configure grace period (0-300 seconds, default: 10s)
- Introduce DM_THREAD_GRACE_PERIOD state for threads awaiting reuse
- Implement thread reuse for matching device/dso combinations
- Add pthread condition variables and mutexes for grace period synchronization
- Add thread usage counter and enhanced debug logging
- Add _reset_pending_signal() to handle SIGALRM cleanup on thread reuse
- Refactor _monitor_thread() to support grace period workflow
- Update timeout thread to skip non-running threads
- Simplify thin plugin logging

This optimization significantly reduces thread creation/destruction overhead
in scenarios with rapid device registration/unregistration cycles, such as
creating snapshots of thin volumes, while maintaining proper cleanup and
thread safety.
2025-07-31 00:46:38 +02:00
Zdenek Kabelac
c74ea97121 tests: update checked message
lvconvert output printed message was slighlty updated
2025-07-30 17:06:26 +02:00
Zdenek Kabelac
e7d6df8600 Revert "tests: Adapt RAID test to changes"
This reverts commit 53db14171c.
2025-07-30 17:06:22 +02:00
Marian Csontos
06c87e4f8a post-release 2025-07-30 15:34:41 +02:00
Marian Csontos
f6abf8abe2 pre-release 2.03.34 2025-07-30 15:34:41 +02:00
Zdenek Kabelac
a79085612d WHATS_NEW: update 2025-07-30 11:37:33 +02:00
Zdenek Kabelac
bfae3beef0 lvconvert: add non changing conversion message
Print message about raid/mirror conversion for case,
where the raid/mirror is already in the requested state.

This case currently returns success.
2025-07-30 11:37:33 +02:00
Zdenek Kabelac
2ecbfe0246 Revert "test: adjust lvconvert-raid.sh to now erroring non-changing image raid1 request"
This reverts commit ed13916859.
2025-07-30 11:37:33 +02:00
Zdenek Kabelac
aab17a04b4 Revert "test: fix invalid if-then-fi logic"
This reverts commit 612a22ac08.
2025-07-30 11:37:33 +02:00
Zdenek Kabelac
c868c1bbd8 Revert "test: adjust lvconvert-mirror-basic.sh to now erroring non-changing image mirror request"
This reverts commit 8e2cdcc006.
2025-07-30 11:37:33 +02:00
Zdenek Kabelac
4671f99bdc Revert "test: use proper if-then-fi sequence"
This reverts commit d2a66d4343.
2025-07-30 11:37:33 +02:00
Zdenek Kabelac
9636d15473 Revert "lvconvert: error mirror LV non-changing request"
This reverts commit 1593a6e47c.
2025-07-30 11:37:33 +02:00
Zdenek Kabelac
9ba6eaf702 Revert "lvconvert: error raid1 LV non-changing image count request"
This reverts commit c901528053.
2025-07-30 10:56:39 +02:00
Zdenek Kabelac
6a31246bdd dmeventd: _get_status returns success for non monitoring
No longer returning EINVAL when the dmeventd is not monitoring
any device (there are no registered devices).

This makes usable i.e. 'dmeventd -R' for the case, the dmeventd
was not monnitoring anything during this call.

Previously this actually cause refuse of 'restart' - since
restarting 'dmeventd' has seen failing resutl of a call:
DM_EVENT_CMD_GET_STATUS
2025-07-30 10:54:51 +02:00
David Teigland
c705eda4ad vgextend: fix dev_read_reservation message
Common vgextend commands were logging a message about
dev_read_reservation when PR was not being used.

Only attempt PR work from vgextend when either the
PR require or autostart settings are enabled on the VG.
2025-07-28 13:35:16 -05:00
David Teigland
8486aef090 nvme: fix log messages in dev_find_key_nvme
they were mistakenly logging as dev_read_reservation
2025-07-28 13:34:11 -05:00
Peter Rajnoha
f4398897a8 man: add note about return codes for LV resize with and without FS resize 2025-07-24 10:52:53 +02:00
Zdenek Kabelac
220f855e8a WHATS_NEW: update 2025-07-23 14:51:57 +02:00
Zdenek Kabelac
fa2ec32c4e dmeventd: add device existence check
Add device existence check after successful wait ioctl to prevent
processing events on removed devices.

When dm_task_run() succeeds on a WAITEVENT ioctl, the success might
actually indicate that the device was removed rather than a genuine
device event. Without this check, dmeventd would attempt to process
ERROR events on non-existent devices, leading to unnecessary error
commands and log noise.

This fix adds a _fill_device_data() call immediately after successful
wait completion to verify the device still exists. If the device is
gone, execution jumps to the existing ENXIO error path which properly
handles device disappearance.

Note: Future kernel versions may return ENXIO directly from the wait
ioctl when devices are removed, making this workaround unnecessary.
Until then, this extra INFO ioctl provides the needed verification.
2025-07-23 14:51:57 +02:00
Zdenek Kabelac
175a80157a dmeventd: check device exists
Check first whether the monitored device actually really exists,
before resolving its device name.

In the case device is not present in DM table, fail _fill_device_data().
2025-07-23 14:51:57 +02:00
Zdenek Kabelac
6c6fc6d507 dmeventd: update types in thin plugin
Use matching dm_percent_t type to store percent values.
2025-07-23 14:51:57 +02:00
Zdenek Kabelac
e30289c855 scripts: refactor lvmdump directory validation
Break down complex one-liner directory check into explicit steps with
clear error messages and comments.

The original code used a dense subshell expression combining multiple
tests with logical operators, making it difficult to understand and
maintain. This refactoring separates the logic into:

1. Check directory accessibility (read/write/execute permissions)
2. Check if directory is empty (including hidden files)

Each check now has a specific error message, making it easier for users
to understand what went wrong. The functionality remains identical, but
the code is now more maintainable and debuggable.

Changes:
- Split accessibility and emptiness checks into separate if statements
- Add descriptive comments explaining each validation step
- Provide specific error messages for different failure conditions
- Maintain original behavior including dotglob/nullglob handling
2025-07-23 14:51:57 +02:00
Zdenek Kabelac
af42fa8553 vdo: fix 32b portability issue in vdo_header struct
Replace size_t with uint64_t in struct vdo_header to ensure consistent
64-bit size field across all architectures.

On 32-bit platforms, size_t is only 4 bytes, which causes incorrect
structure layout when reading VDO metadata that expects a 64-bit size
field. This fix ensures the VDO header structure maintains the same
binary layout regardless of target architecture.

While 32-bit architectures are not officially supported for VDO,
this change improves code correctness and prevents potential issues
during cross-compilation or when building on 32-bit development
environments.
2025-07-23 14:51:57 +02:00
Peter Rajnoha
d5abc55fcf lvmdevices: log_error when writing devices file fails 2025-07-23 09:31:40 +02:00
Peter Rajnoha
80144223e7 device_id: log_warn instead of log_error in device_ids_write
It is not always the case that the whole command fails if
device_ids_write fail so change all log_error to log_warn and let the
caller decide.
2025-07-23 09:26:58 +02:00
Peter Rajnoha
222445f2dc test: lvresize-fs-crypt: test not enough space left for crypt data 2025-07-22 12:16:56 +02:00
Peter Rajnoha
986ff7b9cd WHATS_NEW: update 2025-07-22 09:46:39 +02:00
Peter Rajnoha
1cd2f35655 lvmdevices: return error if writing device ids fail for --delldev 2025-07-21 13:41:32 +02:00
Peter Rajnoha
03e3b27ba0 device_id: always log_error on device ids write error 2025-07-21 13:40:30 +02:00
Peter Rajnoha
5da3676ff3 lv_manip.c: fix lvresize corruption in LV->crypt->FS stack if near crypt min size limit
If we have LV->crypt->FS stack, check that the adjustment for the crypt
data offset will left space for the crypt data itself. Fix possible underflow.

Example:

❯  lvs -o name,size vg/lvol0
  lv_name lv_size
  lvol0   124.00m

❯  lsblk /dev/vg/lvol0
NAME     MAJ:MIN RM  SIZE RO TYPE  MOUNTPOINTS
vg-lvol0 252:2    0  124M  0 lvm
└─a      252:4    0  108M  0 crypt

Before this patch (the incorrect resulting underflowed file system size after adjustment
for crypt data offset, crypt data then severed by the LV resize without proper
crypt resize beforehand):

❯  lvreduce --yes --resizefs -L -123M  vg/lvol0
  Rounding size to boundary between physical extents: 120.00 MiB.
  Checking crypt device /dev/dm-4 on LV vg/lvol0.
  File system size 18446744073696968704b is adjusted for crypt data offset 16777216b.
  File system ext4+crypto_LUKS found on vg/lvol0.
  File system size (108.00 MiB) is smaller than the requested size (<16.00 EiB).
  File system reduce is not needed, skipping.
  crypt device is already reduced to 113246208 bytes.
  Size of logical volume vg/lvol0 changed from 124.00 MiB (31 extents) to 4.00 MiB (1 extents).
  Logical volume vg/lvol0 successfully resized.

With this patch applied:

❯  lvreduce --yes --resizefs -L -123M  vg/lvol0
  Rounding size to boundary between physical extents: 120.00 MiB.
  Checking crypt device /dev/dm-4 on LV vg/lvol0.
  Crypt header requires 16.00 MiB, not enough space left for crypt data.
2025-07-18 15:32:42 +02:00
Zdenek Kabelac
ff7f9ee113 test: simplify bash
Just check directly /proc/mdstat  - if it's missing or there is not
raid1 string present do 'modprobe'.
2025-07-17 22:18:42 +02:00
Zdenek Kabelac
457603e3f1 test: aux simplify bash condition 2025-07-17 22:18:42 +02:00
Zdenek Kabelac
ce71153788 test: report possibly issue for loop device remove
Warn if there are problems when removing loop devices.
Also use slightly smaller raid arrays with smaller extent size.
2025-07-17 22:18:42 +02:00
Zdenek Kabelac
8fd6300642 test: use proper DM_DEV_DIR
Use correct path - if the system does not have installed lvm udev rules
these /dev/vgname/lvname symlinks are not created - but test
running in test's dev dir gets symlinks created by lvm2 itself.
2025-07-17 22:18:42 +02:00
Zdenek Kabelac
f530425f56 test: simplify if logic
Easier to read set of  'if' conditions.
2025-07-17 22:18:42 +02:00
Zdenek Kabelac
612a22ac08 test: fix invalid if-then-fi logic
Replace incorrect test && lvconvert || lvconvert
Use simplier NOT.
2025-07-17 22:18:42 +02:00
Zdenek Kabelac
501efc7f3f test: raid tuning
Use slightly bigger PVs, so the raid takes a bit more time to fully
reshape arrays - so we avoid conversion to be finished to fast even
with slowered devices.

Grab blockdev size before calling 'lvs' command.
2025-07-17 22:18:42 +02:00
Zdenek Kabelac
550a84414b scripts: lvm_import_vdo simplier bash logic 2025-07-17 22:18:42 +02:00
Zdenek Kabelac
35a4eeebf0 scripts: blkdeactivate simplify bash
Use correct if-then-fi.
Use local IFS  instead handling ORIG_IFS.
2025-07-17 22:18:42 +02:00
Peter Rajnoha
6fa5510b65 revert: lv_manip: retuurn failure for LV resize without actual LV+FS resize
We have different behavior for lvreduce (contains the fs size
pre-check before calling the external script) and lvextend
(does not ave the pre-check).

Also, there's different behavior with "lvreduce --fs resize"
(contains the pre-check) and "lvreduce --fs resize_fsadm"
(does not have the pre-check).

Obvously, only "lvreduce --fs resize" does have the pre-check.
To make it consitent all across, we should remove that one
and everybody will be happy.
2025-07-17 12:07:06 +02:00
Peter Rajnoha
bc2e280e8e lv_manip: also track if FS resize executed when using fsadm 2025-07-17 10:25:11 +02:00
Peter Rajnoha
0b8716e25c lv_manip: add error message for size 0 after adjusting size for LV resize 2025-07-16 15:19:09 +02:00
Peter Rajnoha
ee62860b62 tests: resizing to same size is considered an error 2025-07-16 15:19:09 +02:00
Peter Rajnoha
9c599292aa lv_manip: return failure for LV resize without actual LV+FS resize
Also return failure if there is no change in file system size while
resizing an LV including the file system, lik with lvresize/lvreduce --fs resize'.
2025-07-16 15:18:05 +02:00
Zdenek Kabelac
2877232e24 WHATS_NEW: update 2025-07-16 12:37:48 +02:00
Zdenek Kabelac
eeaa3b2df3 test: some updates for valgrind run
Since execution with valgrind is much slower we need
to skip some 'race-based' tests.
2025-07-16 12:35:14 +02:00
Zdenek Kabelac
15c73e044e test: skip raid resizing on buggy kernel
Kernel without commit kernel commit 9f346f7d4ea73692b82f5102ca8698e4040469ea
cannot reasize raid LV without failing the raid itself.
So skip some tests for kernels 6.13 6.13 6.15.

TODO: maybe we want to print some warning message to the users
with affected kernels ??
2025-07-16 00:12:37 +02:00
Zdenek Kabelac
dedaa201a8 test: lvconvert-raid-reshape-size add verify udev
With the use of --noudevsync we actually need to also ensure
we verify link create - as without synchronization we are not
able to properly wait - so lvm2 needs to create links itself.
It's hack where it would be better to not use it - but so far
there is no easy fix.

Make skip variables easily overridable by setting make vars.
Also further reduce used PV sizes.
2025-07-16 00:12:21 +02:00
Zdenek Kabelac
65a997b985 debug: add message for noudevsync path
To avoid confusion, there is no synchronization of device names
when option --noudevsync is used. Make it obvious from debug trace.
2025-07-16 00:07:19 +02:00
Zdenek Kabelac
7b383df03e test: aux add more ignored dirs 2025-07-14 02:29:49 +02:00
Zdenek Kabelac
31cea1bbdc test: fix skipping of this repair test
Fix the usage of delay_dev so the test is properly executed
and not skiped. For major mirror slowdown use smalled region
sizes that are cause way more frequent commits so we can go
with significantly smaller delays.

Also check repair to work for failing mirror leg and mirror log.
2025-07-14 02:29:49 +02:00
Zdenek Kabelac
e4ef309d62 test: update for upper case warning
As WARNING consistency patch slighly change some reported messages,
update some tests (and use  'grep -i').
2025-07-14 02:29:49 +02:00
Zdenek Kabelac
4cf9077899 test: use same device match for btrfs testing
Copy the btrfs device matching from lvresize helper script.
2025-07-14 02:29:49 +02:00
Zdenek Kabelac
2539aadb50 lvresize: use major:minor to compare btrfs device
What we really do want to compare is devnode the device
name is actually using - this is uniq match.
2025-07-14 02:29:49 +02:00
Zdenek Kabelac
584d6aff95 WHATS_NEW: update 2025-07-13 20:55:43 +02:00
Zdenek Kabelac
04d75d7a63 make: generate 2025-07-13 20:55:43 +02:00
Zdenek Kabelac
6cb61996b6 configure: update autotools 2025-07-13 20:55:43 +02:00
Heinz Mauelshagen
527b54cb17 test: refactor lvconvert-raid-reshape-size.sh
Improve the RAID reshape size test script with the following changes:

**Code Quality Improvements:**
- Add proper shell quoting throughout the script to prevent word splitting issues
- Replace manual arithmetic with cleaner shell arithmetic syntax
- Improve variable handling and remove unnecessary local variable assignments
- Fix typo: "hilesystem" -> "filesystem"

**Test Reliability Enhancements:**
- Add EXTENSIVE_FSCK environment variable for optional additional filesystem validation
- Reduce delay times from 40ms/25ms to 20ms for all RAID types to speed up testing
- Add helper functions _delay_dev() and _restore_dev() for cleaner device delay management
- Use --noudevsync flag in lvconvert to avoid udev-related timing issues
- Remove unnecessary sleep calls and udevadm settle commands

**Functionality Improvements:**
- Improve _check_size() function to return proper exit codes instead of echo statements
- Better error handling in conditional statements using proper test syntax
- Cleaner parameter passing using "$@" instead of manual argument handling
- More robust device path handling using $DM_DEV_DIR consistently

**Code Structure:**
- Extract device delay logic into reusable helper functions
- Improve readability with better variable naming and consistent formatting
- Add explanatory comments for complex operations
2025-07-13 20:55:43 +02:00
Heinz Mauelshagen
cbd1918dce test: lvconvert-raid-reshape-size.sh return from _check_size 2025-07-13 20:55:43 +02:00
Heinz Mauelshagen
c53c895612 test: lvconvert-raid-reshape-size.sh only create PVs+VG once
Saves a few seconds in test run.
Add --noudevsync to save big time.
2025-07-13 20:55:43 +02:00
Heinz Mauelshagen
07bc54f333 test: lvconvert-raid-reshape-size.sh fix test bug 2nd
Up'ed millisecnd delays.
Undelayed earlier.
Only delaying rimage allocations, not lvm2 mda or rmeta ones.
2025-07-13 20:55:43 +02:00
Heinz Mauelshagen
eb13823985 test: lvconvert-raid-reshape-size.sh fix test bug further
_check_size_timeout function added compensating the block layer bdev update race
thus avoiding other explicit sleeps spread in the test code.
"udevadm settle" approach gone.
No --noudevsync mandatory.
2025-07-13 20:55:43 +02:00
Heinz Mauelshagen
312b29ecfe test: lvconvert-raid-reshape-size.sh fix test bug
Size check for stripe size reshape was bogus.

Whilst on it, optimize delay on test device to
avoid delying LVM2 MDA and RAID rmeta SubLV.

Also update some comments.
2025-07-13 20:55:43 +02:00
Zdenek Kabelac
c5084b4ba5 test: update lvresize-btrfs.sh
Slightlty better integration with test suite.
Use $lv1, $lv2, $lv3.
Use properly "" around string (shellcheck).
2025-07-13 20:55:43 +02:00
Zdenek Kabelac
e76eba860f test: drop unused variable
Remove unused max_log_count.
Update some skip messages.
2025-07-13 20:55:43 +02:00
Zdenek Kabelac
d2a66d4343 test: use proper if-then-fi sequence
Adapting the test for the changed behavior of lvconvert
where the mirror leg and log count is not changing.

Properly test for this condition - checking only leg count is
not enough to expect error return code.

And finaly fixing invalid bash scripting logic since:

test && TRUE || FALSE

is not bash equivalent of:

if test ; then
   TRUE
else
   FALSE
fi
2025-07-13 20:55:43 +02:00
Zdenek Kabelac
bdfdc52093 debug: log_warn sentence begins with capital
Improve the consistency and readability of warning messages.
Capitalize the first word of all warning messages.
Add periods at the end of warning messages.

The changes are purely cosmetic and do not affect functionality.
2025-07-13 20:55:43 +02:00
Zdenek Kabelac
296fcd4c79 man: fix some typos and grammar issues
Drop misplaced letter 'I'.
Missing articles (a, an, the)
Incorrect prepositions (in/into, to/in)
Subject-verb agreement errors.
Awkward phrasing that needs smoothing.
Fixed prepositions ("prior to" instead of "prior the")
Corrected subject-verb agreement ("are becoming" instead of "is becoming")
Fixed word choices ("represents" instead of "presents")
Used consistent terminology ("environment" instead of "environmental")
Fixed pronoun references ("them" instead of "it" when referring to plural subjects)

Originated-by: warp-terminal
2025-07-13 20:55:43 +02:00
Andre Beaud
cfeeee9b3d cleanup: a/an fixups
Some a/an fixups along with a couple more odds and ends.
Hopefully this is useful like this as plain diff output
or let me know if something else will work better.
2025-07-13 20:55:43 +02:00
Zdenek Kabelac
a23ef8e26f gcc: ensure pointer is properly initialized
Fix gcc warning by ensuring pointers are properly defined and
initialized before use in man-generator code to prevent potential
undefined behavior.
2025-07-13 20:55:43 +02:00
Zdenek Kabelac
ca844f7715 cov: replace unsafe string sscanf
Althouh here we were copying to the properly allocated space
let's just replace it with this copy code.
2025-07-13 20:55:43 +02:00
Zdenek Kabelac
61159f127a cov: reduce strcpy
Copy fix we already have device_mapper through commit:
7bc5c8ac3d
2025-07-13 20:55:43 +02:00
Zdenek Kabelac
274e09755c cov: remove unused header
Remove unused header file.
Warp also identified duplicated header file inclusion.
2025-07-13 20:55:43 +02:00
Zdenek Kabelac
c6b924c843 cov: remove unused variables
Remove unused variables identified by coverity analysis to clean up
code and eliminate static analysis warnings.
2025-07-13 20:55:43 +02:00
Zdenek Kabelac
8be572d4f4 cov: reduce printf format string parameters
Simplify printf format strings by removing unnecessary parameters
in libdm-report and toollib components to resolve coverity warnings
about format string mismatches.
2025-07-13 20:55:43 +02:00
Zdenek Kabelac
3e811e5f85 cov: use proper enum value for bitmask operation
Fix coverity warning by using the correct enum value instead of
a raw integer for bitmask operations in activation code.
2025-07-13 20:55:43 +02:00
Zdenek Kabelac
e1e35840f3 cov: suppress false positive warnings
Add coverity annotations to suppress false positive warnings for
unimportant results across multiple files including dmeventd,
lvmlockd, display, logging, dmsetup, and man-generator components.
2025-07-13 20:55:43 +02:00
Zdenek Kabelac
0695846dcc glibc: switch to standard endian conversion macros
Replace all uses of Linux kernel-style endian conversion macros/functions
(e.g., le32_to_cpu, cpu_to_le32, xlate32, xlate64, etc.) with the standard
POSIX/glibc macros (e.g., le32toh, htole32, htobe32, be32toh, etc.) from
<endian.h>.

- Update all code to use le16toh, le32toh, le64toh, htole16, htole32, htole64,
  htobe16, htobe32, htobe64, be16toh, be32toh, be64toh as appropriate.
- Provide fallback macro definitions in xlate.h for systems lacking these
  standard macros, ensuring backward compatibility with older glibc and non-glibc
  systems.
- Remove or replace all project-specific xlateXX and cpu_to_leXX/cpu_to_beXX
  macros.
- No functional change intended; this is a mechanical, treewide modernization
  for clarity, portability, and future maintainability.
2025-07-13 20:55:43 +02:00
Zdenek Kabelac
ed63b90441 cov: add explicit enum casts to fix type warnings
Add explicit casts to enum types in dmeventd and libdevmapper-event
to resolve coverity warnings about implicit type conversions.
2025-07-13 20:55:43 +02:00
Zdenek Kabelac
96b0f1a178 lvresize: update code to get btrfs devid
Let's try different mechanism to obtain devid when
resizing btrfs filesystem spread across multiple volumes.

Using patch from https://github.com/lvmteam/lvm2/issues/180

Originated-by:  Damenly Su <l@damenly.org>
2025-07-13 20:55:43 +02:00
Zdenek Kabelac
1593a6e47c lvconvert: error mirror LV non-changing request
To have the very same matching logic to raid1 commit:
c901528053
we add similar check for mirror where we check if mirror leg and
log count is not changing which will now return also an error.
2025-07-13 17:20:43 +02:00
Zdenek Kabelac
5d16b1d734 tools: simplify LVM_DID_EXEC environment variable
Set LVM_DID_EXEC to "1" instead of using the command name string,
avoiding potential issues with unusual command names and improving
consistency in environment variable handling.
2025-07-13 17:18:56 +02:00
Zdenek Kabelac
adb8ca503b tools: add arg_force_value() for enum handling
Add arg_force_value() function that returns the correct force_t enum
type, replacing direct string comparisons. Update lvconvert and
pvremove to use this new function for better type safety.

This is cleaner solution over just plain cast to force_t as we can
validate force level in use.
2025-07-13 17:18:56 +02:00
Zdenek Kabelac
a68cfa5691 command: replace manual binary search with bsearch
Replace custom binary search implementation with the standard library's
bsearch() function for better maintainability.
Also convert command_name from pointer to char array and simplify name
ordering validation logic.
2025-07-13 17:18:56 +02:00
Zdenek Kabelac
7c79abc33f command: fix alignment in help output formatting
Fix inconsistent spacing in command help output by introducing
_print_opt_with_align() function that properly handles alignment
for options with and without short forms. This resolves the extra
spaces that were being printed in --longhelp output.

Fixes regression introduced in commit:
491c6652ae.
2025-07-13 17:18:56 +02:00
Zdenek Kabelac
0b7b6ccd79 command-lines: fix typo in configurable name
Fix type in lvm.conf option name used for lvcreate
and replace global/mirror_segfault_default with correct
name global/mirror_segtype_default.
2025-07-13 17:18:56 +02:00
Zdenek Kabelac
f82c46e673 sanlock: fix file descriptor leak in error path
Add proper cleanup of file descriptor in the error handling path
to prevent resource leaks when sanlock operations fail.
2025-07-13 17:16:20 +02:00
Zdenek Kabelac
b86b1da80a sanlock: fix struct copy to avoid aliasing issues
Replace direct structure assignment with explicit copying to prevent
potential undefined behavior from structure aliasing. This ensures
proper memory handling when working with sanlock structures.

This possibly fixes regression introduced with commit: e9640e5178
as unintended side effect.
2025-07-13 17:16:20 +02:00
Peter Rajnoha
bd26e768ef udev: fix autoactivation on top of loop dev PVs
We already check loop devices for LVM_LOOP_PV_ACTIVATED="1" in udev
rules to see if have executed pvscan before. If that is the case, we
don't want to execute it again to avoid VG reactivation.

However, the rules missed the IMPORT{db}="LVM_LOOP_PV_ACTIVATED" rule
to actually get the value already stored in udev db from previous event.
As a result, the pvscan executed on each CHANGE udev event, hence the
VG autoactivation triggered each time as well.

Fix this by adding the missing IMPORT{db}="LVM_LOOP_PV_ACTIVATED" rule
(just like we already do for MD devices).

Note: Keep the behavior for ADD events. That is, we still want the
autoactivation to trigger each time, otherwise coldplug will not work
(again, we have the same principle used for MD devices).
2025-07-09 12:48:48 +02:00
Heinz Mauelshagen
8e2cdcc006 test: adjust lvconvert-mirror-basic.sh to now erroring non-changing image mirror request
See commit c901528053
2025-07-02 14:05:18 +02:00
Zdenek Kabelac
a2c9e252a0 sanlock: add function only for newer SANLOCK
Avoid adding unused static function with older SANLOCK.
2025-07-02 11:51:20 +02:00
Zdenek Kabelac
95c77bc922 sanlock: match lm_lock_sanlock prototype 2025-07-02 11:51:20 +02:00
David Teigland
3358e0339a lvmlockd-sanlock: remove info file when vg is removed 2025-07-01 13:36:23 -05:00
David Teigland
f35f074afd lvmlockd-sanlock: check lock_lv_offset_from_args result 2025-07-01 11:23:16 -05:00
David Teigland
78e087f54c lvmlockd: check adopt file fflush and fclose 2025-07-01 11:17:06 -05:00
David Teigland
e16439b8aa lvmlockd: check sscanf results when reading file values 2025-07-01 11:11:59 -05:00
David Teigland
fcca60fda6 lvmlockd: free structs in adopt error path 2025-07-01 10:53:33 -05:00
David Teigland
592cd62de3 lvmlockd-sanlock: fix size in dm_snprintf 2025-07-01 10:29:11 -05:00
David Teigland
1eaada302b lvmlockd-sanlock: fix uninitialized time value 2025-07-01 10:29:11 -05:00
David Teigland
03a343dc9e lvmlockd-sanlock: fix struct pointer in release_rename 2025-07-01 10:29:11 -05:00
Zdenek Kabelac
c03631ed67 configure: update 2025-07-01 17:22:53 +02:00
Heinz Mauelshagen
a60f958707 WHATS_NEW: update 2025-07-01 16:33:18 +02:00
Heinz Mauelshagen
ed13916859 test: adjust lvconvert-raid.sh to now erroring non-changing image raid1 request
See commit c901528053.
2025-07-01 16:29:45 +02:00
Heinz Mauelshagen
c901528053 lvconvert: error raid1 LV non-changing image count request
In case a Raid1LV has e.g. 3 images already, running "lvconvert --mirrors 2 $Raid1LV"
results in success even though the image count didn't change.
Make it fail in such case.

Related issue: https://issues.redhat.com/browse/RHEL-82138
2025-07-01 16:00:21 +02:00
David Teigland
4bc52d2dc5 lvmlockd: add repair option to reinitialize sanlock leases
If sanlock leases become corrupted, adding --lockopt repair
to the command will let lvmlockd reinitialize them.
2025-06-30 12:59:49 -05:00
Zdenek Kabelac
69d7beba91 WHATS_NEW: update 2025-06-30 16:56:43 +02:00
Zdenek Kabelac
8a7c026451 gcc: fix signness warnings with explicit casts
Add explicit type casts to resolve GCC signness comparison warnings:
- Cast dest_size to int in lvmlockctl.c
- Cast NVME_IDENTIFY_DATA_SIZE to int in nvme.c
- Cast bitwise AND results to int in nvme.c and persist.c
- Cast DM_STATS_GROUP_NOT_PRESENT to int in libdm-stats.c
2025-06-30 16:56:43 +02:00
Zdenek Kabelac
3541b483d7 gcc: clean cast from size_t to void ptr 2025-06-30 16:56:43 +02:00
Zdenek Kabelac
0be635934c gcc: for C90 don't mix declaration and code
This commit fixes C90 compatibility issues by ensuring variable declarations
are placed at the beginning of code blocks before any executable statements.
2025-06-30 16:56:43 +02:00
Zdenek Kabelac
29dd3800e4 cov: ensure nsid is defined 2025-06-30 16:56:43 +02:00
Zdenek Kabelac
9fcc66316c cov: check for potential empty row list
Skip potential 0 length allocation and return early for empty list.
2025-06-30 16:56:43 +02:00
Zdenek Kabelac
bf580fcc2f cov: check for potential empty registry list
Check early for empty thread_registry list and return EINVAL
instead of doing zero length allocation.
2025-06-30 16:56:43 +02:00
Zdenek Kabelac
483da854a3 cov: fix warn for variable-sized dm_ulog_request structure
Change kernel_send() function signature from accepting struct dm_ulog_request*
to void* to properly handle variable-sized data access.

The dm_ulog_request structure contains a flexible array member (data[0])
that allows variable-sized payloads to be appended. When accessing data
beyond the base structure size, Coverity correctly flags this as a
potential buffer overrun since the structure size doesn't account for
the variable data.

By using void* as the parameter type, we make it explicit that we're
working with a memory region that may extend beyond the base structure,
eliminating the false positive while maintaining type safety through
proper casting within the function.
2025-06-30 16:56:43 +02:00
Zdenek Kabelac
2c5489dd13 cov: explicitly zero allocated mem for array
Replace malloc() with calloc() when allocating the string pointer array
for regex pattern matching in _create_field_selection(). This ensures
all array elements are initialized to NULL pointers, preventing potential
use of uninitialized memory objected by Coverity.

Existing code sets all elements in the follow up loop.
2025-06-30 16:56:43 +02:00
Zdenek Kabelac
ae407d2f3c cov: add explicit check for 0 size 2025-06-30 16:56:43 +02:00
Zdenek Kabelac
49e8ecc2dd cov: explicitly ignore return of _lv_types_match()
Add explicit (void) cast to ignore the return value of _lv_types_match()
in _check_lv_rules() function. This addresses Coverity warning about
unused return values and maintains consistency with other similar
function calls in the codebase that properly handle return values.
2025-06-30 16:56:43 +02:00
Zdenek Kabelac
f1f94d987d cov: add annotations to suppress fp warnings
Add Coverity annotations to suppress false positive warnings in several
files where the static analysis tool incorrectly flags potential issues
that are actually safe due to proper validation or intentional behavior.

The annotations address the following false positives:

- daemons/dmeventd/dmeventd.c: overflow_sink warnings for 'current' variable
  that is validated to be positive before use in buffer operations

- daemons/lvmlockd/lvmlockd-core.c: overflow_sink warning for 'ret' variable
  that is validated to be positive before use

- lib/config/config.c: overflow_sink warning for 'sz' variable that is
  validated to be positive before use in read operations

- libdm/dm-tools/dmsetup.c: overflow_sink, overflow, and deref_overflow
  warnings for 'n' variable that is validated to be positive before use
  in buffer operations and string termination

- libdm/libdm-stats.c: overflow_sink warning for 'i & j' variables that are
  validated to be positive before use in array indexing
2025-06-30 16:56:43 +02:00
Zdenek Kabelac
29a799961c cov: add checked variants for mda_is_ignored and rlocn_is_ignored
Introduce _mda_is_ignored() and _rlocn_is_ignored() wrapper functions
with warn_unused_result attribute to enforce return value checking.

This follows the established pattern used by dm_strncpy() and _dm_strncpy():
- Functions without underscore prefix can be used without checking return values
- Functions with underscore prefix must have their return values checked

The change improves static analysis coverage by ensuring that critical
metadata area and raw location ignored state checks are properly validated,
reducing the risk of unhandled error conditions in metadata processing.
2025-06-30 16:56:43 +02:00
Zdenek Kabelac
a53352b4aa cov: fix va_end resource leak in szscanf()
- Fix potential resource leak by ensuring va_end() is called on error path
- Set matched = -1 and break from while loop instead of immediate return
- This ensures proper cleanup of va_list when unsupported format
  specifiers are encountered in lvmlockctl.

The szscanf function is a custom string scanner used for parsing lvmlockd
status information. Previously, encountering an unsupported format
specifier would cause an immediate return without calling va_end(),
leading to undefined behavior and potential resource leaks.

This fix ensures proper cleanup of variable argument lists in all code paths.
2025-06-30 16:56:43 +02:00
Zdenek Kabelac
ce8dc67c47 cov: replace unsafe strcpy
Replace potentially unsafe strcpy() with bounds-checked memcpy()
and proper null termination in the _sysfs_get_dm_name() function.
This prevents buffer overflow vulnerabilities when copying device
mapper names from sysfs.

Also replace another strcpy() with _dm_strncpy() which also checks
whether copied string with into a given buffer in the function
_sysfs_get_kernel_name().

Changes:

- Replace strcpy(buf, temp_buf) with memcpy(buf, temp_buf, len) + buf[len] = '\0'
- Use stack-allocated buffers instead of malloc/dm_malloc for better performance
- Improve error handling logic for ENOENT vs other errors
- Add proper newline stripping with bounds checking
- Remove memory allocation failure paths and cleanup code

This addresses potential security issues identified by static analysis
tools while also improving performance by avoiding dynamic memory allocation.
2025-06-30 16:56:43 +02:00
Zdenek Kabelac
543a87e12a cov: reduce strcpy usage
Coverity does not like strcpy() calls...
2025-06-30 16:56:43 +02:00
Zdenek Kabelac
5c42822eab cov: improve page size validation and calculation
- Add bounds checking for sysconf(_SC_PAGESIZE) return value
- Validate page size is positive and reasonable (< 16MB)
- Use size_t for page_size variable to match usage context
- Simplify page calculation with ceiling division
- Fix potential integer overflow in page count calculation

This improves robustness when handling edge cases in clustered
mirror log disk operations.
2025-06-30 16:56:43 +02:00
Zdenek Kabelac
5fbdd7014a cov: prevent unsigned underflow
Use signed int instead of size_t for loop counter to prevent reporting
unsigned underflow when decrementing from 0 in Coverity.
Loops itself worked just fine.
2025-06-30 16:56:43 +02:00
Zdenek Kabelac
ad016ea4e3 cov: prefer snprintf 2025-06-30 16:56:43 +02:00
Zdenek Kabelac
39a45f212d cov: ensure read got some bytes 2025-06-30 16:56:43 +02:00
Zdenek Kabelac
c45ad22806 cov: check error return from mktime
Handle mktime() error path value -1 and for such invalid time_t value
return 0 tz offset.
2025-06-30 16:56:43 +02:00
Zdenek Kabelac
c0c47ead98 cov: simplify obtaining value
Function arg_str_value() calls arg_is_seg() to check whether arg is set.
At the same time Coverity can see check for non NULL of 'op'.
2025-06-30 16:56:42 +02:00
Zdenek Kabelac
8873599b66 cov: fix integer underflow in _count handling
The _count variable was declared as uint64_t but used in arithmetic operations
that could result in underflow when subtracting from smaller values. This
could cause issues when calculating interval numbers or handling count-based
reporting.

Changes:
- Change _count variable type from uint64_t to int64_t
- Update _interval_num() to use proper casting for arithmetic
- Change UINT64_MAX to INT64_MAX for default count value
- Remove unnecessary casting in count assignment

This prevents potential underflow issues when _count is decremented or used
in subtraction operations, ensuring proper behavior for interval-based
reporting and count tracking in dmsetup commands.

The fix maintains compatibility while providing safer integer arithmetic
for the reporting loop logic.
2025-06-30 16:56:42 +02:00
Zdenek Kabelac
5f73db83bc cov: fix double-close bug in _btrfs_get_mnt function
Ensure file descriptor is closed only once by moving close() call
to immediately after read() and setting fd = -1 to prevent reuse.
2025-06-30 16:56:42 +02:00
Zdenek Kabelac
2a2ad7317f cov: prevent potential negative array index
The _stats_map_extents() function processes file extents returned
by FIEMAP ioctl calls. When handling the case where a file has
only a single extent, the code accesses fm_ext[i - 1] to check
if the logical offset is 0.

However, when i is 0 (no extents processed yet), this results in a negative
array index access which can cause undefined behavior or crashes.

So check early whether there are fm_mapped_extents to process.
This avoids using negative index array.

Existing code already checks fm_mapped_extents == 0 before calling
this function so the patch is not fixing any real bug.
2025-06-30 16:56:42 +02:00
Zdenek Kabelac
11154dfab2 debug: add missing error path traces
Trace failures of close() and unlink() syscalls.
2025-06-30 16:56:42 +02:00
Zdenek Kabelac
50abb2c2c9 lvmlockd: optimize lock_type access in lockd_start_vg
Store vg->lock_type in a local variable to avoid repeated null checks
and string comparisons throughout the function. This improves code
readability and eliminates redundant conditional evaluations.
2025-06-30 16:56:42 +02:00
Zdenek Kabelac
e5f0d312b3 lvconvert: refactor counting of failed mirrors
Change return value semantics:
- Previously returned -1 for non-mirrored segments (error condition)
- Now returns 0 for non-mirrored segments (no failed mirrors) and
  reports INTERNAL_ERROR for such case.
- This makes the function more consistent as it counts failures, not errors

Simplify recursive calls:
- Remove unnecessary intermediate variable 'r' in both functions
- Directly add recursive call results to return value
- Eliminates redundant error checking for recursive calls

Code cleanup:
- Remove unused variable declarations
- Improve code readability and reduce compiler warnings

The refactoring makes the functions more robust and easier to understand
while preserving their core behavior of counting failed mirror images
and logs across logical volume segments.
2025-06-30 16:56:42 +02:00
Zdenek Kabelac
2dec6f5493 libdm-stats: fix type mismatch in bit operations
The stats implementation was using uint64_t for group_id and loop variables
while calling dm_bit_* functions that return int types. This created a
potential issue where large values could be incorrectly handled due to
implicit casting between signed and unsigned types.

Changes:
- Change loop variables from uint64_t to int in _stats_group_tag_len()
- Change loop variable from uint64_t to int in _stats_clear_group_regions()
- Change loop variables from uint64_t to int in dm_stats_get_counter()
- Change loop variable from uint64_t to int in dm_stats_get_region_len()
- Fix _stats_create_group() to properly handle dm_bit_get_first() return value

This ensures consistent type usage and prevents potential issues with
values exceeding INT_MAX (2^31 - 1). Also this limitats group_id to 31 bits
as a constraint that may need addressing in the future.

FIXME: Maybe consider implementing 64-bit variants of dm_bit functions or
documenting this limitation more prominently is this ever become an
issue...
2025-06-30 16:56:42 +02:00
Zdenek Kabelac
879fb36f0a lvmlockd: allow 1 more extra character
Function dm_strncpy() ensures the last character is \0,
so pass whole array size for buffer size.

This give 1 extra character for use to store owner state and name.
2025-06-30 16:56:42 +02:00
Zdenek Kabelac
bc417b2e25 tests: check lvcreate thin with setautoactivation 2025-06-30 16:56:42 +02:00
Friedrich Weber
1fba3b876b lvcreate: accept --setautoactivation flag for all volumes
lvcreate accepts --setautoactivation for thick logical volumes, but
not for e.g. thin volumes (see linked bug report). Currently, in such
cases, a subsequent lvchange invocation is necessary to change the
autoactivation flag.

To fix this, make lvcreate accept the flag for all volumes by adding
it to LVCREATE_ARGS.

Fixes: https://gitlab.com/lvmteam/lvm2/-/issues/32
Fixes: 0a28e3c44 ("Add metadata-based autoactivation property for VG and LV")
Signed-off-by: Friedrich Weber <f.weber@proxmox.com>
2025-06-30 13:14:52 +02:00
Zdenek Kabelac
460033c3d4 aux: missed _executable in config name 2025-06-27 10:26:42 +02:00
Zdenek Kabelac
a9ffaeb6c0 WHATS_NEW: update 2025-06-27 10:26:39 +02:00
Zdenek Kabelac
c2cca24ff0 make: generate 2025-06-27 10:26:00 +02:00
Zdenek Kabelac
8e630ebf2c gcc: keep code compilable with std=c99 2025-06-27 10:26:00 +02:00
Zdenek Kabelac
83debc25a3 gcc: ensure proper value initialization 2025-06-27 10:26:00 +02:00
Zdenek Kabelac
6e0fa754be man: install lvmpersist page 2025-06-27 10:26:00 +02:00
Zdenek Kabelac
9039295c5e tests: configure lvresize_fs_helper_executable_CFG
Update test infrastructure to use the lvresize_fs_helper script
from the LVM2 codebase instead of relying on the system-installed
version. This ensures consistent testing behavior and avoids
issues when the system version doesn't exist or differs from
the expected implementation.

- Add lvresize_fs_helper to LVM_SCRIPTS in test/Makefile.in
  for installation
- Configure global/lvresize_fs_helper in test/lib/aux.sh
  to point to the test version
2025-06-27 10:26:00 +02:00
Zdenek Kabelac
70e8ef249b config: add lvresize_fs_helper_executable option
- Add global_lvresize_fs_helper_executable_CFG config option to allow
  specifying the path to the lvresize_fs_helper script.
- Add DEFAULT_LVRESIZE_FS_HELPER_PATH macro for default value.
- Update _get_lvresize_fs_helper_path() in lib/device/filesystem.c
  to read the path from configuration using find_config_tree_str,
  similar to _fsadm_cmd().
- This allows users to override the helper path via configuration,
  improving flexibility and consistency with fsadm_executable handling.
- Avoid using static variable to get helper path just once, since
  it may change between commands via lvm.conf in lvm2 shell.
2025-06-27 10:26:00 +02:00
David Teigland
5f0ddd0fd8 lvmlockd: fix missing free in vg_status
and add more checking of get_hosts result.

used by lockd_vg_is_started() for the PR feature.
2025-06-27 10:26:00 +02:00
Zdenek Kabelac
fb250d23f2 nvme: match header prototype for dev_find_key_nvme
Missed to synchronize with previous commit.
2025-06-27 10:26:00 +02:00
Biswapriyo Nath
2d5ef4a4ef device_id: Fix compiling when versionsort not found
alphasort was replaced with versionsort in 09e508cd43 commit.

This commit fixes the following compiler error.

device/device_id.c:1608:65: error: use of undeclared identifier 'versionsort'
1608 |         sort_count = scandir(dirpath, &namelist, _filter_backup_files, versionsort);
     |                                                                        ^
2025-06-27 10:26:00 +02:00
Zdenek Kabelac
b6878873db configure: autoreconf 2025-06-27 10:26:00 +02:00
A. Wilcox
6ccc8f801e configure: Use portable string comparison
= and == are equivalent in Bash for strings, but = is the only portable
operator for compatibility with other shells.  Before this change,
running ./configure with Dash as /bin/sh resulted in:

./configure: 14558: test: yes: unexpected operator

and the test did not work (i.e. --enable-cmdlib --disable-shared allowed
a failed build to continue).  Now, the test works in Bash and Dash.
2025-06-27 10:26:00 +02:00
David Teigland
e3871db279 persistent reservations
Enable lvm to use persistent reservations on a VG, which
are applied to each PV in the VG.

. lvmpersist is a low level script, which uses commands
  sg_persist, mpathpersist, and nvme to do PR operations
  on devices. This script is used by higher level lvm
  commands, and would not often be run by users.

. vgchange --setpersist is a VG metadata configuration command
  that specifies how PR should be started and enforced for a VG
  relative to other lvm commands.

. vgchange --persist is a command to change PR state of PVs in
  the VG, e.g. start PR to register and reserve.

The lvmpersist man page contains a complete description.
2025-06-27 10:26:00 +02:00
David Teigland
e97ce575f4 devices: add dev_is_scsi and dev_is_mpath 2025-06-27 10:26:00 +02:00
Marian Csontos
c3e69d89bf post-release 2025-06-27 10:14:33 +02:00
Marian Csontos
0e01a5d3ae pre-release 2.03.33 2025-06-27 10:14:33 +02:00
Peter Rajnoha
6f86a9ad2a WHATS_NEW: update 2025-06-26 10:50:20 +02:00
Adrian Astley
a8941ec608 libdm: Escape all literal control characters in report strings
LVM objects (like pv_device_id) can sometimes contain literal control characters. The JSON spec disallows control characters. So we need to escape them for output.

Closes https://gitlab.com/lvmteam/lvm2/-/issues/35
2025-06-26 02:48:17 +00:00
Zdenek Kabelac
6708b2f5d2 WHATS_NEW: update 2025-06-25 22:48:42 +02:00
Zdenek Kabelac
97449a611b codespell: fix various typos across codebase
- lib/device/filesystem.c: 'avaiable' -> 'available' in btrfs comment
- lib/format_text/export.c: 'sting' -> 'string' in comment
- lib/log/log.c: 'expectes' -> 'expects' in coverity comment
- lib/metadata/metadata.c: 'damanging' -> 'damaging' in comment
- lib/metadata/metadata.h: 'Aditional' -> 'Additional' in comment
- test/shell/000-basic.sh: 'supression' -> 'suppression' in comment
- test/shell/pvcreate-partition.sh: 'lable' -> 'label' in comment
- test/shell/topology-support.sh: 'standart' -> 'standard' in comment
- WHATS_NEW:
  * 'propperly' -> 'properly'
  * 'cachable' -> 'cacheable'
2025-06-25 22:48:42 +02:00
Zdenek Kabelac
4ee806d391 tests: switch to new skip options for test scripts
Update test scripts to use new command-line options for skipping tests,
replacing the previous use of environment variables. The following options
are now supported:

  --skip-root-dm-check
  --skip-with-devices-file
  --skip-with-lvmpolld
  --skip-with-lvmlockd

- Add command-line option parsing to lib/inittest.sh.
- Replace SKIP_ROOT_DM_CHECK=1 with --skip-root-dm-check.
- Replace SKIP_WITH_DEVICES_FILE=1 with --skip-with-devices-file.
- Replace SKIP_WITH_LVMPOLLD=1 with --skip-with-lvmpolld.
- Replace SKIP_WITH_LVMLOCKD=1 with --skip-with-lvmlockd.
- Update 410 test files to use the new syntax.

This change provides a cleaner, more consistent, and maintainable
way to handle test skipping across the test suite.
Also eliminates number of shellcheck errors.

TODO: convert couple more remaining.
2025-06-25 22:48:42 +02:00
Zdenek Kabelac
7417698823 build: fix include paths for out-of-source builds
Fix include paths in cmd_enum.h and command.c by removing the "include/"
prefix from #include directives. This resolves build failures when
building from a directory different from the source directory.

The include paths were incorrectly referencing "include/cmds.h" instead
of "cmds.h", causing compilation errors in out-of-source builds.
2025-06-25 22:48:42 +02:00
Zdenek Kabelac
63c6a2629a man: fix ellipsis formatting
(use \&... instead of ... for proper troff rendering)
in lvmlockd, lvmreport, lvmvdo man pages
2025-06-25 22:48:42 +02:00
Zdenek Kabelac
c117dde67a man: remove quotes from section headers
Remove unnecessary quotes from section headers in man pages:
- lvm_import_vdo.8_main: .SH "NAME" -> .SH NAME
- fsadm.8_main: .SH "NAME" -> .SH NAME

This improves consistency and follows man page conventions.

Originated-by: Cursor AI
2025-06-25 22:48:42 +02:00
Zdenek Kabelac
26154af9e4 man: fix company name formatting (missing comma)
Fix company name format in .TH headers by adding missing comma:
- dmeventd.8_main: 'Red Hat Inc' -> 'Red Hat, Inc.'
- cmirrord.8_main: 'Red Hat Inc' -> 'Red Hat, Inc.'
- lvmpolld.8_main: 'Red Hat Inc' -> 'Red Hat, Inc.'
- lvmdbusd.8_main: 'Red Hat Inc' -> 'Red Hat, Inc.'
- lvm_import_vdo.8_main: 'Red Hat, Inc' -> 'Red Hat, Inc.'
- lvmlockctl.8_main: 'Red Hat, Inc' -> 'Red Hat, Inc.'
- lvmcache.7_main: 'Red Hat, Inc' -> 'Red Hat, Inc.'
- lvmvdo.7_main: 'Red Hat, Inc' -> 'Red Hat, Inc.'
- blkdeactivate.8_main: 'Red Hat, Inc' -> 'Red Hat, Inc.'
- lvmthin.7_main: 'Red Hat, Inc' -> 'Red Hat, Inc.'
- lvmreport.7_main: 'Red Hat, Inc' -> 'Red Hat, Inc.'
- lvmsadc.8_main: 'Red Hat, Inc' -> 'Red Hat, Inc.'
- lvmautoactivation.7_main: 'Red Hat, Inc' -> 'Red Hat, Inc.'
- lvmlockd.8_main: 'Red Hat, Inc' -> 'Red Hat, Inc.'
- fsadm.8_main: 'Red Hat, Inc' -> 'Red Hat, Inc.'
- lvmraid.7_main: 'Red Hat, Inc' -> 'Red Hat, Inc.'
- lvmsystemid.7_main: 'Red Hat, Inc' -> 'Red Hat, Inc.'
- lvmsar.8_main: 'Red Hat, Inc' -> 'Red Hat, Inc.'

This ensures consistent company name formatting across all man pages.

Originated-by: Cursor AI
2025-06-25 22:48:42 +02:00
Zdenek Kabelac
6b61dea9bb man: fix English grammar and style issues
- cmirrord.8_main: Remove unnecessary article 'the' before 'corosync'
- dmsetup.8_main: Fix multiple grammar and punctuation issues
  * Add missing 'to' in 'Set this to zero to continue'
  * Fix 'eg,' -> 'e.g.,' and add missing comma
  * Add missing 'the' in 'for the live device'
  * Fix 'customised by following options' -> 'customised by the following options'
  * Fix 'comma-separate' -> 'comma-separated'
- fsadm.8_main: Improve sentence structure for dm-crypt description
- lvm.8_main: Fix capitalization 'volume Groups' -> 'Volume Groups'
- lvm_import_vdo.8_main: Fix header title and multiple grammar issues
  * Fix header title 'FSADM' -> 'LVM_IMPORT_VDO'
  * Fix 'LV a backend device' -> 'LV as a backend device'
  * Fix 'the of volume group' -> 'the name of the volume group'
  * Remove extra 'with' in 'with within volume group'
- lvmsystemid.7_main: Fix punctuation 'e.g.' -> 'e.g.,' and 'i.e.' -> 'i.e.,'

These changes improve grammatical correctness, consistency, and readability.

Originated-by: Cursor AI
2025-06-25 22:48:42 +02:00
Zdenek Kabelac
95585bc2fa man: fix grammar and spelling issues
- dmeventd.8_main: Fix verb form 'present' -> 'presents' and spelling
  'free recover' -> 'recover free'
- dmfilemapd.8_main: Fix missing preposition
  'mode the daemon' -> 'mode of the daemon'
- dmstats.8_main: Fix American spelling 'Capitalise' -> 'Capitalize'
- lvmcache.7_main: Fix missing article
  'writecache block size' -> 'a writecache block size'

These changes improve grammatical correctness and consistency.

Originated-by: Cursor AI
2025-06-25 22:48:42 +02:00
Zdenek Kabelac
97768cf302 tools: fix English grammar and spelling issues in args.h
- Fix typo: writethough -> writethrough in cachemode description
- Fix grammar: 'enabled or disable' -> 'enabled or disabled' for VDO options
- Fix typo: 'user date' -> 'user data' in RAID nosync description
- Fix grammar: 'a an LV' -> 'an LV' in poolmetadata description

These changes improve documentation clarity and correctness.

Originated-by: Cursor AI
2025-06-25 22:48:42 +02:00
Zdenek Kabelac
86f2d0668d tests: typo
7 should have replaced 8.
2025-06-12 23:38:44 +02:00
Zdenek Kabelac
f88565316c tests: aux lower 8EiB size
Reduce ~8EiB sized device by few sectors to avoid endless loop
from systemd-udev device scan.

Use of 180143985094819876 solves the issues.
2025-06-12 17:00:09 +02:00
Zdenek Kabelac
9aa346a0c6 tests: aux teardown clear tables in parallel
To avoid getting possibly stuck waiting on suspended LVs,
run 'dmsetup clear' in parallel in teardown of device stack.
2025-06-12 17:00:09 +02:00
Peter Rajnoha
4ef8acb018 WHATS_NEW: update 2025-06-12 10:18:52 +02:00
Peter Rajnoha
cbf4a7c53b tools: reporter: cleanup: setting of cmd->report_strict_type_mode
Make setting of cmd->report_string_type_mode easier to follow.
2025-06-12 10:18:52 +02:00
Peter Rajnoha
f024936924 tools: reporter: override LC_NUMERIC if needed for json_std format
Override LC_NUMERIC part of the locale to "C" if we detect that the
radix character interferes with JSON_STD format. If that's the case,
override LC_NUMERIC locale to "C" in report_format_init, that is,
before any reporting is executed (including log reporting). Restore
it back in report_format_destroy, that is, once we're sure that all
reporting is finished.

Related: https://gitlab.com/lvmteam/lvm2/-/issues/33
2025-06-12 10:18:52 +02:00
Peter Rajnoha
0a665d0c17 tools: reporter: cleanup: factor out code to new report_format_destroy
We already have report_format_init. Having report_format_destroy makes
it easier to read and follow the code using these functions.
2025-06-12 10:18:46 +02:00
Peter Rajnoha
f110b32239 libdm: report: require '.' radix char for DM_REPORT_GROUP_JSON_STD
When a report is under DM_REPORT_GROUP_JSON_STD, the formatting of the
report follows more standard form of the JSON output. This includes
unquoted numbers (as opposed to the DM_REPORT_GROUP_JSON).

The JSON standard dictates the radix character (decimal point) must
be '.' only (https://www.rfc-editor.org/rfc/rfc7158#section-6).

However, some locales may use other character for the radix delimiter,
like ','. This character also interferes with ',' used as delimiter for
json items.

Therefore, we need to check whether current locale is not posing an
issue when using DM_REPORT_GROUP_JSON_STD. If that's the case, simply
error out from dm_report_group_create as we don't want to override
current locale in libdm or do anything else at this level. The libdm
caller is responsible here for setting the proper locale.

Related: https://gitlab.com/lvmteam/lvm2/-/issues/33
2025-06-12 10:12:59 +02:00
Heinz Mauelshagen
37b28216fd lvmlockctl: fix leading spaces in scanf alternative commit 0217887fcd 2025-05-14 14:36:27 +02:00
Zdenek Kabelac
80b1ccd2f3 tests: aux use 8EiB sized devices
From kernel 6.15 DM block devices with size >= 8EiB can't be created.
2025-05-14 12:53:38 +02:00
Su Yue
46a6d0d2bd test: addm shell/lvresize-btrfs.sh
refer legacy patche:
- Ondrej Kozina <okozina@redhat.com>
https://listman.redhat.com/archives/lvm-devel/2012-November/msg00055.html

Signed-off-by: Heming Zhao <heming.zhao@suse.com>
[Adjust to lvresize]
Signed-off-by: Su Yue <glass.su@suse.com>
2025-05-13 12:27:17 -05:00
Su Yue
93013c09be lvresize: add btrfs support
This commit adds lvresize/lvextend/lvreduce support for btrfs.
'btrfs filesystem resize [devid:][+/-]<newsize>[kKmMgGtTpPeE]|[devid:]max <path>'
is used to resize one device only when it's mounted.
The code pattern is like xfs but it supports shrink.

For multi-devices btrfs, There is one difficulty to be handled:

If `lvreduce --fs resize` is given, lvm2 will check newsize vs current fs size
to judge if it's need to shrink fs or not.
For one device btrfs, fslastblock * fsblocksize/FSSIZE is the correct value like
ext* and xfs. But for multi-devices btrfs, the two values are whole fs size.
There is no other way without relying btrfs superblock parse. It's too
complicated and inproper to implemnt the logic in lvm2.
So here just sets fs_last_byte to 0 for btrfs and skips boundary check in
_fs_reduce_allow(). It's safe as btrfs will handle it well.

The another complicated part is how to get mount point info if multi-devices.
There is only one mnt entry per mounted fs in /etc/mtab even it's a
multi-devices btrfs. So we first get uuid from lv device then traverse devices
under /sys/fs/btrfs/$uuid/devices and compare them to the mnt entry to get the
mount point.

Signed-off-by: Su Yue <glass.su@suse.com>
2025-05-13 12:27:17 -05:00
Su Yue
9edb10b5f4 filesystem: factor out get mount point logic from fs_get_info() into _fs_get_mnt()
The new _fs_get_mnt() is used to get mount point info for fses.
No functional change.

Signed-off-by: Su Yue <glass.su@suse.com>
2025-05-13 12:27:17 -05:00
Su Yue
7c65c16a66 filesystem: get device uuid in fs_get_blkid
Add new field fs_info::uuid to record device uuid when calling
fs_get_blkid() for further use.

No functional change.

Signed-off-by: Su Yue <glass.su@suse.com>
2025-05-13 12:27:17 -05:00
Zdenek Kabelac
7c9a3ba381 raid: use byte order conversion macros
As we already use  le_to_cpu() and cpu_to_be() elsewhere
and have a macros usable across wide variety of distros,
switch to use these.
2025-05-12 15:48:35 +02:00
Zdenek Kabelac
239f4be1f0 tests: fix typo in PAGE_SIZE check
Here 1 meant to by shifted by 20 bits...
Otherwise it always falback to just 4K.
2025-05-12 15:07:49 +02:00
Zdenek Kabelac
759d1bfe11 WHATS_NEW: update 2025-05-12 15:07:49 +02:00
Zdenek Kabelac
22364ce9b6 man: update raid man
Mention repair of transiently lost devices.
2025-05-12 15:07:49 +02:00
David Teigland
88910c200f lvmlockd: fix sanlock_release for vgremove
incorrect data was being copied to lease structs passed
to sanlock_release(), making the lease removal fail.
2025-05-08 10:54:50 -05:00
David Teigland
53752ef851 lvmlockd: fix hosts check for vgremove
errors from lock manager were not being considered.
EAGAIN from sanlock should be considered EBUSY.
2025-05-07 17:51:01 -05:00
Zdenek Kabelac
dbac36adf0 lvmlockd: keep using ifdef
We are not defining LOCKDSANLOCK_SUPPORT when there is no support
for sanlock enabled.
2025-05-07 17:03:29 +02:00
Zdenek Kabelac
5d7f862b9b configure: autoreconf 2025-05-07 17:03:29 +02:00
Zdenek Kabelac
1e7a614c34 configure.ac: set lowest version
As we always require and check for version 3.7,
avoid extra CHECK_EXIST and go for CHECK_MODULE.

LOCKDSANLOCK_SUPPORT is not defined is the build
is not enabled.

When build for sanlock is enabled, and
CHEKC_MODULE does not detect at least version 3.7
then whole configure process errors out.
2025-05-07 17:03:29 +02:00
Zdenek Kabelac
0cafb18978 test: check raid superblock clearing 2025-05-07 16:54:55 +02:00
Zdenek Kabelac
0a8f560c75 lvconvert: allow clearing superblocks 2025-05-07 16:54:55 +02:00
Heinz Mauelshagen
03d8661657 raid: count or clear transiently failed devices
Count or clear transiently failed devices as of dm-raid superblocks.
Updated debuging.
Use lvconvert --repair to repair transiently failed legs.
Activating all 'meta' LVs with single sync_local_dev_names().
Using proper DM path for meta LV.

Modified-by: zkabelac@redhat.com
2025-05-07 16:54:12 +02:00
David Teigland
b66cc11b78 lvmlockd: detect sanlock version in configure to enable new code 2025-05-06 16:06:24 -05:00
David Teigland
54f3656b7e lvmlockd: disable use of new sanlock apis 2025-05-06 12:07:54 -05:00
David Teigland
a1b27f0656 lvmlockd: use error for corrupted sanlock lease in start
if sanlock delta lease for host_id is corrupt, then
return ELOCKREPAIR.
2025-05-06 11:34:51 -05:00
David Teigland
47a48fd0b6 lvmlockd: add error for corrupted sanlock lease
A specific error message can be printed for this case:
"sanlock lease needs repair"
2025-05-06 11:34:51 -05:00
David Teigland
a494f07aec lvmlockd: add vg_status operation and fix sanlock read_lockspace_info 2025-05-06 11:34:51 -05:00
David Teigland
bd363a4284 lvmlockd: use new sanlock_read_lockspace_host for prev generation
return previous sanlock generation number in the start_vg response.
2025-05-06 11:34:51 -05:00
David Teigland
9b51b3d3f1 lvmlockd: use new sanlock_acquire2 to return owner info
Use the new sanlock_acquire2() which returns info about the owner
of a lease.  Pass this info back to the lvm command, where it's
initially used to print the host_id of a host holding a lock
when it cannot be acquired.
2025-05-06 11:34:51 -05:00
David Teigland
0217887fcd lvmlockctl: sscanf alternative
Add szscanf() to use in place of sscanf. It takes a buffer size for
strings, so avoids needing to use max field width, which is hard to
read when implemented with stringify macros.
2025-05-05 15:48:48 -05:00
Marian Csontos
086b0ee6e4 post-release 2025-05-05 17:02:06 +02:00
Marian Csontos
8817523c56 pre-release 2.03.32 2025-05-05 17:02:06 +02:00
Marian Csontos
338bb7e68b WHATS_NEW: update 2025-04-29 15:02:04 +02:00
Zdenek Kabelac
8acb84f5bd tests: check for resulting size
Add some extra validation check for size and slabsize.
2025-04-28 14:19:18 +02:00
Zdenek Kabelac
480bf01936 make: generate 2025-04-28 14:19:18 +02:00
Zdenek Kabelac
c1bfc8737f man: updates and typography
Manually enhance pages for thin, cache, raid, vdo.

Replace usage of .HP with .TP when it makes sense (but keep .HP
where so far we don't have replacement giving same visual results).

Use .CMS, .CME  macros in dmsetup/dmstats so it easy to switch
But keep using .HP when the rendering looks simply better in terminal
although HTML output does not looks that well - so we may eventually
switch here to .TP.

For basic command synopsis use .NSY macro that will
use .SY for graphical rendering (postscript/pdf) but keep
using .TP for ASCII terminal output, as here many HTML renderers
are emitting unreadable pages.

For options use '\ ' (non-breakable space) between option and
its argument and option are not across line.

Reformat lines to fit in 80 columns.

Use  .EX .. .EE  for example output - this improves
character alignment for poststrict/pdf rendering as
it use monospace fonts (unlike .nf .. .fi).
Also with Example section never let the line being with space
and use '\' for such line.
If the Example line should being with '.' it needs to be
prefix with \&.
Add .nf/.fi macros for cases where .EX & .EE are undefined
(this happens i.e. with man2html)

Avoid use of tables (.TS .. .TE) as HTML renderers often use
images (.png) files for such tables and this does not scale well
when user changes font size in browser.
(and the large/long table were split into 2 pieces
so it does fit to 80 columns).

Use .MT .ME for emails.

Use .UR .UE. for URL.

Use  .\|.\|.\& as sequence of 3 dots and add \& to not create end of
sentence and possibly wrong alignment.

On lines starting with .BR & .IR avoid using \fB \fI as this
can cause problem when i.e. html rendered may keep use
italic bold when just italic was really wanted.

When using series of .TP/.IP - set the size only with the
first tag - and let renderer align others to match the column.

Correct some small typographical rendering issues.

Rendering was evaluated for readable results with:
- mandoc -T html  (-O style=mandoc.css)
- groff  -Thtml -mman
- man2html
- man -Thtml
- man -Tps
- man

Unfortunatelly various g/troff troubles are with each of them,
so we need to select usage of macros in a way, that is not mangling
results for above engines.
2025-04-28 14:19:18 +02:00
Zdenek Kabelac
fe14628818 man: generator update
Improve generated output for better compliance with '-T lint' checker
(mandoc -T lint and groff --mandoc).

Try to properly place .P sections and also correctly use .TP rendering
where we need to place '.na .ad'  after the first rendered keyword,
otherwise it has not the desired impact.

Also use  .nh .na ..  .ad .hy around whole command USAGE description
so we avoid unwanted alignment,spacing,hyphenation there.

Make sure we are emitting properly order paragraphs and avoid
i.e. submit of .br after .RS/.in  that has this implicit

Also more frequently emit '\n' so there are not too long lines as
rendering engine will format line breaking according to its rules.

To keep generated page better controllable emit more empty line
and use such lines for every .SH, .TP.

Use 'short_ops' loop to avoid duplicating code.

Emit .\|.\|. for 3dot sequence for proper graphical rendering

Emit \\0\\0\\0 (3 white space of width of letter '0')
for better alignment of options with graphical rendering.

There is ATM prepare '#define TABBED' - enabling this make
initial option list nicely aligned in graphical rendering
and doesn't seem to have bad side effect on text rendering.

man: generator use macros for options

Predefine all options used by the command into list of '.de O_name'
macros that are pregenerated in the front of man page.
(interestingly usage of groff strings (.ds) seems to have some
non-trivial issues across rendering engines)

This allows to use '\t' without producing warnings with
'mandoc -T lint' - as normally tabs are allowed only within
'.nf ... .fi' section, but than there is not working line-breaking.

While we could use purely 'tab' base version, for some 'html' (ascii)
redering its producing not so well indented option list.
For this reason use tabs only with graphical renderers .ie  t / .el
and use only spaces for ascii rendering.

Ensure the ...   (3dots continuation is properly renderer with
a single space after repeatable option/argument and not adding extra
space before i.e. closing bracket.

Using .ta for graphical rendering - allows to keep option aligned
with proportional font.
2025-04-28 14:19:15 +02:00
Zdenek Kabelac
df45871754 man: minor refactor
Minor updates to generator code.
2025-04-28 14:18:45 +02:00
David Teigland
9b985f3519 libdaemon: change connect error to log_debug
The message is unnecessary noise since callers print a
more user friendly message.
2025-04-22 16:18:51 -05:00
David Teigland
dcfa77c345 lvmdevices: skip lvmlockd connection
the command doesn't use locks from lvmlockd
2025-04-22 16:12:18 -05:00
Zdenek Kabelac
11b64b0c0c lvmcmdline: still support use of profile
Couple commands (lvcreate,lvconvert,vgcreate,lvchange,vgchange)
has the 'specific' property that within them the option --profile
behaves like --metadataprofile, while for all other commands this
option should be simply an alias for --commandprofile.

We may eventually drop this rather confusing behavior in the future
version and there will be only one use as --[command]profile

It should be noted this --commandprofile can be often used
instead of --config option for preconfiguring setting
for some group of commands - we should possibly more propagate
this usage.
2025-04-04 14:48:57 +02:00
Zdenek Kabelac
6838881956 libdm: fix missed init of regex pointer
Recent patch set for select enhancement missed to initialize
ssl struct element regex to NULL and this code might have
crashed on this code path evaluation.
2025-04-04 14:48:57 +02:00
Zdenek Kabelac
5d16beee57 WHATS_NEW: update 2025-04-01 15:37:36 +02:00
Zdenek Kabelac
26e86f9da9 make: generate 2025-04-01 15:37:36 +02:00
Zdenek Kabelac
b8b0fcfa10 cov: remove unused header 2025-04-01 15:37:36 +02:00
Zdenek Kabelac
6679438437 tests: check resize of snapshot with mounted origin 2025-04-01 15:37:36 +02:00
Zdenek Kabelac
1bf3961bbe tests: resize of mounted fs missed workaround
For older kernel, we need to suspend/resume.
2025-04-01 15:37:36 +02:00
Zdenek Kabelac
dcf37af2ca tests: preserve signess 2025-04-01 15:37:36 +02:00
Zdenek Kabelac
ebbdaccd9c tests: check unsupported vdo conversions
Validate unsupported vdo conversions are rejected.
2025-04-01 15:37:36 +02:00
Zdenek Kabelac
fafc0f76c5 tests: remove testing of old mirror with vdo
Actually mirror were never supposed to be usable with any newer
target as they are very problematic with any stacked usage.
So now it's going to be properly checked and prohibited.

Users are always supposed to use 'raid1' --type instead.
2025-04-01 15:37:36 +02:00
Zdenek Kabelac
491c6652ae command: use loop for short_opts pass
Slight refactoring of the code to take less size
as the code is used rather occasionally.

Correct some minor typographical issue.
2025-04-01 15:37:36 +02:00
Zdenek Kabelac
ea73594f07 man-generator: print LV1 also for options
We can print list of supported LV types for
options like --cachepool,--thinpool,--vdopool when
they are specifying particular LV.

TODO: while we nicely document them, the parser engine ATM
is not capable to validate and enforce these properties,
so the code needs to match them on its own.
2025-04-01 15:37:36 +02:00
Zdenek Kabelac
9ed7528d1f man-generator: add check for option overlap
Report --check error, when the option is required and optional
for the command.
2025-04-01 15:37:36 +02:00
Zdenek Kabelac
7becd29494 lvconvert: fix _lvconvert_visible_check ret code
_lvconvert_visible_check() used to validate visibility
of converted LV for changing mirrorlog, regionsize
and merging images.
2025-04-01 15:37:36 +02:00
Zdenek Kabelac
3687f7fee3 lvconvert: validate converted LV to vdopool
Although our command-line description file describes
supported types for conversion with some rules,
these are technically not yet fully implemented in
the code, thus we need explicit functionality to
validate passed LVs for conversion.
2025-04-01 15:37:36 +02:00
Zdenek Kabelac
74c178f7bf lvconvert: fix move is positional args
Properly shift args by 1 - hopefully 'argv[]' has the right size
to fit this single shift (as some option must have been there...)
2025-04-01 15:37:36 +02:00
Zdenek Kabelac
82789f6134 lvconvert: simplify passing LV for conversion
Since command is defined to not taky any'free args',
we can actully avoid playing with positional args here
and just pass argv with a single arg.
2025-04-01 15:37:36 +02:00
Zdenek Kabelac
30fdd6b9b4 args: update name of kernel module
Use  '_' for kernel module name.
2025-04-01 15:37:36 +02:00
Zdenek Kabelac
63088e1f82 command-lines.in: matching vdopool conversion
Just use options in the same order as with --type vdo-pool
conversion.
2025-04-01 15:37:36 +02:00
Zdenek Kabelac
579054452b command-lines.in update some description
Add some explicit warning for commands that are destroying content
of converted volume.

Add thinpooldata to the list of allow LVs for caching
(as the code already support this).
2025-04-01 15:37:36 +02:00
Zdenek Kabelac
253ef42362 command-lines.in: add info about implicity type
Short description about how the default implied type
is selected for this lvcreate command.
2025-04-01 15:37:36 +02:00
Zdenek Kabelac
54831ecabd command: update parameter from description
Parameter --profile is already 'generic' parameter,
so it's been listed twice in lvchange & vgchange.

Parameter --uuid was listed 2x in pvchange.
2025-04-01 15:37:36 +02:00
Zdenek Kabelac
a4951801fa tools: add suppport to recognize thinpooldata 2025-04-01 15:37:36 +02:00
Zdenek Kabelac
d0c9bcf6d7 validation: add check for single vdo segments
Add check for VDO LV and VDOPOOL LV having just
a single segment in LV.
Also add couple missing '.'  in error messages.
2025-04-01 15:37:36 +02:00
David Disseldorp
43a755d568 device-types: support zram
See Linux source Documentation/admin-guide/blockdev/zram.rst .
zram devices offer a good performance and efficient resource utilization
through the use of compression.

Signed-off-by: David Disseldorp <ddiss@suse.de>
2025-04-01 15:37:36 +02:00
Bryn M. Reeves
12419e3b67 snapshot: fix lvresize when greater than max COW size
If lvresize is given a size > the maximum COW size for a given origin
the command will fail with an internal error and no error message:

  # lvresize --size 1.6g fedora/snaptest-snap
    Rounding size to boundary between physical extents: <1.59 GiB.
    Reached maximum COW size <1.01 GiB (258 extents).
    Command failed with status code 5.

  With -vvv:

  Found snapshot target v1.16.0.
  Getting target version for snapshot-origin
  dm versions   [ opencount flush ]   [2048] (*1)
  Found snapshot-origin target v1.9.0.
  Reached maximum COW size <1.01 GiB (258 extents). <<<
  Unlock: Memlock counters: prioritized:0 locked:0 critical:0 daemon:0 suspended:0
  Syncing device names
  Unlocking /run/lock/lvm/V_fedora
  _undo_flock /run/lock/lvm/V_fedora
  Freeing VG fedora at 0x55781b142890.
  Freeing VG fedora at 0x55781b136860.
  global/notify_dbus not found in config: defaulting to 1
  Destroy lvmcache content
  Completed: lvresize -vvv --debug --size 1706243072b fedora/snaptest-snap
  Internal error: Failed command did not use log_error

This happens because in this case _lvresize_adjust_extents() returns
early without setting lp->resize to either LV_EXTEND or LV_REDUCE after
capping lp->extents to the maximum COW size.

Fix this by just capping lp->extents and relying on the existing code in
_lvresize_adjust_extents() to fixup lp->resize in the case that
lp->extents == existing_logical_extents. This is consistent with the
no-op case where -l is given as the existing size:

root@localhost:~/src/git/lvm2# LD_LIBRARY_PATH="$PWD/tools" ./tools/lvm lvresize -L 1.6g fedora/snaptest-snap
  Rounding size to boundary between physical extents: 1.60 GiB.
  Reached maximum COW size <1.01 GiB (258 extents).
  New size (258 extents) matches existing size (258 extents).
  No size change.
2025-04-01 15:36:26 +02:00
Peter Rajnoha
0d17105292 libdm: report: select: remove fixme note from _create_field_selection
Let's keep the fail-safe check in for the case some combination (e.g.
after adding a new type) is not caught earlier in the _parse_selection.
2025-03-28 10:12:20 +01:00
Peter Rajnoha
1d94dd075d libdm: report: select: add support for string list regex selection
The c065b407cb77a7a14d7c7c3c94e09fcca2fcff09..872e085030ae8039f18908f6e45bad7ba99250a7
was for device_mapper/libdm-report.c. Do the same for libdm/libdm-report.c
2025-03-25 12:17:27 +01:00
Peter Rajnoha
872e085030 WHATS_NEW: update 2025-03-25 10:25:08 +01:00
Peter Rajnoha
959f775985 tests: select-report: cover string list regex selection 2025-03-25 10:25:08 +01:00
Peter Rajnoha
0c970d8ec7 man: lvmreport: update parts about string list selection 2025-03-25 10:25:08 +01:00
Peter Rajnoha
8d41afbc1f libdm: report: select: support string list selection based on a regex
Wire the field<-->selection comparison logic for regexes used for
string lists.
2025-03-25 10:25:08 +01:00
Peter Rajnoha
b4ebf69739 libdm: report: select: support parsing regex for a string list
Recognize regex in string list selection criterion, including grouping
items by using {} and [] together with && (or ",") and || (or "#")
logical operators:
  - [ <regex> && <regex> ... ]
  - [ <regex> || <regex> ... ]
  - { <regex> && <regex> ... ]
  - { <regex> || <regex> ... ]

Also recognize simple "<regex>" (without any grouping operators)
as a shortcut for "{ <regex> }".
2025-03-25 10:25:08 +01:00
Peter Rajnoha
8c696e463f libdm: report: select: lower initial size for selection mempool
The selection doesn't use that much memory, adjust the size accordingly.
2025-03-25 10:25:08 +01:00
Peter Rajnoha
91c29c318f libdm: report: selection: use separate regex mempool
Regex remembers the mempool it was given during dm_regex_create and
then it uses it for further allocation during dm_regex_match. This
could be dangerous in case we used the same mempool for any other
allocations/frees in between dm_regex_create and dm_regex_match calls
in the outer code. This patch adds separate regex mempool for the
report/select to avoid the possible issues.
2025-03-25 10:25:07 +01:00
Peter Rajnoha
d556d77363 libdm: report: select: default to subset if no grouping operator used
Previous patch made a proper difference between [...||...] and
[...&&...]. If the criterion for a string list does not use any [] or
{}, we need to make sure that proper matching function is called -
in this case not using {} or [] is the same as if {} was used
(matching subset).
2025-03-25 10:25:07 +01:00
Peter Rajnoha
649d17d221 tests: select-report: adjust test for matching [...||...] in string lists 2025-03-25 10:25:07 +01:00
Peter Rajnoha
b4a9897bd8 libdm: report: select: fix string list match for [...||...] selection
Matching a string list criterion which had [... || ... ] was not
correctly implemented - it was the same as [ ... && ... ]. This patch
makes a difference between the two:
  - [ ... || ... ] matches if all items from string list value are
    matched by ANY item from selection string list (that is, not
    all the selection string list items need to match)

  - [ ... && ... ] matches if all items from string list value are
    matched by an item from selection string list 1:1 (that is,
    all the selection string list items need to match)
2025-03-25 10:25:07 +01:00
Peter Rajnoha
523d796b15 libdm: report: select: remove superfluous struct reserved_value_wrapper param
Remove superfluous struct reserved_value_wrapper param for
_tok_value_regex function. The only thing that _tok_value did was
zeroing the reserve field within the struct. But this one is already
zero-initialied in outer _parse_selection function.
2025-03-25 10:25:07 +01:00
Peter Rajnoha
d9832565ec libdm: report: select: make internal errors related to incorrect field types clearer 2025-03-25 10:25:07 +01:00
Peter Rajnoha
6565ce22b7 libdm: report: select: also log function name for internal errors 2025-03-25 10:25:07 +01:00
Peter Rajnoha
53ccbdab1b libdm: report: select: add/edit comments for parser 2025-03-25 10:25:06 +01:00
Peter Rajnoha
c065b407cb libdm: report: select: move regex handling under common value token parsing
This is a cleanup and a preparation for adding support for regex matching
in string lists in subsequent patches.
2025-03-24 14:39:11 +01:00
David Teigland
22b628924f tests: fix metadata-old with lvmlockd_test 2025-03-17 11:49:54 -05:00
Zdenek Kabelac
06baec439e make: generate 2025-03-17 13:52:03 +01:00
Zdenek Kabelac
92493361f3 WHATS_NEW: updates 2025-03-17 13:51:24 +01:00
Zdenek Kabelac
5efa388206 man: indent with command
Avoid spaces showing as the 1st. character on the man page line.
Also start with actual text and move .IP sequence to the line end.
2025-03-17 13:51:24 +01:00
Zdenek Kabelac
fe1cf7174f makefile: rebuild man when see_also changes
Missed rebuild dependency, when see_also file changes.
2025-03-17 13:48:58 +01:00
Zdenek Kabelac
6e5e7b3193 makefile: cleanup tab 2025-03-17 13:48:58 +01:00
Zdenek Kabelac
a6264f6a44 tests: don't restart lvmdbusd
Since lvmdbusd execution of lvm2 command was fixed
stop retrying to restart lvmdbuds and abort testig
when it fails.
2025-03-17 13:48:58 +01:00
Zdenek Kabelac
b2f8e744de lvm: option description only for man generator
There is no need to include option description text
within command binary itself.

It's only used only for man generating.
2025-03-17 13:48:58 +01:00
Zdenek Kabelac
01e4764c40 man: fixes in argument description
Describe missed --segments opt for lvdisplay (matches lvs).

Describe lvm-fullreport --all option - show text for lvs,vgs,pvs.

Missed '.' for --separator.
2025-03-17 13:48:58 +01:00
Zdenek Kabelac
c9ee8d8a06 lvmdbusd: ensure readout on exit 2025-03-17 13:48:58 +01:00
Zdenek Kabelac
154befd4b8 cache: ensure UUID ends with \0
Initialization of union is somewhat tricky as it initialize only
the first member + padding, but in our case this does not clear
the whole size of union so explicitly set \0 after 2 'struct id'
and make sure DM uuid is not using random characters from stack.

Also add explicit .id designators (c99).
2025-03-17 13:48:58 +01:00
David Teigland
951fd6358b metadata: replace pv status WRONG_VG with pv bit field
Avoid any special meaning associated with the status field.
2025-03-06 10:52:50 -06:00
David Teigland
8efbffe086 lvmcache: unpair wrong PV devs and improve duplicate name warnings
After detecting that a VG has wrongly claimed a PV, unpair
the pv->dev setting.  This will cause the usual "missing PV"
message to appear for that VG.  Make this message, and some
others, clearer by using the VGID rather than the VG name
when there are multiple VGs with the same name.
2025-03-06 10:02:29 -06:00
David Teigland
cff93e4d5c lvmcache: fix check for no pvid 2025-03-05 16:03:42 -06:00
David Teigland
227d3ca507 lvmcache: add WRONG_VG PV status flag
_vg_read() calls lvmcache_update_vg_from_read() which detects
that the VG metadata is incorrectly claiming the PV.  Flag this
condition in the PV status as WRONG_VG.  Later, vg_read() can
simply check the WRONG_VG flag rather than repeating the same
PV/VG checks that were already done in lvmcache_update_vg_from_read.
2025-03-05 14:28:42 -06:00
David Teigland
cc843151b4 lvmcache: ignore incorrect PV claim from old metadata
Outdated VG metadata that appears when an old device is attached
to the system can result in PVs appearing to belong to the
old/wrong VG, and commands are allowed to use (corrupt) the PVs.

- vgcreate old /dev/sda /dev/sdb /dev/sdc
- offline /dev/sda
- vgreduce --removemissing old
- vgremove old
- vgcreate new /dev/sdb /dev/sdc
- online /dev/sda

When sda is reattached, sdb and sdc will appear to be
in VG old again.  An attempt to correct the problem,
e.g. with vgremove old or vgreduce old, would modify
sdb and sdc, removing them from the new VG.

To fix this, check that sdb and sdc contain metadata for
VG old before allowing VG old to claim ownership of them.
With the fix, sdb and sdc are not displayed as part of
VG old, and commands to change VG old will fail as long
as it references incorrect PVs.

To fix VG old (sda), remove the incorrect PVs from VG old
while limiting the command to see only the correct PVs:
vgreduce --removemissing --devices /dev/sda old
2025-03-05 14:16:46 -06:00
David Teigland
7dd2f101c7 integrity: round meta size up to minimum one extent
If VG extents are larger than the required integrity metadata size,
use one extent as the size.
2025-03-03 11:31:40 -05:00
David Teigland
381b45b5a9 lvmlockd: add helpful error message for vgremove
Print a helpful error message when the lockspace is not started.
2025-03-03 11:05:04 -05:00
David Teigland
8273a6e2e1 pvresize: accept autobackup option 2025-02-27 10:05:27 -06:00
Marian Csontos
c59a8e2d56 doc: Update metadata on 2.03.31 release notes 2025-02-27 16:53:55 +01:00
Marian Csontos
a1e449dea2 post-release 2025-02-27 16:51:29 +01:00
Marian Csontos
3a6e221c56 pre-release 2.03.31 2025-02-27 16:51:29 +01:00
Marian Csontos
d80d346f4e doc: WHATS_NEW and release note update 2025-02-27 16:49:34 +01:00
Marian Csontos
54ade3a6bb doc: Apply markdown formatting 2025-02-27 16:12:52 +01:00
Eric Blake
1dcd9fbe08 misc: Typo fix s/loose/lose/
Signed-off-by: Eric Blake <eblake@redhat.com>
2025-02-26 10:32:19 +00:00
Eric Blake
a853649565 misc: Typo fix s/more then/more than/
Also a few instances of s/less then/less than/.

Signed-off-by: Eric Blake <eblake@redhat.com>
2025-02-26 10:32:19 +00:00
Zdenek Kabelac
a512bf3c62 WHATS_NEW: update 2025-02-26 01:35:12 +01:00
Zdenek Kabelac
9197880050 make: generate 2025-02-26 01:31:50 +01:00
Zdenek Kabelac
16bc80c389 test: check LVM_SUPPRESS_FD_WARNINGS
Add test for suppression messages about leaked descriptors.
2025-02-26 01:31:49 +01:00
Zdenek Kabelac
4fa6c76181 lvmlockd: drop return from void function 2025-02-26 01:31:49 +01:00
Zdenek Kabelac
b4c9f29eb3 man: update generator code
Generate pages more complaint with 'mandoc -T lint'
Remove some generated space on EOL.
Replace .ad l with .na  macro.
Remove some .br duplicates.
2025-02-26 01:30:31 +01:00
Zdenek Kabelac
8d855ff23a man: reformat args.h to fit in 80 lines
Compliance to mandoc -T lint to fit lines into 80 chars
in generated man pages.
2025-02-26 01:29:54 +01:00
Zdenek Kabelac
ba9c4368f4 man: updates
Updates for 'mandot -T lint'
Fit lines into 80 characters.
Use  .na .ad   instead of  .ad l  .ad b
Remove some misplaced  .P  & .br
Trim spaces for EOL.
2025-02-26 01:27:15 +01:00
Jack Wilsdon
1f728f370f libdaemon: fix suppressing stray fd warnings
Restore support for LVM_SUPPRESS_FD_WARNINGS as
this was seemingly lost with refactoring to
use daemon_close_stray_fds().
2025-02-26 01:21:19 +01:00
David Teigland
80ee9e45cb uncache and splitcache should restore inactive state
If an inactive LV is being cached in writeback mode, then
removing the cache does a temporary activation to flush
the cache back to the main LV.  However, it forgot to
deactivate the LV again, so the temporary activation
was left in place.
2025-02-25 15:48:28 -06:00
David Teigland
297808c269 lvmlockd: add debug line 2025-02-25 15:48:28 -06:00
David Teigland
dfb4ed13f6 lvmlockd: expand lockopt skip options
The lockopt options for skipping locks were not being used
in many places, making it impossible to override locking to
forcibly run some commands.
2025-02-25 12:40:36 -06:00
Zdenek Kabelac
be25429ea7 test: result is some for lvmpolld
Drop 'TEST WARNING' from this case - the code works the same
were for 'pvmove -b' polling as for lvmpolld.

Just keep there 'TODO' notice we want to eventually reduce amount
of 'worked' pvmove monitoring process - ATM there will be 1 per LV.
2025-02-25 01:10:04 +01:00
Salvatore Bonaccorso
36bdffb6a4 man: clarify --stripes number of device
The current manpage is unclear in the example of a raid10 type LV RAID
with --mirrors 1 --stripes 4. The number of devices in each raid1 mirror
is NumberStripes/(NumberMirrors+1). Thus the example should read:

e.g. mirrors 1 and stripes 4 will stripe data across two raid1
mirrors, where each mirror contains two devices.

Fixes: https://gitlab.com/lvmteam/lvm2/-/issues/26
Signed-off-by: Salvatore Bonaccorso <carnil@debian.org>
2025-02-25 01:10:04 +01:00
Dion Bosschieter
6f9e247285 man: fix grammar in lvmlockd.8_main
Remove redundant 'the' in 'When the another VG'.

Signed-off-by: Dion Bosschieter <dionbosschieter@gmail.com>
2025-02-25 01:10:04 +01:00
Tyler Clark
be0b2ea01a man: removing duplicate words in man pages.
This patch removes some sequentially duplicated words in a few man pages.
2025-02-25 01:10:04 +01:00
Zdenek Kabelac
d5ac344465 clang: match prototype 2025-02-25 01:10:04 +01:00
Zdenek Kabelac
4789abbcd2 cov: some missed arg_is_set changes 2025-02-25 01:10:04 +01:00
Zdenek Kabelac
a29d0c014a lvconvert: validate mirror image counting
Since _failed_mirrors_count() may eventually return -1,
add extra validation before using returned count.
2025-02-25 01:10:04 +01:00
Zdenek Kabelac
7d0acdbcb0 thin: fix checking monitor mode
Previous commit 874a8ab4d0 missed 'IGNORE' mode.
Fix it by adding rather 'explicit' test for this value,
so the code is better readable.

Also unlock memory earlier and drop unneeded <backtrace>
from return since we already logged error in this function.
2025-02-25 01:09:49 +01:00
David Teigland
5430eec2b9 lvmlockd: fix missing lvremove free_lv
Fix missing lockd_free_lv in commit
e3f0af8f1f lvmlockd: fixes for lvremove
2025-02-24 16:36:01 -06:00
Zdenek Kabelac
d83f40d25a tests: reduce Exa test size
Since kernel patch 3d9a9e9a77c5ebecda43b514f2b9659644b904d0  (6.14)
it seem device size is no limitted to <8Exa bytes (so LLONG loff_t
works across whole device).

So reduce our tested size to 8191 Peta  ~ <8 Exa.
2025-02-24 18:59:58 +01:00
Zdenek Kabelac
c40bd459df test: wait for polling finish
Increase the used mirror size for longer processing.

Add more -vvvv traces to pvmove to better chase test error.

Add extra code to wait for finish of polling pvmove after it's
been aborted - so it doesn't break 'next' test.
2025-02-24 18:59:58 +01:00
Zdenek Kabelac
d016158ff9 WHATS_NEW: updates 2025-02-24 18:59:58 +01:00
Zdenek Kabelac
874a8ab4d0 cov: add value check 2025-02-24 18:59:58 +01:00
Zdenek Kabelac
0fe1613c9b cov: use arg_count for unchecked usage
Reserve usage of  'arg_is_set()' to tested use case and use
arg_count() for unchecked one.
2025-02-24 18:59:58 +01:00
Zdenek Kabelac
56398a2180 cov: explicitly ignore value 2025-02-24 18:59:58 +01:00
Bjarni Ingi Gislason
bb458e9528 man: remarks and editorial changes for dmstats
Use "groff -e ' $' -e '\\~$' <file>" to find obvious trailing spaces.
Use "mandoc -T lint  dmstats.8"
Use "test-groff -mandoc -t -ww -z dmstats.8"

-.-.

Lines containing '\c' (' \c' does not make sense):

503:.B \-\-units \c

-.-

Change '-' (\-) to '\(en' (en-dash) for a (numeric) range.
GNU gnulib has recently (2023-06-18) updated its
"build_aux/update-copyright" to recognize "\(en" in man pages.

dmstats.8:470:expressed as a hyphen separated range, for example: '1\-10'.

-.-.

Add a (no-break, "\ " or "\~") space between a number and a unit,
as these are not one entity.

1114:Create a 32M region 1G into device d0

-.-.

Add a "\&" after "e.g." and "i.e.", or use English words
(man-pages(7)).
Abbreviation points should be protected against being interpreted as
an end of sentence, if they are not, and that independent of the
current place on the line.

511:Can also specify custom units e.g. \fB\-\-units\ 3M\fP.

-.-.

Wrong distance between sentences in the input file.

  Separate the sentences and subordinate clauses; each begins on a new
line.  See man-pages(7) ("Conventions for source file layout") and
"info groff" ("Input Conventions").

  The best procedure is to always start a new sentence on a new line,
at least, if you are typing on a computer.

Remember coding: Only one command ("sentence") on each (logical) line.

-.-.

The name of a man page is typeset in bold and the section in roman
(see man-pages(7)).

798:extents). This currently includes \fBxfs(5)\fP and \fBext4(5)\fP.
801:group, and the group alias is set to the \fBbasename(3)\fP of the

-.-.

Use thousand markers to make large numbers easy to read

560:is equivalent to 10000000. Latency values with a precision of less than

-.-.

Remove quotes when there is a printable
but no space character between them
and the quotes are not for emphasis (markup),
for example as an argument to a macro.

1:.TH DMSTATS 8 "Jun 23 2016" "Linux" "MAINTENANCE COMMANDS"

-.-.

Output from "test-groff  -mandoc -t -K utf8 -rF0 -rHY=0 -rCHECKSTYLE=10 -ww -z ":

.-.

Additionally:

  Fix some arguments for '.TP'.  A single-font macro does not work with
'\c', so use a two-font macro.

-.-

  Use the pair ".na / .ad" to set no-adjustment (same result as '.ad l')
and '.ad' to restore previous adjustment.
[Replacing ".ad l" ... ".ad b"]

  Set singular '.ad b' to '.ad \*(AD' as the user should have the choice to
control the adjustment from the command line.

  Add an empty string to string 'AD' with '.as AD "\"' to avoid a warning
about an undefined string.

-.-

Generally:

Split (sometimes) lines after a punctuation mark; before a conjunction.

Updated-by: zkabelac@redhat.com
2025-02-24 18:59:58 +01:00
Bjarni Ingi Gislason
2fae69cc4b man: remarks and editorial changes for dmsetup
Checking for defects with a new version

Use test-[g|n]roff -mandoc -t -K utf8 -rF0 -rHY=0 -rCHECKSTYLE=10 -ww -z < "man page"
Use "groff -e ' $' -e '\\~$' <file>" to find obvious trailing spaces.
Use "mandoc -T lint  dmsetup.8":
Use "test-groff -mandoc -t -ww -z dmsetup.8":

-.-.

Add a (no-break, "\ " or "\~") space between a number and a unit,
as these are not one entity.

-.-.

Use "\e" to print the escape character instead of "\\" (which gets
interpreted in copy mode).

487:with its hex value (two digits) prefixed by \\x.

-.-.

Strings longer than 3/4 of a standard line length (80)
Use "\:" to split the string at the end of an output line, for example a
long URL (web address)

1030 <name>,<uuid>,\:<minor>,<flags>,\:<table>\:[,<table>+]\:[;<name>,<uuid>,\:<minor>,<flags>,<table>\:[,<table>+]]

-.-.

Add a "\&" after "e.g." and "i.e.", or use English words
(man-pages(7)).
Abbreviation points should be protected against being interpreted as
an end of sentence, if they are not, and that independent of the
current place on the line.

581:Note: Same cookie should be used for same type of operations i.e. creation of
767:Attempts to remove all device definitions i.e. reset the driver.  This also runs
946:e.g. striped 2 32 /dev/hda1 0 /dev/hdb1 0

-.-.

Wrong distance between sentences in the input file.

  Separate the sentences and subordinate clauses; each begins on a new
line.  See man-pages(7) ("Conventions for source file layout") and
"info groff" ("Input Conventions").

  The best procedure is to always start a new sentence on a new line,
at least, if you are typing on a computer.

Remember coding: Only one command ("sentence") on each (logical) line.

Mark a final abbreviation point as such by suffixing it with "\&".

Some sentences (etc.) do not begin on a new line.

Split (sometimes) lines after a punctuation mark; before a conjunction.

-.-.

Use \(en (en-dash) for a dash at the beginning (en) of a line,
or between space characters,
not a minus (\-) or a hyphen (-), except in the NAME section.

-.-.

Remove quotes when there is a printable
but no space character between them
and the quotes are not for emphasis (markup),
for example as an argument to a macro.

1:.TH DMSETUP 8 "Apr 06 2006" "Linux" "MAINTENANCE COMMANDS"

-.-.

Output from "test-groff  -mandoc -t -K utf8 -rF0 -rHY=0 -rCHECKSTYLE=10 -ww -z ":

Updated-by: <zkabelac@redhat.com>
2025-02-24 18:59:58 +01:00
Zdenek Kabelac
0d4418fe6c polldaemon: handle sigint from nanosleep
Handle interruption caught in sleep between polling and
abort() tool execution in such case.
(Although ATM we are not normally signalling the tool this way).
2025-02-24 18:59:58 +01:00
Zdenek Kabelac
bb66753a14 polldaemon: enhance error tracking
Improve error handling in polling functions where errors
were previously ignored. These errors result from serious
failures (e.g., allocation errors) and should lead to a full
command exit, as the tool cannot function in such a state.

FIXME:

However, there is a fundamental design issue worth considering:
when a command like pvmove --abort cancels an ongoing operation,
the existing polling command continues running and only terminates
once it detects that there is nothing left to poll.

Next issue is perment reopening of a VG when 'monitoring' progress.

And the last is big trouble with '--interval 0' which is able to
wait in DM ioctl() and hold the VG lock, and there is not good way
to about such operation (other then sending a signal to such process).
2025-02-24 18:59:58 +01:00
Zdenek Kabelac
c1bc0c9726 lvmpolld: easier alloc code
Share _free_lvmpolld_lv() function.
2025-02-24 18:59:58 +01:00
Zdenek Kabelac
685e704373 test: skip retry only for lvconvert
Mirror creation is creating log volumes and needs occasionally
retry loop for deactivation.
2025-02-24 18:59:58 +01:00
Zdenek Kabelac
4be1c7b6ca makefile: remove old lcov files
Remove any older lcov generated files ('*.gcda|gcno') then the currently
generated 'make.file' before creating a new lcov report.

Otherwise we may hit the problem of using some older generated files
possibly with different format.
2025-02-24 18:59:58 +01:00
Jianqi Zeng
36be0778f8 libdm: restore missing symbols
Restore missing symbols to the libdevmapper.so library.

These symbols:

dm_bitset_parse_list@@DM_1_02_138
and dm_tree_node_size_changed@Base

become 'lost' with commit: 40b277ae17
which supposedly cleaned local 'symbols' from visibility,
however these missing symbols were impproperly exported.

Signed-off-by: Jianqi Zeng <zengjianqi@kylinos.cn>
2025-02-24 18:59:58 +01:00
David Teigland
6ad474385b lvmlockd: recognize error ELMERR 2025-02-20 10:18:28 -06:00
David Teigland
b02e6cd4a9 lvmlockd: disallow shared activation of LV with cow snapshot
The check for disallowing shared activation was missing
a check for this type.
2025-02-19 16:19:42 -06:00
Zdenek Kabelac
bb0bbc6d74 test: repeatedly restart lvmdbusd
It looks like occasionally supports_json() in cmdhandler.py
for some reason does not find  'fullreport' in err output
of lvm help...  let's see more traces...
2025-02-19 00:36:46 +01:00
Zdenek Kabelac
8417a6a578 revert "test: aux gives more time for lvmdbusd start"
This reverts commit 8425c1b468.

Seems we have different problem with lvmdbusd test start.
2025-02-19 00:36:46 +01:00
Zdenek Kabelac
79c022133b test: improve holding device open
Use 'exec' to open device and then just pass descriptor to sleep.
2025-02-19 00:36:46 +01:00
David Teigland
e3f0af8f1f lvmlockd: fixes for lvremove
The simple common case of locking the LV to remove with a
persistent lock would usually be fine, but there are a number
of special cases that were not addressed:
- no locking was done for removing cow snapshot
- direct locking to vdo pool
- dm-cache uncache using lvremove was not handled
2025-02-18 11:57:01 -06:00
David Teigland
5359737c29 lvmlockd: use lockd_lvcreate_lock for multiple LV types
Use the same lockd_lvcreate_lock() for all cases in which
creating a new LV first requires locking another associated
LV, e.g. locking the pool or origin for the new LV.
2025-02-18 11:50:52 -06:00
Zdenek Kabelac
b13b55884a test: add check for no such file 2025-02-17 15:51:03 +01:00
Zdenek Kabelac
da19ef49b1 cov: refactor code for warning
Refactor resizing loop, so Coverity no longer sees
the loop as 'infinite' and the code is also readable.
2025-02-17 15:51:03 +01:00
Zdenek Kabelac
03b78fa666 cov: refactor code
Refactor code, so Coverity doesn't complain about over-running
an array with char*.
(IMHO this seemed like a problem in Coverity code evaluation)
2025-02-17 15:51:03 +01:00
Zdenek Kabelac
a87cc133e2 cov: initialize arrays values 2025-02-17 15:51:03 +01:00
Zdenek Kabelac
07f23d4b81 clang: refactor code for easier alloc tracking
Refactor _get_split_name(). code to simplify detection of memory leak
in _destroy_split_name(). Now there are always just 2 pointers
instead of conditional pointer free() which is hard to follow.
2025-02-17 15:51:03 +01:00
Zdenek Kabelac
8bdc234348 clang: call alloca with non-zero size
Make sure that some non 0 size is also for (mirrors == 0).
2025-02-17 15:51:03 +01:00
Zdenek Kabelac
05f1e78f3e clang: pointer protection 2025-02-17 15:51:03 +01:00
Zdenek Kabelac
9f425a62fc clang: validate command before exec
Add extra check for command existence in argv before fork().
2025-02-17 15:51:03 +01:00
Zdenek Kabelac
1e91c16112 clang: use better readable code
Here we make sure, that we always free fopen() fp.
As theoretically we may have had opened 'stdout'.
2025-02-17 15:51:03 +01:00
Zdenek Kabelac
12efeb6d51 clang: validation 2025-02-17 15:51:03 +01:00
Zdenek Kabelac
5fd50ae192 tools: using proper header order
ARG_COUNT is generated by processing command_enums and
then it can be used by command.h.

So correct include order and later use command.h.
2025-02-17 15:51:03 +01:00
Zdenek Kabelac
5a6d318b29 cleanup: headers self compilable
In most cases header should be self-compilable, so the
do not expect other 'header' files to be used upfront
so the header would be compilable.

No functional change.
2025-02-17 15:51:03 +01:00
Zdenek Kabelac
924221765e cleanup: match function prototype with definition
Match variable name in function definition with
its prototype. Pick the name which better fits
the usage.

No functional change.
2025-02-17 15:51:03 +01:00
Zdenek Kabelac
a6b2ce6299 cleanup: project headers in front
Include project headers before system header files.
2025-02-17 15:51:03 +01:00
Zdenek Kabelac
464c30e6c3 clang: silence warning
Make the code pass through Coverity/clang.
As it didn't like theoretical access beyond
_yes[] & _no[] array elements.
2025-02-17 15:51:03 +01:00
Zdenek Kabelac
5e127fb8e9 clang: correcting imprecise prototype
These internal header were using misleading variable names
in function prototypes, but correct names were used in
function definition. Noticed with:

clang-tidy --checks=readability-inconsistent-declaration-parameter-name

No functional change.
2025-02-17 15:51:02 +01:00
Zdenek Kabelac
f66c76e5ea clang: make pointer defined 2025-02-17 15:51:02 +01:00
Zdenek Kabelac
3a700dd2f2 clang: add known mask value
Bit flags likely should never have been 'enum' but since
we have this in a public header - it might be hard to
replace this. So at least add missing 'enum' element
we use.
2025-02-17 15:51:02 +01:00
Zdenek Kabelac
bacd9f394d clang: check pointers 2025-02-17 15:51:02 +01:00
Zdenek Kabelac
cb0c43898a clang: pointer validation 2025-02-17 15:51:02 +01:00
Zdenek Kabelac
ff1f1188c3 clang: better visibility of non-null lock_type
clang can't see transient result, however
it would be still better to check for type string just once.
2025-02-17 15:51:02 +01:00
Zdenek Kabelac
9cc6b15dd9 clang: ensure defined value
Although this radix_tree_simple code is not being unused ATM...
2025-02-17 15:51:02 +01:00
Zdenek Kabelac
e737c54d8a clang: validate allocated buffer size
Validate for not using 0 size arg for allocation,
however this can never heapen for running code...
2025-02-17 15:51:02 +01:00
Zdenek Kabelac
1d13b391f8 clang: trace rewind errno
Although rewind() return void, it's API suggest
to check for 'errno' value.
2025-02-17 15:51:02 +01:00
Zdenek Kabelac
15b3cf1104 clang: reduce padding in struct cfg_def_item
Reorder struct members to minimize padding.
2025-02-17 15:51:02 +01:00
Zdenek Kabelac
4ff8c706db clang: reduce padding in struct command_name
Reorder struct members to minimize padding.
2025-02-17 15:51:02 +01:00
Zdenek Kabelac
0c3c08b95f clang: refactor code to always run inner loop
Make it more clear to analyzer the inner loop always runs.
Otherwise it may complain about *c being NULL.
2025-02-17 15:51:02 +01:00
Zdenek Kabelac
063984afde clang: valid area is required
Do not try to check references when verifying
LV segments with missing area.
2025-02-17 15:51:02 +01:00
Zdenek Kabelac
623e98e16c clang: ensure extents is usable
Although the code was exiting only for  (update == 0),
the later code actually used requires 'extents' to exist
also for  (update != 0).

TODO: The logic here is not very clear, more testing needed.
2025-02-17 15:49:54 +01:00
Zdenek Kabelac
f0a707f6b4 clang: fix double free in error path
When prefix insertion to radix_tree would fail, the error
path might try to possible double free allocated memory.
2025-02-17 15:41:53 +01:00
Zdenek Kabelac
bea43e4faa raid: set warn print level
Since there conversion messages are not causing direct
command error, switch message level to log_warn().
2025-02-17 15:41:53 +01:00
David Teigland
c326796a89 man lvm: add tag info
Restore basic info about tags that was dropped years ago
during the reworking for man page generation.
Also some other minor random updates.
2025-02-13 12:21:51 -06:00
David Teigland
fd341c818d lvcreate: accept lockopt option
The redundant lvcreate.c implementation of accepted options needs
to be removed.
2025-02-13 11:42:24 -06:00
Zdenek Kabelac
00a3664a5c test: improve for use with older systems
Improve test, so it's also working on systems without delay_dev
and test is actually more 'race' resistant.
2025-02-13 11:05:23 +01:00
Zdenek Kabelac
625a38c855 raid: remove struct overlap with possible_takeover
After reorganizing elements in `possible_takeover_reshape_type`
(in commit 5b92ce741f),
it became apparent that the code relied on struct overlap,
which is somewhat unsafe. This commit removes it and ensures
proper `const` qualification for the struct usage.
2025-02-13 11:04:30 +01:00
David Teigland
04cacff3b9 lvmlockd: lockd_vg return value cleanup 2025-02-12 11:16:16 -06:00
Zdenek Kabelac
852f3c20bb lcov: ignore some errors
While building lcov files - ignore errors from 'negative' counter
(perhaps we can use -fprofile-update=atomic - but it would be another
slowdown of test runs)

Also ignore unexecuted blocks warnings with 'gcov'.

Failure of lcov goal is not supposed to error whole make build.
2025-02-12 15:12:31 +01:00
Zdenek Kabelac
8a67936e7e cleanup: match prototype 2025-02-12 15:11:56 +01:00
Zdenek Kabelac
13fcb7e428 cleanup: use full source path to header 2025-02-12 15:11:56 +01:00
Zdenek Kabelac
736db4247c test: handle lvmpolling case
When test runs with lvmpolld - we cannot check
messages from pvmove - as those are visible through
output of lvmpolld - so just skip this and
only check LVs are in expected state.
2025-02-12 15:11:56 +01:00
Zdenek Kabelac
0bb06eb99b coverity: cleanup model code 2025-02-12 14:31:37 +01:00
Zdenek Kabelac
5b92ce741f gcc: better structure padding
Since we use '.option' to assign struct member - just suffle
structure element for better padding.
2025-02-12 14:31:37 +01:00
Zdenek Kabelac
c0b725d6e6 gcc: fabsf float based operation
Use 'float' version of 'fabs()' to compare floats.
2025-02-12 14:31:37 +01:00
Zdenek Kabelac
75a39003b0 clang: just use regular final else
There is no need to compare, so just keep 'if' part as the comment.
2025-02-12 14:31:37 +01:00
Zdenek Kabelac
e9640e5178 sanlock: more variable structure part to the end
Move variable part so there is no need to use 'gnu' compiler extension.
2025-02-12 13:55:29 +01:00
Zdenek Kabelac
e410715154 mirror: make sure 0 is not clz arg
Just make sure there will be never ever used '0'
as parameter for clz().
2025-02-12 13:55:29 +01:00
Zdenek Kabelac
d6934ea31d lvmcmdline: fix printed error messages
Since long_opt was changed to char[], we were only comparing pointers
that always exist, whereas the original intention of the test was
to verify the presence of a string
(i.e., checking that the first byte is not \0).
2025-02-12 13:55:22 +01:00
David Teigland
a1017024f1 raidintegrity: support removal of partial images
vgreduce --removemissing --force replaces a partial image
with an error target.  When that image includes an integrity
layer, that layer needs to first be removed.
2025-02-10 12:10:08 -06:00
Zdenek Kabelac
e7ae3fbd10 WHATS_NEW: update 2025-02-10 11:31:53 +01:00
Zdenek Kabelac
8425c1b468 test: aux gives more time for lvmdbusd start
Try 20s delay to see whether dbus service will be alive...
2025-02-10 11:31:53 +01:00
Zdenek Kabelac
7f12b5d0dc test: split mirror with opened leg 2025-02-10 11:31:53 +01:00
Zdenek Kabelac
550ce921fa test: check layout for error and zero 2025-02-10 11:31:53 +01:00
Zdenek Kabelac
d913d776d1 test: pvmove with open temporary volumes
Test pvmove logic when various pvmove mirror volumes are opened
while pvmove is finishing.
2025-02-10 11:31:53 +01:00
Zdenek Kabelac
a9fcc3ab0c gcc: compare same signedness 2025-02-10 11:31:53 +01:00
Zdenek Kabelac
a187f02ed5 vdo: correctly size string array
Fix logging of VDO configuration info message which has acutally
printed " and," using next element..
Increase the array element size so it can store >=5 bytes
for " and" + \0.
2025-02-10 11:31:53 +01:00
Zdenek Kabelac
74a2325261 mirror: splitting handles opened devices
Similar to the pvmove update, enhance error path handling
for scenarios where legs or logs remain open and cannot be
closed during the splitting of a mirror image.

Remove the now obsolete _delete_lv() function,
as it will no longer be needed.
2025-02-10 11:31:53 +01:00
Zdenek Kabelac
be1b83a76f mirror: move status bit masking
Use bit masking in replace_lv_with_error_segment().
2025-02-10 11:31:53 +01:00
Zdenek Kabelac
87a4e7bb68 debug: update message for pvmove
Add some more consistency to message printed for pvmove.
2025-02-10 11:31:53 +01:00
Zdenek Kabelac
7858c25427 debug: use more similar skipping messages 2025-02-10 11:31:53 +01:00
Zdenek Kabelac
425ae9aaf0 debug: reinitialize debug pid after fork 2025-02-10 11:31:53 +01:00
Zdenek Kabelac
2a34723511 lv_manip: print layout for error and zero 2025-02-10 11:31:53 +01:00
Zdenek Kabelac
ed9468153e mirror: enhance error path for pvmove finish
When the pvmove operation is completing, it attempts to deactivate
the temporary mirror and remove its mirror legs. However,
if an external tool holds these volumes open, the operation would
previously abort entirely, leaving the LVM2 metadata in a partially
unusable state that required manual administrative fixes.

To improve this, the code has been enhanced to handle such scenarios
more gracefully. It will now complete the pvmove operation even
if some volumes cannot be deactivated, marking them in the metadata
with an error segment. While the command will report errors,
the metadata will remain in a usable state. The administrator
can then remove the orphaned volumes when they are no longer in use.
2025-02-10 11:31:52 +01:00
David Teigland
09e508cd43 devices file: fix backup limit
Fix the code that limited the total number of backup files.
It failed, and left excess files, when the file version
number was greated than 9999, exceeding the four digit suffix.

Now, after version 9999, the suffix intentionally grows beyond
four digits as needed, and is not a fixed width, or zero padded.
2025-02-05 20:40:59 -06:00
Zdenek Kabelac
a6408163dd lvmlockd: correct prototype for sanlock-less build 2025-02-03 10:45:09 +01:00
Zdenek Kabelac
c68af364e7 lvmlockd: compilation fixes 2025-02-02 20:06:10 +01:00
Zdenek Kabelac
d5cc65f683 gcc: std=c11 for test suite as well 2025-02-02 20:00:44 +01:00
Zdenek Kabelac
082d475ea9 debug: missed stack tracing 2025-02-02 20:00:44 +01:00
Zdenek Kabelac
29bb84f17b raid: refactor code to _raid_leg_degraded
Move common code into _raid_leg_degraded().
2025-02-02 20:00:44 +01:00
David Teigland
48d7511808 lvmlockd: fix free_lv immediately after init_lv
Fix for recent commit "lvmlockd: free resource structs for LVs"

When a vg_write() fails in lvcreate, lvmlockd sees init_lv()
followed by free_lv().  The LV lock is not acquired prior to
free_lv, and no prior resource struct exists. This wasn't being
handled.
2025-01-31 18:38:39 -06:00
David Teigland
ffeee23537 lvmlockd: log correct name in error path
fix for recent "lvmlockd: free resource structs for LVs"
2025-01-30 16:38:33 -06:00
Zdenek Kabelac
46a48f1320 vg_read: correct error path for DM cache update
New code for updating DM cache traveled through couple destination
however in this place only 'return_0' is missing unlocking in
error path.
2025-01-30 20:02:25 +01:00
Zdenek Kabelac
2c63b12bd3 tests: more info from test 2025-01-30 17:26:08 +01:00
Zdenek Kabelac
36ae51c3cb dev-type: require 4k only for some topology attrs
Previous commit 5f71cebcbe was not
correct. 4k requirement cannot be put on attribute_offset - where
it is valid to have this only 512b aligned.
The rule might get more complicated to recognized invalid values.
For this moment however add more easier requirement - we
impose 4K restriction on minimal and optimal io size if they
are bigger then 1 sector (512B).
2025-01-30 17:23:45 +01:00
Zdenek Kabelac
1e21b0a6f2 WHATS_NEW: update 2025-01-30 13:38:31 +01:00
Zdenek Kabelac
12f1472972 cov: annotate 2025-01-30 13:38:31 +01:00
Zdenek Kabelac
1719f1169f cov: ensure buffer does not underflow
Add explicit check for having always positive value.
2025-01-30 13:38:31 +01:00
Zdenek Kabelac
d32ee0b7ab cov: avoid expression overflow
Keep max memory in MiB  (>> 20).
2025-01-30 13:38:31 +01:00
Zdenek Kabelac
42a43c37de cov: explicitly ignore return codes 2025-01-30 13:38:31 +01:00
Zdenek Kabelac
583e5f952e cov: add validation of FID pointer
Ensure NULL theoretical NULL FID pointer is not
dereferenced.
2025-01-30 13:38:31 +01:00
Zdenek Kabelac
fd91edfd15 cov: limit buffer size for sscanf
Limit sscanf parser buffer width for string.
2025-01-30 13:38:31 +01:00
Zdenek Kabelac
51030c57a1 cov: use bigger buffer
Since pvck's  _check_vgname_start is actually checking
up-to (NAME_LEN + 2) bytes  (130),
use at least this size for (MAX_LINE_CHECK + 3).
2025-01-30 13:38:31 +01:00
Zdenek Kabelac
1e21a93ead cov: limit log levels to 7
lvm2 is using 7 levels for logging.
(Which might be already probably too much...)
2025-01-30 13:38:31 +01:00
Zdenek Kabelac
cae445443e cov: add sscanf width specifiers for lvmlockctl 2025-01-30 13:38:31 +01:00
Zdenek Kabelac
f582c7be1d cov: add space for string 0
Sscan may automatically add 0 after field width mark,
and since it's not exactlu trivial to do a macro calculation
for PATH_MAX - 1, rather make buffer for sscanf results bigger.

Also use matching FSTYPE_MAX as field width specifier.
2025-01-30 13:38:31 +01:00
Zdenek Kabelac
09d896810b cov: add extra byte for 0
Since we use 'DM_NAME_LEN' size for sscanf - it may need to store
extra string 0, which is added automatically after 'maximum field
width' specifier.
2025-01-30 13:38:31 +01:00
Zdenek Kabelac
07b595d0f3 gcc: updates for use with std=c11
Let gcc -std=c11 pass...
Useful i.e. to get working Coverity scan ATM.
(as gcc15 and stdbool changes makes it problematic.)
2025-01-30 13:38:31 +01:00
Zdenek Kabelac
9fe73c8d95 debug: drop double '/' in created pathname
Our cmd->dev_dir already has '/dev/' so do not use '/dev//devname'.
2025-01-30 13:38:31 +01:00
Zdenek Kabelac
27f0ca79cc tests: update topology test
Check lvm2 create usable VG for optimal_io_size 16776704
(which is not divisible by 4KiB).
2025-01-30 13:38:31 +01:00
Zdenek Kabelac
5f71cebcbe dev-types: ignore non-4K divisible topology values
When topology value is bigger then 1 sector (512b)
we require 4K divisibility for them.
2025-01-30 13:38:03 +01:00
Zdenek Kabelac
e907c3cf9a config: check for 0 from read
When the read returns 0, it could mean the file
was trimmed or some other type of problem.
In this case abort the potentially endless loop.
2025-01-30 13:38:03 +01:00
Zdenek Kabelac
b32c0bb9c5 vg_read: matching missed empty cache
lvm2 is caching DM nodes with the use of DM_LIST_DEVICES ioctl().
And tried to preserve the cached structure for the same list,
however there was 1 case where cache was empty, and new LIST ioctl
returned some elements - if this DM table change has happened
in the moment of 'scanning' and locking -  lvm2 has then continued
to use 'invalid' empty cache.

Fix by capturing this missed case and update cache properly.

TODO: we could possibly use plain memcmp() with previous ioctl result.
2025-01-30 13:37:19 +01:00
Zdenek Kabelac
dd09127608 vg_read: rescanning DM cache after taking lock
Since we started to use DM cache now also for basic checks
whether the DM devices is present in DM table, this cache
now needs to be actually refreshed when the LOCK is taken.
This hiddenly happend if there was enabled 'scan_lvs' however
still not at the right place.

Move this explicit cache update call right after the moment
vg_read grabs the lock.

TODO: in the optimal case, we should mark the 'cache invalid'
and later refresh this cache, when the first reader appears,
but since this would be large patch, do this little fix step patch
first and improve performance later.
2025-01-30 13:33:37 +01:00
David Teigland
76b1776367 lvmlockd: fix thin locking case for cow snapshot
The case of lvcreate creating a cow snapshot of a thin volume was
caught by the sanity check for any missed instances of thin locking.
2025-01-29 18:10:00 -06:00
David Teigland
ebb90fd2c6 lvmlockd: free resource structs for LVs
Once created, resource structs for LVs were never being freed.
If LVs are activated, then later removed or never used again,
the unused structs waste memory and cause the resource list
to grow.
2025-01-23 15:57:46 -06:00
David Teigland
7d7b5db230 lvmlockd: thin locking improvements
There was a lot of messy and inefficient locking calls sent from
a command to lvmlockd when working with thin volumes, e.g.
- requesting a lock numerous times that was already held
- releasing a lock numerous times that was already unlocked
- repeating lock/unlock/lock/unlock rather than holding the
  lock until it was no longer needed

Mistakes in the locking could easily hide among all the noise.

The mess was largely because thin-related commands involve a
lot of internal LV manipulations, and lvmlockd calls were done
at the lower level of LV activation/deactivation.  This change
adds locking code that is more specific to the thin command
being run, so it can be more intelligent in acquiring and
releasing locks where needed.
2025-01-17 14:06:21 -06:00
David Teigland
c2cf9a4cae lvmlockd: debug log message improvements 2025-01-17 14:01:17 -06:00
David Teigland
84aa248f07 lvmlockd: reject bogus lease offset values 2025-01-17 14:00:34 -06:00
Marian Csontos
6c2debf917 doc: Release Notes for 2.03.30 2025-01-14 20:57:47 +01:00
Marian Csontos
6de7c51dce post-release 2025-01-14 20:55:33 +01:00
Marian Csontos
9f81fccd65 pre-release 2.03.30 2025-01-14 20:55:33 +01:00
Marian Csontos
ffbf3a8ca2 WHATS_NEW: update 2025-01-10 17:19:16 +01:00
Marian Csontos
8247752ce1 doc: Try to test limit of release notes
This works with newer ikiwiki when building locally, but not on the
gitlab.
2025-01-10 17:06:03 +01:00
Zdenek Kabelac
8cbd417e7a memlock: skip locking unused libs
Skip memlocking libraries unused in critical section.
2025-01-09 14:16:32 +01:00
Zdenek Kabelac
a4bf6667f8 WHATS_NEW: update 2025-01-09 00:20:19 +01:00
Zdenek Kabelac
b47612cd8b configure: autoreconf 2025-01-09 00:20:19 +01:00
Zdenek Kabelac
9ad2980996 configure.ac: notify_dbus works fine with older version
Picking version 218 for notify_dbus support - maybe older works too,
but not being tested...
2025-01-09 00:20:19 +01:00
Zdenek Kabelac
ecf2cbec7f configure.ac: report 'none' when nvme_wwid is missing 2025-01-09 00:20:19 +01:00
Zdenek Kabelac
e95bc8f8c9 cov: check syscall 2025-01-09 00:20:19 +01:00
Zdenek Kabelac
970463fc46 cov: just be sure nsid is defined 2025-01-09 00:20:19 +01:00
Zdenek Kabelac
d582ee591e cov: remove unused header 2025-01-09 00:20:19 +01:00
Zdenek Kabelac
14673b2746 cov: some error path updates 2025-01-09 00:20:19 +01:00
Zdenek Kabelac
8fb58826c0 tests: cleanup typo 2025-01-09 00:20:19 +01:00
Masanari Iida
d7ffd98257 man: fix double words
This patch fixes double words found in man.

Signed-off-by: Masanari Iida <standby24x7@gmail.com>
2025-01-09 00:20:19 +01:00
Zdenek Kabelac
86574ce07a tests: test unsupported lvresize of origin vdo lv 2025-01-09 00:20:19 +01:00
Zdenek Kabelac
f392dab286 tests: check memory locking
Check reserved memory and stack is able to disable mlocking.
2025-01-09 00:20:19 +01:00
Zdenek Kabelac
9414dcae3a lvresize: vdo origin resize is unsupported
Add explicit error message for not (yet) supported resize
of origin VDO volume.
2025-01-08 23:08:30 +01:00
Zdenek Kabelac
0d3b87d19f lvmcmdline: memlock init after config parsing
Since we now support disabling memory locking by setting
reserved memory or stack to 0 - it would be useful if this would
work also with cmdline --config option.

TODO: rework creation and usage of cmdtool context so we avoid
several places in the code which do try to initialized something...
2025-01-08 23:07:26 +01:00
Zdenek Kabelac
4ef211a187 memlock: check for proper reserved size
Fix regression introduced with commit:
964012fdb9
that effectively disabled memory locking before suspending volumes.
From merging/testing there remained wrong condition
as we really want to check for 0 memory reservation value
for both checked settings.
2025-01-08 23:06:47 +01:00
Peter Rajnoha
1576273273 WHATS_NEW: update 2025-01-06 15:35:44 +01:00
Peter Rajnoha
e86a75b4fe tests: adjust lvresize-xfs tests for recent lvextend changes
Because now, we are doing the fsinfo check before extending an LV and if
that check fails, we do not proceed to the LV extension itself and the
lvextend command bails out immediatelly.
2025-01-06 15:31:17 +01:00
Peter Rajnoha
036e88eb85 filesystem: add new_size_bytes to struct fs_info
It seems we need new_size_bytes in places where struct fs_info is also
passed. Store the new_size_bytes inside the struct fs_info so we
can just pass that one to all the functions we call and hence make
the code a bit cleaner and easier to follow.
2025-01-06 15:31:13 +01:00
Peter Rajnoha
5f53ecda36 lv_manip: check fs resize is supported before LV extension
This avoids a situation where we would extend an LV and then we would
not do anything to the FS on it because the FS info check failed for some
reason, like the type was not supported (e.g. swap) or we could not resize
the FS unless being in some supported state (e.g. XFS to be mounted for
the xfs_growfs to work).

Before this patch (LV resized, FS not resized):

❯  lvextend --fs resize -L+4M vg/swap
  Size of logical volume vg/swap changed from 32.00 MiB (8 extents) to 36.00 MiB (9 extents).
  File system extend is not supported (swap).
  File system extend error.
  Logical volume vg/swap successfully resized.

With this patch (LV not resized, FS not resized):

❯  lvextend --fs resize -L+4M vg/swap
  File system extend is not supported (swap).
2025-01-06 15:29:43 +01:00
Zdenek Kabelac
5ef958704c WHATS_NEW: update 2024-12-19 14:57:43 +01:00
Zdenek Kabelac
e1117164a4 make: generate 2024-12-19 14:55:56 +01:00
Zdenek Kabelac
8a9bc6eed8 args: missed option all for vgdisplay 2024-12-19 14:55:25 +01:00
Zdenek Kabelac
3e641578d8 tests: check conversion of in-use volume
Thin-pool conversion fails early when trying to convert
volume which is in use  (simulated by sleep <)
2024-12-19 14:50:32 +01:00
Zdenek Kabelac
6326d00937 thin: deactivate converted volume early
Deactivate converted volume to pool early, so the conversion
exits early and does not leave some already created metadata
volumes that needed manual cleanup by user after command
aborted its conversion operation when the converted volume
was actually in-use  (i.e. when user tried to convert
a mounted LV into a thin-pool, 2 extra volumes needed removal).
2024-12-19 14:47:16 +01:00
Zdenek Kabelac
928b8e9c6e configure: autoreconf 2024-12-09 16:04:53 -06:00
Zdenek Kabelac
cb87e184bc configure.ac: add support for libnvme
Add 2 new options for linking  libnvme with lvm2.
Option  --without-libnvme, --disable-nvme-wwid
2024-12-09 16:04:53 -06:00
David Teigland
d952358636 device_id: nvme devices may use alternate wwids
Device quirks may cause sysfs wwid file to change what it
displays, from a bogus eui... string to an nvme... string.

The old wwid may be saved in system.devices, so recognizing
the device requires finding the old value from libnvme.

After matching the old bogus value using libnvme, system.devices
is updated with the current sysfs wwid value.
2024-12-09 16:03:43 -06:00
Marian Csontos
736d23ad26 doc: Fix limit for inlined release notes 2024-12-09 17:40:14 +01:00
Peter Rajnoha
32ab91e528 udev: create /dev/disk/by-diskseq/<DISKSEQ> symlink for public DM devices
All block devices have a disk sequence number assigned (an ever-increasing 64 bit
sequence number) since kernel v5.15 (February 2021). The number is exported through
/sys/block/<disk>/diskseq property and also as DISKSEQ udev event variable.
The diskseq helps with referencing a device throughout its existence in
race-free way.

By default, the /usr/lib/udev/rules.d/60-persistent-storage.rules set
/dev/disk/by-diskseq/<diskseq> symlink for each block device. However,
these rules do not apply for DM devices because we manage the symlinks
ourselves in 13-dm-disk.rules where it properly follows the
DM_UDEV_DISABLE_DISK_RULES flag, among other things.

Add a rule to 13-dm-disk.rules to create the /dev/disk/by-diskseq/<diskseq>.
2024-12-09 13:17:46 +01:00
Marian Csontos
85014fcd6d post-release 2024-12-09 12:57:57 +01:00
Marian Csontos
32cfcfd151 pre-release 2.03.29 2024-12-09 12:57:57 +01:00
Zdenek Kabelac
3c365e6c5c WHATS_NEW: update 2024-12-06 17:23:01 +01:00
Zdenek Kabelac
4a18f89736 make: generate 2024-12-06 17:23:01 +01:00
Zdenek Kabelac
2b82e882ed configure: autoreconf 2024-12-06 17:22:57 +01:00
Zdenek Kabelac
d8726b07c3 lvmlockd: utilize SD_NOTIFY_SUPPORT
Update makefile and code to better utilize SD_NOTIFY_SUPPORT var.
2024-12-06 17:16:55 +01:00
Su Yue
ee97c5c633 configure.ac: add option disable/enable-sd-notify
Since commit d106ac04ab ("configure.ac: use LIBSYSTEMD"),
lvmlockd is not built with SD_NOTIFY by default but depending
on LIBSYSTEMD_LIBS. There are three prerequisites of
nonempty LIBSYSTEMD_LIBS:
NOTIFYDBUS_SUPPORT, SYSTEMD_JOURNAL_SUPPORT and SYSTEMD_JOURNAL_SUPPORT.

If ./configure is called with options ' --disable-systemd-journal
--disable-app-machineid --enable-lvmlockd-sanlock
--disable-notify-dbus', the lvmlockd built is without sd_notify
support which causes hang of start lvmlockd service in notify type.

This commit adds options disable-sd-notify and enable-sd-notify.
The default value is autodetected and when the lvm2 is build with
systemd then sd-notify is enabled.
If systemd/sd-daemon.h is existed, call PKG_CHECK_MODULES libsystemd.

Signed-off-by: Su Yue <glass.su@suse.com>
Modified-by: Zdenek Kabelac <zkabelac@redhat.com>
2024-12-06 17:14:58 +01:00
David Teigland
f08d1caf47 vgdisplay: remove command def for activevolumegroups
too minor to care about separating
2024-12-06 09:18:23 -06:00
David Teigland
acd7cfbc08 pvdisplay, vgdisplay, lvdisplay: changed listed order
List the common form first, followed by the others.
2024-12-05 16:09:19 -06:00
David Teigland
6c5e8ee18b vgdisplay: add command def for activevolumegroups
This variant does not accecpt positional args like
the others.
2024-12-05 16:03:24 -06:00
David Teigland
017c668fd0 vgdisplay: split code for variants using command defs 2024-12-05 15:31:55 -06:00
David Teigland
ccde015712 pvdisplay: split code for variants using command defs
Also fix the use of --all that was mistakenly included
as an accepted option for vgdisplay and two cases of pvdisplay
in commit "tools: enhance lvdisplay vgdisplay pvdisplay"
2024-12-05 15:31:55 -06:00
David Teigland
9beea2db69 lvdisplay: split code for variants using command defs 2024-12-05 15:31:55 -06:00
Marian Csontos
275c9666b6 doc: Amend 2.03.27 and 28 release notes' date 2024-12-05 14:40:42 +01:00
Zdenek Kabelac
d791f160a8 tests: make reshape bug more easier to hit
Seems this delay_dev usage exposing some reshape window creation bug.
So make delay bigger to hit the error easier.
2024-12-04 16:14:22 +01:00
Zdenek Kabelac
75907f0e80 tests: do not use noudevsync with udev system
Remove --noudevsync option - as this breaks synchronization with
udev which is necessary when trying to i.e. create  _rmeta_3
and wipe it - as the symlinks must be present for wiping.

So if there was some other issue  (behind the comment) - we need to
check for the problem elsewhere instead of disabling udev sync.
2024-12-04 16:14:22 +01:00
Zdenek Kabelac
45344262cc debug: missing stack 2024-12-04 16:14:22 +01:00
Marian Csontos
c695c7a252 doc: Update WHATS_NEW and Release notes 2024-12-03 13:07:03 +01:00
Zdenek Kabelac
94da2c9792 configure: autoreconf 2024-11-26 14:39:09 +01:00
Zdenek Kabelac
ce8e6c8c63 configure.ac: build lvmlockd with notify
Automatically use --enable-notify-dbus when building lvmlockd
if not configured otherwise by a configure user -
as the lvmlockd.service is notify based.
2024-11-26 14:38:23 +01:00
Marian Csontos
60cd279f96 test: Prevent incorrect value propagating into test
In case dbus-send is not present previous random value of i was tested.
2024-11-26 13:25:49 +01:00
Marian Csontos
25638f6a87 spec: Remove [Build]Requires for cluster 2024-11-26 10:59:05 +01:00
David Teigland
47c4f737c9 lvmlockd: allow test mode when dlm is not built 2024-11-25 12:08:43 -06:00
David Teigland
a6e918cd48 man: lvmraid integrity updates 2024-11-25 10:22:43 -06:00
Vojtech Trefny
c77f2697ee dbus: Add function for running lconvert --repair on RAID LVs 2024-11-25 14:22:29 +00:00
Zdenek Kabelac
9259892627 tests: increase mirror size
On fast machines mirror throttling starts to react much later
so try bigger mirror size to fight with race in test.
2024-11-25 14:16:55 +01:00
Zdenek Kabelac
2c06950888 man: update display fields
The --sort option belongs to  '-C' columned output only.
Also add short commmand description for specialized
vg/pv/lvdisplay command.
2024-11-25 14:03:51 +01:00
Zdenek Kabelac
5893ca17da make: generate 2024-11-22 14:25:54 +01:00
Zdenek Kabelac
e8e4324d68 tools: enhance lvdisplay vgdisplay pvdisplay
Split description for display commands so we can better describe
it's usage and combination of individual options in man page.

Now we can separately describe:

lvdisplay, lvdisplay -c, lvdisplay -C
vgdisplay, vgdisplay -c, vgdisplay -C
pvdisplay, pvdisplay -c, pvdisplay -C

TODO: Drop validation from command code itself.
2024-11-22 14:25:54 +01:00
Zdenek Kabelac
502543ffed args: add colon and column for pv/vg/lvdisplay
Better description for --colon and --column option for
pvdisplay, vgdisplay, lvdisplay.
2024-11-22 14:25:54 +01:00
Zdenek Kabelac
03a3863804 man: clean
Both branches printed new line.
2024-11-22 14:25:54 +01:00
Zdenek Kabelac
ebadd3ccc6 man: refactor check for variant
Remove unnecessary checks and move the comment to the 1st. check.
2024-11-22 14:25:54 +01:00
Zdenek Kabelac
c4d4bddfce man: refactor printing option
When generating man pages, use a single function to print
option with its short & long name.
2024-11-22 14:25:54 +01:00
Zdenek Kabelac
efe5af819a man: enhance handling of option description
Update the _print_man_option_desc() to also handle common parts
as the initial text without any specified section and also
add support for '#\n' to be able to revert to common part.
2024-11-22 14:25:54 +01:00
Zdenek Kabelac
ca5d258376 test: shellcheck: use quotation marks 2024-11-15 14:11:30 +01:00
Zdenek Kabelac
4c31e6d56a test: shellcheck: add shell directive
Also add forgotten standard copyright message with shell reference.
2024-11-15 14:10:49 +01:00
Zdenek Kabelac
51a684ef0f shellcheck: separate declaration and assign
So the error exit code can be processed if needed...
2024-11-15 14:10:39 +01:00
Zdenek Kabelac
dfc132a514 shellcheck: validate cd success 2024-11-15 14:10:31 +01:00
Zdenek Kabelac
473e93fbff WHATS_NEW: update 2024-11-13 13:06:15 +01:00
Zdenek Kabelac
270f9306bc tests: improve tracing messages
Avoid printing lvm2 command trace, if the test finds the 'dmeventd'
was started unxpectedly during testing as the last command is hardly
ever responsible for this

Also reorder some messages when doing teardown of devices.

Do not print 'help' message from hostname command, when it does
not support option '-I'.
2024-11-13 13:00:42 +01:00
Zdenek Kabelac
7b9bdcb4d4 tests: check _tdata conversion to raid1 2024-11-13 13:00:42 +01:00
Zdenek Kabelac
c2f41c1a59 raid: fix name rotation
Since we now keep lv names valid all the time (as they are part
of radix_tree) - there is a problem with this renaming code, that
for a moment used duplicated name in vg struct.

Fix it by interating LVs backwared - which avoids breaking consitency
and also actually makes code more simple.
2024-11-13 13:00:42 +01:00
Zdenek Kabelac
cbfc31ee2b tests: aux check for leaked symlinks
Add check for 'leaked' symlinks after test and trap
the case when some 'danglink' links are present.
This might be some problem with udev synchronization
or some other strange race.

All such symlinks will be also removed so they will not
influence following tests.
2024-11-08 19:41:50 +01:00
Zdenek Kabelac
dcac774f09 tests: check vdo minimum_io_size 2024-11-08 19:41:50 +01:00
Zdenek Kabelac
e4b5f8a485 debug: remove unused define 2024-11-08 19:41:50 +01:00
Zdenek Kabelac
c3ed3f28a2 device_mapper: suppress warns about inactive query
When command prints warning about suppressing query
for inactive table, because this is not supported
by kernel - 1 printed message is just enough, no
reason to 'spam' command output all the time, message
will remain only in debug log.

Also drop 'WARNING:' from real 'error' message.
WARNIGS are supposed to be just warning and command
then exists with 'success'.
2024-11-08 19:41:50 +01:00
Zdenek Kabelac
158d3243b6 vdo: fix input units for minimim_io_size
When specifying minimum_io_size with --vdosettings,
command assumed wrong unit (sectors).

So '--vdosettings minimum_io_size=512|4096' resulted into
an error that only 512 or 4096 values are allowed, but
at the same time values  1 or 8 were accepted.

So fix by converting any number >= 512 to 'sectors' and
keep input of 1 or 8 still valid if anyone has been using
this before.

So now we take  512 or 4096  and still also  1 or 8 with the
same effect.

Also correct the 'error' message when invalid minimum_io_size
is specified.
2024-11-08 19:41:18 +01:00
Peter Rajnoha
44a04b71f8 WHATS_NEW: update 2024-11-07 07:57:34 +01:00
Peter Rajnoha
a2ca20dad9 tests: remove superfluous -a option for df used in lvresize-xfs.sh
The df -a looks at whole system and it returns an error code in case
there's an inaccessible fs which is not even part of the testing environment.
The -a for df is not actually needed here in the lvresize-xfs test, so remove it.
2024-11-07 07:57:34 +01:00
Peter Rajnoha
1d8a4c4817 lv_manip: use the same param validation for RAID 0 as for RAID 1/4/5/6
This actually reverts commit 83ae675f8d.
2024-11-07 07:57:34 +01:00
Peter Rajnoha
b5249fa3c2 lv_manip: fix stripe count and size validation for RAID LVs
Fix stripe count and size parameter validation for RAID LVs and
include existing automatic setting of these parameters based
on current shape of the RAID LV in case these are not set
on command line fully.

Previously, this was done only to a certain subset given by this
condition (where the 'stripes' is the '-i|--stripes' cmd line arg
and  the 'stripe_size' is actually the '-I|--stripesize' cmd line arg):

  !(stripes == 1 || (stripes > 1 && stripe_size))

This condition is a bit harder to follow at first sight and there
are no comments around with explanation for why this one is used,
so let's analyze it a bit more.

First, let's convert this to an equivalent condition (De Morgan law)
so it's easier to read for humans:

  stripes != 1 && !(stripes > 1 && stripe_size)

Note: Both stripe and stripesize are unsigned integers, so they can't be negative.

Now, based on that condition, we were running the code to deduce the
stripe/stripesize and do the checks ("the code") only if both of these
are true:

  - stripes is different from 1

  - we don't have stripes > 1 and stripe_size defined at the same time

But this is not correct in all cases, because:

  A) if someone uses stripes = 0, then "the code" is executed
    (correct)

  B) if someone uses stripes = 1, then "the code" is not executed
    (wrong: we still need to be able to check the args against
            existing RAID LV stripes whether it matches)

  - if someone uses stripes > 1, then "the code" is:

     C) if stripe_size = 0, executed
       (correct)

     D) if stripe_size > 0, not executed
       (wrong: we still want to check against existing RAID LV stripes)

Current issues with this condition:
  The B) ends up with segfault.

    ❯ lvextend -i 1 -l+1 vg/lvol0
      Rounding size 4.00 MiB (1 extents) up to stripe boundary size 8.00 MiB (2 extents).
    Segmentation fault (core dumped)

  The D) ends up with errors like:

    ❯ lvextend -i 3 -l+1 -I128k vg/lvol0
      Rounding size 4.00 MiB (1 extents) up to stripe boundary size 8.00 MiB (2 extents).
      Rounding size (4 extents) up to stripe boundary size for segment (5 extents).
      Size of logical volume vg/lvol0 changed from 8.00 MiB (2 extents) to 20.00 MiB (5 extents).
      LV lvol0: segment 1 with len=5  has inconsistent area_len 3
      Couldn't read all logical volumes for volume group vg.
      Failed to write VG vg.

Conclusion:
  The condition needs to be removed so we always run "the code" to check
  given striping args given on command line against existing RAID LV
  striping. The reason is that we don't want to allow changing stripe
  count for RAID LVs through lvextend and we need to end up with the
  error:
    "Unable to extend <RAID segment type> segment type with different number of stripes"

  (We do support changing the striping by lvconvert's reshaping functionality only).
2024-11-07 07:57:23 +01:00
Zdenek Kabelac
a210e9d768 makefiles: flip condition
With previous commit, in this case we need to flip condition,
to make it working here as expected.
2024-11-06 12:33:24 +01:00
Zdenek Kabelac
0fc7266353 gcc: do not mix signess compare 2024-11-06 00:04:54 +01:00
Zdenek Kabelac
2a1a7a863d gcc: make older compilers happier
Use {{}} for array initializer to quite warning for older gcc.
2024-11-06 00:04:54 +01:00
Zdenek Kabelac
f7df63748a makefiles: eliminate error output
Hide error message from 'find', if the 'lib' dir has
not been create yet (in case of non-srcdir build).
2024-11-06 00:04:54 +01:00
Zdenek Kabelac
987256aaa8 makefiles: use filter 2024-11-06 00:04:54 +01:00
Zdenek Kabelac
d53c71a4f2 makefiles: fix clean rule for non srcdir builds
With commit acbeaa7a8d we started
to use symlinks to link test suite shell scripts, however
they remained within CLEAN_TARGETS.
So when running 'make clean' within non-srcdir build dir, we
were cleaning actuall shell script in this dir.
So remove list of this script from CLEAN_TARGETS in this case.
2024-11-06 00:04:54 +01:00
Zdenek Kabelac
dfa74465e9 tests: runner better handle help messages
Postpone check for root uuid so we can print help message.
2024-11-06 00:04:54 +01:00
Zdenek Kabelac
cf6cbfb7f7 tests: check strftime result 2024-11-06 00:04:54 +01:00
Zdenek Kabelac
352b1b1817 cov: check result of sync_local_dev_names
Although ATM this function always returns 1.
(maybe should be void)
2024-11-05 14:18:50 +01:00
Zdenek Kabelac
03782806eb lvmdiskscan: use while loop
Use more readable while() loop like in other similar instancies.
2024-11-05 14:18:50 +01:00
Marian Csontos
e42ceccc6d post-release 2024-11-04 16:42:12 +01:00
Marian Csontos
f87a6ad6d6 pre-release 2.03.28 2024-11-04 16:42:12 +01:00
Zdenek Kabelac
8ada61dbed gcc: fix warning about uninitialized use
get_sizes_lockspace() may not always initilize all passed values
in case the bitfield would not trigger if() path.
So just in case keep the path initilized.

TODO: maybe add INTERNAL_ERROR to get_sizes_lockspace().
2024-11-01 17:48:28 +01:00
David Teigland
0aa585a29f lvmlockd: remove unused vg_sysid
from structs and info dump.
2024-11-01 10:48:12 -05:00
Zdenek Kabelac
fc2e4a7b70 tests: skip test on older version
Prevent crashing kernel on older systems.
2024-11-01 13:27:20 +01:00
Zdenek Kabelac
057314ff8d lvmlockd: update prototype for non-lvmlockd build
Match prototype to last updates of lockd_init_lv_args().
2024-11-01 11:27:02 +01:00
David Teigland
88a085c485 lvmlockd: optimize new lv lease search
When converting a VG to locktype sanlock, a new
lease is allocated for each existing lv.  Finding
a new lease location involved searching the lvmlock
LV from the start for an unused location, which
would be very slow with many LVs.  Improve this by
starting each search from the last used location.
2024-10-31 20:29:00 -05:00
David Teigland
4eb66fd20c lvmlockd: fix vgchange --locktype sanlock
Fix regression from commit 7f29afdb06
"lvmlockd: configurable sanlock lease sizes on 4K disks"

That change failed to recognize that a running lockspace will not
exist in lvmlockd when converting a local VG to a sanlock VG, i.e.
vgchange --locktype sanlock vgname.  When the vgchange attempted
to initialize new lv leases for existing LVs, lvmlockd would
return an error when it found no lockspace.
2024-10-31 16:31:35 -05:00
Zdenek Kabelac
354ca52e8c WHATS_NEW: update 2024-10-31 17:56:59 +01:00
Zdenek Kabelac
c2afa7a116 vg: add radix_tree for lv uuids
When searching for committed LV by uuid, this search can
be expensive for commands like 'vgremove' - so for
this part introduce  'lv_uuids' radix_tree that is
build with first access to lv_committed().
2024-10-31 17:55:31 +01:00
Zdenek Kabelac
db0f1b799f metadata: use radix_tree for find_lv_in_vg
Since there is a group of commands that need to access 'lv_list'
while still need to search for LV by its name, make the whole
struct lv_list a member of logical_volume structure.
This makes it easy to return also 'lv_list' this list this LV
within VG.
Also the patch should not use more memory, since we were allocating
lv_list for each LV anyway when linkin LV to VG.

Since find_lv_by_name() is now using radix_tree(),
use the same 'search for /' in LV in name for both
find_lv() & find_lv_in_vg().

TODO: Possibly refactor code and use only dm_list
instead of lv_list and dereference LV with container_of()
(thus saving pointer within struct logical_volume) - but
we use 'lv_list' currently in many places...
2024-10-31 17:55:31 +01:00
Zdenek Kabelac
0e5beb92c5 config: introduce validate_metadata
Add lvm.conf  config/validate_metadata  configurable setting.
Allows to disable validation of volume_group structure before
writing to disk.
Call of vg_validate() is supposed to catch any inconsistency
of in-memory volume group structure and possibly early aborting
commnand before making any more 'damage' in case the VG struct
is found insistent after some metadata manipulation.

This is almost always useful for devel - and also for normal user
as for small metadata size this doesn't add too much overhead.

However if the volume_group size is large and operations are just
adding removing simple LVs - this validation time may add noticable
to final command running time.

So if the user seeks the highest perfomance of command and does
not do any 'complex' metadata manipulation - it's reasonably safe
to disable validation (with the use of setting "none") here.
2024-10-31 17:55:31 +01:00
Zdenek Kabelac
7bf404db3b validate_lvname: early exit
If the LV name does not any have '_' chr,
there is no point trying to call 'strstr()' to look for "_suffix".
Also we can search from _.
2024-10-31 17:55:31 +01:00
Zdenek Kabelac
ae8ba49142 cov: validate string with lock mode
Check the dev_mode string is not NULL before use.
2024-10-30 13:09:31 +01:00
Zdenek Kabelac
6ebcb0015e cov: add stacktraces
Add stacktraces for unexpected paths.
2024-10-30 13:08:56 +01:00
Zdenek Kabelac
699696b0a6 vdo: reader checks there is enough data
Validate enough of data was read from disk to parse vdo header.
TODO: there should be a loop for buffer reading.
2024-10-30 12:59:08 +01:00
Zdenek Kabelac
8095a6c14c metadata: pahole logical_volume
Shuffle some variables to remove 'extra' alignment holes
within the structure thus making it smaller.
2024-10-30 12:59:08 +01:00
Zdenek Kabelac
9e8bd57e15 metadata: lv_set_name use uniq_insert
With presence of uniq_insert, use this function also
here for extra protection and check for duplicate lv_name
when inserting a new name into radix_tree.
2024-10-30 12:59:08 +01:00
Zdenek Kabelac
b66b72b115 get_alloc_string: compare only enum
Instead of possibly checking for cling_by_tags string twice,
just compare resulting alloc number from search loop.
2024-10-30 12:57:34 +01:00
Zdenek Kabelac
30adf7e91c toolcontext: use the striped string first 2024-10-30 12:57:34 +01:00
Zdenek Kabelac
e2a5715a60 cache_manip: reset sigint handler
After processing interrupt, reset the interrupt counter,
so further code is not mislead and continues processing
in 'locked' section as expected.
2024-10-30 12:57:34 +01:00
Zdenek Kabelac
0e64d49642 tests: use longer tag
Avoid config 'grep' with actual 'randomly' generated path name
which may eventually contain 'cc' as part the path and
causing a mismatch of the grep test.
2024-10-30 12:57:34 +01:00
Zdenek Kabelac
608418e4f2 debug: missing stacktrace 2024-10-28 20:07:37 +01:00
Zdenek Kabelac
16241b2dc7 lv_manip: init major minor in alloc_lv
Move initialization of major and minor to alloc_lv().
2024-10-28 20:07:37 +01:00
Zdenek Kabelac
e2b00dd162 device_mapper: use static array for dm_size_to_string
Avoid copying this structure on stack with every call.
2024-10-28 20:07:37 +01:00
Zdenek Kabelac
b05e0df4e1 tests: add reproducer for failing raid5 activation
For now use 'should' to mark this 'known' failure.
This case needs solution.
2024-10-28 20:07:37 +01:00
Zdenek Kabelac
86dc72c28c tests: flip to use FSLASTBLOCK
It seems FSSIZE is newer then FSLASTBLOCK so use this one instead.
2024-10-28 20:07:37 +01:00
Zdenek Kabelac
a934231623 tests: correcting expected return code
Expecting success when using with '-r'.
2024-10-28 20:07:37 +01:00
Heinz Mauelshagen
708435d187 man: lvchange update about --syncaction being transient 2024-10-25 22:03:18 +02:00
Zdenek Kabelac
034b6a262c WHATS_NEW: update 2024-10-25 15:08:03 +02:00
Zdenek Kabelac
143545a08c lvmlockd: fix incorrect function definition
In commit 7f29afdb06 this function
was added with misplaced ';'.
2024-10-25 15:08:03 +02:00
Zdenek Kabelac
c8a8c7286f tests: add test to resize to same size
Check that 'lvresize/extend -r' resizing to the same size is
doing the fs resize.
2024-10-25 15:08:03 +02:00
Zdenek Kabelac
5a293968ec lvresize: fix regression when resizing with fs
When 'lvresize -r' is used to resize the volume, it's valid to
resize even to the same size of an LV, as the command then runs
fs-resize utility to eventually upsize the fs to the current
volume size.

Return code of such command then reflects the return value
of this fs-resize tool.

This fixes the regression introduced when the support
for option --fs was added (2.03.17).
2024-10-25 15:06:39 +02:00
Peter Rajnoha
43ce78e5c6 tests: lvresize-fs: check blkid version for lvresize with swap test 2024-10-25 13:21:57 +02:00
Peter Rajnoha
aa0200c3ff dev-type: update comment about swap info from blkid 2024-10-25 12:53:07 +02:00
Zdenek Kabelac
40010e3eb8 clang: close file on memory alloc error path 2024-10-25 01:26:40 +02:00
Zdenek Kabelac
ebc5c0cb1d clang: check for dirfd result 2024-10-25 01:26:40 +02:00
Zdenek Kabelac
0fbcb3b308 clang: check segment lv is defined 2024-10-25 01:26:40 +02:00
Zdenek Kabelac
5ec8f744d0 clang: ensure pointer is defined
Check for new_segtype and lv is defined
before dereferencing.
2024-10-25 01:26:40 +02:00
Zdenek Kabelac
ea4daeb28e cov: use 64bit arithmentic 2024-10-25 01:26:40 +02:00
Zdenek Kabelac
1363a5ffb2 cov: ensure detached_log_lv exists before use 2024-10-25 01:26:40 +02:00
Zdenek Kabelac
5a3375f958 debug: use major:minor
Print major:minor as in other places.
2024-10-25 01:26:40 +02:00
Zdenek Kabelac
edfa4955d8 device_id: close only opened dir
After more of opendir, make sure 'dir' is closed
only when it's been opened.
2024-10-25 01:26:40 +02:00
Zdenek Kabelac
a5e3f0e6dd metadata: check for mda_device existance 2024-10-25 01:26:39 +02:00
Zdenek Kabelac
f61572eef2 dev-cache: ensure list has elements
When updating DM cache, check whether the list even has entries
before comparing it with old cached instance.
2024-10-25 01:26:39 +02:00
Zdenek Kabelac
87f68f443c metadata: fallback search without radix_tree
If we use some dummy vg struct, allow fallback
plain dm_list search.
2024-10-25 01:26:39 +02:00
Zdenek Kabelac
7d48c1f6e3 device_mapper: add omitted error message 2024-10-25 01:26:39 +02:00
Zdenek Kabelac
188dd3c357 device_mapper: check for pv before use in error msg 2024-10-25 01:26:39 +02:00
David Teigland
875012fb5d lvmlockd: enable lockopt nodelay for lockstart
Avoid the sanlock add_lockspace delay in vgchange --lockstart
by adding --lockopt nodelay.  This is for testing, and is not
safe to use in general.
2024-10-24 17:15:16 -05:00
Zdenek Kabelac
77332669d0 WHATS_NEW: update 2024-10-24 21:38:35 +02:00
long.yunjian@zte.com.cn
639fb633d3 cleanup: correct invalid function
Use proper function names in annotation

There are no fuction named print_common_options_cmd()
and print_common_options_lvm(). So, rename them to the
real function named print_usage_common_cmd() and
print_usage_common_lvm().

Signed-off-by: YunJian Long
2024-10-24 21:38:06 +02:00
Zdenek Kabelac
9295de7cea tests: do not use shell pipe for reshape_len
Tricky one - as the pipe exit codes may result into whole
test failure depending on how quick/slow command exits
are within pipeline.

So get the len without piping.
2024-10-24 21:24:26 +02:00
Zdenek Kabelac
2c5bf25187 devicesfile: move opendir after fclose
Call opendir() after new file is stored within dir,
otherwise this new file would not accounted.
2024-10-24 21:24:26 +02:00
Zdenek Kabelac
b88cbc7f17 metadata: missed lv_set_name users
Missed when introduced lv_set_name().
2024-10-24 21:24:26 +02:00
Zdenek Kabelac
c27d6695c1 lv: add lv_set_vg
To keep vg->lv_names up-to-date also for merge & split,
add function lv_set_vg() the will update also radix tree
reference for a VG.
2024-10-24 21:23:49 +02:00
Zdenek Kabelac
73c7dac1a8 WHATS_NEW: update 2024-10-24 17:38:09 +02:00
Zdenek Kabelac
21517c2bd5 metadata: use radix tree to find lv_names
Replace usage of dm_hash with radix_tree to quickly find LV name
with a vg and also index PV names with set of available PVs.
This PV index is only needed during the import, but instead
of passing 'radix_tree *' everywhere, just keep this within
a VG struct as well and once the parsing is finished, release
this PV index radix_tree.

This also makes it easier to replace this structure
in the future if needed.

lv_set_name now uses  radix_tree remove+insert to keep lv_names
tree in-sync and usable for  find_lv queries.
2024-10-24 17:38:09 +02:00
Zdenek Kabelac
1825e782cc revert "metadata: use lv_hash in segment-specific metadata parsing"
This reverts commit f42aef4706.

Going to replace dm_hash with radix_tree and use 'find_lv()'
to abstract lookup for LV with VG.
2024-10-24 17:38:09 +02:00
Zdenek Kabelac
956b2c568f metadata: use lv_set_name for raid and mirror
Use lv_set_name API also for raid and mirror LV manipulation.
2024-10-24 17:38:09 +02:00
Zdenek Kabelac
c681d4e61a metadata: add lv_set_name
Add function to set lv->name.
Also when creating empty LV, first add this LV
to linked list in a VG and just after that allocate lv name.
2024-10-24 17:38:09 +02:00
Zdenek Kabelac
73f24443e5 check_pv_segments: resolve pv name once 2024-10-24 17:38:09 +02:00
Zdenek Kabelac
eb4b307d0c log: postpone some initialization
Clear buffers when really logging.
2024-10-24 17:38:09 +02:00
Zdenek Kabelac
dee8bc9ae4 lv_manip: remove duplicate check for max lv
This check is always performed with call to link_lv_to_vg().
2024-10-24 17:37:30 +02:00
Zdenek Kabelac
d62170d646 flags: drop no longer needed header
After code refactoring, this header is not needed here anymore.
2024-10-24 17:35:33 +02:00
Zdenek Kabelac
668c185949 vg_validate: use uniq_insert
Enhance usage with uniq_insert and also try to better
utilize CPU cache and do a smaller loop for individual
hashing of lvname and separately lvid.

Also correcting usage of 'continue' within validation of
historical names as it should report as much errors
as it can within a loop.
2024-10-24 17:35:33 +02:00
Zdenek Kabelac
0852c3171d tests: unit test for uniq insert into radix_tree 2024-10-24 17:35:33 +02:00
Zdenek Kabelac
5b1ebed3fc radix_tree: add radix_tree_uniq_insert
When using radix_tree to identify duplicate entries we may
avoid to call an extra 'lookup()' prior the insert() operation
add radix_tree_uniq_insert/_ptr() that is able to report -1 if
there was already set a value for the given key.
2024-10-24 17:24:40 +02:00
Zdenek Kabelac
dd856edaab vgcfgrestore: validate complete VG
Avoid finding problems in vg_validate when restoring
invalid VG metadata as that would lead to internal error.
i.e. adding unsupported METADATA_FLAG to zero segtype
can trigger such thing.
2024-10-23 20:16:14 +02:00
Zdenek Kabelac
2916a8a1f3 read_lvflags: keep flag reading focused on flags
Previous update needed to add handling segtype within flag.c
which somewhat breaks API separition and also had bug in hanlding
actual flags.

So instead keep segtype code in _read_segtype_and_lvflags() within
import_vsn1.c and handle purly flags in read_lvflags() from const
string.
2024-10-23 20:16:14 +02:00
Zdenek Kabelac
1f0530919e export: typo with buffer zeroing
Lost '= 0' in cut & paste.
Also get rid of no longer needed 'goto' section.
2024-10-23 20:15:48 +02:00
Zdenek Kabelac
ea39c58127 export: add missed buffer initialization
Since we reduced emitting to single string list,
we need to make sure empty list are not producing
garbage strings.
2024-10-23 14:38:21 +02:00
Zdenek Kabelac
056ad4a8f4 WHATS_NEW: update 2024-10-23 14:10:46 +02:00
Zdenek Kabelac
e0421ee7bf export: change to read_segtype_and_lvflags
Instead of duplicating whole segtype string with flags and
using 2 calls read_segtype_lvflags() + get_segtype_from_string(),
merge the functionality into a single read_segtype_and_lvflags().
This allows to make only a local string copy (no allocs) and eventually
to not copy segtype string at all, when there are no flags.
2024-10-23 14:10:46 +02:00
Zdenek Kabelac
4929c55bc5 export: reduce emit_to_buffer calls
As the 'emit_to_buffer' uses relatively complex
vsnprintf() call inside, try to reduce number
of unnecessary calls and try replace some more
complex string build with a single call instead.
2024-10-23 14:10:46 +02:00
Zdenek Kabelac
7156b4930d dev-cache: enhance usability of dm cache
With existing code, the cache was working only to the 2nd. locking.
So i.e. when 'lvs' scans system with more then one VG, the caching
was effectively not working.

Update the code, so the label invalidate code is able to update DM
cache - so whenever we take a new lock - we will refresh the cache.

TODO: the refresh ATM does a very simple compare of old a new list
of cached DM device, and with the first spotted difference, it just
fallback to the full rebuild of DM cache - with large amount of active
devices this might not the most efficient way....
2024-10-23 14:10:35 +02:00
Zdenek Kabelac
96cea466a5 tests: skip test for too old sfdisk 2024-10-22 22:30:47 +02:00
Zdenek Kabelac
0f793fcbca check_lv_segment: correct last change
Previous commit 7c5cca600c
was not correctly aliging block that was checking mirrors.
2024-10-22 22:25:54 +02:00
Zdenek Kabelac
5666728b27 WHATS_NEW: update 2024-10-22 19:36:00 +02:00
Zdenek Kabelac
d121707ffa debug: drop stack 2024-10-22 19:36:00 +02:00
Zdenek Kabelac
c19dfe11a5 debug: use just LV name for debug message
Since we detect 'debug' level after calling 'log_debug()' - all
the arguments are evaluated, so in this case display_lvname() was
preparing a string that is not used in case debugging is not enabled.

So since these string are on 'hot-path' and it's already known
which VG is being worked on, in these few cases just use lv->name.
2024-10-22 19:36:00 +02:00
Zdenek Kabelac
ccd693d065 reporting: prepare id string only for json output
When processing LVs for a command we stored  '*object_id' & '*group_id'
as printable string that was however only used with json reporting.

Refactor code so we simply store there 'struct id*' that is just
converted into printable string when json reporting is really used.

Also check for 'sigint()' right before loop processing begins which
is primary purpose of this test.
2024-10-22 19:36:00 +02:00
Zdenek Kabelac
34b5d7f8bd vg_validate: use radix_tree
Replace dm_hash with radix_tree which uses less memory
and gives same performance.
2024-10-22 19:36:00 +02:00
Zdenek Kabelac
5827c9e337 config: use dm_config_parse_only_section 2024-10-22 19:36:00 +02:00
Zdenek Kabelac
5d2d3c53a4 device_mapper: add dm_config_parse_only_section
This function call is able to setup config parser so it stops
parsing 'subsection' nodes after parsing named section node.
Only nodes at 'level' 0 will be still processed. And this nodes
are found by searching for last  \n}\n sequence from the end of
buffer   (instead of trying to analyze all the text in buffer).
2024-10-22 19:36:00 +02:00
Zdenek Kabelac
4dc0ee8e56 export: use radix_tree for write formatter
Replace use of dm_hash with radix_tree when making PV index names.

Store just the index number itself and use pv%d for outf() string.

For lookup up a PV - use just the PV pointer itself, it's faster then
converint for it's ID to UUID format.
2024-10-22 19:36:00 +02:00
Zdenek Kabelac
7c5cca600c check_lv_segment: split into incomplete complete
Split single check_lv_segments() into 2 separate
versions so they can be called independently.
This allow to 'skip' already checked segment
check after it's been imported to VG and also
avoid another repeated checking when validating
segment with complete vg.

**
check_lv_segments_incomplete_vg()

this check just basic LV segment properties and does not
validate those requiring full VG.

**
check_lv_segments_complete_vg()

Remaining check that expects complete VG is present.
2024-10-22 19:36:00 +02:00
Zdenek Kabelac
fa11ef6846 metadata: look for LV by name with find_lv
Avoid getting dm_list reference when looking for logical_volume*.
2024-10-22 19:36:00 +02:00
Zdenek Kabelac
1755ceb17c thin: check only for profiled config vars
ATM this rather save a lot of unncessary log entries as it grabs
the global autoextend_threshold (profile == NULL) just once instead
of revealing it every time with NULL profile.
2024-10-22 19:36:00 +02:00
Zdenek Kabelac
8fcfac7c89 lv: set creation uses const string
There is no need to duplicate const string we got and keep
from uname() call.
2024-10-22 19:36:00 +02:00
Zdenek Kabelac
b4156bb4de export: limit generation of comment strings
Generate comment string only for formatter with comments.
2024-10-22 19:36:00 +02:00
Zdenek Kabelac
0179f00e0c import: check fixup mirror only when needed
Track whether import has even seen segment of LV with log_lv,
and call fixup mirror only in this case.

Also avoid repeated lookup of get_segtype_from_string for
SEG_TYPE_NAME_MIRROR.
2024-10-22 19:36:00 +02:00
Zdenek Kabelac
89da9ae251 device_mapper: increase mem pool chunk size
Use bigger memory pool chunk size and reduces amount of
memory pool extensions when handling larger metadata, but do not
make it noticable bigger when handling small ones...

Use same large value also when allocating VG memory pool.
2024-10-22 19:36:00 +02:00
Zdenek Kabelac
9c9953dc3e device_mapper: join flags checks together
Just use a single bitmask flag check and OR fields together.
2024-10-22 19:36:00 +02:00
Zdenek Kabelac
fd9f7d10ca device_mapper: query for json report once
Remember _is_json_report() check for whole function.
2024-10-22 19:36:00 +02:00
Zdenek Kabelac
f59fa69507 device_mapper: use on stack allocation
Reduce number of heap allocation calls and for smaller
locally used string, use on stack allocation.
2024-10-22 19:36:00 +02:00
Zdenek Kabelac
d8996a2a12 device_mapper: store string on stack
Instead of allocating string from a pool, for shorted strings
use buffer on stack since the string after the use in _find_or_make_node()
as no longer needed.
Eventually we may enhance code also for TOK_STRING_ESCAPED and TOK_STRING,
but they appear to be unused for _section().
2024-10-22 19:36:00 +02:00
Zdenek Kabelac
c29e3410c9 device_mapper: slight improvement of tok_match
Reduce amount of unnecessary instructions for some code paths.
2024-10-22 19:36:00 +02:00
Zdenek Kabelac
92158a24a5 device_mapper: optimize _get_token
For the 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().

Also help a bit more 'gcc' optimizer to grab buffer char just once and
simplify jump to next characted in the buffer when checking for token.
2024-10-22 19:36:00 +02:00
Zdenek Kabelac
2f022f5cbb device_mapper: nodes and values with strings
Avoid double dm_pool allocation call by copying string
for node name and config value directly after the end
of node/value structure.

It would be likely better to not copy these strings at all
and derefence it from the original string however that
needs futher changes in the code base.
2024-10-22 19:36:00 +02:00
Zdenek Kabelac
b185578321 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-22 19:36:00 +02:00
Zdenek Kabelac
f55c949410 crc: move static table
Move static table upward in the code so it can be shared with
another 'crc' implementation.
2024-10-22 19:36:00 +02:00
Zdenek Kabelac
d07e273aff lvmlockd: drop return 1 from void function
When compiling code without lvmlockd, the void function
lockd_free_lv_after_updatei()  should not return any value.
2024-10-22 19:15:55 +02:00
Peter Rajnoha
e96d6b7442 lv_manip: fall back to direct zeroing on any BLKZEROOUT ioctl failure
When BLKZEROOUT ioctl fails, it should not stop us from trying the direct
zeroing as a fallback action, since this is an optimization only.
We should be able to continue with new LV creation if we succeed
with that direct fallback then.

Related report: https://issues.redhat.com/browse/RHEL-58737
2024-10-18 11:44:34 +02:00
David Teigland
6ab2a22fcf lvremove: fix failed remove of all LVs in shared VG
commit a125a3bb50 "lv_remove: reduce commits for removed LVs"
changed "lvremove <vgname>" from removing one LV at a time,
to removing all LVs in one vg write/commit.  It also changed
the behavior if some of the LVs could not be removed, from
removing those LVs that could be removed, to removing nothing
if any LV could not be removed.  This caused a regression in
shared VGs using sanlock, in which the on-disk lease was
removed for any LV that could be removed, even if the command
decided to remove nothing.  This would leave LVs without a
valid ondisk lease, and "lock failed: error -221" would be
returned for any command attempting to lock the LV.

Fix this by not freeing the on-disk leases until after the
command has decided to go ahead and remove everything, and
has written the VG metadata.

Before the fix:

node1: lvchange -ay vg/lv1
node2: lvchange -ay vg/lv2

node1: lvs
  lv1  test -wi-a----- 4.00m
  lv2  test -wi------- 4.00m
node2: lvs
  lv1  test -wi------- 4.00m
  lv2  test -wi-a----- 4.00m

node1: lvremove -y vg/lv1 vg/lv2
  LV locked by other host: vg/lv2

(lvremove removed neither of the LVs, but it freed
the lock for lv1, which could have been removed
except for the proper locking failure on lv2.)

node1: lvs
  lv1  test -wi------- 4.00m
  lv2  test -wi------- 4.00m

node1: lvremove -y vg/lv1
LV vg/lv1 lock failed: error -221

(The lock for lv1 is gone, so nothing can be done with it.)
2024-10-16 13:18:14 -05:00
Peter Rajnoha
8e3db44036 device_id: fix segfault if devices file has PVID=. 2024-10-15 10:58:16 +02:00
798 changed files with 45162 additions and 20527 deletions

View File

@@ -134,6 +134,7 @@ install_system_dirs:
$(INSTALL_ROOT_DIR) $(DESTDIR)$(DEFAULT_LOCK_DIR)
$(INSTALL_ROOT_DIR) $(DESTDIR)$(DEFAULT_RUN_DIR)
$(INSTALL_ROOT_DATA) /dev/null $(DESTDIR)$(DEFAULT_CACHE_DIR)/.cache
$(INSTALL_ROOT_DIR) $(DESTDIR)/var/lib/lvm
install_initscripts:
$(MAKE) -C scripts install_initscripts
@@ -172,7 +173,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 " print-VARIABLE Resolve make variable."
@echo " rpm Build rpm."
@echo " run-unit-test Run unit tests."
@echo " tags Generate c/etags."
@@ -194,7 +195,8 @@ ifneq ("$(GENHTML)", "")
lcov:
$(RM) -rf $(LCOV_REPORTS_DIR)
$(MKDIR_P) $(LCOV_REPORTS_DIR)
$(LCOV) --capture --directory $(top_builddir) --ignore-errors source \
-find . -name '*.gc[dn][ao]' ! -newer make.tmpl -delete
-$(LCOV) --capture --directory $(top_builddir) --ignore-errors source,negative,gcov \
--output-file $(LCOV_REPORTS_DIR)/out.info
-test ! -s $(LCOV_REPORTS_DIR)/out.info || \
$(GENHTML) -o $(LCOV_REPORTS_DIR) --ignore-errors source \

View File

@@ -1 +1 @@
2.03.28(2)-git (2024-10-02)
2.03.36(2)-git (2025-09-09)

View File

@@ -1 +1 @@
1.02.202-git (2024-10-02)
1.02.210-git (2025-09-09)

106
WHATS_NEW
View File

@@ -1,5 +1,109 @@
Version 2.03.28 -
Version 2.03.36 -
==================
Detect and use existing XFS quota mount options for lvresize --fs resize.
Version 2.03.35 - 09th September 2025
=====================================
Fix unlocking devices file only after all PVs are processed.
Avoid creating system.devices when deleting entries.
Fix existing issues with persistent reservations.
Fix possible report output format inconsistencies while processing PVs.
Allow report options for pv/vg/lvdisplay only if used with -C|--columns.
Fix vgsplit failing to split a VG with RAID+integrity or cache with cachevol.
Fix --lockopt handling in lvmlockd when --nolocking is used.
Optimize dmeventd when remonitoring active devices.
Version 2.03.34 - 30th July 2025
================================
Support dmeventd restart when there are no monitored devices.
Dmeventd no longer calls 'action commands' on removed devices.
Fix reader of VDO metadata on 32bit architecture.
Fix lvmdevices --deldev/--delpvid to error out if devices file not writeable.
Fix lvresize corruption in LV->crypt->FS stack if near crypt min size limit.
Enhanced lvresize -r support for btrfs.
Use glibc standard functions htoX, Xtoh functions for endian conversion.
Fix structure copying within sanlock's release_rename().
Fix autoactivation on top of loop dev PVs to trigger once for change uevents.
Add lvmlockd --lockopt repair to reinitialize corrupted sanlock leases.
Fix support for lvcreate -T --setautoactivation.
Add lvm.conf global/lvresize_fs_helper_executable.
Enable lvm to use persistent reservations on a VG.
Version 2.03.33 - 27th June 2025
================================
Various spelling, grammar, formatting, test, and build script improvements.
Override LC_NUMERIC locale if unsuitable for json_std report format.
Repair raid arrays with transiently lost devices.
Version 2.03.32 - 05th May 2025
===============================
Lvconvert vdopool conversion properly validates acceptable LVs.
Accept thin pool data LV as cacheable LV.
Allow using zram block devices (likely for testing).
Fix lvresize when resizing COW snapshots already covering origin.
Fix lvmdbusd read of executed lvm commands output.
Fix construction of DM UUID for cachevol _cdata and _cmeta devices.
Ignore PV claims from old metadata when then PV belongs to a new VG.
Fix integrity metadata rounding.
Accept --autobackup option in pvresize.
Version 2.03.31 - 27th February 2025
====================================
Reduce 'mandoc -T lint' reported issues for man pages.
Restore support for LVM_SUPPRESS_FD_WARNINGS (2.03.24).
Fix uncache and split cache restoring original state of volume.
Extend use of lockopt skip to more scenarios.
Enhance error path resolving in polling code.
Disallow shared activation of LV with CoW snapshot.
Fix lvmlockd use in lvremove of CoW snapshot, VDO pool, and uncache.
Improve mirror split with opened temporary volumes.
Improve pvmove finish with opened temporary volumes.
Fix backup limit for devices file, handle over 10,000 files.
Ignore reported optimal_io_size not divisible by 4096.
Fix busy-loop in config reading when read returned 0.
Fix DM cache preserving logic (2.03.28).
Improve use of lvmlockd for usecases involving thin volumes and pools.
Version 2.03.30 - 14th January 2025
===================================
Lvresize reports origin vdo volume cannot be resized.
Support setting reserved_memory|stack of --config cmdline.
Fix support for disabling memory locking (2.03.27).
Do not extend an LV if FS resize unsupported and '--fs resize' used.
Prevent leftover temporary device when converting in use volume to a pool.
lvconvert detects early volume in use when converting it to a pool.
Handle NVMe with quirk changed WWID not matching WWID in devices file.
Version 2.03.29 - 09th December 2024
====================================
Configure --enable/disable-sd-notify to control lvmlockd build with sd-notify.
Allow test mode when lvmlockd is built without dlm support.
Add a note about RAID + integrity synchronization to lvmraid(7) man page.
Add a function for running lvconvert --repair on RAID LVs to lvmdbusd.
Improve option section of man pages for listing commands ({pv,lv,vg}{s,display}).
Fix renaming of raid sub LVs when converting a volume to raid (2.03.28).
Fix segfault/VG write error for raid LV lvextend -i|--stripes -I|--stripesize.
Revert ignore -i|--stripes, -I|--stripesize for lvextend on raid0 LV (2.03.27).
Version 2.03.28 - 04th November 2024
====================================
Use radix_tree to lookup for UUID within committed metadata.
Use radix_tree to lookup LV list entry within VG struct.
Introduce setting config/validate_metadata = full | none.
Restore fs resize call for lvresize -r on the same size LV (2.03.17).
Correct off-by-one devicesfile backup counting.
Replace use of dm_hash with radix_tree for lv names and uuids.
Refactor vg_validate with uniq_insert and better use of CPU caches.
Add radix_tree_uniq_insert.
Update DM cache when taking next VG lock instead of dropping it.
Generate json string id only for json reporting.
For vgsummary use new API call dm_config_parse_only_section().
Use radix_tree for PV names mapping.
Split check_lv_segment into separate _in/complete_vg variant.
Use find_lv instead of find_lv_in_vg when possible.
Do a mirror fixup only when mirrors with logs are imported.
Add faster crc32 calculation from zlib code for x86_64.
Fall back to direct zeroing if BLKZEROOUT fails during new LV initialization.
Version 2.03.27 - 02nd October 2024
===================================

View File

@@ -1,6 +1,40 @@
Version 1.02.202 -
Version 1.02.210 -
===================
Version 1.02.209 - 09th September 2025
======================================
Version 1.02.208 - 30th July 2025
=================================
Version 1.02.207 - 27th June 2025
=================================
Escape the escape character itself on JSON report format output.
Fail dm_report_group_create if radix char from locale unsuitable for JSON_STD.
Version 1.02.206 - 05th May 2025
================================
Add support for using regex in selection criteria for string lists.
Fix string list selection when using [<item> || <item> ...].
Version 1.02.205 - 27th February 2025
=====================================
Restore missing symbol dm_tree_node_size_changed@Base (1.02.175).
Restore missing symbol dm_bitset_parse_list@@DM_1_02_138 (1.02.175).
Version 1.02.204 - 14th January 2025
====================================
Create /dev/disk/by-diskseq/<DISKSEQ> symlink for public DM devices.
Version 1.02.203 - 09th December 2024
=====================================
Version 1.02.202 - 04th November 2024
=====================================
Introduce dm_config_parse_only_section to stop parsing after section.
For shorter string use on stack buffers when generating sections.
Enhance dm_config tokenizer.
Version 1.02.201 - 02nd October 2024
====================================
Cleanup udev sync semaphore if dm_{udev_create,task_set}_cookie fails.
@@ -260,7 +294,7 @@ Version 1.02.136 - 5th November 2016
Still produce output when dmsetup dependency tree building finds dev missing.
Check and report pthread_sigmask() failure in dmeventd.
Check mem alloc fail in _canonicalize_field_ids().
Use unsigned math when checking more then 31 legs of raid.
Use unsigned math when checking more than 31 legs of raid.
Fix 'dmstats delete' with dmsetup older than v1.02.129
Fix stats walk segfault with dmsetup older than v1.02.129

48
aclocal.m4 vendored
View File

@@ -1,6 +1,6 @@
# generated automatically by aclocal 1.16.5 -*- Autoconf -*-
# generated automatically by aclocal 1.18.1 -*- Autoconf -*-
# Copyright (C) 1996-2021 Free Software Foundation, Inc.
# Copyright (C) 1996-2025 Free Software Foundation, Inc.
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -422,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-2021 Free Software Foundation, Inc.
# Copyright (C) 1999-2025 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -456,9 +456,12 @@ AC_DEFUN([AM_PATH_PYTHON],
dnl Find a Python interpreter. Python versions prior to 2.0 are not
dnl supported. (2.0 was released on October 16, 2000).
m4_define_default([_AM_PYTHON_INTERPRETER_LIST],
[python python2 python3 dnl
[python python3 dnl
python3.20 python3.19 python3.18 python3.17 python3.16 dnl
python3.15 python3.14 python3.13 python3.12 python3.11 python3.10 dnl
python3.9 python3.8 python3.7 python3.6 python3.5 python3.4 python3.3 dnl
python3.2 python3.1 python3.0 dnl
python2 dnl
python2.7 python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 dnl
python2.0])
@@ -653,15 +656,29 @@ try:
if python_implementation() == 'CPython' and sys.version[[:3]] == '2.7':
can_use_sysconfig = 0
except ImportError:
pass"
pass" # end of am_python_setup_sysconfig
# More repeated code, for figuring out the installation scheme to use.
am_python_setup_scheme="if hasattr(sysconfig, 'get_default_scheme'):
scheme = sysconfig.get_default_scheme()
else:
scheme = sysconfig._get_default_scheme()
if scheme == 'posix_local':
if '$am_py_prefix' == '/usr':
scheme = 'deb_system' # should only happen during Debian package builds
else:
# Debian's default scheme installs to /usr/local/ but we want to
# follow the prefix, as we always have.
# See bugs#54412, #64837, et al.
scheme = 'posix_prefix'" # end of am_python_setup_scheme
dnl emacs-page Set up 4 directories:
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 directory as in early automake betas. This behavior
dnl is more consistent with lispdir.m4 for example.
dnl Query distutils for this directory.
dnl Query sysconfig or distutils (per above) for this directory.
dnl
AC_CACHE_CHECK([for $am_display_PYTHON script directory (pythondir)],
[am_cv_python_pythondir],
@@ -673,7 +690,11 @@ except ImportError:
am_cv_python_pythondir=`$PYTHON -c "
$am_python_setup_sysconfig
if can_use_sysconfig:
sitedir = sysconfig.get_path('purelib', vars={'base':'$am_py_prefix'})
try:
$am_python_setup_scheme
sitedir = sysconfig.get_path('purelib', scheme, vars={'base':'$am_py_prefix'})
except:
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')
@@ -703,7 +724,8 @@ sys.stdout.write(sitedir)"`
dnl 3. pyexecdir: directory for installing python extension modules
dnl (shared libraries).
dnl Query distutils for this directory.
dnl Query sysconfig or distutils for this directory.
dnl Much of this is the same as for prefix setup above.
dnl
AC_CACHE_CHECK([for $am_display_PYTHON extension module directory (pyexecdir)],
[am_cv_python_pyexecdir],
@@ -715,7 +737,11 @@ sys.stdout.write(sitedir)"`
am_cv_python_pyexecdir=`$PYTHON -c "
$am_python_setup_sysconfig
if can_use_sysconfig:
sitedir = sysconfig.get_path('platlib', vars={'platbase':'$am_py_exec_prefix'})
try:
$am_python_setup_scheme
sitedir = sysconfig.get_path('platlib', scheme, vars={'platbase':'$am_py_exec_prefix'})
except:
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_exec_prefix')
@@ -766,7 +792,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-2021 Free Software Foundation, Inc.
# Copyright (C) 2001-2025 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,

View File

@@ -279,7 +279,7 @@ static bool _insert_prefix_chain(struct radix_tree *rt, struct value *v, const u
pc->len = i;
if (!_insert(rt, &pc->child, kb + i, ke, rv)) {
free(pc2);
free(pc->child.value.ptr);
return false;
}
@@ -293,6 +293,7 @@ static bool _insert_prefix_chain(struct radix_tree *rt, struct value *v, const u
if (pc->len == 1) {
n4->values[0] = pc->child;
free(pc);
v->value.ptr = NULL;
} else {
memmove(pc->prefix, pc->prefix + 1, pc->len - 1);
pc->len--;
@@ -564,6 +565,13 @@ bool radix_tree_insert(struct radix_tree *rt, const void *key, size_t keylen, un
return _insert(rt, lr.v, lr.kb, ke, rv);
}
int radix_tree_uniq_insert(struct radix_tree *rt, const void *key, size_t keylen, union radix_value rv)
{
unsigned entries = rt->nr_entries;
return radix_tree_insert(rt, key, keylen, rv) ?
((entries != rt->nr_entries) ? 1 : -1) : 0;
}
// Note the degrade functions also free the original node.
static void _degrade_to_n4(struct node16 *n16, struct value *result)
{

View File

@@ -193,12 +193,12 @@ bool radix_tree_remove(struct radix_tree *rt, const void *key, size_t keylen)
return true;
}
unsigned radix_tree_remove_prefix(struct radix_tree *rt, const void *key, size_t keylen)
unsigned radix_tree_remove_prefix(struct radix_tree *rt, const void *prefix, size_t prefix_len)
{
const uint8_t *kb = key;
const uint8_t *ke = kb + keylen;
const uint8_t *kb = prefix;
const uint8_t *ke = kb + prefix_len;
struct node **pn;
unsigned count;
unsigned count = 0;
pn = _lookup(&rt->root, kb, ke);
@@ -280,7 +280,7 @@ static void _dump(FILE *out, struct node *n, unsigned indent)
fprintf(out, " ");
if (n->has_value) {
fprintf(out, "value: %llu\n", n->value.n);
fprintf(out, "value: %lu\n", (unsigned long) n->value.n);
} else {
fprintf(out, "key: '%c' [0x%02x] %u\n",
isprint(n->key) ? n->key : ' ', n->key, indent);

View File

@@ -35,6 +35,10 @@ void radix_tree_destroy(struct radix_tree *rt);
unsigned radix_tree_size(struct radix_tree *rt);
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: 1 success
// 0 failure during insert
// -1 key had already existing value (that was updated)
int radix_tree_uniq_insert(struct radix_tree *rt, const void *key, size_t keylen, union radix_value v);
// Returns the number of values removed
unsigned radix_tree_remove_prefix(struct radix_tree *rt, const void *prefix, size_t prefix_len);
@@ -78,6 +82,12 @@ static inline bool radix_tree_insert_ptr(struct radix_tree *rt, const void *key,
union radix_value v = { .ptr = ptr };
return radix_tree_insert(rt, key, keylen, v);
}
static inline int radix_tree_uniq_insert_ptr(struct radix_tree *rt, const void *key, size_t keylen, void *ptr)
{
union radix_value v = { .ptr = ptr };
return radix_tree_uniq_insert(rt, key, keylen, v);
}
//----------------------------------------------------------------
#endif

View File

@@ -36,6 +36,19 @@ config {
# This configuration option has an automatic default value.
# checks = 1
# Configuration option config/validate_metadata.
# Allows to select the level of validation after metadata transformation.
# Validation takes extra CPU time to verify internal consistency.
# Accepted values:
# full
# Do a full metadata validation before disk write.
# none
# Skip any checks (unrecommended, slightly faster).
#
# This configuration option is advanced.
# This configuration option has an automatic default value.
# validate_metadata = "full"
# Configuration option config/abort_on_errors.
# Abort the LVM process if a configuration mismatch is found.
# This configuration option has an automatic default value.
@@ -573,7 +586,7 @@ allocation {
# Configuration option allocation/thin_pool_crop_metadata.
# Older version of lvm2 cropped pool's metadata size to 15.81 GiB.
# This is slightly less then the actual maximum 15.88 GiB.
# This is slightly less than the actual maximum 15.88 GiB.
# For compatibility with older version and use of cropped size set to 1.
# This configuration option has an automatic default value.
# thin_pool_crop_metadata = 0
@@ -1366,6 +1379,12 @@ global {
# This configuration option has an automatic default value.
# fsadm_executable = "@FSADM_PATH@"
# Configuration option global/lvresize_fs_helper_executable.
# The full path to the lvresize_fs_helper command.
# LVM uses this command to help with filesystem operations during lvresize.
# This configuration option has an automatic default value.
# lvresize_fs_helper_executable = "@LVRESIZE_FS_HELPER_PATH@"
# Configuration option global/system_id_source.
# The method LVM uses to set the local system ID.
# Volume Groups can also be given a system ID (by vgcreate, vgchange,

View File

@@ -38,6 +38,14 @@ local {
# This configuration option has an automatic default value.
# system_id = ""
# Configuration option local/pr_key.
# The local persistent reservation key in hexadecimal.
# The value must be unique among all hosts using the same VG.
# The max length is 16 hex characters (8 bytes), plus an optional
# 0x prefix. If pr_key is not set, host_id will be used to create a key.
# This configuration option has an automatic default value.
# pr_key = ""
# Configuration option local/extra_system_ids.
# A list of extra VG system IDs the local host can access.
# VGs with the system IDs listed here (in addition to the host's own
@@ -52,7 +60,9 @@ local {
# 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.
# When using persistent reservations, lvm will generate a PR key from the host_id
# if pr_key is not defined. All hosts using a sanlock shared VG with PR must use
# the same approach for configuring their PR key (pr_key or host_id.)
# This configuration option has an automatic default value.
# host_id = 0
}

322
configure vendored
View File

@@ -678,6 +678,7 @@ SILENT_RULES
SHARED_LINK
SELINUX_STATIC_LIBS
SELINUX_PC
SD_NOTIFY_SUPPORT
SBINDIR
RT_LIBS
PYTHON3DIR
@@ -787,6 +788,8 @@ LIBSYSTEMD_LIBS
LIBSYSTEMD_CFLAGS
UDEV_LIBS
UDEV_CFLAGS
LIBNVME_LIBS
LIBNVME_CFLAGS
BLKID_LIBS
BLKID_CFLAGS
SYSTEMD_RUN_CMD
@@ -912,6 +915,7 @@ enable_silent_rules
enable_static_link
enable_shared
with_blkid
with_libnvme
with_systemd
with_udev
with_user
@@ -971,8 +975,10 @@ enable_use_lvmpolld
with_lvmpolld_pidfile
enable_systemd_journal
enable_app_machineid
enable_sd_notify
with_systemd_run
enable_blkid_wiping
enable_nvme_wwid
enable_udev_sync
enable_udev_rules
enable_udev_rule_exec_detection
@@ -1045,6 +1051,8 @@ LIBSEAGATEILM_CFLAGS
LIBSEAGATEILM_LIBS
BLKID_CFLAGS
BLKID_LIBS
LIBNVME_CFLAGS
LIBNVME_LIBS
UDEV_CFLAGS
UDEV_LIBS
LIBSYSTEMD_CFLAGS
@@ -1713,8 +1721,10 @@ Optional Features:
--disable-systemd-journal
disable LVM systemd journaling
--disable-app-machineid disable LVM system ID using app-specific machine-id
--disable-sd-notify disable LVM sd_notify
--disable-blkid_wiping disable libblkid detection of signatures when wiping
and use native code instead
--disable-nvme-wwid do not use libnvme to detect alternate WWIDs
--enable-udev_sync enable synchronization with udev processing
--enable-udev_rules install rule files needed for udev synchronization
--enable-udev-rule-exec-detection
@@ -1741,6 +1751,7 @@ Optional Packages:
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
--without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
--without-blkid do not build with blkid library
--without-libnvme do not build with libnvme library
--without-systemd do not build with systemd library
--without-udev do not build with udev library
--with-user=USER set the owner of installed files [USER=]
@@ -1880,6 +1891,10 @@ Some influential environment variables:
BLKID_CFLAGS
C compiler flags for BLKID, overriding pkg-config
BLKID_LIBS linker flags for BLKID, overriding pkg-config
LIBNVME_CFLAGS
C compiler flags for LIBNVME, overriding pkg-config
LIBNVME_LIBS
linker flags for LIBNVME, overriding pkg-config
UDEV_CFLAGS C compiler flags for UDEV, overriding pkg-config
UDEV_LIBS linker flags for UDEV, overriding pkg-config
LIBSYSTEMD_CFLAGS
@@ -9128,6 +9143,16 @@ esac
fi
# Check whether --with-libnvme was given.
if test ${with_libnvme+y}
then :
withval=$with_libnvme;
else case e in #(
e) with_libnvme="yes" ;;
esac
fi
# Check whether --with-systemd was given.
if test ${with_systemd+y}
then :
@@ -12149,6 +12174,23 @@ printf "%s\n" "$BUILD_LOCKDSANLOCK" >&6; }
if test "$BUILD_LOCKDSANLOCK" = "yes"
then :
LOCKDSANLOCK_SUPPORT=370
if test -n "$PKG_CONFIG" && \
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsanlock_client >= 4.0.0\""; } >&5
($PKG_CONFIG --exists --print-errors "libsanlock_client >= 4.0.0") 2>&5
ac_status=$?
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
LOCKDSANLOCK_SUPPORT=400
fi
if test -n "$PKG_CONFIG" && \
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsanlock_client >= 4.1.0\""; } >&5
($PKG_CONFIG --exists --print-errors "libsanlock_client >= 4.1.0") 2>&5
ac_status=$?
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
LOCKDSANLOCK_SUPPORT=410
fi
pkg_failed=no
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for libsanlock_client >= 3.7.0" >&5
@@ -12241,7 +12283,7 @@ printf "%s\n" "yes" >&6; }
BUILD_LVMLOCKD="yes"
fi
printf "%s\n" "#define LOCKDSANLOCK_SUPPORT 1" >>confdefs.h
printf "%s\n" "#define LOCKDSANLOCK_SUPPORT $LOCKDSANLOCK_SUPPORT" >>confdefs.h
fi
@@ -12724,9 +12766,18 @@ SYSTEMD_MIN_VERSION=0
NOTIFYDBUS_SUPPORT="no"
SYSTEMD_JOURNAL_SUPPORT="no"
APP_MACHINEID_SUPPORT="no"
SD_NOTIFY_SUPPORT="no"
if test "$with_systemd" = "yes"
then :
if test -n "$PKG_CONFIG" && \
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"systemd >= 218\""; } >&5
($PKG_CONFIG --exists --print-errors "systemd >= 218") 2>&5
ac_status=$?
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
SYSTEMD_MIN_VERSION=218 SD_NOTIFY_SUPPORT="maybe"
fi
if test -n "$PKG_CONFIG" && \
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"systemd >= 221\""; } >&5
($PKG_CONFIG --exists --print-errors "systemd >= 221") 2>&5
ac_status=$?
@@ -12814,6 +12865,41 @@ printf "%s\n" "#define APP_MACHINEID_SUPPORT 1" >>confdefs.h
fi
################################################################################
if test "$SD_NOTIFY_SUPPORT" != "no"
then :
ac_fn_c_check_header_compile "$LINENO" "systemd/sd-daemon.h" "ac_cv_header_systemd_sd_daemon_h" "$ac_includes_default"
if test "x$ac_cv_header_systemd_sd_daemon_h" = xyes
then :
SD_NOTIFY_SUPPORT="yes"
else case e in #(
e) SD_NOTIFY_SUPPORT="no" ;;
esac
fi
fi
# Check whether --enable-sd-notify was given.
if test ${enable_sd_notify+y}
then :
enableval=$enable_sd_notify; if test "$enableval" = "yes" && test "$SD_NOTIFY_SUPPORT" = "no"
then :
as_fn_error $? "--enable-sd-notify requires systemd/sd-daemon.h. (--with-systemd=$with_systemd)" "$LINENO" 5
fi
SD_NOTIFY_SUPPORT=$enableval
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to enable to sd_notify" >&5
printf %s "checking whether to enable to sd_notify... " >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $SD_NOTIFY_SUPPORT" >&5
printf "%s\n" "$SD_NOTIFY_SUPPORT" >&6; }
if test "$SD_NOTIFY_SUPPORT" = "yes"
then :
printf "%s\n" "#define SD_NOTIFY_SUPPORT 1" >>confdefs.h
fi
################################################################################
# Check whether --with-systemd-run was given.
@@ -13129,6 +13215,181 @@ printf "%s\n" "$BLKID_WIPING" >&6; }
printf "%s\n" "#define DEFAULT_USE_BLKID_WIPING $DEFAULT_USE_BLKID_WIPING" >>confdefs.h
################################################################################
# Check whether --enable-nvme-wwid was given.
if test ${enable_nvme_wwid+y}
then :
enableval=$enable_nvme_wwid; NVME_WWID=$enableval
else case e in #(
e) if test "$with_libnvme" = "yes"
then :
NVME_WWID="maybe"
else case e in #(
e) NVME_WWID="no" ;;
esac
fi ;;
esac
fi
# ATM NVME_WWID is the only user of libnvme, so skip checking for libnvme when disabled
if test "$NVME_WWID" = "no"
then :
with_libnvme="no"
fi
if test "$with_libnvme" = "yes"
then :
pkg_failed=no
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for libnvme >= 1.4" >&5
printf %s "checking for libnvme >= 1.4... " >&6; }
if test -n "$LIBNVME_CFLAGS"; then
pkg_cv_LIBNVME_CFLAGS="$LIBNVME_CFLAGS"
elif test -n "$PKG_CONFIG"; then
if test -n "$PKG_CONFIG" && \
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libnvme >= 1.4\""; } >&5
($PKG_CONFIG --exists --print-errors "libnvme >= 1.4") 2>&5
ac_status=$?
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
pkg_cv_LIBNVME_CFLAGS=`$PKG_CONFIG --cflags "libnvme >= 1.4" 2>/dev/null`
test "x$?" != "x0" && pkg_failed=yes
else
pkg_failed=yes
fi
else
pkg_failed=untried
fi
if test -n "$LIBNVME_LIBS"; then
pkg_cv_LIBNVME_LIBS="$LIBNVME_LIBS"
elif test -n "$PKG_CONFIG"; then
if test -n "$PKG_CONFIG" && \
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libnvme >= 1.4\""; } >&5
($PKG_CONFIG --exists --print-errors "libnvme >= 1.4") 2>&5
ac_status=$?
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
pkg_cv_LIBNVME_LIBS=`$PKG_CONFIG --libs "libnvme >= 1.4" 2>/dev/null`
test "x$?" != "x0" && pkg_failed=yes
else
pkg_failed=yes
fi
else
pkg_failed=untried
fi
if test $pkg_failed = yes; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
_pkg_short_errors_supported=yes
else
_pkg_short_errors_supported=no
fi
if test $_pkg_short_errors_supported = yes; then
LIBNVME_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libnvme >= 1.4" 2>&1`
else
LIBNVME_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libnvme >= 1.4" 2>&1`
fi
# Put the nasty error message in config.log where it belongs
echo "$LIBNVME_PKG_ERRORS" >&5
if test "$NVME_WWID" = "yes"
then :
NVME_WWID="error"
else case e in #(
e) NVME_WWID="no" ;;
esac
fi
elif test $pkg_failed = untried; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
if test "$NVME_WWID" = "yes"
then :
NVME_WWID="error"
else case e in #(
e) NVME_WWID="no" ;;
esac
fi
else
LIBNVME_CFLAGS=$pkg_cv_LIBNVME_CFLAGS
LIBNVME_LIBS=$pkg_cv_LIBNVME_LIBS
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
printf "%s\n" "yes" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for NVME_NIDT_CSI in libnvme.h" >&5
printf %s "checking for NVME_NIDT_CSI in libnvme.h... " >&6; }
if test ${ac_cv_have_libnvme_csi+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <libnvme.h>
const int a = NVME_NIDT_CSI;
int
main (void)
{
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
ac_cv_have_libnvme_csi="yes"
else case e in #(
e) ac_cv_have_libnvme_csi="no" ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_libnvme_csi" >&5
printf "%s\n" "$ac_cv_have_libnvme_csi" >&6; }
if test "$NVME_WWID" != "no"
then :
if test $ac_cv_have_libnvme_csi = yes
then :
NVME_WWID="yes"
printf "%s\n" "#define NVME_SUPPORT 1" >>confdefs.h
else case e in #(
e) NVME_WWID="error" ;;
esac
fi
fi
fi
else case e in #(
e) if test "$NVME_WWID" = "yes"
then :
NVME_WWID="error"
fi ;;
esac
fi
if test "$NVME_WWID" = "error"
then :
as_fn_error $? "--enable-nvme-wwid requires libnvme library >= 1.1. (--with-libnvme=$with_libnvme)" "$LINENO" 5
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to use libnvme for alternate WWIDs" >&5
printf %s "checking whether to use libnvme for alternate WWIDs... " >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $NVME_WWID" >&5
printf "%s\n" "$NVME_WWID" >&6; }
################################################################################
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to enable synchronization with udev processing" >&5
printf %s "checking whether to enable synchronization with udev processing... " >&6; }
@@ -13427,7 +13688,11 @@ printf "%s\n" "$BUILD_LVMDBUSD" >&6; }
# Check whether --enable-notify-dbus was given.
if test ${enable_notify_dbus+y}
then :
enableval=$enable_notify_dbus; NOTIFYDBUS_SUPPORT=$enableval
enableval=$enable_notify_dbus; if test "enableval" = "yes" && test "$NOTIFYDBUS_SUPPORT" = "no"
then :
as_fn_error $? "--enable-notify-dbus requires systemd >= 221. (--with-systemd=$with_systemd)" "$LINENO" 5
fi
NOTIFYDBUS_SUPPORT=$enableval
fi
@@ -13444,10 +13709,6 @@ fi
if test "$NOTIFYDBUS_SUPPORT" = "yes"
then :
if test "$SYSTEMD_MIN_VERSION" -lt 221
then :
as_fn_error $? "--enable-notify-dbus requires systemd >= 221. (--with-systemd=$with_systemd)" "$LINENO" 5
fi
printf "%s\n" "#define NOTIFYDBUS_SUPPORT 1" >>confdefs.h
@@ -13459,10 +13720,10 @@ printf %s "checking whether to build notifydbus... " >&6; }
printf "%s\n" "$NOTIFYDBUS_SUPPORT" >&6; }
################################################################################
if test "$NOTIFYDBUS_SUPPORT" = "yes" || test "$SYSTEMD_JOURNAL_SUPPORT" = "yes" || test "$APP_MACHINEID_SUPPORT" = "yes"
if test "$NOTIFYDBUS_SUPPORT" = "yes" || test "$SYSTEMD_JOURNAL_SUPPORT" = "yes" ||
test "$APP_MACHINEID_SUPPORT" = "yes" || test "$SD_NOTIFY_SUPPORT" = "yes"
then :
pkg_failed=no
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for libsystemd" >&5
printf %s "checking for libsystemd... " >&6; }
@@ -13553,7 +13814,6 @@ else
printf "%s\n" "yes" >&6; }
fi
fi
################################################################################
@@ -13880,7 +14140,21 @@ try:
if python_implementation() == 'CPython' and sys.version[:3] == '2.7':
can_use_sysconfig = 0
except ImportError:
pass"
pass" # end of am_python_setup_sysconfig
# More repeated code, for figuring out the installation scheme to use.
am_python_setup_scheme="if hasattr(sysconfig, 'get_default_scheme'):
scheme = sysconfig.get_default_scheme()
else:
scheme = sysconfig._get_default_scheme()
if scheme == 'posix_local':
if '$am_py_prefix' == '/usr':
scheme = 'deb_system' # should only happen during Debian package builds
else:
# Debian's default scheme installs to /usr/local/ but we want to
# follow the prefix, as we always have.
# See bugs#54412, #64837, et al.
scheme = 'posix_prefix'" # end of am_python_setup_scheme
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON script directory (pythondir)" >&5
@@ -13897,7 +14171,11 @@ else case e in #(
am_cv_python_pythondir=`$PYTHON -c "
$am_python_setup_sysconfig
if can_use_sysconfig:
sitedir = sysconfig.get_path('purelib', vars={'base':'$am_py_prefix'})
try:
$am_python_setup_scheme
sitedir = sysconfig.get_path('purelib', scheme, vars={'base':'$am_py_prefix'})
except:
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')
@@ -13927,7 +14205,7 @@ printf "%s\n" "$am_cv_python_pythondir" >&6; }
pkgpythondir=\${pythondir}/$PACKAGE
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON extension module directory (pyexecdir)" >&5
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON extension module directory (pyexecdir)" >&5
printf %s "checking for $am_display_PYTHON extension module directory (pyexecdir)... " >&6; }
if test ${am_cv_python_pyexecdir+y}
then :
@@ -13941,7 +14219,11 @@ else case e in #(
am_cv_python_pyexecdir=`$PYTHON -c "
$am_python_setup_sysconfig
if can_use_sysconfig:
sitedir = sysconfig.get_path('platlib', vars={'platbase':'$am_py_exec_prefix'})
try:
$am_python_setup_scheme
sitedir = sysconfig.get_path('platlib', scheme, vars={'platbase':'$am_py_exec_prefix'})
except:
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_exec_prefix')
@@ -14290,7 +14572,7 @@ printf %s "checking whether to compile liblvm2cmd.so... " >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CMDLIB" >&5
printf "%s\n" "$CMDLIB" >&6; }
if test "$CMDLIB" == "yes" && test "$SHARED_LINK" = "no"
if test "$CMDLIB" = "yes" && test "$SHARED_LINK" = "no"
then :
as_fn_error $? "--enable-cmdlib requires dynamic linking." "$LINENO" 5
fi
@@ -16221,6 +16503,11 @@ LVRESIZE_FS_HELPER_PATH="$LIBEXECDIR/lvresize_fs_helper"
printf "%s\n" "#define LVRESIZE_FS_HELPER_PATH \"$LVRESIZE_FS_HELPER_PATH\"" >>confdefs.h
LVMPERSIST_PATH="$SBINDIR/lvmpersist"
printf "%s\n" "#define LVMPERSIST_PATH \"$LVMPERSIST_PATH\"" >>confdefs.h
################################################################################
# Check whether --with-dmeventd-pidfile was given.
@@ -16564,6 +16851,7 @@ AIO_LIBS=${AIO_LIBS:--laio}
################################################################################
@@ -17961,3 +18249,9 @@ then :
printf "%s\n" "$as_me: WARNING: Building D-Bus support without D-Bus notifications!" >&2;}
fi
if test "$BUILD_LVMLOCKD" = "yes" && test "$SD_NOTIFY_SUPPORT" = "no"
then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Building lvmlockd without sd-notify support may block!" >&5
printf "%s\n" "$as_me: WARNING: Building lvmlockd without sd-notify support may block!" >&2;}
fi

View File

@@ -1,4 +1,3 @@
###############################################################################
## Copyright (C) 2000-2004 Sistina Software, Inc. All rights reserved.
## Copyright (C) 2004-2023 Red Hat, Inc. All rights reserved.
##
@@ -217,6 +216,8 @@ test "$exec_prefix" = "NONE" && exec_prefix='${prefix}'
AC_ARG_WITH(blkid, [AS_HELP_STRING([--without-blkid], [do not build with blkid library])],
[], with_blkid="yes")
AC_ARG_WITH(libnvme, [AS_HELP_STRING([--without-libnvme], [do not build with libnvme library])],
[], with_libnvme="yes")
AC_ARG_WITH(systemd, [AS_HELP_STRING([--without-systemd], [do not build with systemd library])],
[], with_systemd="yes")
AC_ARG_WITH(udev, [AS_HELP_STRING([--without-udev], [do not build with udev library])],
@@ -933,8 +934,11 @@ AC_MSG_RESULT([$BUILD_LOCKDSANLOCK])
dnl -- Look for sanlock libraries
AS_IF([test "$BUILD_LOCKDSANLOCK" = "yes"], [
LOCKDSANLOCK_SUPPORT=410
PKG_CHECK_EXISTS(libsanlock_client >= 4.0.0, [LOCKDSANLOCK_SUPPORT=400])
PKG_CHECK_EXISTS(libsanlock_client >= 4.1.0, [LOCKDSANLOCK_SUPPORT=410])
PKG_CHECK_MODULES(LIBSANLOCKCLIENT, libsanlock_client >= 3.7.0, [BUILD_LVMLOCKD="yes"])
AC_DEFINE([LOCKDSANLOCK_SUPPORT], 1, [Define to 1 to include code that uses lvmlockd sanlock option.])
AC_DEFINE_UNQUOTED([LOCKDSANLOCK_SUPPORT], [$LOCKDSANLOCK_SUPPORT], [Define version of sanlock.])
])
################################################################################
@@ -1046,7 +1050,9 @@ SYSTEMD_MIN_VERSION=0
NOTIFYDBUS_SUPPORT="no"
SYSTEMD_JOURNAL_SUPPORT="no"
APP_MACHINEID_SUPPORT="no"
SD_NOTIFY_SUPPORT="no"
AS_IF([test "$with_systemd" = "yes"],
PKG_CHECK_EXISTS(systemd >= 218, [SYSTEMD_MIN_VERSION=218 SD_NOTIFY_SUPPORT="maybe"])
PKG_CHECK_EXISTS(systemd >= 221, [SYSTEMD_MIN_VERSION=221 NOTIFYDBUS_SUPPORT="maybe" SYSTEMD_JOURNAL_SUPPORT="maybe"])
PKG_CHECK_EXISTS(systemd >= 234, [SYSTEMD_MIN_VERSION=234 APP_MACHINEID_SUPPORT="maybe"]))
@@ -1082,6 +1088,22 @@ AC_MSG_RESULT([$APP_MACHINEID_SUPPORT])
AS_IF([test "$APP_MACHINEID_SUPPORT" = "yes"],
AC_DEFINE([APP_MACHINEID_SUPPORT], 1, [Define to 1 to include code that uses libsystemd machine-id apis.]))
################################################################################
dnl -- Build with sd_notify when the header file sd-daemon.h is present
AS_IF([test "$SD_NOTIFY_SUPPORT" != "no"],
AC_CHECK_HEADER([systemd/sd-daemon.h], [SD_NOTIFY_SUPPORT="yes"], [SD_NOTIFY_SUPPORT="no"]))
AC_ARG_ENABLE(sd-notify,
AS_HELP_STRING([--disable-sd-notify],
[disable LVM sd_notify]),
AS_IF([test "$enableval" = "yes" && test "$SD_NOTIFY_SUPPORT" = "no"],
AC_MSG_ERROR([--enable-sd-notify requires systemd/sd-daemon.h. (--with-systemd=$with_systemd)]))
SD_NOTIFY_SUPPORT=$enableval, [])
AC_MSG_CHECKING([whether to enable to sd_notify])
AC_MSG_RESULT([$SD_NOTIFY_SUPPORT])
AS_IF([test "$SD_NOTIFY_SUPPORT" = "yes"],
AC_DEFINE([SD_NOTIFY_SUPPORT], 1, [Define to 1 to include code that uses sd_notify.]))
################################################################################
dnl -- Support override for systemd-run path if they need to (NixOS builds)
AC_ARG_WITH(systemd-run,
@@ -1139,6 +1161,38 @@ AC_MSG_RESULT([$BLKID_WIPING])
AC_DEFINE_UNQUOTED(DEFAULT_USE_BLKID_WIPING, [$DEFAULT_USE_BLKID_WIPING],
[Use blkid wiping by default.])
################################################################################
dnl -- Enable nvme alternate WWID via libnvme
AC_ARG_ENABLE(nvme-wwid,
AS_HELP_STRING([--disable-nvme-wwid],
[do not use libnvme to detect alternate WWIDs]),
NVME_WWID=$enableval,
[AS_IF([test "$with_libnvme" = "yes"], [NVME_WWID="maybe"], [NVME_WWID="no"])])
# ATM NVME_WWID is the only user of libnvme, so skip checking for libnvme when disabled
AS_IF([test "$NVME_WWID" = "no"], [with_libnvme="no"])
AS_IF([test "$with_libnvme" = "yes"], [
PKG_CHECK_MODULES([LIBNVME], [libnvme >= 1.4], [
AC_CACHE_CHECK([for NVME_NIDT_CSI in libnvme.h],
[ac_cv_have_libnvme_csi],
[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include <libnvme.h>
const int a = NVME_NIDT_CSI;
])], [ac_cv_have_libnvme_csi="yes"], [ac_cv_have_libnvme_csi="no"])])
AS_IF([test "$NVME_WWID" != "no"], [
AC_IF_YES(ac_cv_have_libnvme_csi, [NVME_WWID="yes"
AC_DEFINE(NVME_SUPPORT, 1, [Use libnvme for WWID.])],
[NVME_WWID="error"])])
], [AS_IF([test "$NVME_WWID" = "yes"], [NVME_WWID="error"], [NVME_WWID="no"])])
], [AS_IF([test "$NVME_WWID" = "yes"], [NVME_WWID="error"])])
AS_IF([test "$NVME_WWID" = "error"],
[AC_MSG_ERROR([--enable-nvme-wwid requires libnvme library >= 1.1. (--with-libnvme=$with_libnvme)])])
AC_MSG_CHECKING([whether to use libnvme for alternate WWIDs])
AC_MSG_RESULT([$NVME_WWID])
################################################################################
dnl -- Enable udev synchronization
AC_MSG_CHECKING([whether to enable synchronization with udev processing])
@@ -1231,24 +1285,25 @@ AC_MSG_RESULT([$BUILD_LVMDBUSD])
dnl -- Build notifydbus
AC_ARG_ENABLE(notify-dbus,
[AS_HELP_STRING([--enable-notify-dbus], [enable LVM notification using dbus])],
[NOTIFYDBUS_SUPPORT=$enableval])
[AS_IF([test "enableval" = "yes" && test "$NOTIFYDBUS_SUPPORT" = "no"],
[AC_MSG_ERROR([--enable-notify-dbus requires systemd >= 221. (--with-systemd=$with_systemd)])])
NOTIFYDBUS_SUPPORT=$enableval])
AS_IF([test "$NOTIFYDBUS_SUPPORT" = "maybe"],
[AS_IF([test "$BUILD_LVMDBUSD" = "yes"], [NOTIFYDBUS_SUPPORT="yes"], [NOTIFYDBUS_SUPPORT="no"])])
[AS_IF([test "$BUILD_LVMDBUSD" = "yes"],
[NOTIFYDBUS_SUPPORT="yes"], [NOTIFYDBUS_SUPPORT="no"])])
AS_IF([test "$NOTIFYDBUS_SUPPORT" = "yes"],
[AS_IF([test "$SYSTEMD_MIN_VERSION" -lt 221],
[AC_MSG_ERROR([--enable-notify-dbus requires systemd >= 221. (--with-systemd=$with_systemd)])])
AC_DEFINE([NOTIFYDBUS_SUPPORT], 1, [Define to 1 to include code that uses dbus notification.])])
[AC_DEFINE([NOTIFYDBUS_SUPPORT], 1, [Define to 1 to include code that uses dbus notification.])])
AC_MSG_CHECKING([whether to build notifydbus])
AC_MSG_RESULT([$NOTIFYDBUS_SUPPORT])
################################################################################
dnl -- Look for libsystemd libraries if needed
AS_IF([test "$NOTIFYDBUS_SUPPORT" = "yes" || test "$SYSTEMD_JOURNAL_SUPPORT" = "yes" || test "$APP_MACHINEID_SUPPORT" = "yes"], [
PKG_CHECK_MODULES(LIBSYSTEMD, [libsystemd])
])
AS_IF([test "$NOTIFYDBUS_SUPPORT" = "yes" || test "$SYSTEMD_JOURNAL_SUPPORT" = "yes" ||
test "$APP_MACHINEID_SUPPORT" = "yes" || test "$SD_NOTIFY_SUPPORT" = "yes"],
[PKG_CHECK_MODULES(LIBSYSTEMD, [libsystemd])])
################################################################################
dnl -- Enable Python dbus library
@@ -1341,7 +1396,7 @@ AS_IF([test "$CMDLIB" != "yes"], [CMDLIB="no" LVM2CMD_LIB=], [LVM2CMD_LIB="-llvm
AC_MSG_CHECKING([whether to compile liblvm2cmd.so])
AC_MSG_RESULT([$CMDLIB])
AS_IF([test "$CMDLIB" == "yes" && test "$SHARED_LINK" = "no"],
AS_IF([test "$CMDLIB" = "yes" && test "$SHARED_LINK" = "no"],
[AC_MSG_ERROR([--enable-cmdlib requires dynamic linking.])])
@@ -1717,6 +1772,9 @@ LIBEXECDIR="$(eval echo $(eval echo $libexecdir))"
LVRESIZE_FS_HELPER_PATH="$LIBEXECDIR/lvresize_fs_helper"
AC_DEFINE_UNQUOTED(LVRESIZE_FS_HELPER_PATH, ["$LVRESIZE_FS_HELPER_PATH"], [Path to lvresize_fs_helper script.])
LVMPERSIST_PATH="$SBINDIR/lvmpersist"
AC_DEFINE_UNQUOTED(LVMPERSIST_PATH, ["$LVMPERSIST_PATH"], [Path to lvmpersist script.])
################################################################################
dnl -- dmeventd pidfile and executable path
AC_ARG_WITH(dmeventd-pidfile,
@@ -1938,6 +1996,7 @@ AC_SUBST(PYTHON3)
AC_SUBST(PYTHON3DIR)
AC_SUBST(RT_LIBS)
AC_SUBST(SBINDIR)
AC_SUBST(SD_NOTIFY_SUPPORT)
AC_SUBST(SELINUX_LIBS)
AC_SUBST(SELINUX_PC)
AC_SUBST(SELINUX_STATIC_LIBS)
@@ -2075,3 +2134,6 @@ AS_IF([test "$ODIRECT" != "yes"],
AS_IF([test "$BUILD_LVMDBUSD" = "yes" && test "$NOTIFYDBUS_SUPPORT" = "no"],
[AC_MSG_WARN([Building D-Bus support without D-Bus notifications!])])
AS_IF([test "$BUILD_LVMLOCKD" = "yes" && test "$SD_NOTIFY_SUPPORT" = "no"],
[AC_MSG_WARN([Building lvmlockd without sd-notify support may block!])])

View File

@@ -30,6 +30,8 @@
struct lv_segment;
struct logical_volume;
struct cmd_context;
struct profile;
struct lv_segment *first_seg(const struct logical_volume *lv)
{
@@ -57,7 +59,7 @@ struct logical_volume *origin_from_cow(const struct logical_volume *lv)
*/
/* simple_memccpy() from glibc */
void *memccpy(void *dest, const void *src, int c, size_t n)
void *memccpy(void *dest, const void *src, int c, unsigned long n)
{
const char *s = src;
char *d = dest;
@@ -90,9 +92,14 @@ void model_FD_ZERO(void *fdset)
/* Resent Coverity reports quite weird errors... */
int *__errno_location(void)
{
static int _i = 0;
return &_i;
}
const unsigned short **__ctype_b_loc (void)
{
static const unsigned short *_a[1] = { 0 };
return _a;
}

View File

@@ -197,7 +197,7 @@ int cluster_send(struct clog_request *rq)
iov.iov_base = rq;
iov.iov_len = sizeof(struct clog_request) + rq->u_rq.data_size;
rq->u.version[0] = xlate64(CLOG_TFR_VERSION);
rq->u.version[0] = htole64(CLOG_TFR_VERSION);
rq->u.version[1] = CLOG_TFR_VERSION;
r = clog_request_to_network(rq);

View File

@@ -52,19 +52,19 @@ static void v5_data_endian_switch(struct clog_request *rq, int to_network __attr
case DM_ULOG_GET_REGION_SIZE:
case DM_ULOG_GET_SYNC_COUNT:
pu64 = (uint64_t *)rq->u_rq.data;
*pu64 = xlate64(*pu64);
*pu64 = htole64(*pu64);
break;
case DM_ULOG_IS_CLEAN:
case DM_ULOG_IN_SYNC:
pi64 = (int64_t *)rq->u_rq.data;
*pi64 = xlate64(*pi64);
*pi64 = htole64(*pi64);
break;
case DM_ULOG_GET_RESYNC_WORK:
case DM_ULOG_IS_REMOTE_RECOVERING:
pi64 = (int64_t *)rq->u_rq.data;
pu64 = ((uint64_t *)rq->u_rq.data) + 1;
*pi64 = xlate64(*pi64);
*pu64 = xlate64(*pu64);
*pi64 = htole64(*pi64);
*pu64 = htole64(*pu64);
break;
default:
LOG_ERROR("Unknown request type, %u", rq_type);
@@ -94,7 +94,7 @@ static void v5_data_endian_switch(struct clog_request *rq, int to_network __attr
case DM_ULOG_IN_SYNC:
case DM_ULOG_IS_REMOTE_RECOVERING:
pu64 = (uint64_t *)rq->u_rq.data;
*pu64 = xlate64(*pu64);
*pu64 = htole64(*pu64);
break;
case DM_ULOG_MARK_REGION:
case DM_ULOG_CLEAR_REGION:
@@ -102,13 +102,13 @@ static void v5_data_endian_switch(struct clog_request *rq, int to_network __attr
pu64 = (uint64_t *)rq->u_rq.data;
for (i = 0; i < end; i++)
pu64[i] = xlate64(pu64[i]);
pu64[i] = htole64(pu64[i]);
break;
case DM_ULOG_SET_REGION_SYNC:
pu64 = (uint64_t *)rq->u_rq.data;
pi64 = ((int64_t *)rq->u_rq.data) + 1;
*pu64 = xlate64(*pu64);
*pi64 = xlate64(*pi64);
*pu64 = htole64(*pu64);
*pi64 = htole64(*pi64);
break;
default:
LOG_ERROR("Unknown request type, %u", rq_type);
@@ -124,15 +124,15 @@ static int v5_endian_to_network(struct clog_request *rq)
size = sizeof(*rq) + u_rq->data_size;
u_rq->error = xlate32(u_rq->error);
u_rq->seq = xlate32(u_rq->seq);
u_rq->error = htole32(u_rq->error);
u_rq->seq = htole32(u_rq->seq);
rq->originator = xlate32(rq->originator);
rq->originator = htole32(rq->originator);
v5_data_endian_switch(rq, 1);
u_rq->request_type = xlate32(u_rq->request_type);
u_rq->data_size = xlate32(u_rq->data_size);
u_rq->request_type = htole32(u_rq->request_type);
u_rq->data_size = htole32(u_rq->data_size);
return size;
}
@@ -142,7 +142,7 @@ int clog_request_to_network(struct clog_request *rq)
int r;
/* FIXME: Remove this safety check */
if (rq->u.version[0] != xlate64(rq->u.version[1])) {
if (rq->u.version[0] != htole64(rq->u.version[1])) {
LOG_ERROR("Programmer error: version[0] must be LE");
exit(EXIT_FAILURE);
}
@@ -165,12 +165,12 @@ static int v5_endian_from_network(struct clog_request *rq)
int size;
struct dm_ulog_request *u_rq = &rq->u_rq;
u_rq->error = xlate32(u_rq->error);
u_rq->seq = xlate32(u_rq->seq);
u_rq->request_type = xlate32(u_rq->request_type);
u_rq->data_size = xlate32(u_rq->data_size);
u_rq->error = htole32(u_rq->error);
u_rq->seq = htole32(u_rq->seq);
u_rq->request_type = htole32(u_rq->request_type);
u_rq->data_size = htole32(u_rq->data_size);
rq->originator = xlate32(rq->originator);
rq->originator = htole32(rq->originator);
size = sizeof(*rq) + u_rq->data_size;
@@ -182,7 +182,7 @@ static int v5_endian_from_network(struct clog_request *rq)
int clog_request_from_network(void *data, size_t data_len)
{
uint64_t *vp = data;
uint64_t version = xlate64(vp[0]);
uint64_t version = htole64(vp[0]);
struct clog_request *rq = data;
switch (version) {

View File

@@ -8,6 +8,8 @@
#ifndef _LVM_CLOG_COMPAT_H
#define _LVM_CLOG_COMPAT_H
#include <stddef.h>
/*
* The intermachine communication structure version are:
* 0: Unused
@@ -19,6 +21,8 @@
*/
#define CLOG_TFR_VERSION 5
struct clog_request;
int clog_request_to_network(struct clog_request *rq);
int clog_request_from_network(void *data, size_t data_len);

View File

@@ -380,8 +380,8 @@ static int _clog_ctr(char *uuid, uint64_t luid,
int disk_log;
char disk_path[PATH_MAX] = { 0 };
int unlink_path = 0;
long page_size;
int pages;
long ps;
size_t pages, page_size;
/* If core log request, then argv[0] will be region_size */
if (!strtoll(argv[0], &p, 0) || *p) {
@@ -488,14 +488,15 @@ static int _clog_ctr(char *uuid, uint64_t luid,
lc->sync_count = (log_sync == NOSYNC) ? region_count : 0;
if (disk_log) {
if ((page_size = sysconf(_SC_PAGESIZE)) < 0) {
if (((ps = sysconf(_SC_PAGESIZE)) <= 0) ||
(ps > (1 << 24))) {
LOG_ERROR("Unable to read pagesize: %s",
strerror(errno));
r = errno;
goto fail;
}
pages = *(lc->clean_bits) / page_size;
pages += *(lc->clean_bits) % page_size ? 1 : 0;
page_size = (size_t)ps;
pages = (*(lc->clean_bits) + page_size - 1) / page_size;
pages += 1; /* for header */
r = open(disk_path, O_RDWR | O_DIRECT);

View File

@@ -326,10 +326,11 @@ static int do_local_work(void *data __attribute__((unused)))
*
* Returns: 0 on success, -EXXX on failure
*/
int kernel_send(struct dm_ulog_request *u_rq)
int kernel_send(void *data)
{
int r;
uint16_t size;
struct dm_ulog_request *u_rq = data;
if (!u_rq)
return -EINVAL;
@@ -353,7 +354,7 @@ int kernel_send(struct dm_ulog_request *u_rq)
size = sizeof(struct dm_ulog_request);
}
r = kernel_send_helper(u_rq, size);
r = kernel_send_helper(data, size);
if (r)
LOG_ERROR("Failed to send msg to kernel.");

View File

@@ -12,9 +12,11 @@
#ifndef _LVM_CLOG_LOCAL_H
#define _LVM_CLOG_LOCAL_H
struct dm_ulog_request;
int init_local(void);
void cleanup_local(void);
int kernel_send(struct dm_ulog_request *rq);
int kernel_send(void *data);
#endif /* _LVM_CLOG_LOCAL_H */

View File

@@ -35,6 +35,7 @@
#include <fcntl.h> /* for musl libc */
#include <unistd.h>
#include <syslog.h>
#include <sys/utsname.h>
#ifdef __linux__
/*
@@ -92,6 +93,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;
/* Default grace period for thread cleanup 10 seconds */
#define DMEVENTD_DEFAULT_GRACE_PERIOD 10
static int _grace_period = DMEVENTD_DEFAULT_GRACE_PERIOD;
static int _systemd_activation = 0;
static int _foreground = 0;
static time_t _idle_since = 0;
@@ -209,7 +214,8 @@ struct message_data {
/* There are three states a thread can attain. */
enum {
DM_THREAD_REGISTERING, /* Registering, transitions to RUNNING */
DM_THREAD_RUNNING, /* Working on events, transitions to DONE */
DM_THREAD_RUNNING, /* Working on events, transitions to GRACE or DONE */
DM_THREAD_GRACE_PERIOD, /* Thread awaits reuse for a grace period */
DM_THREAD_DONE /* Terminated and cleanup is pending */
};
@@ -233,12 +239,15 @@ struct thread_status {
} device;
int processing; /* Set when event is being processed */
int status; /* See DM_THREAD_{REGISTERING,RUNNING,DONE} */
int status; /* See DM_THREAD_{REGISTERING,RUNNING,GRACE_PERIOD,DONE} */
int events; /* bitfield for event filter. */
int current_events; /* bitfield for occurred events. */
struct dm_task *wait_task;
int pending; /* Set when event filter change is pending */
int used; /* Count thread reusage (for debugging) */
pthread_cond_t grace_cond; /* Condition variable for grace period wait */
uint64_t inode; /* Device path inode of monitored volume */
time_t next_time;
uint32_t timeout;
struct dm_list timeout_list;
@@ -268,7 +277,7 @@ static void _free_dso_data(struct dso_data *data)
static struct dso_data *_alloc_dso_data(struct message_data *data)
{
struct dso_data *ret = (typeof(ret)) zalloc(sizeof(*ret));
struct dso_data *ret = (__typeof__(ret)) zalloc(sizeof(*ret));
if (!ret)
return_NULL;
@@ -395,11 +404,17 @@ static void _free_thread_status(struct thread_status *thread)
_lib_put(thread->dso_data);
if (thread->wait_task)
dm_task_destroy(thread->wait_task);
/* Clean up grace period condition variable */
pthread_cond_destroy(&thread->grace_cond);
free(thread->device.uuid);
free(thread->device.name);
free(thread);
}
static int _lock_mutex(void);
static int _unlock_mutex(void);
/* Note: events_field must not be 0, ensured by caller */
static struct thread_status *_alloc_thread_status(const struct message_data *data,
struct dso_data *dso_data)
@@ -427,6 +442,12 @@ static struct thread_status *_alloc_thread_status(const struct message_data *dat
if (!(thread->device.name = strdup(data->device_uuid)))
goto_out;
/* Initialize grace period condition variable */
if (pthread_cond_init(&thread->grace_cond, NULL)) {
log_error("Failed to initialize grace period condition variable.");
goto_out;
}
/* runs ioctl and may register lvm2 plugin */
thread->processing = 1;
thread->status = DM_THREAD_REGISTERING;
@@ -606,11 +627,14 @@ static int _fill_device_data(struct thread_status *ts)
if (!dm_task_run(dmt))
goto fail;
free(ts->device.name);
if (!(ts->device.name = strdup(dm_task_get_name(dmt))))
if (!dm_task_get_info(dmt, &dmi))
goto fail;
if (!dm_task_get_info(dmt, &dmi))
if (!dmi.exists)
goto fail;
free(ts->device.name);
if (!(ts->device.name = strdup(dm_task_get_name(dmt))))
goto fail;
ts->device.major = dmi.major;
@@ -626,9 +650,9 @@ fail:
static struct dm_task *_get_device_status(struct thread_status *ts)
{
struct dm_task *dmt = dm_task_create(DM_DEVICE_STATUS);
struct dm_task *dmt;
if (!dmt)
if (!(dmt = dm_task_create(DM_DEVICE_STATUS)))
return_NULL;
if (!dm_task_set_uuid(dmt, ts->device.uuid)) {
@@ -648,6 +672,60 @@ static struct dm_task *_get_device_status(struct thread_status *ts)
return dmt;
}
static uint64_t _get_device_inode(struct thread_status *ts)
{
static int _kernel_major = -1;
struct utsname uts;
struct stat buf;
char path[PATH_MAX];
/* Get kernel version to determine path format */
if (_kernel_major < 0) {
_kernel_major = 0;
if (uname(&uts))
log_sys_debug("uname", "");
else if (sscanf(uts.release, "%d", &_kernel_major) != 1)
log_debug("Cannot parse kernel version from %s.", uts.release);
}
if (_kernel_major >= 3) {
/* Use sysfs path with major:minor format for modern kernels */
if (dm_snprintf(path, sizeof(path), "%sdev/block/%d:%d",
dm_sysfs_dir(), ts->device.major, ts->device.minor) < 0)
return_0;
} else {
/* Use /dev/mapper/name device path for kernel version <3.
* Older kernels do not change inode numbers for devices!
* Relies on correct files in /dev/mapper directory.
*/
if (dm_snprintf(path, sizeof(path), "%s/%s",
dm_dir(), ts->device.name) < 0)
return_0;
}
if (stat(path, &buf) < 0) {
log_sys_debug("stat", path);
if (_kernel_major >= 3)
return 0;
/* Since monitoring is not synchronized with udev
* symlink may not exists, so also try /dev/dm-X */
if (dm_snprintf(path, sizeof(path), "%s/../dm-%d",
dm_dir(), ts->device.minor) < 0)
return_0;
if (stat(path, &buf) < 0) {
log_sys_debug("stat", path);
return 0;
}
}
log_debug("Device %s with inode %" PRIu64 " (kernel %d).",
path, (uint64_t) buf.st_ino, _kernel_major);
return (uint64_t) buf.st_ino;
}
/*
* Find an existing thread for a device.
*
@@ -664,6 +742,22 @@ static struct thread_status *_lookup_thread_status(struct message_data *data)
return NULL;
}
static struct thread_status *_lookup_grace_thread_status(struct message_data *data)
{
struct thread_status *thread;
dm_list_iterate_items(thread, &_thread_registry_unused)
if ((thread->status == DM_THREAD_GRACE_PERIOD) &&
!strcmp(data->device_uuid, thread->device.uuid) &&
!strcmp(data->dso_name, thread->dso_data->dso_name) &&
(thread->inode == _get_device_inode(thread))) {
DEBUGLOG("Found reusable thread %x in grace period.",(int)thread->thread);
return thread;
}
return NULL;
}
static int _get_status(struct message_data *message_data)
{
struct dm_event_daemon_message *msg = message_data->msg;
@@ -680,9 +774,15 @@ static int _get_status(struct message_data *message_data)
return -EINVAL;
_lock_mutex();
count = dm_list_size(&_thread_registry);
if (!(count = dm_list_size(&_thread_registry))) {
_unlock_mutex();
ret = 0; /* no monitored devices */
goto out;
}
buffers = alloca(sizeof(char*) * count);
dm_list_iterate_items(thread, &_thread_registry) {
/* coverity[overflow_sink] - only positive 'current' is used */
if ((current = dm_asprintf(buffers + i, "0:%d %s %s %u %" PRIu32 ";",
i, thread->dso_data->dso_name,
thread->device.uuid, thread->events,
@@ -691,6 +791,7 @@ static int _get_status(struct message_data *message_data)
goto out;
}
++i;
/* coverity[overflow] - only positive 'current' is used */
size += current; /* count with trailing '\0' */
}
_unlock_mutex();
@@ -785,7 +886,11 @@ static void *_timeout_thread(void *unused __attribute__((unused)))
if (thread->next_time <= curr_time) {
thread->next_time = curr_time + thread->timeout;
_lock_mutex();
if (thread->processing) {
if (thread->status != DM_THREAD_RUNNING) {
/* Skip wake up of non running thread (i.e. in grace period) */
log_debug("Skipping SIGALRM to non running Thr %x for timeout.",
(int) thread->thread);
} else if (thread->processing) {
/* Cannot signal processing monitoring thread */
log_debug("Skipping SIGALRM to processing Thr %x for timeout.",
(int) thread->thread);
@@ -804,8 +909,8 @@ static void *_timeout_thread(void *unused __attribute__((unused)))
timeout.tv_sec = thread->next_time;
}
pthread_cond_timedwait(&_timeout_cond, &_timeout_mutex,
&timeout);
(void) pthread_cond_timedwait(&_timeout_cond, &_timeout_mutex,
&timeout);
}
DEBUGLOG("Timeout thread finished.");
@@ -872,6 +977,43 @@ enum {
DM_WAIT_FATAL
};
/* Reset pending signal for a task/thread */
static int _reset_pending_signal(int signal)
{
sigset_t prev_mask, mask;
struct sigaction prev_act, act = { .sa_handler = SIG_IGN };
sigemptyset(&act.sa_mask);
sigemptyset(&prev_mask);
sigemptyset(&mask);
sigaddset(&mask, signal);
if (pthread_sigmask(SIG_SETMASK, &mask, &prev_mask) != 0) {
log_sys_error("pthread_sigmask", "ignore signal");
return 0; /* What better */
}
if (sigaction(signal, &act, &prev_act) < 0) {
log_sys_error("sigaction", "ignore signal");
return 0;
}
if (sigaction(signal, &prev_act, NULL) < 0) {
log_sys_error("sigaction", "restore signal");
return 0;
}
/* And also restore the process's original sigmask */
if (pthread_sigmask(SIG_SETMASK, &prev_mask, NULL) < 0) {
log_sys_error("pthread_sigmask", "restore signal");
return 0;
}
return 1;
}
/* Wait on a device until an event occurs. */
static int _event_wait(struct thread_status *thread)
{
@@ -894,6 +1036,9 @@ static int _event_wait(struct thread_status *thread)
}
if (dm_task_run(thread->wait_task)) {
/* Recheck device info whether is still exists */
if (!_fill_device_data(thread))
goto disappeared; /* device is gone... */
thread->current_events |= DM_EVENT_DEVICE_ERROR;
ret = DM_WAIT_INTR;
/* Update event_nr */
@@ -902,6 +1047,7 @@ static int _event_wait(struct thread_status *thread)
} else {
switch (dm_task_get_errno(thread->wait_task)) {
case ENXIO:
disappeared:
log_error("%s disappeared, detaching.",
thread->device.name);
ret = DM_WAIT_FATAL;
@@ -958,7 +1104,8 @@ static void _do_process_event(struct thread_status *thread)
if (!task)
log_error("Lost event in Thr %x.", (int)thread->thread);
else {
thread->dso_data->process_event(task, thread->current_events, &(thread->dso_private));
thread->dso_data->process_event(task, (enum dm_event_mask) thread->current_events,
&(thread->dso_private));
if (task != thread->wait_task)
dm_task_destroy(task);
}
@@ -970,6 +1117,12 @@ static void _thread_unused(struct thread_status *thread)
LINK(thread, &_thread_registry_unused);
}
static void _thread_used(struct thread_status *thread)
{
UNLINK_THREAD(thread);
LINK_THREAD(thread);
}
/* Thread cleanup handler to unregister device. */
static void _monitor_unregister(void *arg)
{
@@ -1006,32 +1159,11 @@ static void _monitor_unregister(void *arg)
kill(getpid(), SIGINT);
}
/* Device monitoring thread. */
static void *_monitor_thread(void *arg)
static int _monitor_events(struct thread_status *thread)
{
struct thread_status *thread = arg;
int ret;
int ret = 0;
sigset_t pendmask;
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
pthread_cleanup_push(_monitor_unregister, thread);
if (!_fill_device_data(thread)) {
log_error("Failed to fill device data for %s.", thread->device.uuid);
_lock_mutex();
goto out;
}
if (!_do_register_device(thread)) {
log_error("Failed to register device %s.", thread->device.name);
_lock_mutex();
goto out;
}
_lock_mutex();
thread->status = DM_THREAD_RUNNING;
thread->processing = 0;
/* Loop awaiting/analyzing device events. */
while (thread->events) {
@@ -1077,6 +1209,96 @@ static void *_monitor_thread(void *arg)
break;
}
}
return ret;
}
/* Thread awaits condition wake up for a grace period */
static void _monitor_grace_period_wait(struct thread_status *thread)
{
struct timespec grace_timeout = { .tv_sec = time(NULL) + _grace_period };
DEBUGLOG("Thread %x entering grace period for %d seconds.",
(int)thread->thread, _grace_period);
/* Wait on per-thread condition variable with global mutex */
while (!_exit_now && !thread->events &&
(ETIMEDOUT != pthread_cond_timedwait(&thread->grace_cond,
&_global_mutex, &grace_timeout)))
/* Waiting */;
DEBUGLOG("Thread %x wakeup grace period.", (int)thread->thread);
}
/* Device monitoring thread. */
static void *_monitor_thread(void *arg)
{
struct thread_status *thread = arg;
int ret;
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
pthread_cleanup_push(_monitor_unregister, thread);
if (!_fill_device_data(thread)) {
log_error("Failed to fill device data for %s.", thread->device.uuid);
_lock_mutex();
goto out;
}
/* Now with resolved major:minor store also device inode */
thread->inode = _get_device_inode(thread);
if (!_do_register_device(thread)) {
log_error("Failed to register device %s.", thread->device.name);
_lock_mutex();
goto out;
}
_lock_mutex();
/* Main monitoring loop with grace period support */
while (thread->events) {
DEBUGLOG("Monitoring %s with Thr %x (events: %x, used: %d).",
thread->device.name, (int)thread->thread,
thread->events, thread->used);
thread->status = DM_THREAD_RUNNING;
thread->processing = 0;
thread->used++;
ret = _monitor_events(thread);
/* No grace period when set to 0
* or there were left some processing events which is an error state
* or there is on going exit
* or there was fatal error while waiting for some event */
if (!_grace_period || thread->events || _exit_now || (ret == DM_WAIT_FATAL))
break;
/* Before restarting event loop reset any pending SIGALRM signal */
if (!_reset_pending_signal(SIGALRM)) {
stack;
break; /* Something is wrong... */
}
thread->current_events = 0;
thread->status = DM_THREAD_GRACE_PERIOD; /* No events - enter grace period */
_thread_unused(thread);
DEBUGLOG("Gracing %s with Thr %x (events: %x, used: %d).",
thread->device.name, (int)thread->thread,
thread->events, thread->used);
_monitor_grace_period_wait(thread);
_unlock_mutex();
pthread_mutex_lock(&_timeout_mutex);
thread->next_time = time(NULL) + thread->timeout;
pthread_mutex_unlock(&_timeout_mutex);
_lock_mutex();
_thread_used(thread);
}
out:
/* ';' fixes gcc compilation problem with older pthread macros
* "label at end of compound statement" */
@@ -1105,6 +1327,15 @@ static int _update_events(struct thread_status *thread, int events)
thread->events = events;
thread->pending = DM_EVENT_REGISTRATION_PENDING;
/* If needed, wake up thread waiting in grace period */
if ((events || _exit_now) && (thread->status == DM_THREAD_GRACE_PERIOD)) {
DEBUGLOG("Waking up thread %x waiting in grace period (events=%x).",
(int)thread->thread, events);
/* Signal per-thread condition variable while holding global mutex */
pthread_cond_signal(&thread->grace_cond);
return 0;
}
/* Only non-processing threads can be notified */
if (!thread->processing) {
DEBUGLOG("Sending SIGALRM to wakeup Thr %x.", (int)thread->thread);
@@ -1119,9 +1350,7 @@ static int _update_events(struct thread_status *thread, int events)
}
}
/* Threads with no events has to be moved to unused */
if (!thread->events)
_thread_unused(thread);
/* Threads with no events will enter grace period in their main loop */
return -ret;
}
@@ -1223,7 +1452,8 @@ static int _register_for_event(struct message_data *message_data)
_lock_mutex();
if ((thread = _lookup_thread_status(message_data))) {
if ((thread = _lookup_thread_status(message_data)) ||
(thread = _lookup_grace_thread_status(message_data))) {
/* OR event # into events bitfield. */
ret = _update_events(thread, (thread->events | message_data->events_field));
} else {
@@ -1337,11 +1567,13 @@ static int _get_registered_dev(struct message_data *message_data, int next)
/*
* If we didn't get a match, try the threads waiting to be deleted.
* Threads in grace period are skipped.
* FIXME Do something similar if 'next' is set.
*/
if (!hit && !next)
dm_list_iterate_items(thread, &_thread_registry_unused)
if (_want_registered_device(message_data->dso_name,
if ((thread->status != DM_THREAD_GRACE_PERIOD) &&
_want_registered_device(message_data->dso_name,
message_data->device_uuid, thread)) {
hit = thread;
goto reg;
@@ -1426,8 +1658,8 @@ static int _open_fifo(const char *path)
{
struct stat st;
int fd = -1;
/*
/*
* FIXME Explicitly verify the code's requirement that path is secure:
* - All parent directories owned by root without group/other write access unless sticky.
*/
@@ -1716,8 +1948,8 @@ static void _process_request(struct dm_event_fifos *fifos)
free(msg.data);
if (cmd == DM_EVENT_CMD_DIE) {
_exit_now = DM_SCHEDULED_EXIT; /* No grace period */
_unregister_all_threads();
_exit_now = DM_SCHEDULED_EXIT;
log_info("dmeventd exiting for restart.");
}
}
@@ -2250,16 +2482,18 @@ bad:
static void _usage(char *prog, FILE *file)
{
fprintf(file, "Usage:\n"
"%s [-d [-d [-d]]] [-e path] [-f] [-h] [i] [-l] [-R] [-V] [-?]\n\n"
"%s [-d [-d [-d]]] [-e path] [-g seconds] [-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"
" -g Grace period for thread cleanup (0-300 seconds, default: %d)\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"
" -V Show version of dmeventd\n\n", prog);
" -V Show version of dmeventd\n\n", prog,
_grace_period);
}
int main(int argc, char *argv[])
@@ -2279,7 +2513,7 @@ int main(int argc, char *argv[])
optopt = optind = opterr = 0;
optarg = (char*) "";
while ((opt = getopt(argc, argv, ":?e:fhiVdlR")) != EOF) {
while ((opt = getopt(argc, argv, ":?e:g:fhiVdlR")) != EOF) {
switch (opt) {
case 'h':
_usage(argv[0], stdout);
@@ -2300,6 +2534,13 @@ int main(int argc, char *argv[])
}
_exit_on=optarg;
break;
case 'g':
_grace_period = atoi(optarg);
if (_grace_period < 0 || _grace_period > 300) {
fprintf(stderr, "dmeventd: grace period must be between 0 and 300 seconds.\n");
return EXIT_FAILURE;
}
break;
case 'f':
_foreground++;
break;

View File

@@ -15,6 +15,8 @@
#ifndef __DMEVENTD_DOT_H__
#define __DMEVENTD_DOT_H__
#include <stdint.h>
/* FIXME This stuff must be configurable. */
#define DM_EVENT_FIFO_CLIENT DEFAULT_DM_RUN_DIR "/dmeventd-client"

View File

@@ -829,7 +829,7 @@ int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next)
}
dm_event_handler_set_dso(dmevh, reply_dso);
dm_event_handler_set_event_mask(dmevh, reply_mask);
dm_event_handler_set_event_mask(dmevh, (enum dm_event_mask) reply_mask);
free(reply_dso);
reply_dso = NULL;
@@ -988,7 +988,7 @@ void dm_event_log(const char *subsys, int level, const char *file,
fprintf(stream, "%28s:%4d %s", file, line, indent);
vfprintf(stream, _(format), ap);
fputc('\n', stream);
fflush(stream);
(void) fflush(stream);
}
pthread_mutex_unlock(&_log_mutex);

View File

@@ -29,20 +29,23 @@
*/
enum dm_event_mask {
DM_EVENT_SETTINGS_MASK = 0x0000FF,
DM_EVENT_SINGLE = 0x000001, /* Report multiple errors just once. */
DM_EVENT_MULTI = 0x000002, /* Report all of them. */
DM_EVENT_SETTINGS_MASK = 0x0000FF,
DM_EVENT_ERROR_MASK = 0x00FF00,
DM_EVENT_SECTOR_ERROR = 0x000100, /* Failure on a particular sector. */
DM_EVENT_DEVICE_ERROR = 0x000200, /* Device failure. */
DM_EVENT_PATH_ERROR = 0x000400, /* Failure on an io path. */
DM_EVENT_ADAPTOR_ERROR = 0x000800, /* Failure of a host adaptor. */
DM_EVENT_ERROR_MASK = 0x00FF00,
DM_EVENT_STATUS_MASK = 0xFF0000,
DM_EVENT_SYNC_STATUS = 0x010000, /* Mirror synchronization completed/failed. */
DM_EVENT_TIMEOUT = 0x020000, /* Timeout has occurred */
DM_EVENT_ERROR_AND_TIMEOUT_MASK = 0x02FF00,
DM_EVENT_STATUS_MASK = 0xFF0000,
DM_EVENT_REGISTRATION_PENDING = 0x1000000, /* Monitor thread is setting-up/shutting-down */
};
@@ -70,10 +73,10 @@ int dm_event_handler_set_dso(struct dm_event_handler *dmevh, const char *path);
int dm_event_handler_set_dmeventd_path(struct dm_event_handler *dmevh, const char *dmeventd_path);
/*
* Identify the device to monitor by exactly one of device_name, uuid or
* Identify the device to monitor by exactly one of dev_name, uuid or
* device number. String arguments are duplicated, see above.
*/
int dm_event_handler_set_dev_name(struct dm_event_handler *dmevh, const char *device_name);
int dm_event_handler_set_dev_name(struct dm_event_handler *dmevh, const char *dev_name);
int dm_event_handler_set_uuid(struct dm_event_handler *dmevh, const char *uuid);

View File

@@ -25,6 +25,8 @@
#ifndef _DMEVENTD_LVMWRAP_H
#define _DMEVENTD_LVMWRAP_H
#include <stddef.h>
struct dm_pool;
int dmeventd_lvm2_init(void);

View File

@@ -112,7 +112,7 @@ static int _remove_failed_devices(const char *cmd_lvconvert, const char *device)
}
void process_event(struct dm_task *dmt,
enum dm_event_mask event __attribute__((unused)),
enum dm_event_mask evmask __attribute__((unused)),
void **user)
{
struct dso_state *state = *user;

View File

@@ -84,7 +84,7 @@ static int _process_raid_event(struct dso_state *state, char *params, const char
*/
if (!state->warned && status->insync_regions < status->total_regions) {
state->warned = 1;
log_warn("WARNING: waiting for resynchronization to finish "
log_warn("WARNING: Waiting for resynchronization to finish "
"before initiating repair on RAID device %s.", device);
/* Fall through to allow lvconvert to run. */
}
@@ -114,7 +114,7 @@ out:
}
void process_event(struct dm_task *dmt,
enum dm_event_mask event __attribute__((unused)),
enum dm_event_mask evmask __attribute__((unused)),
void **user)
{
struct dso_state *state = *user;

View File

@@ -163,7 +163,7 @@ static void _umount(const char *device, int major, int minor)
}
void process_event(struct dm_task *dmt,
enum dm_event_mask event __attribute__((unused)),
enum dm_event_mask evmask __attribute__((unused)),
void **user)
{
struct dso_state *state = *user;

View File

@@ -45,10 +45,10 @@
struct dso_state {
struct dm_pool *mem;
int metadata_percent_check;
int metadata_percent;
int data_percent_check;
int data_percent;
dm_percent_t metadata_percent_check;
dm_percent_t metadata_percent;
dm_percent_t data_percent_check;
dm_percent_t data_percent;
uint64_t known_metadata_size;
uint64_t known_data_size;
unsigned fails;
@@ -155,7 +155,7 @@ static int _wait_for_pid(struct dso_state *state)
}
void process_event(struct dm_task *dmt,
enum dm_event_mask event __attribute__((unused)),
enum dm_event_mask evmask,
void **user)
{
const char *device = dm_task_get_name(dmt);
@@ -179,7 +179,7 @@ void process_event(struct dm_task *dmt,
return;
}
if (event & DM_EVENT_DEVICE_ERROR) {
if (evmask & DM_EVENT_DEVICE_ERROR) {
/* Error -> no need to check and do instant resize */
state->data_percent = state->metadata_percent = 0;
if (_use_policy(dmt, state))
@@ -223,10 +223,12 @@ void process_event(struct dm_task *dmt,
}
#if THIN_DEBUG
log_debug("Thin pool status " FMTu64 "/" FMTu64 " "
FMTu64 "/" FMTu64 ".",
log_debug("Thin pool status " FMTu64 "/" FMTu64 " (" FMTu64 ") "
FMTu64 "/" FMTu64 " (" FMTu64").",
tps->used_data_blocks, tps->total_data_blocks,
state->known_data_size,
tps->used_metadata_blocks, tps->total_metadata_blocks,
tps->used_data_blocks, tps->total_data_blocks);
state->known_metadata_size);
#endif
/* Thin pool size had changed. Clear the threshold. */
@@ -382,11 +384,10 @@ int register_device(const char *device,
} else /* Unsupported command format */
goto inval;
state->max_fails = 1;
state->pid = -1;
*user = state;
log_info("Monitoring thin pool %s.", device);
return 1;
inval:
log_error("Invalid command for monitoring: %s.", cmd_str);
@@ -430,7 +431,6 @@ int unregister_device(const char *device,
_restore_thread_signals(state);
dmeventd_lvm2_exit_with_pool(state);
log_info("No longer monitoring thin pool %s.", device);
return 1;
}

View File

@@ -146,7 +146,7 @@ static int _wait_for_pid(struct dso_state *state)
}
void process_event(struct dm_task *dmt,
enum dm_event_mask event __attribute__((unused)),
enum dm_event_mask evmask __attribute__((unused)),
void **user)
{
const char *device = dm_task_get_name(dmt);
@@ -169,7 +169,7 @@ void process_event(struct dm_task *dmt,
return;
}
if (event & DM_EVENT_DEVICE_ERROR) {
if (evmask & DM_EVENT_DEVICE_ERROR) {
#if VDO_DEBUG
log_debug("VDO event error.");
#endif

View File

@@ -160,6 +160,8 @@ def call_lvm(command, debug=False, line_cb=None,
# Check to see if process has terminated, None when running
if process.poll() is not None:
stdout_text += read_decoded(process.stdout)
stderr_text += read_decoded(process.stderr)
break
except IOError as ioe:
log_debug("call_lvm:" + str(ioe))
@@ -552,6 +554,14 @@ def lv_vdo_deduplication(lv_path, enable, dedup_options):
return call(cmd)
def lv_raid_repair(lv_path, new_pvs, repair_options):
cmd = ['lvconvert', '-y', '--repair']
cmd.append(lv_path)
cmd.extend(new_pvs)
cmd.extend(options_to_cli_args(repair_options))
return call(cmd)
def supports_json():
cmd = ['help']
rc, out, err = call(cmd)

View File

@@ -795,6 +795,39 @@ class Lv(LvCommon):
cache_options), cb, cbe)
cfg.worker_q.put(r)
@staticmethod
def _repair_raid_lv(lv_uuid, lv_name, new_pvs, repair_options):
# Make sure we have a dbus object representing it
pv_dests = []
dbo = LvCommon.validate_dbus_object(lv_uuid, lv_name)
# If we have PVs, verify them
if len(new_pvs):
for pv in new_pvs:
pv_dbus_obj = cfg.om.get_object_by_path(pv)
if not pv_dbus_obj:
raise dbus.exceptions.DBusException(
LV_INTERFACE,
'PV Destination (%s) not found' % pv)
pv_dests.append(pv_dbus_obj.lvm_id)
LvCommon.handle_execute(*cmdhandler.lv_raid_repair(
dbo.lvm_id, pv_dests, repair_options))
return "/"
@dbus.service.method(
dbus_interface=LV_INTERFACE,
in_signature='aoia{sv}',
out_signature='o',
async_callbacks=('cb', 'cbe'))
def RepairRaidLv(self, new_pvs, tmo, repair_options, cb, cbe):
r = RequestEntry(
tmo, Lv._repair_raid_lv,
(self.Uuid, self.lvm_id, new_pvs,
repair_options), cb, cbe, return_tuple=False)
cfg.worker_q.put(r)
# noinspection PyPep8Naming
@utils.dbus_property(VDO_POOL_INTERFACE, 'OperatingMode', 's')

View File

@@ -272,7 +272,7 @@ class ObjectManager(AutomatedProperties):
For a given lvm asset return the dbus object path registered for it.
This method first looks up by uuid and then by lvm_id. You
can search by just one by setting uuid == lvm_id (uuid or lvm_id).
If the object is not found and path_create is a not None, the
If the object is not found and path_create is not None, the
path_create function will be called to create a new object path and
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
@@ -295,7 +295,7 @@ class ObjectManager(AutomatedProperties):
if uuid == lvm_id:
path = self._id_lookup(lvm_id)
else:
# We have an uuid and a lvm_id we can do sanity checks to ensure
# We have a uuid and an lvm_id we can do sanity checks to ensure
# that they are consistent
# If a PV is missing its device path is '[unknown]' or some

View File

@@ -15,7 +15,7 @@ srcdir = @srcdir@
top_srcdir = @top_srcdir@
top_builddir = @top_builddir@
SOURCES = lvmlockd-core.c
SOURCES = lvmlockd-core.c lvmlockd-helper.c
SOURCES2 = lvmlockctl.c
TARGETS = lvmlockd lvmlockctl
@@ -50,8 +50,7 @@ INCLUDES += -I$(top_srcdir)/libdaemon/server
LDFLAGS += -L$(top_builddir)/libdaemon/server $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS)
LIBS += $(DAEMON_LIBS) $(PTHREAD_LIBS)
ifneq (,$(firstword $(LIBSYSTEMD_LIBS)))
DEFS += -DUSE_SD_NOTIFY
ifeq ("@SD_NOTIFY_SUPPORT@", "yes")
CFLAGS += $(LIBSYSTEMD_CFLAGS)
LIBS += $(LIBSYSTEMD_LIBS)
endif

View File

@@ -67,6 +67,160 @@ do { \
syslog(LOG_WARNING, fmt, ##args); \
} while (0)
/*
* Like sscanf, but requires buffer size to be specified
* for storing scanned strings, e.g.
*
* szscanf("%s", sizeof(buf), buf);
*
* Up to size-1 input bytes will be copied into buf.
* A null byte will be written to buf following the
* last copied byte. When nothing is copied to buf,
* no terminating null byte is written.
*
* If an input string matching %s is too long for the
* specified buffer size, the characters that would have
* been copied are ignored.
*
* Only recognizes: %d, %u, %s.
*/
static int szscanf(const char *input, const char *format, ...)
{
va_list args;
const char *fm;
const char *in;
int matched = 0;
int n;
va_start(args, format);
fm = format;
in = input;
while (*fm != '\0') {
/*
* format is a string containing:
* 1. %d matching int from input
* %u matching unsigned int from input
* %s matching non-whitespace characters from input
* 2. whitespace chars matching zero or more whitespace
* characters from input
* 3. non-whitespace chars matching the same input chars
*/
if (*fm == '%') {
/*
* case 1: %u, %d, or %s
*/
/* advance past '%' character, to look for 'u', 'd' or 's' */
fm++;
if (*fm == 'd') {
/*
* read an int (%d)
*/
int *dest = va_arg(args, int *);
if (sscanf(in, "%d%n", dest, &n) == 1) {
in += n;
matched++;
} else {
/* matching failure: no input int */
break;
}
} else if (*fm == 'u') {
/*
* read an unsigned int (%u)
*/
unsigned int *dest = va_arg(args, unsigned int *);
if (sscanf(in, "%u%n", dest, &n) == 1) {
in += n;
matched++;
} else {
/* matching failure: no input unsigned int */
break;
}
} else if (*fm == 's') {
/*
* read a string (%s) into dest buffer with dest_size
* copy up to dest_size-1 characters into dest buffer
* write null byte into dest buffer following the last
* character copied. When dest_size-1 bytes are copied,
* the null byte is written into the final byte of the
* dest buffer. input bytes that would have been copied
* but did not fit in the dest buffer are skipped.
*/
size_t dest_size = va_arg(args, size_t);
char *dest = va_arg(args, char *);
char *out = dest;
/* don't copy leading input whitespace to dest */
while (isspace((unsigned char)*in))
in++;
/* copy non-whitespace characters from input to dest */
n = 0;
while (*in != '\0' && !isspace((unsigned char)*in) && (n < (int)dest_size-1)) {
*out = *in;
out++;
in++;
n++;
}
if (n) {
dest[n] = '\0';
matched++;
} else {
/* matching failure: no input string chars */
break;
}
/* ignore input bytes that would have been copied but didn't fit */
while (*in != '\0' && !isspace((unsigned char)*in))
in++;
} else {
/* unsupported format specifier */
matched = -1;
break;
}
/* advance past 'd', 'u', or 's' character */
fm++;
} else if (isspace((unsigned char)*fm)) {
/*
* case 2: format whitespace skips zero or more input
* whitespace characters
*/
while (isspace((unsigned char)*in))
in++;
/* advance past whitespace character */
fm++;
} else if (*fm == *in) {
/*
* case 3: literal character match between format and input
*/
fm++;
in++;
} else {
/*
* matching failure: format and input don't match
*/
break;
}
}
va_end(args);
return matched;
}
#define MAX_LINE 512
/* copied from lvmlockd-internal.h */
@@ -97,8 +251,11 @@ static void save_client_info(char *line)
uint32_t client_id = 0;
char name[MAX_NAME+1] = { 0 };
(void) sscanf(line, "info=client pid=%u fd=%d pi=%d id=%u name=%s",
&pid, &fd, &pi, &client_id, name);
/* info=client pid=%u fd=%d pi=%d id=%u name=%s */
if (szscanf(line, "info=client pid=%u fd=%d pi=%d id=%u name=%s",
&pid, &fd, &pi, &client_id, sizeof(name), name) < 0)
return;
clients[num_clients].client_id = client_id;
clients[num_clients].pid = pid;
@@ -126,20 +283,26 @@ static void format_info_ls(char *line)
char ls_name[MAX_NAME+1] = { 0 };
char vg_name[MAX_NAME+1] = { 0 };
char vg_uuid[MAX_NAME+1] = { 0 };
char vg_sysid[MAX_NAME+1] = { 0 };
char lock_args[MAX_ARGS+1] = { 0 };
char lock_type[MAX_NAME+1] = { 0 };
char vg_args[MAX_ARGS+1] = { 0 };
char lm_type[MAX_NAME+1] = { 0 };
(void) sscanf(line, "info=ls ls_name=%s vg_name=%s vg_uuid=%s vg_sysid=%s vg_args=%s lm_type=%s",
ls_name, vg_name, vg_uuid, vg_sysid, lock_args, lock_type);
/* info=ls ls_name=%s vg_name=%s vg_uuid=%s vg_args=%s lm_type=%s */
if (szscanf(line, "info=ls ls_name=%s vg_name=%s vg_uuid=%s vg_args=%s lm_type=%s",
sizeof(ls_name), ls_name,
sizeof(vg_name), vg_name,
sizeof(vg_uuid), vg_uuid,
sizeof(vg_args), vg_args,
sizeof(lm_type), lm_type) < 0)
return;
if (!first_ls)
printf("\n");
first_ls = 0;
printf("VG %s lock_type=%s %s\n", vg_name, lock_type, vg_uuid);
printf("VG %s lock_type=%s %s\n", vg_name, lm_type, vg_uuid);
printf("LS %s %s\n", lock_type, ls_name);
printf("LS %s %s\n", lm_type, ls_name);
}
static void format_info_ls_action(char *line)
@@ -151,8 +314,14 @@ static void format_info_ls_action(char *line)
uint32_t pid = 0;
char cl_name[MAX_NAME+1] = { 0 };
(void) sscanf(line, "info=ls_action client_id=%u %s %s op=%s",
&client_id, flags, version, op);
/* info=ls_action client_id=%u flags=%s version=%u op=%s rt=%s mode=%s lm_type=%s result=%d lm_rv=%d */
if (szscanf(line, "info=ls_action client_id=%u flags=%s version=%s op=%s",
&client_id,
sizeof(flags), flags,
sizeof(version), version,
sizeof(op), op) < 0)
return;
find_client_info(client_id, &pid, cl_name);
@@ -164,11 +333,18 @@ static void format_info_r(char *line, char *r_name_out, char *r_type_out)
char r_name[MAX_NAME+1] = { 0 };
char r_type[4] = { 0 };
char mode[4] = { 0 };
char sh_count[MAX_NAME+1] = { 0 };
uint32_t ver = 0;
int sh_count = 0;
unsigned int ver = 0;
(void) sscanf(line, "info=r name=%s type=%s mode=%s %s version=%u",
r_name, r_type, mode, sh_count, &ver);
/* info=r name=%s type=%s mode=%s sh_count=%d version=%s */
if (szscanf(line, "info=r name=%s type=%s mode=%s sh_count=%d version=%u",
sizeof(r_name), r_name,
sizeof(r_type), r_type,
sizeof(mode), mode,
&sh_count,
&ver) < 0)
return;
strcpy(r_name_out, r_name);
strcpy(r_type_out, r_type);
@@ -193,8 +369,8 @@ static void format_info_r(char *line, char *r_name_out, char *r_type_out)
static void format_info_lk(char *line, char *r_name, char *r_type)
{
char mode[4] = { 0 };
uint32_t ver = 0;
char flags[MAX_NAME+1] = { 0 };
uint32_t ver = 0;
uint32_t client_id = 0;
uint32_t pid = 0;
char cl_name[MAX_NAME+1] = { 0 };
@@ -205,8 +381,14 @@ static void format_info_lk(char *line, char *r_name, char *r_type)
return;
}
(void) sscanf(line, "info=lk mode=%s version=%u %s client_id=%u",
mode, &ver, flags, &client_id);
/* info=lk mode=%s version=%s flags=%s client_id=%u */
if (szscanf(line, "info=lk mode=%s version=%u flags=%s client_id=%u",
sizeof(mode), mode,
&ver,
sizeof(flags), flags,
&client_id) < 0)
return;
find_client_info(client_id, &pid, cl_name);
@@ -229,9 +411,9 @@ static void format_info_r_action(char *line, char *r_name, char *r_type)
char op[MAX_NAME+1] = { 0 };
char rt[4] = { 0 };
char mode[4] = { 0 };
char lm[MAX_NAME+1] = { 0 };
char result[MAX_NAME+1] = { 0 };
char lm_rv[MAX_NAME+1] = { 0 };
char lm_type[MAX_NAME+1] = { 0 };
int result = 0;
int lm_rv = 0;
uint32_t pid = 0;
char cl_name[MAX_NAME+1] = { 0 };
@@ -241,8 +423,19 @@ static void format_info_r_action(char *line, char *r_name, char *r_type)
return;
}
(void) sscanf(line, "info=r_action client_id=%u %s %s op=%s rt=%s mode=%s %s %s %s",
&client_id, flags, version, op, rt, mode, lm, result, lm_rv);
/* info=r_action client_id=%u flags=%s version=%s op=%s rt=%s mode=%s lm_type=%s result=%d lm_rv=%d */
if (szscanf(line, "info=r_action client_id=%u flags=%s version=%s op=%s rt=%s mode=%s lm_type=%s result=%d lm_rv=%d",
&client_id,
sizeof(flags), flags,
sizeof(version), version,
sizeof(op), op,
sizeof(rt), rt,
sizeof(mode), mode,
sizeof(lm_type), lm_type,
&result,
&lm_rv) < 0)
return;
find_client_info(client_id, &pid, cl_name);

View File

@@ -57,5 +57,14 @@ static inline void lvmlockd_close(daemon_handle h)
#define EORPHAN 222
#define EADOPT_NONE 223
#define EADOPT_RETRY 224
#define EIOTIMEOUT 225
#define ELOCKREPAIR 226
#define LOCKARGS_VERSION 0x00000001 /* meta only */
#define LOCKARGS_LVMLOCK 0x00000002 /* meta only */
#define LOCKARGS_TIMEOUT 0x00000004 /* user only */
#define LOCKARGS_NOTIMEOUT 0x00000008 /* meta or user */
#define LOCKARGS_PERSIST 0x00000010 /* meta or user */
#define LOCKARGS_NOPERSIST 0x00000020 /* user only */
#endif /* _LVM_LVMLOCKD_CLIENT_H */

File diff suppressed because it is too large Load Diff

View File

@@ -13,7 +13,7 @@
#include "tools/tool.h"
#include "daemon-server.h"
#include "libdaemon/server/daemon-server.h"
#include "lib/mm/xlate.h"
#include "lvmlockd-internal.h"
@@ -31,7 +31,6 @@
#include <errno.h>
#include <endian.h>
#include <fcntl.h>
#include <byteswap.h>
#include <syslog.h>
#include <dirent.h>
@@ -77,7 +76,7 @@ static int check_args_version(char *vg_args)
unsigned int major = 0;
int rv;
rv = version_from_args(vg_args, &major, NULL, NULL);
rv = lockd_lockargs_get_version(vg_args, &major, NULL, NULL);
if (rv < 0) {
log_error("check_args_version %s error %d", vg_args, rv);
return rv;
@@ -169,8 +168,10 @@ int lm_prepare_lockspace_dlm(struct lockspace *ls)
struct lm_dlm *lmd;
int rv;
if (daemon_test)
if (daemon_test) {
log_debug("lm_prepare_lockspace_dlm test");
goto skip_args;
}
memset(sys_clustername, 0, sizeof(sys_clustername));
memset(arg_clustername, 0, sizeof(arg_clustername));
@@ -361,7 +362,7 @@ int lm_rem_lockspace_dlm(struct lockspace *ls, int free_vg)
return 0;
}
static int lm_add_resource_dlm(struct lockspace *ls, struct resource *r, int with_lock_nl)
int lm_add_resource_dlm(struct lockspace *ls, struct resource *r, int with_lock_nl)
{
struct lm_dlm *lmd = (struct lm_dlm *)ls->lm_data;
struct rd_dlm *rdd = (struct rd_dlm *)r->lm_data;
@@ -582,9 +583,9 @@ int lm_lock_dlm(struct lockspace *ls, struct resource *r, int ld_mode,
if (daemon_test) {
if (rdd->vb) {
vb_out->version = le16_to_cpu(rdd->vb->version);
vb_out->flags = le16_to_cpu(rdd->vb->flags);
vb_out->r_version = le32_to_cpu(rdd->vb->r_version);
vb_out->version = le16toh(rdd->vb->version);
vb_out->flags = le16toh(rdd->vb->flags);
vb_out->r_version = le32toh(rdd->vb->r_version);
}
return 0;
}
@@ -636,9 +637,9 @@ lockrv:
memcpy(&vb, lksb->sb_lvbptr, sizeof(struct val_blk));
memcpy(rdd->vb, &vb, sizeof(vb));
vb_out->version = le16_to_cpu(vb.version);
vb_out->flags = le16_to_cpu(vb.flags);
vb_out->r_version = le32_to_cpu(vb.r_version);
vb_out->version = le16toh(vb.version);
vb_out->flags = le16toh(vb.flags);
vb_out->r_version = le32toh(vb.r_version);
}
out:
return 0;
@@ -663,9 +664,9 @@ int lm_convert_dlm(struct lockspace *ls, struct resource *r,
if (rdd->vb && r_version && (r->mode == LD_LK_EX)) {
if (!rdd->vb->version) {
/* first time vb has been written */
rdd->vb->version = cpu_to_le16(VAL_BLK_VERSION);
rdd->vb->version = htole16(VAL_BLK_VERSION);
}
rdd->vb->r_version = cpu_to_le32(r_version);
rdd->vb->r_version = htole32(r_version);
memcpy(lksb->sb_lvbptr, rdd->vb, sizeof(struct val_blk));
log_debug("%s:%s convert_dlm set r_version %u",
@@ -722,17 +723,17 @@ int lm_unlock_dlm(struct lockspace *ls, struct resource *r,
memcpy(&vb_next, rdd->vb, sizeof(struct val_blk));
if (!vb_prev.version) {
vb_next.version = cpu_to_le16(VAL_BLK_VERSION);
vb_next.version = htole16(VAL_BLK_VERSION);
new_vb = 1;
}
if ((lmu_flags & LMUF_FREE_VG) && (r->type == LD_RT_VG)) {
vb_next.flags = cpu_to_le16(VBF_REMOVED);
vb_next.flags = htole16(VBF_REMOVED);
new_vb = 1;
}
if (r_version) {
vb_next.r_version = cpu_to_le32(r_version);
vb_next.r_version = htole32(r_version);
new_vb = 1;
}
@@ -742,12 +743,12 @@ int lm_unlock_dlm(struct lockspace *ls, struct resource *r,
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),
le32_to_cpu(vb_prev.r_version),
le16_to_cpu(vb_next.version),
le16_to_cpu(vb_next.flags),
le32_to_cpu(vb_next.r_version));
le16toh(vb_prev.version),
le16toh(vb_prev.flags),
le32toh(vb_prev.r_version),
le16toh(vb_next.version),
le16toh(vb_next.flags),
le32toh(vb_next.r_version));
} else {
log_debug("%s:%s unlock_dlm vb unchanged", ls->name, r->name);
}
@@ -797,6 +798,14 @@ int lm_unlock_dlm(struct lockspace *ls, struct resource *r,
* the stale lockspaces on the others eventually.)
*/
/*
* On error, returns < 0
*
* On success:
* If other hosts are found, returns the number.
* If no other hosts are found (only ourself), returns 0.
*/
int lm_hosts_dlm(struct lockspace *ls, int notify)
{
char ls_nodes_path[PATH_MAX];

View File

@@ -0,0 +1,264 @@
/*
* Copyright 2025 Red Hat, Inc.
*
* 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 General Public License v2 or (at your option) any later version.
*/
#include <inttypes.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stddef.h>
#include <poll.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <limits.h>
#include <time.h>
#include <stdarg.h>
#include <signal.h>
#include <ctype.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/prctl.h>
#include <grp.h>
#include <syslog.h>
#include "lvmlockd-internal.h"
struct list_head commands; /* helper_msg_list entries */
static int _log_stderr;
#define log_helper(fmt, args...) \
do { \
if (_log_stderr) \
fprintf(stderr, fmt "\n", ##args); \
} while (0)
static void _save_command(struct helper_msg *msg)
{
struct helper_msg_list *ml;
ml = malloc(sizeof(struct helper_msg_list));
if (!ml)
return;
memcpy(&ml->msg, msg, sizeof(struct helper_msg));
list_add_tail(&ml->list, &commands);
}
static struct helper_msg_list *_get_command(int pid)
{
struct helper_msg_list *ml;
list_for_each_entry(ml, &commands, list) {
if (ml->msg.pid == pid)
return ml;
}
return NULL;
}
static int read_msg(int fd, struct helper_msg *msg)
{
int rv;
retry:
rv = read(fd, msg, sizeof(struct helper_msg));
if (rv == -1 && errno == EINTR)
goto retry;
if (rv != sizeof(struct helper_msg))
return -1;
return 0;
}
static void exec_command(char *cmd_str)
{
char arg[ONE_ARG_LEN];
char *av[MAX_AV_COUNT + 1]; /* +1 for NULL */
int av_count = 0;
int i, arg_len, cmd_len;
for (i = 0; i < MAX_AV_COUNT + 1; i++)
av[i] = NULL;
if (!cmd_str[0])
return;
/* this should already be done, but make sure */
cmd_str[RUN_COMMAND_LEN - 1] = '\0';
memset(&arg, 0, sizeof(arg));
arg_len = 0;
cmd_len = strlen(cmd_str);
for (i = 0; i < cmd_len; i++) {
if (!cmd_str[i])
break;
if (av_count == MAX_AV_COUNT)
break;
if (cmd_str[i] == '\\') {
if (i == (cmd_len - 1))
break;
i++;
if (cmd_str[i] == '\\') {
arg[arg_len++] = cmd_str[i];
continue;
}
if (isspace(cmd_str[i])) {
arg[arg_len++] = cmd_str[i];
continue;
} else {
break;
}
}
if (isalnum(cmd_str[i]) || ispunct(cmd_str[i])) {
arg[arg_len++] = cmd_str[i];
} else if (isspace(cmd_str[i])) {
if (arg_len)
av[av_count++] = strdup(arg);
memset(arg, 0, sizeof(arg));
arg_len = 0;
} else {
break;
}
}
if ((av_count < MAX_AV_COUNT) && arg_len) {
av[av_count++] = strdup(arg);
}
execvp(av[0], av);
}
static int send_result(struct helper_msg *msg, int fd)
{
int rv;
rv = write(fd, msg, sizeof(struct helper_msg));
if (rv == sizeof(struct helper_msg))
return 0;
return -1;
}
#define IDLE_TIMEOUT_MS (30 * 1000)
#define ACTIVE_TIMEOUT_MS 500
__attribute__((noreturn)) void helper_main(int in_fd, int out_fd, int log_stderr)
{
struct pollfd pollfd;
struct helper_msg msg;
struct helper_msg_list *ml;
siginfo_t info;
unsigned int fork_count = 0;
unsigned int done_count = 0;
int timeout = IDLE_TIMEOUT_MS;
int rv, pid;
INIT_LIST_HEAD(&commands);
_log_stderr = log_stderr;
rv = setgroups(0, NULL);
if (rv < 0)
log_helper("error clearing helper groups errno %i", errno);
memset(&pollfd, 0, sizeof(pollfd));
pollfd.fd = in_fd;
pollfd.events = POLLIN;
openlog("lvmlockd-helper", LOG_CONS | LOG_PID, LOG_LOCAL4);
while (1) {
rv = poll(&pollfd, 1, timeout);
if (rv == -1 && errno == EINTR)
continue;
if (rv < 0)
exit(0);
if (pollfd.revents & POLLIN) {
memset(&msg, 0, sizeof(msg));
rv = read_msg(in_fd, &msg);
if (rv)
continue;
if (msg.type == HELPER_COMMAND) {
pid = fork();
if (!pid) {
exec_command(msg.command);
exit(1);
}
msg.pid = pid;
_save_command(&msg);
fork_count++;
}
}
if (pollfd.revents & (POLLERR | POLLHUP | POLLNVAL))
exit(0);
/* collect child exits until no more children exist (ECHILD)
or none are ready (WNOHANG) */
while (1) {
memset(&info, 0, sizeof(info));
rv = waitid(P_ALL, 0, &info, WEXITED | WNOHANG);
if ((rv < 0) && (errno == ECHILD)) {
/*
log_helper("helper no children exist fork_count %d done_count %d", fork_count, done_count);
*/
timeout = IDLE_TIMEOUT_MS;
}
else if (!rv && !info.si_pid) {
log_helper("helper no children ready fork_count %d done_count %d", fork_count, done_count);
timeout = ACTIVE_TIMEOUT_MS;
}
else if (!rv && info.si_pid) {
done_count++;
if (!(ml = _get_command(info.si_pid))) {
log_helper("command for pid %d result %d not found",
info.si_pid, info.si_status);
continue;
}
log_helper("command for pid %d result %d done", info.si_pid, info.si_status);
ml->msg.type = HELPER_COMMAND_RESULT;
ml->msg.result = info.si_status;
send_result(&ml->msg, out_fd);
list_del(&ml->list);
free(ml);
continue;
}
else {
log_helper("helper waitid rv %d errno %d fork_count %d done_count %d",
rv, errno, fork_count, done_count);
}
break;
}
}
}

View File

@@ -13,7 +13,7 @@
#include "tools/tool.h"
#include "daemon-server.h"
#include "libdaemon/server/daemon-server.h"
#include "lib/mm/xlate.h"
#include "lvmlockd-internal.h"
@@ -490,7 +490,7 @@ out:
return rv;
}
static int lm_add_resource_idm(struct lockspace *ls, struct resource *r)
int lm_add_resource_idm(struct lockspace *ls, struct resource *r)
{
struct rd_idm *rdi = (struct rd_idm *)r->lm_data;
@@ -556,9 +556,9 @@ int lm_lock_idm(struct lockspace *ls, struct resource *r, int ld_mode,
if (daemon_test) {
if (rdi->vb) {
vb_out->version = le16_to_cpu(rdi->vb->version);
vb_out->flags = le16_to_cpu(rdi->vb->flags);
vb_out->r_version = le32_to_cpu(rdi->vb->r_version);
vb_out->version = le16toh(rdi->vb->version);
vb_out->flags = le16toh(rdi->vb->flags);
vb_out->r_version = le32toh(rdi->vb->r_version);
}
return 0;
}

View File

@@ -13,6 +13,9 @@
#include "base/memory/container_of.h"
#include <stdint.h>
#include <pthread.h>
#define MAX_NAME 64
#define MAX_ARGS 64
@@ -59,6 +62,11 @@ enum {
LD_OP_BUSY,
LD_OP_QUERY_LOCK,
LD_OP_REFRESH_LV,
LD_OP_VG_STATUS,
LD_OP_FENCE,
LD_OP_FENCE_RESULT,
LD_OP_SETLOCKARGS_BEFORE,
LD_OP_SETLOCKARGS_FINAL,
};
/* resource types */
@@ -113,6 +121,9 @@ struct client {
#define LD_AF_LV_UNLOCK 0x00080000
#define LD_AF_SH_EXISTS 0x00100000
#define LD_AF_ADOPT_ONLY 0x00200000 /* adopt orphan or fail */
#define LD_AF_NODELAY 0x00400000
#define LD_AF_REPAIR 0x00800000
#define LD_AF_NO_TIMEOUT 0x01000000
/*
* Number of times to repeat a lock request after
@@ -126,12 +137,52 @@ struct pvs {
int num;
};
#define RUN_COMMAND_LEN 1024
#define MAX_AV_COUNT 32
#define ONE_ARG_LEN 256
/* helper_msg types */
#define HELPER_COMMAND 0x1
#define HELPER_COMMAND_RESULT 0x2
struct helper_msg {
uint8_t type;
uint8_t act;
uint16_t unused1;
uint32_t msg_id;
int pid;
int result;
char ls_name[MAX_NAME+1];
uint8_t unused2;
uint16_t unused3;
char command[RUN_COMMAND_LEN];
};
struct helper_msg_list {
struct helper_msg msg;
struct list_head list;
};
#define OWNER_NAME_SIZE 64
#define OWNER_STATE_SIZE 32
struct owner {
uint32_t host_id;
uint32_t generation;
uint32_t timestamp;
char state[OWNER_STATE_SIZE];
char name[OWNER_NAME_SIZE];
};
struct action {
struct list_head list;
uint32_t client_id;
uint32_t flags; /* LD_AF_ */
uint32_t msg_id;
uint32_t version;
uint64_t host_id;
uint32_t host_id;
uint64_t ourkey;
uint64_t remkey;
uint64_t lv_size_bytes;
int8_t op; /* operation type LD_OP_ */
int8_t rt; /* resource type LD_RT_ */
@@ -149,7 +200,8 @@ struct action {
char lv_uuid[MAX_NAME+1];
char vg_args[MAX_ARGS+1];
char lv_args[MAX_ARGS+1];
char vg_sysid[MAX_NAME+1];
char other_args[MAX_ARGS+1];
struct owner owner;
struct pvs pvs; /* PV list for idm */
};
@@ -162,12 +214,14 @@ struct resource {
unsigned int sh_count; /* number of sh locks on locks list */
uint32_t version;
uint32_t last_client_id; /* last client_id to lock or unlock resource */
uint32_t dispose_client_id; /* client_id disposing of resource struct */
unsigned int lm_init : 1; /* lm_data is initialized */
unsigned int adopt : 1; /* temp flag in remove_inactive_lvs */
unsigned int version_zero_valid : 1;
unsigned int use_vb : 1;
struct list_head locks;
struct list_head actions;
struct list_head fence_wait_actions;
char lv_args[MAX_ARGS+1];
char lm_data[]; /* lock manager specific data */
};
@@ -188,10 +242,12 @@ struct lockspace {
char vg_name[MAX_NAME+1];
char vg_uuid[64];
char vg_args[MAX_ARGS+1]; /* lock manager specific args */
char vg_sysid[MAX_NAME+1];
int8_t lm_type; /* lock manager: LM_DLM, LM_SANLOCK */
void *lm_data;
uint64_t host_id;
uint32_t lock_args_flags;
uint32_t host_id;
uint64_t generation;
uint64_t ourkey;
uint64_t free_lock_offset; /* for sanlock, start search for free lock here */
struct pvs pvs; /* for idm: PV list */
@@ -206,12 +262,14 @@ struct lockspace {
unsigned int thread_done : 1;
unsigned int sanlock_gl_enabled: 1;
unsigned int sanlock_gl_dup: 1;
unsigned int free_vg: 1;
unsigned int kill_vg: 1;
unsigned int drop_vg: 1;
unsigned int fence_pr: 1;
unsigned int no_timeout: 1;
struct list_head actions; /* new client actions */
struct list_head resources; /* resource/lock state for gl/vg/lv */
struct list_head dispose; /* resources to free */
struct list_head fence_history; /* internally created actions for fencing */
};
/* val_blk version */
@@ -278,15 +336,15 @@ static inline int list_empty(const struct list_head *head)
list_entry((ptr)->next, type, member)
#define list_for_each_entry(pos, head, member) \
for (pos = list_entry((head)->next, typeof(*pos), member); \
for (pos = list_entry((head)->next, __typeof__(*pos), member); \
&pos->member != (head); \
pos = list_entry(pos->member.next, typeof(*pos), member))
pos = list_entry(pos->member.next, __typeof__(*pos), member))
#define list_for_each_entry_safe(pos, n, head, member) \
for (pos = list_entry((head)->next, typeof(*pos), member), \
n = list_entry(pos->member.next, typeof(*pos), member); \
for (pos = list_entry((head)->next, __typeof__(*pos), member), \
n = list_entry(pos->member.next, __typeof__(*pos), member); \
&pos->member != (head); \
pos = n, n = list_entry(n->member.next, typeof(*n), member))
pos = n, n = list_entry(n->member.next, __typeof__(*n), member))
/* to improve readability */
@@ -370,7 +428,9 @@ void log_level(int level, const char *fmt, ...) __attribute__((format(printf, 2
struct lockspace *alloc_lockspace(void);
int lockspaces_empty(void);
int last_string_from_args(char *args_in, char *last);
int version_from_args(char *args, unsigned int *major, unsigned int *minor, unsigned int *patch);
void helper_main(int in_fd, int out_fd, int log_stderr);
int lockd_lockargs_get_user_flags(const char *str, uint32_t *flags);
int lockd_lockargs_get_version(char *str, unsigned int *major, unsigned int *minor, unsigned int *patch);
static inline const char *mode_str(int x)
{
@@ -397,6 +457,7 @@ int lm_prepare_lockspace_dlm(struct lockspace *ls);
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_add_resource_dlm(struct lockspace *ls, struct resource *r, int with_lock_nl);
int lm_lock_dlm(struct lockspace *ls, struct resource *r, int ld_mode,
struct val_blk *vb_out, int adopt_only, int adopt_ok);
int lm_convert_dlm(struct lockspace *ls, struct resource *r,
@@ -420,69 +481,102 @@ static inline int lm_support_dlm(void)
static inline int lm_init_vg_dlm(char *ls_name, char *vg_name, uint32_t flags, char *vg_args)
{
if (daemon_test)
return 0;
return -1;
}
static inline int lm_prepare_lockspace_dlm(struct lockspace *ls)
{
if (daemon_test)
return 0;
return -1;
}
static inline int lm_add_lockspace_dlm(struct lockspace *ls, int adopt_only, int adopt_ok)
{
if (daemon_test)
return 0;
return -1;
}
static inline int lm_purge_locks_dlm(struct lockspace *ls)
{
if (daemon_test)
return 0;
return -1;
}
static inline int lm_rem_lockspace_dlm(struct lockspace *ls, int free_vg)
{
if (daemon_test)
return 0;
return -1;
}
static inline int lm_add_resource_dlm(struct lockspace *ls, struct resource *r, int with_lock_nl)
{
if (daemon_test)
return 0;
return -1;
}
static inline int lm_lock_dlm(struct lockspace *ls, struct resource *r, int ld_mode,
struct val_blk *vb_out, int adopt_only, int adopt_ok)
{
if (daemon_test)
return 0;
return -1;
}
static inline int lm_convert_dlm(struct lockspace *ls, struct resource *r,
int ld_mode, uint32_t r_version)
{
if (daemon_test)
return 0;
return -1;
}
static inline int lm_unlock_dlm(struct lockspace *ls, struct resource *r,
uint32_t r_version, uint32_t lmu_flags)
{
if (daemon_test)
return 0;
return -1;
}
static inline int lm_rem_resource_dlm(struct lockspace *ls, struct resource *r)
{
if (daemon_test)
return 0;
return -1;
}
static inline int lm_get_lockspaces_dlm(struct list_head *ls_rejoin)
{
if (daemon_test)
return 0;
return -1;
}
static inline int lm_data_size_dlm(void)
{
if (daemon_test)
return 0;
return -1;
}
static inline int lm_is_running_dlm(void)
{
if (daemon_test)
return 1;
return 0;
}
static inline int lm_support_dlm(void)
{
if (daemon_test)
return 1;
return 0;
}
@@ -505,16 +599,17 @@ 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 opt_align_mb);
int lm_init_lv_sanlock(struct lockspace *ls, char *lv_name, char *vg_args, char *lv_args);
int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_args, int opt_align_mb, char *other_args);
int lm_init_lv_sanlock(struct lockspace *ls, char *ls_name, char *vg_name, char *lv_name, char *vg_args, char *lv_args, char *prev_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_only, int adopt_ok);
int lm_prepare_lockspace_sanlock(struct lockspace *ls, uint64_t *prev_generation, int repair);
int lm_add_lockspace_sanlock(struct lockspace *ls, int adopt_only, int adopt_ok, int nodelay);
int lm_rem_lockspace_sanlock(struct lockspace *ls, int free_vg);
int lm_add_resource_sanlock(struct lockspace *ls, struct resource *r);
int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode,
struct val_blk *vb_out, int *retry,
int adopt_only, int adopt_ok);
struct val_blk *vb_out, int *retry, struct owner *owner,
int adopt_only, int adopt_ok, int repair);
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,
@@ -528,6 +623,10 @@ 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 lv_size_bytes);
int lm_vg_status_sanlock(struct lockspace *ls, struct action *act);
void lm_set_host_dead_sanlock(struct lockspace *ls, struct owner *owner);
int lm_setlockargs_supported_sanlock(struct lockspace *ls, struct action *act);
int lm_setlockargs_vg_sanlock(char *ls_name, char *vg_name, struct action *act);
static inline int lm_support_sanlock(void)
{
@@ -536,12 +635,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, int opt_align_mb)
static inline int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_args, int opt_align_mb, char *other_args)
{
return -1;
}
static inline int lm_init_lv_sanlock(struct lockspace *ls, char *lv_name, char *vg_args, char *lv_args)
static inline int lm_init_lv_sanlock(struct lockspace *ls, char *ls_name, char *vg_name, char *lv_name, char *vg_args, char *lv_args, char *prev_args)
{
return -1;
}
@@ -556,12 +655,12 @@ static inline int lm_rename_vg_sanlock(char *ls_name, char *vg_name, uint32_t fl
return -1;
}
static inline int lm_prepare_lockspace_sanlock(struct lockspace *ls)
static inline int lm_prepare_lockspace_sanlock(struct lockspace *ls, uint64_t *prev_generation, int repair)
{
return -1;
}
static inline int lm_add_lockspace_sanlock(struct lockspace *ls, int adopt_only, int adopt_ok)
static inline int lm_add_lockspace_sanlock(struct lockspace *ls, int adopt_only, int adopt_ok, int nodelay)
{
return -1;
}
@@ -571,9 +670,14 @@ static inline int lm_rem_lockspace_sanlock(struct lockspace *ls, int free_vg)
return -1;
}
static inline int lm_add_resource_sanlock(struct lockspace *ls, struct resource *r)
{
return -1;
}
static inline int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode,
struct val_blk *vb_out, int *retry,
int adopt_only, int adopt_ok)
struct val_blk *vb_out, int *retry, struct owner *owner,
int adopt_only, int adopt_ok, int repair)
{
return -1;
}
@@ -630,7 +734,12 @@ static inline int lm_is_running_sanlock(void)
return 0;
}
static inline int lm_find_free_lock_sanlock(struct lockspace *ls, uint64_t lv_size_bytes);
static inline int lm_find_free_lock_sanlock(struct lockspace *ls, uint64_t lv_size_bytes)
{
return -1;
}
static inline int lm_vg_status_sanlock(struct lockspace *ls, struct action *act)
{
return -1;
}
@@ -640,6 +749,20 @@ static inline int lm_support_sanlock(void)
return 0;
}
void lm_set_host_dead_sanlock(struct lockspace *ls, struct owner *owner)
{
}
int lm_setlockargs_supported_sanlock(struct lockspace *ls, struct action *act)
{
return 0;
}
int lm_setlockargs_vg_sanlock(char *ls_name, char *vg_name, struct action *act)
{
return 0;
}
#endif /* sanlock support */
#ifdef LOCKDIDM_SUPPORT
@@ -649,6 +772,7 @@ 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_only, int adopt_ok);
int lm_rem_lockspace_idm(struct lockspace *ls, int free_vg);
int lm_add_resource_idm(struct lockspace *ls, struct resource *r);
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_only, int adopt_ok);
@@ -694,6 +818,11 @@ static inline int lm_rem_lockspace_idm(struct lockspace *ls, int free_vg)
return -1;
}
static inline int lm_add_resource_idm(struct lockspace *ls, struct resource *r)
{
return -1;
}
static inline int lm_lock_idm(struct lockspace *ls, struct resource *r, int ld_mode,
struct val_blk *vb_out, char *lv_uuid, struct pvs *pvs,
int adopt_only, int adopt_ok)

File diff suppressed because it is too large Load Diff

View File

@@ -15,8 +15,8 @@
#include "lvmpolld-common.h"
#include "lvm-version.h"
#include "daemon-server.h"
#include "daemon-log.h"
#include "libdaemon/server/daemon-server.h"
#include "libdaemon/server/daemon-log.h"
#include <getopt.h>
#include <poll.h>
@@ -390,6 +390,11 @@ static void *fork_and_poll(void *args)
goto err;
}
if (!pdlv->cmdargv || !*(pdlv->cmdargv)) {
ERROR(ls, "%s: %s", PD_LOG_PREFIX, "Missing command");
goto err;
}
DEBUGLOG(ls, "%s: %s", PD_LOG_PREFIX, "cmd line arguments:");
debug_print(ls, pdlv->cmdargv);
DEBUGLOG(ls, "%s: %s", PD_LOG_PREFIX, "---end---");

View File

@@ -46,7 +46,7 @@ static char *_construct_lvm_system_dir_env(const char *sysdir)
* - or -
* just single char to store NULL byte
*/
size_t l = sysdir ? strlen(sysdir) + 16 : 1;
size_t l = sysdir ? strlen(sysdir) + sizeof(LVM_SYSTEM_DIR): 1;
char *env = (char *) malloc(l * sizeof(char));
if (!env)
@@ -89,6 +89,17 @@ char *construct_id(const char *sysdir, const char *uuid)
return id;
}
static void _free_lvmpolld_lv(struct lvmpolld_lv *p)
{
free((void *)p->devicesfile);
free((void *)p->lvm_system_dir_env);
free((void *)p->lvmpolld_id);
free((void *)p->lvname);
free((void *)p->sinterval);
free((void *)p->cmdargv);
free((void *)p->cmdenvp);
}
struct lvmpolld_lv *pdlv_create(struct lvmpolld_state *ls, const char *id,
const char *vgname, const char *lvname,
const char *sysdir, enum poll_type type,
@@ -96,30 +107,26 @@ struct lvmpolld_lv *pdlv_create(struct lvmpolld_state *ls, const char *id,
struct lvmpolld_store *pdst,
const char *devicesfile)
{
char *lvmpolld_id = strdup(id), /* copy */
*full_lvname = _construct_full_lvname(vgname, lvname), /* copy */
*lvm_system_dir_env = _construct_lvm_system_dir_env(sysdir); /* copy */
char *devicesfile_dup = devicesfile ? strdup(devicesfile) : NULL;
struct lvmpolld_lv tmp = {
.ls = ls,
.type = type,
.lvmpolld_id = lvmpolld_id,
.lvid = _get_lvid(lvmpolld_id, sysdir),
.lvname = full_lvname,
.devicesfile = devicesfile_dup,
.lvm_system_dir_env = lvm_system_dir_env,
.sinterval = strdup(sinterval), /* copy */
.lvmpolld_id = strdup(id),
.lvname = _construct_full_lvname(vgname, lvname),
.devicesfile = devicesfile ? strdup(devicesfile) : NULL,
.lvm_system_dir_env = _construct_lvm_system_dir_env(sysdir),
.sinterval = strdup(sinterval),
.pdtimeout = pdtimeout < MIN_POLLING_TIMEOUT ? MIN_POLLING_TIMEOUT : pdtimeout,
.cmd_state = { .retcode = -1, .signal = 0 },
.pdst = pdst,
.init_rq_count = 1
}, *pdlv = (struct lvmpolld_lv *) malloc(sizeof(struct lvmpolld_lv));
if (!pdlv || !tmp.lvid || !tmp.lvname || !tmp.lvm_system_dir_env || !tmp.sinterval)
if (!pdlv || !tmp.lvmpolld_id || !tmp.lvname || !tmp.lvm_system_dir_env || !tmp.sinterval)
goto err;
memcpy(pdlv, &tmp, sizeof(*pdlv));
tmp.lvid = _get_lvid(tmp.lvmpolld_id, sysdir),
*pdlv = tmp;
if (pthread_mutex_init(&pdlv->lock, NULL))
goto err;
@@ -127,29 +134,20 @@ struct lvmpolld_lv *pdlv_create(struct lvmpolld_state *ls, const char *id,
return pdlv;
err:
free((void *)devicesfile_dup);
free((void *)full_lvname);
free((void *)lvmpolld_id);
free((void *)lvm_system_dir_env);
free((void *)tmp.sinterval);
free((void *)pdlv);
_free_lvmpolld_lv(&tmp);
free(pdlv);
return NULL;
}
void pdlv_destroy(struct lvmpolld_lv *pdlv)
{
free((void *)pdlv->lvmpolld_id);
free((void *)pdlv->devicesfile);
free((void *)pdlv->lvname);
free((void *)pdlv->sinterval);
free((void *)pdlv->lvm_system_dir_env);
free((void *)pdlv->cmdargv);
free((void *)pdlv->cmdenvp);
_free_lvmpolld_lv(pdlv);
pthread_mutex_destroy(&pdlv->lock);
free((void *)pdlv);
free(pdlv);
}
unsigned pdlv_get_polling_finished(struct lvmpolld_lv *pdlv)

View File

@@ -15,7 +15,10 @@
#ifndef _LVM_LVMPOLLD_DATA_UTILS_H
#define _LVM_LVMPOLLD_DATA_UTILS_H
#include "base/data-struct/hash.h"
#include <pthread.h>
#include <stdio.h>
struct buffer;
struct lvmpolld_state;
@@ -93,7 +96,7 @@ struct lvmpolld_thread_data {
struct lvmpolld_lv *pdlv;
};
char *construct_id(const char *sysdir, const char *lvid);
char *construct_id(const char *sysdir, const char *uuid);
/* LVMPOLLD_LV_T section */

View File

@@ -25,6 +25,7 @@ DEVICE_MAPPER_SOURCE=\
device_mapper/libdm-targets.c \
device_mapper/libdm-timestamp.c \
device_mapper/mm/pool.c \
device_mapper/raid/raid_parser.c \
device_mapper/regex/matcher.c \
device_mapper/regex/parse_rx.c \
device_mapper/regex/ttree.c \

View File

@@ -19,6 +19,7 @@
#include "base/data-struct/list.h"
#include "base/data-struct/hash.h"
#include "raid/target.h"
#include "vdo/target.h"
#include <inttypes.h>
@@ -191,7 +192,7 @@ struct dm_versions {
int dm_get_library_version(char *version, size_t size);
int dm_task_get_driver_version(struct dm_task *dmt, char *version, size_t size);
int dm_task_get_info(struct dm_task *dmt, struct dm_info *dmi);
int dm_task_get_info(struct dm_task *dmt, struct dm_info *info);
/*
* This function returns dm device's UUID based on the value
@@ -1051,7 +1052,7 @@ int dm_tree_node_add_vdo_target(struct dm_tree_node *node,
const char *vdo_pool_name,
const char *data_uuid,
uint64_t data_size,
const struct dm_vdo_target_params *param);
const struct dm_vdo_target_params *vtp);
/*
* FIXME Add individual cache policy pairs <key> = value, like:
@@ -1178,9 +1179,9 @@ void dm_tree_node_set_presuspend_node(struct dm_tree_node *node,
struct dm_tree_node *presuspend_node);
int dm_tree_node_add_target_area(struct dm_tree_node *node,
const char *dev_name,
const char *dlid,
uint64_t offset);
const char *dev_name,
const char *uuid,
uint64_t offset);
/*
* Only for temporarily-missing raid devices where changes are tracked.
@@ -1590,9 +1591,9 @@ int dm_fclose(FILE *stream);
* Pointer to the buffer is stored in *buf.
* Returns -1 on failure leaving buf undefined.
*/
int dm_asprintf(char **buf, const char *format, ...)
int dm_asprintf(char **result, const char *format, ...)
__attribute__ ((format(printf, 2, 3)));
int dm_vasprintf(char **buf, const char *format, va_list ap)
int dm_vasprintf(char **result, const char *format, va_list aq)
__attribute__ ((format(printf, 2, 0)));
/*
@@ -1941,7 +1942,7 @@ void dm_report_free(struct dm_report *rh);
* Prefix added to each field name with DM_REPORT_OUTPUT_FIELD_NAME_PREFIX
*/
int dm_report_set_output_field_name_prefix(struct dm_report *rh,
const char *report_prefix);
const char *output_field_name_prefix);
int dm_report_set_selection(struct dm_report *rh, const char *selection);
@@ -2034,6 +2035,7 @@ struct dm_config_tree *dm_config_create(void);
struct dm_config_tree *dm_config_from_string(const char *config_settings);
int dm_config_parse(struct dm_config_tree *cft, const char *start, const char *end);
int dm_config_parse_without_dup_node_check(struct dm_config_tree *cft, const char *start, const char *end);
int dm_config_parse_only_section(struct dm_config_tree *cft, const char *start, const char *end, const char *section);
void *dm_config_get_custom(struct dm_config_tree *cft);
void dm_config_set_custom(struct dm_config_tree *cft, void *custom);
@@ -2080,7 +2082,7 @@ int dm_config_write_one_node_out(const struct dm_config_node *cn, const struct d
struct dm_config_node *dm_config_find_node(const struct dm_config_node *cn, const char *path);
int dm_config_has_node(const struct dm_config_node *cn, const char *path);
int dm_config_remove_node(struct dm_config_node *parent, struct dm_config_node *remove);
int dm_config_remove_node(struct dm_config_node *parent, struct dm_config_node *rem_node);
const char *dm_config_find_str(const struct dm_config_node *cn, const char *path, const char *fail);
const char *dm_config_find_str_allow_empty(const struct dm_config_node *cn, const char *path, const char *fail);
int dm_config_find_int(const struct dm_config_node *cn, const char *path, int fail);
@@ -2112,7 +2114,7 @@ unsigned dm_config_maybe_section(const char *str, unsigned len);
const char *dm_config_parent_name(const struct dm_config_node *n);
struct dm_config_node *dm_config_clone_node_with_mem(struct dm_pool *mem, const struct dm_config_node *node, int siblings);
struct dm_config_node *dm_config_clone_node_with_mem(struct dm_pool *mem, const struct dm_config_node *cn, int siblings);
struct dm_config_node *dm_config_create_node(struct dm_config_tree *cft, const char *key);
struct dm_config_value *dm_config_create_value(struct dm_config_tree *cft);
struct dm_config_node *dm_config_clone_node(struct dm_config_tree *cft, const struct dm_config_node *cn, int siblings);

View File

@@ -70,6 +70,7 @@ static unsigned _dm_version_minor = 0;
static unsigned _dm_version_patchlevel = 0;
static int _log_suppress = 0;
static struct dm_timestamp *_dm_ioctl_timestamp = NULL;
static int _dm_warn_inactive_suppress = 0;
/*
* If the kernel dm driver only supports one major number
@@ -485,7 +486,7 @@ static void _dm_zfree_string(char *string)
{
if (string) {
memset(string, 0, strlen(string));
asm volatile ("" ::: "memory"); /* Compiler barrier. */
__asm__ volatile ("" ::: "memory"); /* Compiler barrier. */
free(string);
}
}
@@ -494,7 +495,7 @@ static void _dm_zfree_dmi(struct dm_ioctl *dmi)
{
if (dmi) {
memset(dmi, 0, dmi->data_size);
asm volatile ("" ::: "memory"); /* Compiler barrier. */
__asm__ volatile ("" ::: "memory"); /* Compiler barrier. */
free(dmi);
}
}
@@ -769,7 +770,7 @@ static size_t _align_val(size_t val)
}
static void *_align_ptr(void *ptr)
{
return (void *)_align_val((size_t)ptr);
return (void *)(uintptr_t)_align_val((size_t)ptr);
}
static int _check_has_event_nr(void) {
@@ -1412,22 +1413,23 @@ static struct dm_ioctl *_flatten(struct dm_task *dmt, unsigned repeat_count)
}
if (dmt->query_inactive_table) {
if (!_dm_inactive_supported())
log_warn("WARNING: Inactive table query unsupported "
"by kernel. It will use live table.");
log_warn_suppress(_dm_warn_inactive_suppress++,
"WARNING: Inactive table query unsupported by kernel. "
"It will use live table.");
dmi->flags |= DM_QUERY_INACTIVE_TABLE_FLAG;
}
if (dmt->new_uuid) {
if (_dm_version_minor < 19) {
log_error("WARNING: Setting UUID unsupported by "
"kernel. Aborting operation.");
log_error("Setting UUID unsupported by kernel. "
"Aborting operation.");
goto bad;
}
dmi->flags |= DM_UUID_FLAG;
}
if (dmt->ima_measurement) {
if (_dm_version_minor < 45) {
log_error("WARNING: IMA measurement unsupported by "
"kernel. Aborting operation.");
log_error("IMA measurement unsupported by kernel. "
"Aborting operation.");
goto bad;
}
dmi->flags |= DM_IMA_MEASUREMENT_FLAG;

View File

@@ -16,6 +16,8 @@
#ifndef LIB_DMTARGETS_H
#define LIB_DMTARGETS_H
#include "device_mapper/all.h"
#include <inttypes.h>
#include <sys/types.h>

View File

@@ -511,7 +511,7 @@ int unmangle_string(const char *str, const char *str_name, size_t len,
char *buf, size_t buf_len, dm_string_mangling_t mode)
{
int strict = mode != DM_STRING_MANGLING_NONE;
char str_rest[DM_NAME_LEN];
char str_rest[DM_NAME_LEN + 1];
size_t i, j;
unsigned int code;
int r = 0;
@@ -1832,32 +1832,27 @@ int dm_mountinfo_read(dm_mountinfo_line_callback_fn read_fn, void *cb_data)
static int _sysfs_get_dm_name(uint32_t major, uint32_t minor, char *buf, size_t buf_size)
{
char *sysfs_path, *temp_buf = NULL;
char sysfs_path[PATH_MAX], temp_buf[2 * DM_NAME_LEN];
FILE *fp = NULL;
int r = 0;
size_t len;
if (!(sysfs_path = malloc(PATH_MAX)) ||
!(temp_buf = malloc(PATH_MAX))) {
log_error("_sysfs_get_dm_name: failed to allocate temporary buffers");
goto bad;
}
if (dm_snprintf(sysfs_path, PATH_MAX, "%sdev/block/%" PRIu32 ":%" PRIu32
if (dm_snprintf(sysfs_path, sizeof(sysfs_path),
"%sdev/block/%" PRIu32 ":%" PRIu32
"/dm/name", _sysfs_dir, major, minor) < 0) {
log_error("_sysfs_get_dm_name: dm_snprintf failed");
log_error("_sysfs_get_dm_name: dm_snprintf failed.");
goto bad;
}
if (!(fp = fopen(sysfs_path, "r"))) {
if (errno != ENOENT)
log_sys_error("fopen", sysfs_path);
else
if (errno == ENOENT)
log_sys_debug("fopen", sysfs_path);
else
log_sys_error("fopen", sysfs_path);
goto bad;
}
if (!fgets(temp_buf, PATH_MAX, fp)) {
if (!fgets(temp_buf, sizeof(temp_buf), fp)) {
log_sys_error("fgets", sysfs_path);
goto bad;
}
@@ -1865,20 +1860,21 @@ static int _sysfs_get_dm_name(uint32_t major, uint32_t minor, char *buf, size_t
len = strlen(temp_buf);
if (len > buf_size) {
log_error("_sysfs_get_dm_name: supplied buffer too small");
log_error("_sysfs_get_dm_name: supplied buffer too small.");
goto bad;
}
temp_buf[len ? len - 1 : 0] = '\0'; /* \n */
strcpy(buf, temp_buf);
if (len)
--len; /* strip \n */
memcpy(buf, temp_buf, len);
buf[len] = '\0';
r = 1;
bad:
if (fp && fclose(fp))
log_sys_error("fclose", sysfs_path);
free(temp_buf);
free(sysfs_path);
return r;
}

View File

@@ -36,7 +36,7 @@ struct target *create_target(uint64_t start,
uint64_t len,
const char *type, const char *params);
int add_dev_node(const char *dev_name, uint32_t minor, uint32_t major,
int add_dev_node(const char *dev_name, uint32_t major, uint32_t minor,
uid_t uid, gid_t gid, mode_t mode, int check_udev, unsigned rely_on_udev);
int rm_dev_node(const char *dev_name, int check_udev, unsigned rely_on_udev);
int rename_dev_node(const char *old_name, const char *new_name,

View File

@@ -53,6 +53,8 @@ struct parser {
int no_dup_node_check; /* whether to disable dup node checking */
const char *key; /* last obtained key */
unsigned ignored_creation_time;
unsigned section_indent;
const char *stop_after_section;
};
struct config_output {
@@ -89,9 +91,8 @@ static char *_dup_token(struct dm_pool *mem, const char *b, const char *e);
static int _tok_match(const char *str, const char *b, const char *e)
{
while (b < e) {
if (*str != *b)
return 0;
if (!*str)
if (!*str ||
(*str != *b))
return 0;
++str;
++b;
@@ -103,7 +104,7 @@ static int _tok_match(const char *str, const char *b, const char *e)
struct dm_config_tree *dm_config_create(void)
{
struct dm_config_tree *cft;
struct dm_pool *mem = dm_pool_create("config", 10 * 1024);
struct dm_pool *mem = dm_pool_create("config", 63 * 1024);
if (!mem) {
log_error("Failed to allocate config pool.");
@@ -177,7 +178,8 @@ static struct dm_config_node *_config_reverse(struct dm_config_node *head)
return middle;
}
static int _do_dm_config_parse(struct dm_config_tree *cft, const char *start, const char *end, int no_dup_node_check)
static int _do_dm_config_parse(struct dm_config_tree *cft, const char *start, const char *end,
int no_dup_node_check, const char *section)
{
/* TODO? if (start == end) return 1; */
@@ -188,6 +190,7 @@ static int _do_dm_config_parse(struct dm_config_tree *cft, const char *start, co
.fb = start,
.fe = end,
.line = 1,
.stop_after_section = section,
.no_dup_node_check = no_dup_node_check
};
@@ -202,12 +205,23 @@ static int _do_dm_config_parse(struct dm_config_tree *cft, const char *start, co
int dm_config_parse(struct dm_config_tree *cft, const char *start, const char *end)
{
return _do_dm_config_parse(cft, start, end, 0);
return _do_dm_config_parse(cft, start, end, 0, NULL);
}
int dm_config_parse_without_dup_node_check(struct dm_config_tree *cft, const char *start, const char *end)
{
return _do_dm_config_parse(cft, start, end, 1);
return _do_dm_config_parse(cft, start, end, 1, NULL);
}
/*
* Stop parsing more sections after given section is parsed.
* Only non-section config nodes are then still parsed.
* It can be useful, when parsing i.e. lvm2 metadata and only physical_volumes config node is needed.
* This function is automatically running without_dup_node_check.
*/
int dm_config_parse_only_section(struct dm_config_tree *cft, const char *start, const char *end, const char *section)
{
return _do_dm_config_parse(cft, start, end, 1, section);
}
struct dm_config_tree *dm_config_from_string(const char *config_settings)
@@ -593,6 +607,8 @@ static struct dm_config_node *_section(struct parser *p, struct dm_config_node *
struct dm_config_node *root;
struct dm_config_value *value;
char *str;
size_t len;
char buf[8192];
if (p->t == TOK_STRING_ESCAPED) {
if (!(str = _dup_string_tok(p)))
@@ -606,9 +622,16 @@ static struct dm_config_node *_section(struct parser *p, struct dm_config_node *
match(TOK_STRING);
} else {
if (!(str = _dup_tok(p)))
return_NULL;
len = p->te - p->tb;
if (len < (sizeof(buf) - 1)) {
/* Use stack for smaller string */
str = buf;
memcpy(str, p->tb, len);
str[len] = '\0';
} else {
if (!(str = _dup_tok(p)))
return_NULL;
}
match(TOK_IDENTIFIER);
}
@@ -622,12 +645,28 @@ static struct dm_config_node *_section(struct parser *p, struct dm_config_node *
return_NULL;
if (p->t == TOK_SECTION_B) {
if (p->stop_after_section)
++p->section_indent;
match(TOK_SECTION_B);
while (p->t != TOK_SECTION_E) {
if (!(_section(p, root)))
return_NULL;
}
match(TOK_SECTION_E);
if (p->stop_after_section && (--p->section_indent == 1)) {
if (!strcmp(str, p->stop_after_section)) {
/* Found stopping section name -> parsing is finished.
* Now try to find the sequence "\n}\n" from end of b
* parsed buffer to continue filling remaining nodes */
for (p->te = p->fe - 1; p->te > p->tb; --p->te)
if ((p->te[-2] == '\n') &&
(p->te[-1] == '}') &&
(p->te[ 0] == '\n')) {
p->t = TOK_SECTION_E;
break;
}
}
}
} else {
match(TOK_EQ);
p->key = root->key;
@@ -780,60 +819,52 @@ static int _match_aux(struct parser *p, int t)
*/
static void _get_token(struct parser *p, int tok_prev)
{
int values_allowed = 0;
/* Should next token be interpreted as value instead of identifier? */
const int values_allowed = (tok_prev == TOK_EQ ||
tok_prev == TOK_ARRAY_B ||
tok_prev == TOK_COMMA);
const char *te;
char c;
p->tb = p->te;
_eat_space(p);
if (p->tb == p->fe || !*p->tb) {
if (p->tb == p->fe ||
!((c = *p->tb))) {
p->t = TOK_EOF;
return;
}
/* Should next token be interpreted as value instead of identifier? */
if (tok_prev == TOK_EQ || tok_prev == TOK_ARRAY_B ||
tok_prev == TOK_COMMA)
values_allowed = 1;
p->t = TOK_INT; /* fudge so the fall through for
floats works */
te = p->te + 1; /* next character */
te = p->te;
switch (*te) {
switch (c) {
case SECTION_B_CHAR:
p->t = TOK_SECTION_B;
te++;
break;
case SECTION_E_CHAR:
p->t = TOK_SECTION_E;
te++;
break;
case '[':
p->t = TOK_ARRAY_B;
te++;
break;
case ']':
p->t = TOK_ARRAY_E;
te++;
break;
case ',':
p->t = TOK_COMMA;
te++;
break;
case '=':
p->t = TOK_EQ;
te++;
break;
case '"':
p->t = TOK_STRING_ESCAPED;
te++;
while ((te != p->fe) && (*te) && (*te != '"')) {
if ((*te == '\\') && (te + 1 != p->fe) &&
*(te + 1))
@@ -847,7 +878,6 @@ static void _get_token(struct parser *p, int tok_prev)
case '\'':
p->t = TOK_STRING;
te++;
while ((te != p->fe) && (*te) && (*te != '\''))
te++;
@@ -871,7 +901,7 @@ static void _get_token(struct parser *p, int tok_prev)
case '+':
case '-':
if (values_allowed) {
while (++te != p->fe) {
for (; te != p->fe; ++te) {
if (!isdigit((int) *te)) {
if (*te == '.') {
if (p->t != TOK_FLOAT) {
@@ -888,10 +918,10 @@ static void _get_token(struct parser *p, int tok_prev)
default:
p->t = TOK_IDENTIFIER;
while ((te != p->fe) && (*te) && !isspace(*te) &&
(*te != '#') && (*te != '=') &&
(*te != SECTION_B_CHAR) &&
(*te != SECTION_E_CHAR))
while ((te != p->fe) && ((c = *te)) && !isspace(c) &&
(c != '#') && (c != '=') &&
(c != SECTION_B_CHAR) &&
(c != SECTION_E_CHAR))
te++;
if (values_allowed)
p->t = TOK_STRING_BARE;
@@ -944,8 +974,7 @@ static struct dm_config_value *_create_str_value(struct dm_pool *mem, const char
if (str) {
str_buf = (char *)(cv + 1);
if (str_len)
memcpy(str_buf, str, str_len);
memcpy(str_buf, str, str_len);
str_buf[str_len] = '\0';
cv->v.str = str_buf;
}
@@ -965,8 +994,7 @@ static struct dm_config_node *_create_node(struct dm_pool *mem, const char *key,
if (key) {
key_buf = (char *)(cn + 1);
if (key_len)
memcpy(key_buf, key, key_len);
memcpy(key_buf, key, key_len);
key_buf[key_len] = '\0';
cn->key = key_buf;
}
@@ -1390,7 +1418,8 @@ static struct dm_config_value *_clone_config_value(struct dm_pool *mem,
if (v->type == DM_CFG_STRING) {
if (!(new_cv = _create_str_value(mem, v->v.str, strlen(v->v.str)))) {
log_error("Failed to clone string config value.");
return NULL;
}
} else {
if (!(new_cv = _create_value(mem))) {
@@ -1432,9 +1461,9 @@ struct dm_config_node *dm_config_clone_node_with_mem(struct dm_pool *mem, const
return new_cn;
}
struct dm_config_node *dm_config_clone_node(struct dm_config_tree *cft, const struct dm_config_node *node, int sib)
struct dm_config_node *dm_config_clone_node(struct dm_config_tree *cft, const struct dm_config_node *cn, int sib)
{
return dm_config_clone_node_with_mem(cft->mem, node, sib);
return dm_config_clone_node_with_mem(cft->mem, cn, sib);
}
struct dm_config_node *dm_config_create_node(struct dm_config_tree *cft, const char *key)

View File

@@ -19,7 +19,6 @@
#include "misc/dm-ioctl.h"
#include "vdo/target.h"
#include <stdarg.h>
#include <string.h>
#include <sys/utsname.h>
@@ -152,15 +151,17 @@ struct thin_message {
struct load_segment {
struct dm_list list;
unsigned type;
uint64_t size;
unsigned type;
unsigned area_count; /* Linear + Striped + Mirrored + Crypt */
struct dm_list areas; /* Linear + Striped + Mirrored + Crypt */
uint32_t stripe_size; /* Striped + raid */
uint32_t region_size; /* Mirror + raid */
int persistent; /* Snapshot */
uint32_t chunk_size; /* Snapshot */
struct dm_tree_node *cow; /* Snapshot */
@@ -168,7 +169,6 @@ struct load_segment {
struct dm_tree_node *merge; /* Snapshot */
struct dm_tree_node *log; /* Mirror */
uint32_t region_size; /* Mirror + raid */
unsigned clustered; /* Mirror */
unsigned mirror_area_count; /* Mirror */
uint64_t flags; /* Mirror + Raid + Cache */
@@ -540,7 +540,8 @@ static struct dm_tree_node *_create_dm_tree_node(struct dm_tree *dtree,
struct dm_tree_node *node;
dev_t dev;
if (!(node = dm_pool_zalloc(dtree->mem, sizeof(*node))) ||
if (!dtree || !dtree->mem ||
!(node = dm_pool_zalloc(dtree->mem, sizeof(*node))) ||
!(node->name = dm_pool_strdup(dtree->mem, name)) ||
!(node->uuid = dm_pool_strdup(dtree->mem, uuid))) {
log_error("_create_dm_tree_node alloc failed.");

View File

@@ -17,6 +17,7 @@
#include "base/memory/zalloc.h"
#include <ctype.h>
#include <langinfo.h>
#include <math.h> /* fabs() */
#include <float.h> /* DBL_EPSILON */
#include <time.h>
@@ -31,6 +32,7 @@
struct selection {
struct dm_pool *mem;
struct dm_pool *regex_mem;
struct selection_node *selection_root;
int add_new_fields;
};
@@ -204,7 +206,9 @@ static const struct op_def _op_log[] = {
struct selection_str_list {
struct dm_str_list str_list;
unsigned type; /* either SEL_AND or SEL_OR */
struct dm_regex *regex;
size_t regex_num_patterns;
unsigned type; /* either SEL_LIST_LS or SEL_LIST_SUBSET_LS with either SEL_AND or SEL_OR */
};
struct field_selection_value {
@@ -547,7 +551,7 @@ static int _report_field_string_list(struct dm_report *rh,
}
/* more than one item - allocate temporary array for string list items for further processing */
if (!(arr = malloc(list_size * sizeof(struct str_pos_len)))) {
if (!(arr = zalloc(list_size * sizeof(struct str_pos_len)))) {
log_error("%s failed to allocate temporary array for processing", _error_msg_prefix);
goto out;
}
@@ -589,7 +593,8 @@ static int _report_field_string_list(struct dm_report *rh,
for (i = 0, pos = 0; i < list_size; i++) {
arr[i].item.pos = pos;
memcpy(repstr + pos, arr[i].str, arr[i].item.len);
if (arr[i].str)
memcpy(repstr + pos, arr[i].str, arr[i].item.len);
memcpy(repstr_extra + i + 1, &arr[i].item, sizeof(struct pos_len));
pos += arr[i].item.len;
@@ -1411,8 +1416,11 @@ struct dm_report *dm_report_init(uint32_t *report_types,
void dm_report_free(struct dm_report *rh)
{
if (rh->selection)
if (rh->selection) {
dm_pool_destroy(rh->selection->mem);
if (rh->selection->regex_mem)
dm_pool_destroy(rh->selection->regex_mem);
}
if (rh->value_cache)
dm_hash_destroy(rh->value_cache);
dm_pool_destroy(rh->mem);
@@ -1751,8 +1759,74 @@ static int _cmp_field_time(struct dm_report *rh,
return 0;
}
static int _str_list_item_match_regex(const struct str_list_sort_value *val, unsigned int i, struct dm_regex *regex)
{
struct pos_len *item = val->items + i;
char *s = (char *) (val->value + item->pos);
char c = s[item->len];
int r;
/*
* The val->items contains the whole string list in the form of a single string,
* where each item is delimited by a delimiter.
*
* The item->pos + item->len pair then points to the exact item within the val->items.
*
* The dm_regex_match accepts a string, not the pos + len pair, so we need to adapt here:
* replace the delimiter with '\0' temporarily so the item is a proper string.
*/
s[item->len] = '\0';
r = dm_regex_match(regex, s);
s[item->len] = c;
return r;
}
static size_t _bitset_count_set(dm_bitset_t bs)
{
size_t i, size = bs[0]/DM_BITS_PER_INT + 1;
size_t count = 0;
for (i = 1; i <= size; i++)
count += hweight32(bs[i]);
return count;
}
/* Matches if all items from selection string list match list value strictly 1:1. */
static int _cmp_field_string_list_strict_all(const struct str_list_sort_value *val,
static int _cmp_field_string_list_strict_regex_all(const struct dm_report *rh,
const struct str_list_sort_value *val,
const struct selection_str_list *sel)
{
unsigned int i;
dm_bitset_t bs;
int r;
if (!val->items)
return (sel->regex_num_patterns == 1) && dm_regex_match(sel->regex, "") >= 0;
if (!(bs = dm_bitset_create(rh->selection->mem, sel->regex_num_patterns))) {
log_error("Failed to create bitset for regex match counter.");
return 0;
}
for (i = 1; i <= val->items[0].pos; i++) {
if ((r = _str_list_item_match_regex(val, i, sel->regex)) < 0) {
r = 0;
goto out;
}
dm_bit_set(bs, r);
}
r = _bitset_count_set(bs) == sel->regex_num_patterns;
out:
dm_pool_free(rh->selection->mem, bs);
return r;
}
/* Matches if all items from selection string list match list value strictly 1:1. */
static int _cmp_field_string_list_strict_all(const struct dm_report *rh,
const struct str_list_sort_value *val,
const struct selection_str_list *sel)
{
unsigned int sel_list_size = dm_list_size(&sel->str_list.list);
@@ -1784,7 +1858,36 @@ static int _cmp_field_string_list_strict_all(const struct str_list_sort_value *v
}
/* Matches if all items from selection string list match a subset of list value. */
static int _cmp_field_string_list_subset_all(const struct str_list_sort_value *val,
static int _cmp_field_string_list_subset_regex_all(const struct dm_report *rh,
const struct str_list_sort_value *val,
const struct selection_str_list *sel)
{
dm_bitset_t bs;
unsigned int i;
int r;
if (!val->items)
return (sel->regex_num_patterns == 1) && dm_regex_match(sel->regex, "") >= 0;
if (!(bs = dm_bitset_create(rh->selection->mem, sel->regex_num_patterns))) {
log_error("Failed to create bitset for regex match counter.");
return 0;
}
for (i = 1; i <= val->items[0].pos; i++) {
if ((r = _str_list_item_match_regex(val, i, sel->regex)) < 0)
continue;
dm_bit_set(bs, r);
}
r = _bitset_count_set(bs) == sel->regex_num_patterns;
dm_pool_free(rh->selection->mem, bs);
return r;
}
/* Matches if all items from selection string list match a subset of list value. */
static int _cmp_field_string_list_subset_all(const struct dm_report *rh __attribute__((unused)),
const struct str_list_sort_value *val,
const struct selection_str_list *sel)
{
unsigned int sel_list_size = dm_list_size(&sel->str_list.list);
@@ -1819,8 +1922,26 @@ static int _cmp_field_string_list_subset_all(const struct str_list_sort_value *v
}
/* Matches if any item from selection string list matches list value. */
static int _cmp_field_string_list_any(const struct str_list_sort_value *val,
const struct selection_str_list *sel)
static int _cmp_field_string_list_subset_regex_any(const struct dm_report *rh __attribute__((unused)),
const struct str_list_sort_value *val,
const struct selection_str_list *sel)
{
unsigned int i;
if (!val->items)
return dm_regex_match(sel->regex, "") >= 0;
for (i = 1; i <= val->items[0].pos; i++) {
if (_str_list_item_match_regex(val, i, sel->regex) >= 0)
return 1;
}
return 0;
}
/* Matches if any item from selection string list matches list value. */
static int _cmp_field_string_list_subset_any(const struct dm_report *rh __attribute__((unused)),
const struct str_list_sort_value *val,
const struct selection_str_list *sel)
{
struct dm_str_list *sel_item;
unsigned int i;
@@ -1849,7 +1970,59 @@ static int _cmp_field_string_list_any(const struct str_list_sort_value *val,
return 0;
}
static int _cmp_field_string_list(struct dm_report *rh __attribute__((unused)),
/* Matches if all items from list value can be matched by any item from selection list. */
static int _cmp_field_string_list_strict_regex_any(const struct dm_report *rh __attribute__((unused)),
const struct str_list_sort_value *val,
const struct selection_str_list *sel)
{
unsigned int i;
if (!val->items)
return dm_regex_match(sel->regex, "") >= 0;
for (i = 1; i <= val->items[0].pos; i++) {
if (_str_list_item_match_regex(val, i, sel->regex) < 0)
return 0;
}
return 1;
}
/* Matches if all items from list value can be matched by any item from selection list. */
static int _cmp_field_string_list_strict_any(const struct dm_report *rh __attribute__((unused)),
const struct str_list_sort_value *val,
const struct selection_str_list *sel)
{
struct dm_str_list *sel_item;
unsigned int i;
int match;
/* match blank string list with selection that contains blank string */
if (!val->items) {
dm_list_iterate_items(sel_item, &sel->str_list.list) {
if (!strcmp(sel_item->str, ""))
return 1;
}
return 0;
}
for (i = 1; i <= val->items[0].pos; i++) {
match = 0;
dm_list_iterate_items(sel_item, &sel->str_list.list) {
if ((strlen(sel_item->str) == val->items[i].len) &&
!strncmp(sel_item->str, val->value + val->items[i].pos, val->items[i].len)) {
match = 1;
break;
}
}
if (!match)
return 0;
}
return 1;
}
static int _cmp_field_string_list(struct dm_report *rh,
uint32_t field_num, const char *field_id,
const struct str_list_sort_value *val,
struct field_selection *fs)
@@ -1871,11 +2044,16 @@ static int _cmp_field_string_list(struct dm_report *rh __attribute__((unused)),
switch (sel->type & SEL_MASK) {
case SEL_AND:
r = subset ? _cmp_field_string_list_subset_all(val, sel)
: _cmp_field_string_list_strict_all(val, sel);
r = subset ? sel->regex ? _cmp_field_string_list_subset_regex_all(rh, val, sel)
: _cmp_field_string_list_subset_all(rh, val, sel)
: sel->regex ? _cmp_field_string_list_strict_regex_all(rh, val, sel)
: _cmp_field_string_list_strict_all(rh, val, sel);
break;
case SEL_OR:
r = _cmp_field_string_list_any(val, sel);
r = subset ? sel->regex ? _cmp_field_string_list_subset_regex_any(rh, val, sel)
: _cmp_field_string_list_subset_any(rh, val, sel)
: sel->regex ? _cmp_field_string_list_strict_regex_any(rh, val, sel)
: _cmp_field_string_list_strict_any(rh, val, sel);
break;
default:
log_error(INTERNAL_ERROR "_cmp_field_string_list: unsupported string "
@@ -1909,7 +2087,17 @@ static int _compare_selection_field(struct dm_report *rh,
}
if (fs->flags & FLD_CMP_REGEX)
r = _cmp_field_regex((const char *) f->sort_value, fs);
switch (f->props->flags & DM_REPORT_FIELD_TYPE_MASK) {
case DM_REPORT_FIELD_TYPE_STRING:
r = _cmp_field_regex((const char *) f->sort_value, fs);
break;
case DM_REPORT_FIELD_TYPE_STRING_LIST:
r = _cmp_field_string_list(rh, f->props->field_num, field_id, (const struct str_list_sort_value *) f->sort_value, fs);
break;
default:
log_error(INTERNAL_ERROR "_compare_selection_field: regex: incorrect type %" PRIu32 " for field %s",
f->props->flags & DM_REPORT_FIELD_TYPE_MASK, field_id);
}
else {
switch(f->props->flags & DM_REPORT_FIELD_TYPE_MASK) {
case DM_REPORT_FIELD_TYPE_PERCENT:
@@ -1936,7 +2124,8 @@ static int _compare_selection_field(struct dm_report *rh,
r = _cmp_field_time(rh, f->props->field_num, field_id, *(const time_t *) f->sort_value, fs);
break;
default:
log_error(INTERNAL_ERROR "_compare_selection_field: unknown field type for field %s", field_id);
log_error(INTERNAL_ERROR "_compare_selection_field: incorrect type %" PRIu32 " for field %s",
f->props->flags & DM_REPORT_FIELD_TYPE_MASK, field_id);
}
}
@@ -2628,11 +2817,9 @@ static int _check_reserved_values_supported(const struct dm_report_field_type fi
static const char *_tok_value_regex(struct dm_report *rh,
const struct dm_report_field_type *ft,
const char *s, const char **begin,
const char **end, uint32_t *flags,
struct reserved_value_wrapper *rvw)
const char **end, uint32_t *flags)
{
char c;
rvw->reserved = NULL;
s = _skip_space(s);
@@ -2695,7 +2882,8 @@ static int _add_item_to_string_list(struct dm_pool *mem, const char *begin,
static const char *_tok_value_string_list(const struct dm_report_field_type *ft,
struct dm_pool *mem, const char *s,
const char **begin, const char **end,
struct selection_str_list **sel_str_list)
struct selection_str_list **sel_str_list,
uint32_t *flags)
{
static const char _str_list_item_parsing_failed[] = "Failed to parse string list value "
"for selection field %s.";
@@ -2709,12 +2897,11 @@ static const char *_tok_value_string_list(const struct dm_report_field_type *ft,
int list_end = 0;
char c;
if (!(ssl = dm_pool_alloc(mem, sizeof(*ssl)))) {
log_error("_tok_value_string_list: memory allocation failed for selection list");
if (!(ssl = dm_pool_zalloc(mem, sizeof(*ssl)))) {
log_error("_tok_value_string_list: memory allocation failed for selection list.");
goto bad;
}
dm_list_init(&ssl->str_list.list);
ssl->type = 0;
*begin = s;
if (!(op_flags = _tok_op_log(s, &tmp, SEL_LIST_LS | SEL_LIST_SUBSET_LS))) {
@@ -2726,7 +2913,7 @@ static const char *_tok_value_string_list(const struct dm_report_field_type *ft,
}
if (!_add_item_to_string_list(mem, begin_item, end_item, &ssl->str_list.list))
goto_bad;
ssl->type = SEL_OR | SEL_LIST_LS;
ssl->type = SEL_OR | SEL_LIST_SUBSET_LS;
goto out;
}
@@ -2801,12 +2988,17 @@ static const char *_tok_value_string_list(const struct dm_report_field_type *ft,
else
ssl->type |= SEL_LIST_SUBSET_LS;
/* Sort the list. */
if (!(list_size = dm_list_size(&ssl->str_list.list))) {
log_error(INTERNAL_ERROR "_tok_value_string_list: list has no items");
goto bad;
} else if (list_size == 1)
goto out;
if (*flags & FLD_CMP_REGEX)
/* No need to sort the list for regex. */
goto out;
/* Sort the list. */
if (!(arr = malloc(sizeof(item) * list_size))) {
log_error("_tok_value_string_list: memory allocation failed for sort array");
goto bad;
@@ -3135,7 +3327,9 @@ static int _local_tz_offset(time_t t_local)
time_t t_gmt;
gmtime_r(&t_local, &tm_gmt);
t_gmt = mktime(&tm_gmt);
if ((t_gmt = mktime(&tm_gmt)) < 0)
return 0;
/*
* gmtime returns time that is adjusted
@@ -3146,7 +3340,7 @@ static int _local_tz_offset(time_t t_local)
if (tm_gmt.tm_isdst)
t_gmt -= 3600;
return t_local - t_gmt;
return (int)(t_local - t_gmt);
}
static void _get_final_time(time_range_t range, struct tm *tm,
@@ -3322,7 +3516,10 @@ static const char *_tok_value(struct dm_report *rh,
s = _skip_space(s);
s = _get_reserved(rh, expected_type, field_num, implicit, s, begin, end, rvw);
/* recognize possible reserved value (but not in a regex) */
if (!(*flags & FLD_CMP_REGEX))
s = _get_reserved(rh, expected_type, field_num, implicit, s, begin, end, rvw);
if (rvw->reserved) {
/*
* FLD_CMP_NUMBER shares operators with FLD_CMP_TIME,
@@ -3333,17 +3530,24 @@ static const char *_tok_value(struct dm_report *rh,
else if (expected_type == DM_REPORT_FIELD_TYPE_NUMBER)
*flags &= ~FLD_CMP_TIME;
*flags |= expected_type;
/* if we matched a reserved value, skip further processing of this token */
return s;
}
switch (expected_type) {
case DM_REPORT_FIELD_TYPE_STRING:
c = _get_and_skip_quote_char(&s);
if (!(s = _tok_value_string(s, begin, end, c, SEL_AND | SEL_OR | SEL_PRECEDENCE_PE, NULL))) {
log_error("Failed to parse string value "
"for selection field %s.", ft->id);
return NULL;
if (*flags & FLD_CMP_REGEX) {
if (!(s = _tok_value_regex(rh, ft, s, begin, end, flags)))
return NULL;
} else {
c = _get_and_skip_quote_char(&s);
if (!(s = _tok_value_string(s, begin, end, c, SEL_AND | SEL_OR | SEL_PRECEDENCE_PE, NULL))) {
log_error("Failed to parse string value "
"for selection field %s.", ft->id);
return NULL;
}
}
*flags |= DM_REPORT_FIELD_TYPE_STRING;
break;
@@ -3352,7 +3556,7 @@ static const char *_tok_value(struct dm_report *rh,
if (!(str_list = (struct selection_str_list **) custom))
goto_bad;
s = _tok_value_string_list(ft, mem, s, begin, end, str_list);
s = _tok_value_string_list(ft, mem, s, begin, end, str_list, flags);
if (!(*str_list)) {
log_error("Failed to parse string list value "
"for selection field %s.", ft->id);
@@ -3436,7 +3640,7 @@ static const char *_tok_value(struct dm_report *rh,
return s;
bad:
log_error(INTERNAL_ERROR "Forbidden NULL custom detected.");
log_error(INTERNAL_ERROR "_tok_value: Forbidden NULL custom parameter detected.");
return NULL;
}
@@ -3507,6 +3711,19 @@ static int _get_reserved_value(struct dm_report *rh, uint32_t field_num,
return 1;
}
static struct dm_regex *_selection_regex_create(struct selection *selection, const char * const *patterns,
unsigned num_patterns)
{
if (!selection->regex_mem) {
if (!(selection->regex_mem = dm_pool_create("report selection regex", 32 * 1024))) {
log_error("Failed to create report selection regex memory pool.");
return NULL;
}
}
return dm_regex_create(selection->regex_mem, patterns, num_patterns);
}
static struct field_selection *_create_field_selection(struct dm_report *rh,
uint32_t field_num,
int implicit,
@@ -3524,6 +3741,11 @@ static struct field_selection *_create_field_selection(struct dm_report *rh,
struct time_value *tval;
uint64_t factor;
char *s;
const char *s_arr_single[2] = { 0 };
const char **s_arr;
size_t s_arr_size;
struct dm_str_list *sl;
size_t i;
dm_list_iterate_items(fp, &rh->field_props) {
if ((fp->implicit == implicit) && (fp->field_num == field_num)) {
@@ -3588,20 +3810,55 @@ static struct field_selection *_create_field_selection(struct dm_report *rh,
/* store comparison operand */
if (flags & FLD_CMP_REGEX) {
/* REGEX */
if (!(s = malloc(len + 1))) {
log_error("dm_report: malloc failed to store "
"regex value for selection field %s", field_id);
goto error;
}
memcpy(s, v, len);
s[len] = '\0';
switch (flags & DM_REPORT_FIELD_TYPE_MASK) {
case DM_REPORT_FIELD_TYPE_STRING:
if (!(s = malloc(len + 1))) {
log_error("dm_report: malloc failed to store "
"regex value for selection field %s", field_id);
goto error;
}
memcpy(s, v, len);
s[len] = '\0';
s_arr_single[0] = s;
fs->value->v.r = dm_regex_create(rh->selection->mem, (const char * const *) &s, 1);
free(s);
if (!fs->value->v.r) {
log_error("dm_report: failed to create regex "
"matcher for selection field %s", field_id);
goto error;
fs->value->v.r = _selection_regex_create(rh->selection, s_arr_single, 1);
free(s);
if (!fs->value->v.r) {
log_error("dm_report: failed to create regex "
"matcher for selection field %s", field_id);
goto error;
}
break;
case DM_REPORT_FIELD_TYPE_STRING_LIST:
if (!custom)
goto bad;
fs->value->v.l = *((struct selection_str_list **) custom);
if (!(s_arr_size = dm_list_size(&fs->value->v.l->str_list.list)))
break;
if (!(s_arr = calloc(s_arr_size, sizeof(char *)))) {
log_error("dm_report: malloc failed for regex array "
"for selection field %s", field_id);
goto error;
}
i = 0;
dm_list_iterate_items(sl, &fs->value->v.l->str_list.list)
s_arr[i++] = sl->str;
fs->value->v.l->regex = _selection_regex_create(rh->selection, s_arr, s_arr_size);
fs->value->v.l->regex_num_patterns = s_arr_size;
free(s_arr);
if (!fs->value->v.l->regex) {
log_error("dm_report: failed to create regex "
"matcher for selection field %s", field_id);
goto error;
}
break;
default:
log_error(INTERNAL_ERROR "_create_field_selection: regex: incorrect type %" PRIu32 " for field %s",
flags & DM_REPORT_FIELD_TYPE_MASK, field_id);
goto error;
}
} else {
/* STRING, NUMBER, SIZE, PERCENT, STRING_LIST, TIME */
@@ -3715,8 +3972,8 @@ static struct field_selection *_create_field_selection(struct dm_report *rh,
}
break;
default:
log_error(INTERNAL_ERROR "_create_field_selection: "
"unknown type of selection field %s", field_id);
log_error(INTERNAL_ERROR "_create_field_selection: incorrect type %" PRIu32 " for field %s",
flags & DM_REPORT_FIELD_TYPE_MASK, field_id);
goto error;
}
}
@@ -3727,7 +3984,7 @@ error_field_id:
field_id);
goto error;
bad:
log_error(INTERNAL_ERROR "Forbidden NULL custom detected.");
log_error(INTERNAL_ERROR "_create_field_selection: Forbidden NULL custom detected.");
error:
dm_pool_free(rh->selection->mem, fs);
@@ -3821,8 +4078,11 @@ out_reserved_values:
log_warn(" ");
}
static const char _sel_syntax_error_at_msg[] = "Selection syntax error at '%s'.";
static const char _sel_help_ref_msg[] = "Use \'help\' for selection to get more help.";
static void _parse_syntax_error(const char *s)
{
log_error("Selection syntax error at '%s'.", s);
log_error("Use \'help\' for selection to get more help.");
}
/*
* Selection parser
@@ -3863,7 +4123,7 @@ static struct selection_node *_parse_selection(struct dm_report *rh,
char *tmp;
char c;
/* field name */
/* get field name */
if (!(last = _tok_field_name(s, &ws, &we))) {
log_error("Expecting field name");
goto bad;
@@ -3896,7 +4156,7 @@ static struct selection_node *_parse_selection(struct dm_report *rh,
} else
ft = &rh->fields[field_num];
/* comparison operator */
/* get comparison operator */
if (!(flags = _tok_op_cmp(we, &last))) {
_display_selection_help(rh);
log_error("Unrecognised comparison operator: %s", we);
@@ -3908,50 +4168,49 @@ static struct selection_node *_parse_selection(struct dm_report *rh,
goto bad;
}
/* comparison value */
/* check we can use the operator with the field */
if (flags & FLD_CMP_REGEX) {
/*
* REGEX value
*/
if (!(last = _tok_value_regex(rh, ft, last, &vs, &ve, &flags, &rvw)))
goto_bad;
} else {
/*
* STRING, NUMBER, SIZE, PERCENT, STRING_LIST, TIME value
*/
if (flags & FLD_CMP_NUMBER) {
if (!(ft->flags & (DM_REPORT_FIELD_TYPE_NUMBER |
DM_REPORT_FIELD_TYPE_SIZE |
DM_REPORT_FIELD_TYPE_PERCENT |
DM_REPORT_FIELD_TYPE_TIME))) {
_display_selection_help(rh);
log_error("Operator can be used only with number, size, time or percent fields: %s", ws);
goto bad;
}
} else if (flags & FLD_CMP_TIME) {
if (!(ft->flags & DM_REPORT_FIELD_TYPE_TIME)) {
_display_selection_help(rh);
log_error("Operator can be used only with time fields: %s", ws);
goto bad;
}
if (!(ft->flags & (DM_REPORT_FIELD_TYPE_STRING |
DM_REPORT_FIELD_TYPE_STRING_LIST))) {
_display_selection_help(rh);
log_error("Operator can be used only with string or string list fields: %s", ws);
goto bad;
}
} else if (flags & FLD_CMP_NUMBER) {
if (!(ft->flags & (DM_REPORT_FIELD_TYPE_NUMBER |
DM_REPORT_FIELD_TYPE_SIZE |
DM_REPORT_FIELD_TYPE_PERCENT |
DM_REPORT_FIELD_TYPE_TIME))) {
_display_selection_help(rh);
log_error("Operator can be used only with number, size, time or percent fields: %s", ws);
goto bad;
}
} else if (flags & FLD_CMP_TIME) {
if (!(ft->flags & DM_REPORT_FIELD_TYPE_TIME)) {
_display_selection_help(rh);
log_error("Operator can be used only with time fields: %s", ws);
goto bad;
}
if (ft->flags == DM_REPORT_FIELD_TYPE_SIZE ||
ft->flags == DM_REPORT_FIELD_TYPE_NUMBER ||
ft->flags == DM_REPORT_FIELD_TYPE_PERCENT)
custom = &factor;
else if (ft->flags & DM_REPORT_FIELD_TYPE_TIME)
custom = &tval;
else if (ft->flags == DM_REPORT_FIELD_TYPE_STRING_LIST)
custom = &str_list;
else
custom = NULL;
if (!(last = _tok_value(rh, ft, field_num, implicit,
last, &vs, &ve, &flags,
&rvw, rh->selection->mem, custom)))
goto_bad;
}
/* assign custom structures to hold extra information for specific value types */
if (ft->flags == DM_REPORT_FIELD_TYPE_SIZE ||
ft->flags == DM_REPORT_FIELD_TYPE_NUMBER ||
ft->flags == DM_REPORT_FIELD_TYPE_PERCENT)
custom = &factor;
else if (ft->flags & DM_REPORT_FIELD_TYPE_TIME)
custom = &tval;
else if (ft->flags == DM_REPORT_FIELD_TYPE_STRING_LIST)
custom = &str_list;
else
custom = NULL;
/* get value to compare with */
if (!(last = _tok_value(rh, ft, field_num, implicit,
last, &vs, &ve, &flags,
&rvw, rh->selection->mem, custom)))
goto_bad;
*next = _skip_space(last);
/* create selection */
@@ -3967,8 +4226,7 @@ static struct selection_node *_parse_selection(struct dm_report *rh,
return sn;
bad:
log_error(_sel_syntax_error_at_msg, s);
log_error(_sel_help_ref_msg);
_parse_syntax_error(s);
*next = s;
return NULL;
}
@@ -4092,7 +4350,7 @@ error:
static int _alloc_rh_selection(struct dm_report *rh)
{
if (!(rh->selection = dm_pool_zalloc(rh->mem, sizeof(struct selection))) ||
!(rh->selection->mem = dm_pool_create("report selection", 10 * 1024))) {
!(rh->selection->mem = dm_pool_create("report selection", 1024))) {
log_error("Failed to allocate report selection structure.");
if (rh->selection)
dm_pool_free(rh->mem, rh->selection);
@@ -4133,8 +4391,7 @@ static int _report_set_selection(struct dm_report *rh, const char *selection, in
next = _skip_space(fin);
if (*next) {
log_error("Expecting logical operator");
log_error(_sel_syntax_error_at_msg, next);
log_error(_sel_help_ref_msg);
_parse_syntax_error(next);
goto bad;
}
@@ -4371,9 +4628,10 @@ static int _row_compare(const void *a, const void *b)
for (cnt = 0; cnt < rowa->rh->keys_count; cnt++) {
sfa = (*rowa->sort_fields)[cnt];
sfb = (*rowb->sort_fields)[cnt];
if ((sfa->props->flags & DM_REPORT_FIELD_TYPE_NUMBER) ||
(sfa->props->flags & DM_REPORT_FIELD_TYPE_SIZE) ||
(sfa->props->flags & DM_REPORT_FIELD_TYPE_TIME)) {
if (sfa->props->flags &
((DM_REPORT_FIELD_TYPE_NUMBER) |
(DM_REPORT_FIELD_TYPE_SIZE) |
(DM_REPORT_FIELD_TYPE_TIME))) {
const uint64_t numa =
*(const uint64_t *) sfa->sort_value;
const uint64_t numb =
@@ -4413,9 +4671,12 @@ static int _sort_rows(struct dm_report *rh)
struct row *(*rows)[];
uint32_t count = 0;
struct row *row;
size_t cnt_rows;
if (!(rows = dm_pool_alloc(rh->mem, sizeof(**rows) *
dm_list_size(&rh->rows)))) {
if (!(cnt_rows = dm_list_size(&rh->rows)))
return 1; /* nothing to sort */
if (!(rows = dm_pool_alloc(rh->mem, sizeof(**rows) * cnt_rows))) {
log_error("dm_report: sort array allocation failed");
return 0;
}
@@ -4484,6 +4745,7 @@ static const char *_get_field_id(struct dm_report *rh, struct dm_report_field *f
static int _output_field_basic_fmt(struct dm_report *rh, struct dm_report_field *field)
{
char buf_local[8192];
char *field_id;
int32_t width;
uint32_t align;
@@ -4491,25 +4753,26 @@ static int _output_field_basic_fmt(struct dm_report *rh, struct dm_report_field
size_t buf_size = 0;
if (rh->flags & DM_REPORT_OUTPUT_FIELD_NAME_PREFIX) {
if (!(field_id = strdup(_get_field_id(rh, field)))) {
log_error("dm_report: Failed to copy field name");
buf_size = strlen(_get_field_id(rh, field)) + 1;
if (buf_size >= sizeof(buf_local)) {
/* for field names our buf_local should be enough */
log_error(UNABLE_TO_EXTEND_OUTPUT_LINE_MSG);
return 0;
}
field_id = buf_local;
memcpy(field_id, _get_field_id(rh, field), buf_size);
if (!dm_pool_grow_object(rh->mem, rh->output_field_name_prefix, 0)) {
log_error(UNABLE_TO_EXTEND_OUTPUT_LINE_MSG);
free(field_id);
return 0;
}
if (!dm_pool_grow_object(rh->mem, _toupperstr(field_id), 0)) {
log_error(UNABLE_TO_EXTEND_OUTPUT_LINE_MSG);
free(field_id);
return 0;
}
free(field_id);
if (!dm_pool_grow_object(rh->mem, STANDARD_PAIR, 1)) {
log_error(UNABLE_TO_EXTEND_OUTPUT_LINE_MSG);
return 0;
@@ -4532,7 +4795,10 @@ static int _output_field_basic_fmt(struct dm_report *rh, struct dm_report_field
/* Including trailing '\0'! */
buf_size = width + 1;
if (!(buf = malloc(buf_size))) {
if (buf_size < sizeof(buf_local))
/* Use local buffer on stack for smaller strings */
buf = buf_local;
else if (!(buf = malloc(buf_size))) {
log_error("dm_report: Could not allocate memory for output line buffer.");
return 0;
}
@@ -4574,40 +4840,50 @@ static int _output_field_basic_fmt(struct dm_report *rh, struct dm_report_field
}
}
free(buf);
if (buf != buf_local)
free(buf);
return 1;
bad:
free(buf);
if (buf != buf_local)
free(buf);
return 0;
}
static int _safe_repstr_output(struct dm_report *rh, const char *repstr, size_t len)
{
const char *p_repstr;
const char *repstr_next_write = repstr;
const char *repstr_current = repstr;
const char *repstr_end = len ? repstr + len : repstr + strlen(repstr);
/* Escape any JSON_QUOTE that may appear in reported string. */
while (1) {
if (!(p_repstr = memchr(repstr, JSON_QUOTE[0], repstr_end - repstr)))
break;
/* Escape any JSON_ESCAPE_CHAR and JSON_QUOTE that may appear in reported string. */
while (repstr_current < repstr_end) {
if (repstr_current[0] == JSON_ESCAPE_CHAR[0] || repstr_current[0] == JSON_QUOTE[0]) {
// Write out all "sanitized" chars so far
if (repstr_next_write < repstr_current) {
if (!dm_pool_grow_object(rh->mem, repstr_next_write, repstr_current - repstr_next_write)) {
log_error(UNABLE_TO_EXTEND_OUTPUT_LINE_MSG);
return 0;
}
if (p_repstr > repstr) {
if (!dm_pool_grow_object(rh->mem, repstr, p_repstr - repstr)) {
repstr_next_write = repstr_current;
}
// Add an escape
if (!dm_pool_grow_object(rh->mem, JSON_ESCAPE_CHAR, 1)) {
log_error(UNABLE_TO_EXTEND_OUTPUT_LINE_MSG);
return 0;
}
}
if (!dm_pool_grow_object(rh->mem, JSON_ESCAPE_CHAR, 1) ||
!dm_pool_grow_object(rh->mem, JSON_QUOTE, 1)) {
++repstr_current;
}
// Write out all remaining "sanitized" chars
if (repstr_next_write < repstr_end) {
if (!dm_pool_grow_object(rh->mem, repstr_next_write, repstr_end - repstr_next_write)) {
log_error(UNABLE_TO_EXTEND_OUTPUT_LINE_MSG);
return 0;
}
repstr = p_repstr + 1;
}
if (!dm_pool_grow_object(rh->mem, repstr, repstr_end - repstr)) {
log_error(UNABLE_TO_EXTEND_OUTPUT_LINE_MSG);
return 0;
}
return 1;
@@ -4847,6 +5123,7 @@ static int _output_as_columns(struct dm_report *rh)
struct dm_report_field *field;
struct dm_list *last_rowh;
int do_field_delim;
int is_json_report = _is_json_report(rh);
char *line;
/* If headings not printed yet, calculate field widths and print them */
@@ -4866,7 +5143,7 @@ static int _output_as_columns(struct dm_report *rh)
return 0;
}
if (_is_json_report(rh)) {
if (is_json_report) {
if (!dm_pool_grow_object(rh->mem, JSON_OBJECT_START, 0)) {
log_error(UNABLE_TO_EXTEND_OUTPUT_LINE_MSG);
goto bad;
@@ -4881,7 +5158,7 @@ static int _output_as_columns(struct dm_report *rh)
continue;
if (do_field_delim) {
if (_is_json_report(rh)) {
if (is_json_report) {
if (!dm_pool_grow_object(rh->mem, JSON_SEPARATOR, 0) ||
!dm_pool_grow_object(rh->mem, JSON_SPACE, 0)) {
log_error(UNABLE_TO_EXTEND_OUTPUT_LINE_MSG);
@@ -4903,7 +5180,7 @@ static int _output_as_columns(struct dm_report *rh)
dm_list_del(&field->list);
}
if (_is_json_report(rh)) {
if (is_json_report) {
if (!dm_pool_grow_object(rh->mem, JSON_OBJECT_END, 0)) {
log_error(UNABLE_TO_EXTEND_OUTPUT_LINE_MSG);
goto bad;
@@ -5090,6 +5367,15 @@ struct dm_report_group *dm_report_group_create(dm_report_group_type_t type, void
struct dm_pool *mem;
struct report_group_item *item;
if (type == DM_REPORT_GROUP_JSON_STD) {
const char * radixchar = nl_langinfo(RADIXCHAR);
if (radixchar && strcmp(radixchar, ".")) {
log_error("dm_report: incompatible locale used for DM_REPORT_GROUP_JSON_STD, "
"radix character is '%s', expected '.'", radixchar);
return NULL;
}
}
if (!(mem = dm_pool_create("report_group", 1024))) {
log_error("dm_report: dm_report_init_group: failed to allocate mem pool");
return NULL;

View File

@@ -169,7 +169,7 @@ int dm_vasprintf(char **result, const char *format, va_list aq)
}
if (i > 1) {
/* Reallocating more then once? */
/* Reallocating more than once? */
if (!(*result = strdup(buf))) {
free(buf);
return -1;
@@ -471,10 +471,10 @@ const char *dm_size_to_string(struct dm_pool *mem, uint64_t size,
double d;
uint64_t byte = UINT64_C(0);
uint64_t units = UINT64_C(1024);
char *size_buf = NULL;
char *size_buf;
char new_unit_type = '\0', unit_type_buf[2];
const char *prefix = "";
const char * const size_str[][3] = {
static const char _size_str[][3][12] = {
/* BASE_UNKNOWN */
{" ", " ", " "}, /* [0] */
@@ -519,14 +519,14 @@ const char *dm_size_to_string(struct dm_pool *mem, uint64_t size,
/* Case-independent match */
for (s = 0; s < NUM_UNIT_PREFIXES; s++)
if (toupper((int) unit_type) ==
*size_str[BASE_SHARED + s][2]) {
*_size_str[BASE_SHARED + s][2]) {
base = BASE_SHARED;
break;
}
} else {
/* Case-dependent match for powers of 1000 */
for (s = 0; s < NUM_UNIT_PREFIXES; s++)
if (unit_type == *size_str[BASE_1000 + s][2]) {
if (unit_type == *_size_str[BASE_1000 + s][2]) {
base = BASE_1000;
break;
}
@@ -534,7 +534,7 @@ const char *dm_size_to_string(struct dm_pool *mem, uint64_t size,
/* Case-dependent match for powers of 1024 */
if (base == BASE_UNKNOWN)
for (s = 0; s < NUM_UNIT_PREFIXES; s++)
if (unit_type == *size_str[BASE_1024 + s][2]) {
if (unit_type == *_size_str[BASE_1024 + s][2]) {
base = BASE_1024;
break;
}
@@ -544,7 +544,7 @@ const char *dm_size_to_string(struct dm_pool *mem, uint64_t size,
/* Check for special units - s, b or u */
for (s = 0; s < NUM_SPECIAL; s++)
if (toupper((int) unit_type) ==
*size_str[BASE_SPECIAL + s][2]) {
*_size_str[BASE_SPECIAL + s][2]) {
base = BASE_SPECIAL;
break;
}
@@ -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;
snprintf(size_buf, 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;
}
@@ -591,7 +591,7 @@ const char *dm_size_to_string(struct dm_pool *mem, uint64_t size,
if ((s < NUM_UNIT_PREFIXES) &&
((unit_type == 'R') || (unit_type == 'r'))) {
/* When the rounding would cause difference, add '<' prefix
* i.e. 2043M is more then 1.9949G prints <2.00G
* i.e. 2043M is more than 1.9949G prints <2.00G
* This version is for 2 digits fixed precision */
d = 100. * (double) size / byte;
if (!_close_enough(floorl(d), nearbyintl(d)))
@@ -602,7 +602,7 @@ const char *dm_size_to_string(struct dm_pool *mem, uint64_t size,
}
/* FIXME Make precision configurable */
switch (toupper(*size_str[base + s][DM_SIZE_UNIT])) {
switch (toupper(*_size_str[base + s][DM_SIZE_UNIT])) {
case 'B':
case 'S':
precision = 0;
@@ -612,7 +612,7 @@ const char *dm_size_to_string(struct dm_pool *mem, uint64_t size,
}
snprintf(size_buf, SIZE_BUF, "%s%.*f%s", prefix, precision,
(double) size / byte, include_suffix ? size_str[base + s][suffix_type] : "");
(double) size / byte, include_suffix ? _size_str[base + s][suffix_type] : "");
return size_buf;
}

View File

@@ -120,7 +120,7 @@ int dm_get_status_raid(struct dm_pool *mem, const char *params,
if (!(pp = _skip_fields(p, 1)))
goto_bad;
/* Raid target can actually report more then real number of legs in a case
/* Raid target can actually report more than 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;
@@ -335,11 +335,19 @@ int dm_get_status_cache(struct dm_pool *mem, const char *params,
/* Read in policy args */
pp = p;
if (!(p = _skip_fields(p, 1)) ||
!(s->policy_name = dm_pool_zalloc(mem, (p - pp))))
goto bad;
if (sscanf(pp, "%s %d", s->policy_name, &s->policy_argc) != 2)
if (!(p = _skip_fields(p, 1)))
goto_bad;
i = p - pp;
if ((i < 1) ||
!(s->policy_name = dm_pool_zalloc(mem, i)))
goto_bad;
dm_strncpy(s->policy_name, pp, i);
if (sscanf(p, "%d", &s->policy_argc) != 1)
goto bad;
if (s->policy_argc &&
(!(s->policy_argv = dm_pool_zalloc(mem, sizeof(char *) * s->policy_argc)) ||
!(p = _skip_fields(p, 1)) ||
@@ -401,12 +409,12 @@ int dm_get_status_integrity(struct dm_pool *mem, const char *params,
struct dm_status_integrity **status)
{
struct dm_status_integrity *s;
char recalc_str[16] = "\0";
char recalc_str[16] = { 0 };
if (!(s = dm_pool_zalloc(mem, sizeof(*s))))
return_0;
if (sscanf(params, "%llu %llu %s",
if (sscanf(params, "%llu %llu %15s",
(unsigned long long *)&s->number_of_mismatches,
(unsigned long long *)&s->provided_data_sectors,
recalc_str) != 3) {
@@ -571,7 +579,7 @@ int dm_get_status_mirror(struct dm_pool *mem, const char *params,
pos += used;
if (num_devs > DM_MIRROR_MAX_IMAGES) {
log_error(INTERNAL_ERROR "More then " DM_TO_STRING(DM_MIRROR_MAX_IMAGES)
log_error(INTERNAL_ERROR "More than " DM_TO_STRING(DM_MIRROR_MAX_IMAGES)
" reported in mirror status.");
goto out;
}

View File

@@ -13,6 +13,8 @@
# include <linux/types.h>
#endif
#include <stdint.h>
#define DM_DIR "mapper" /* Slashes not supported */
#define DM_CONTROL_NODE "control"
#define DM_MAX_TYPE_NAME 16

View File

@@ -13,7 +13,8 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "dmlib.h"
#include "base/memory/zalloc.h"
#include "device_mapper/misc/dmlib.h"
#include <assert.h>
struct block {

View File

@@ -14,7 +14,7 @@
*/
#ifdef VALGRIND_POOL
#include "memcheck.h"
#include <memcheck.h>
#endif
#include "base/memory/zalloc.h"

View File

@@ -0,0 +1,165 @@
/*
* Copyright (C) 2024 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
*/
/*
* Support counting number of failed device bits in dm-raid superblock bit arrays or clear them out.
*/
#include "device_mapper/misc/dmlib.h"
#include "device_mapper/all.h"
#include "device_mapper/raid/target.h"
#include "lib/mm/xlate.h"
#include <fcntl.h>
#include <unistd.h>
/* Copied/derived from kernel's drivers/md/dm-raid.c so this is prone to out-of-sync (factor out to header file?). */
#define MAX_RAID_DEVICES 253 /* md-raid kernel limit? */
#define UINT64_BITS (sizeof(uint64_t) * 8)
#define DISKS_ARRAY_ELEMS ((MAX_RAID_DEVICES + (UINT64_BITS - 1)) / UINT64_BITS)
#define DM_RAID_SB_MAGIC 0x446D5264 /* "DmRd" */
#define FEATURE_FLAG_SUPPORTS_V190 0x1 /* Supports extended superblock */
/* RAID superblock at beginning of rmeta SubLVs trimmed down to mandatory members. */
struct dm_raid_superblock {
__le32 magic; /* "DmRd" */
__le32 compat_features; /* Used to indicate compatible features (like 1.9.0 ondisk metadata extension) */
__le32 dummy[4];
__le64 failed_devices; /* Pre 1.9.0 part of bit field of devices to */
/* indicate device failures (see extension below) */
__le32 dummy1[7];
/********************************************************************
* BELOW FOLLOW V1.9.0 EXTENSIONS TO THE PRISTINE SUPERBLOCK FORMAT!!!
*
* FEATURE_FLAG_SUPPORTS_V190 in the compat_features member indicates that those exist
*/
__le32 flags; /* Flags defining array states for reshaping */
__le32 dummy2[14];
__le64 extended_failed_devices[DISKS_ARRAY_ELEMS - 1];
__le32 dummy3;
/* Always set rest up to logical block size to 0 when writing ... */
} __packed;
/* END: Copied from ... */
/* Superblock I/O buffer size to be able to Cope with 4K native devices... */
#define SB_BUFSZ 4096
static size_t _get_sb_size(const struct dm_raid_superblock *sb)
{
return (FEATURE_FLAG_SUPPORTS_V190 & le32toh(sb->compat_features)) ?
sizeof(*sb) : ((char *) &sb->flags - (char *) sb);
}
static uint32_t _hweight64(__le64 v)
{
uint32_t r = 0;
while (v) {
r += v & 1;
v >>= 1;
}
return r;
}
static uint32_t _hweight_failed(struct dm_raid_superblock *sb)
{
uint32_t r = _hweight64(sb->failed_devices);
if (_get_sb_size(sb) == sizeof(*sb)) {
int i = (int)DM_ARRAY_SIZE(sb->extended_failed_devices);
while (i--)
r = max(r, _hweight64(sb->extended_failed_devices[i]));
}
return r;
}
static void _clear_failed_devices(struct dm_raid_superblock *sb)
{
sb->failed_devices = 0;
if (_get_sb_size(sb) == sizeof(*sb))
memset(sb->extended_failed_devices, 0, sizeof(sb->extended_failed_devices));
}
static int _count_or_clear_failed_devices(const char *dev_path, bool clear, uint32_t *nr_failed)
{
struct dm_raid_superblock *sb = NULL;
size_t sz;
int fd, r = 0;
if (posix_memalign((void *) &sb, SB_BUFSZ, SB_BUFSZ)) {
log_sys_error("Failed to allocate RAID superblock buffer", dev_path);
return 0;
}
fd = open(dev_path, O_EXCL | ((clear) ? O_RDWR : O_RDONLY) | O_DIRECT);
if (fd < 0) {
log_sys_error("Failed to open RAID metadata volume", dev_path);
goto out;
}
if (read(fd, sb, SB_BUFSZ) != SB_BUFSZ) {
log_sys_error("Failed to read RAID metadata volume", dev_path);
goto out;
}
/* FIXME: big endian??? */
if (sb->magic != htobe32(DM_RAID_SB_MAGIC)) {
log_error("No RAID signature on %s.", dev_path);
goto out;
}
if (nr_failed)
*nr_failed = _hweight_failed(sb);
if (clear) {
if (lseek(fd, 0, SEEK_SET) < 0) {
log_sys_error("Failed to seek RAID metadata volume", dev_path);
goto out;
}
sz = _get_sb_size(sb);
memset((void *)((char *) sb + sz), 0, SB_BUFSZ - sz);
_clear_failed_devices(sb);
if (write(fd, sb, SB_BUFSZ) != SB_BUFSZ) {
log_sys_error("Failed to clear RAID metadata volume", dev_path);
goto out;
}
}
r = 1;
out:
if ((fd >= 0) && close(fd))
log_sys_debug("close", dev_path);
free(sb);
return r;
}
int dm_raid_count_failed_devices(const char *dev_path, uint32_t *nr_failed)
{
return _count_or_clear_failed_devices(dev_path, false, nr_failed);
}
int dm_raid_clear_failed_devices(const char *dev_path, uint32_t *nr_failed)
{
return _count_or_clear_failed_devices(dev_path, true, nr_failed);
}

View File

@@ -0,0 +1,23 @@
/*
* Copyright (C) 2024 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
*/
#ifndef DEVICE_MAPPER_RAID_TARGET_H
#define DEVICE_MAPPER_RAID_TARGET_H
#include <stdint.h>
int dm_raid_count_failed_devices(const char *dev_path, uint32_t *nr_failed);
int dm_raid_clear_failed_devices(const char *dev_path, uint32_t *nr_failed);
#endif

View File

@@ -356,7 +356,7 @@ struct dm_regex *dm_regex_create(struct dm_pool *mem, const char * const *patter
for (i = 0; i < num_patterns; i++) {
ptr += sprintf(ptr, "(.*(%s)%c)", patterns[i], TARGET_TRANS);
if (i < (num_patterns - 1))
if ((i + 1) < num_patterns)
*ptr++ = '|';
}

View File

@@ -13,7 +13,6 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "device_mapper/misc/dmlib.h"
#include "parse_rx.h"
#ifdef DEBUG

View File

@@ -16,6 +16,8 @@
#ifndef _DM_PARSE_REGEX_H
#define _DM_PARSE_REGEX_H
#include "device_mapper/misc/dmlib.h"
enum {
CAT,
STAR,

View File

@@ -13,7 +13,6 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "device_mapper/misc/dmlib.h"
#include "ttree.h"
struct node {
@@ -84,9 +83,7 @@ int ttree_insert(struct ttree *tt, unsigned int *key, void *data)
} while (*c && count);
if (!*c) {
count++;
while (count--) {
do {
if (!(*c = _tree_node(tt->mem, k)))
return_0;
@@ -94,7 +91,7 @@ int ttree_insert(struct ttree *tt, unsigned int *key, void *data)
k = *key++;
c = &((*c)->m);
}
}
} while (count--);
}
(*c)->data = data;

View File

@@ -16,6 +16,8 @@
#ifndef _DM_TTREE_H
#define _DM_TTREE_H
#include "device_mapper/misc/dmlib.h"
struct ttree;
struct ttree *ttree_create(struct dm_pool *mem, unsigned int klen);

View File

@@ -28,11 +28,6 @@
#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>
@@ -72,7 +67,7 @@ enum {
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 */
uint64_t size; /* The size of the data following this header */
} __packed;
struct vdo_geometry_block {
@@ -140,36 +135,36 @@ struct vdo_volume_geometry_4 {
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);
v->major_version = le32toh(v->major_version);
v->minor_version = le32toh(v->minor_version);
}
static void _vdo_decode_header(struct vdo_header *h)
{
h->id = le32_to_cpu(h->id);
h->id = le32toh(h->id);
_vdo_decode_version(&h->version);
h->size = le64_to_cpu(h->size);
h->size = le64toh(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);
vr->id = (enum vdo_volume_region_id) le32toh(vr->id);
vr->start_block = le64toh(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);
vg->release_version = le32toh(vg->release_version);
vg->nonce = le64toh(vg->nonce);
vg->bio_offset = le64toh(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->release_version = le32toh(vg_4->release_version);
vg->nonce = le64toh(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]);
@@ -177,17 +172,17 @@ static void _vdo_decode_volume_geometry_4(struct vdo_volume_geometry *vg,
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);
vc->logical_blocks = le64toh(vc->logical_blocks);
vc->physical_blocks = le64toh(vc->physical_blocks);
vc->slab_size = le64toh(vc->slab_size);
vc->recovery_journal_size = le64toh(vc->recovery_journal_size);
vc->slab_journal_blocks = le64toh(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);
pvc->nonce = le64toh(pvc->nonce);
}
bool dm_vdo_parse_logical_size(const char *vdo_path, uint64_t *logical_blocks)
@@ -226,7 +221,7 @@ bool dm_vdo_parse_logical_size(const char *vdo_path, uint64_t *logical_blocks)
size = st.st_size;
}
if (read(fh, buffer, sizeof(buffer)) < 0) {
if (read(fh, buffer, sizeof(buffer)) < (int)(MAGIC_NUMBER_SIZE + sizeof(h))) {
log_sys_debug("read", vdo_path);
goto err;
}
@@ -270,7 +265,7 @@ bool dm_vdo_parse_logical_size(const char *vdo_path, uint64_t *logical_blocks)
goto err;
}
if (read(fh, buffer, sizeof(buffer)) < 0) {
if (read(fh, buffer, sizeof(buffer)) < (int)(sizeof(struct vdo_geometry_block) + sizeof(vn))) {
log_sys_debug("read", vdo_path);
goto err;
}

View File

@@ -28,7 +28,7 @@ bool dm_vdo_validate_target_params(const struct dm_vdo_target_params *vtp,
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);
(vtp->minimum_io_size << SECTOR_SHIFT));
valid = false;
}

View File

@@ -49,7 +49,7 @@ List of official [mirror sites](https://sourceware.org/mirrors.html) (including
### LVM Releases
[[!inline pages="release-notes/2.03.* and !*/template and !*/Discussion and !tagged(draft) and !tagged(pending)" limit=2 rootpage="release-notes"]]
[[!inline pages="release-notes/2.03.* and !*/template and !*/Discussion and !tagged(draft) and !tagged(pending)" limit="2" show="2" rootpage="release-notes"]]
[[More releases|release-notes/index]]
@@ -72,6 +72,7 @@ incorrectly!
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).
@@ -80,27 +81,34 @@ incorrectly!
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
List LVs 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).
See [lvcreate(8)](https://man7.org/linux/man-pages/man8/lvcreate.8.html).
To change size of LV it is recommended to use [lvresize(8)](https://man7.org/linux/man-pages/man8/lvresize.8.html) with `--resizefs` option.
To change properties of LV (e.g. to acivate/deactivate a volume, or change it to read only) use [lvchange(8)](https://man7.org/linux/man-pages/man8/lvchange.8.html).
To change the type of LV (e.g. change a linear volume to a RAID) use [lvconvert(8)](https://man7.org/linux/man-pages/man8/lvconvert.8.html).
## Avoiding Problems
Good start is to avoid using `{--force|-f}` and `{--yes|-y}` options which are
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
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
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!

View File

@@ -21,6 +21,6 @@ Version 2.03.27
[[!tag]]
<!--
For old releases add Release Timestamp like this, date from git show $COMMIT is fine.
\[[!meta date="Tue Nov 21 14:26:07 2023 +0100"]]
[[!meta date="Wed Oct 2 14:19:23 2024 +0200"]]
-->

View File

@@ -0,0 +1,20 @@
<!-- Page title -->
[[!meta title="Version 2.03.28 - Bug Fix Release"]]
Version 2.03.28
===============
Few bugfixes and a lot of speed improvements mainly for many LVs.
* Introduce setting config/validate_metadata = full | none.
* Restore fs resize call for lvresize -r on the same size LV (2.03.17).
* Correct off-by-one devicesfile backup counting.
* Fall back to direct zeroing if BLKZEROOUT fails during new LV initialization.
<!-- remove the pending tag on release, remove draft tag once editing is complete -->
[[!tag]]
<!--
For old releases add Release Timestamp like this, date from git show $COMMIT is fine.
[[!meta date="Mon Nov 4 16:42:12 2024 +0100"]]
-->

View File

@@ -0,0 +1,23 @@
<!-- Page title -->
[[!meta title="Version 2.03.29 - Bug Fix Release"]]
Version 2.03.29
===============
Mostly bugfix release, few interesting changes:
* **Fix renaming of raid sub LVs when converting a volume to raid (2.03.28)**.
* **Fix segfault/VG write error for raid LV `lvextend -i|--stripes -I|--stripesize`**.
* Add configure --enable/disable-sd-notify to control lvmlockd build with sd-notify.
* Allow test mode when lvmlockd is built without dlm support.
* Add a note about RAID + integrity synchronization to lvmraid(7) man page.
* Add a function for running lvconvert --repair on RAID LVs to lvmdbusd.
* Improve option section of man pages for listing commands ({pv,lv,vg}{s,display}).
* And some cleanup mostly in test code.
<!-- remove the pending tag on release, remove draft tag once editing is complete -->
[[!tag]]
<!--
For old releases add Release Timestamp like this, date from git show $COMMIT is fine.
[[!meta date="Mon Dec 09 12:57:57 2024 +0100"]]
-->

View File

@@ -0,0 +1,24 @@
<!-- Page title -->
[[!meta title="Version 2.03.30 - Bug Fix Release"]]
Version 2.03.30
===============
Small bugfix release:
* **NEW** Create `/dev/disk/by-diskseq/<DISKSEQ>` symlink for public DM devices.
* Lvresize reports origin vdo volume cannot be resized.
* Support setting `reserved_memory|stack` using `--config` on cmdline.
* Fix support for disabling memory locking (2.03.27).
* Do not extend an LV if FS resize unsupported and `--fs resize` used.
* Prevent leftover temporary device when converting in use volume to a pool.
* lvconvert detects volume in use early when converting it to a pool.
* Handle NVMe with quirk changed WWID not matching WWID in devices file.
<!-- remove the pending tag on release, remove draft tag once editing is complete -->
[[!tag]]
<!--
For old releases add Release Timestamp like this, date from git show $COMMIT is fine.
[[!meta date="Tue Jan 14 20:55:33 2025 +0100"]]
-->

View File

@@ -0,0 +1,33 @@
<!-- Page title -->
[[!meta title="Version 2.03.31 - Bug Fix Release"]]
Version 2.03.31
===============
Bugfix release:
* Disallow shared activation of LV with CoW snapshot.
* Ignore reported `optimal_io_size` not divisible by 4096.
* Restore support for `LVM_SUPPRESS_FD_WARNINGS` (2.03.24).
* Fix DM cache preserving logic (2.03.28).
* Restore missing symbol `dm_tree_node_size_changed@Base` (1.02.175).
* Restore missing symbol `dm_bitset_parse_list@@DM_1_02_138` (1.02.175).
* Fix uncache and split cache restoring original state of volume.
* Extend use of lockopt skip to more scenarios.
* Reduce `mandoc -T lint` reported issues for man pages.
* Enhance error path resolving in polling code.
* Fix lvmlockd use in lvremove of CoW snapshot, VDO pool, and uncache.
* Improve mirror split with opened temporary volumes.
* Improve pvmove finish with opened temporary volumes.
* Fix backup limit for devices file, handle over 10,000 files.
* Fix busy-loop in config reading when read returned 0.
* Improve use of lvmlockd for usecases involving thin volumes and pools.
<!-- remove the pending tag on release, remove draft tag once editing is complete -->
[[!tag]]
<!--
For old releases add Release Timestamp like this, date from git show $COMMIT is fine.
[[!meta date="Thu Feb 27 16:51:29 2025 +0100"]]
-->

View File

@@ -0,0 +1,26 @@
<!-- Page title -->
[[!meta title="Version 2.03.32 - Bug Fix Release"]]
Version 2.03.32
===============
Mostly bugfix release:
* Add support for using regex in selection criteria for string lists.
* Accept thin pool data LV as cachable LV.
* Accept `--autobackup` option in pvresize.
* Allow using zram block devices (likely for testing).
* Lvconvert vdopool conversion propperly validates acceptable LVs.
* Fix lvresize when resizing COW snapshots already covering origin.
* Fix lvmdbusd read of executed lvm commands output.
* Fix construction of DM UUID for cachevol `_cdata` and `_cmeta` devices.
* Ignore PV claims from old metadata when then PV belongs to a new VG.
* Fix integrity metadata rounding.
* Fix string list selection when using `[<item> || <item> ...]`.
<!-- remove the pending tag on release, remove draft tag once editing is complete -->
[[!tag]]
<!--
For old releases add Release Timestamp like this, date from git show $COMMIT is fine.
[[!meta date="Mon May 05 17:02:00 2025 +0200"]]
-->

View File

@@ -0,0 +1,19 @@
<!-- Page title -->
[[!meta title="Version 2.03.33 - Bug Fix Release"]]
Version 2.03.33
===============
Mostly bugfix release:
* Use `lvconvert --repair` to repair raid arrays with transiently lost devices.
* Override `LC_NUMERIC` locale if unsuitable for `json_std` report format.
* Fail `dm_report_group_create` if radix char from locale unsuitable for `json_std`.
* Escape the escape character itself on JSON report format output.
<!-- remove the pending tag on release, remove draft tag once editing is complete -->
[[!tag]]
<!--
For old releases add Release Timestamp like this, date from git show $COMMIT is fine.
[[!meta date="Fri Jun 27 10:14:00 2025 +0200"]]
-->

View File

@@ -0,0 +1,30 @@
<!-- Page title -->
[[!meta title="Version 2.03.34 - Bug Fix Release"]]
Version 2.03.34
===============
Add *Persisten Reservations* and many mostly small fixes.
* **NEW** Add support for **persistent reservations** controlling access to shared PVs.
* See [lvmpersist(8)](https://man7.org/linux/man-pages/man8/lvmpersist.8.html) for more details.
* Add `lvmlockd --lockopt repair` to reinitialize corrupted sanlock leases.
* Add *lvm.conf* `global/lvresize_fs_helper_executable`.
* Fix lvresize corruption in LV->crypt->FS stack if near crypt min size limit.
* Support dmeventd restart when there are no monitored devices.
* Dmeventd no longer calls 'action commands' on removed devices.
* Enhanced `lvresize -r` support for btrfs.
* Fix reader of VDO metadata on 32bit architecture.
* Fix `lvmdevices --deldev/--delpvid` to error out if devices file not writeable.
* Use glibc standard functions htoX, Xtoh functions for endian conversion.
* Fix structure copying within sanlock's `release_rename()`.
* Fix autoactivation on top of loop dev PVs to trigger once for change uevents.
* Fix support for `lvcreate -T --setautoactivation`.
* Fix many issues found by coverity static analysis, gcc warnings, typos, tests, and other clean ups.
<!-- remove the pending tag on release, remove draft tag once editing is complete -->
[[!tag]]
<!--
For old releases add Release Timestamp like this, date from git show $COMMIT is fine.
[[!meta date="Wed Jul 30 15:35:00 2025 +0200"]]
-->

View File

@@ -0,0 +1,53 @@
<!-- Page title -->
[[!meta title="Version 2.03.35 - Feature and Bug Fix Release"]]
Version 2.03.35
===============
* Optimize dmeventd when remonitoring active devices.
* Allow report options for `(pv|vg|lv)display` only if used with `-C|--columns`.
* And [[!toggle text="more"]]
[[!toggleable text="""
Features
-----------------------
### Optimize dmeventd when remonitoring active devices.
Add grace period (controlled by `-g SECONDS` option) to [dmeventd(8)](https://man7.org/linux/man-pages/man8/dmeventd.8.html) to reuse threads.
This change help to reduce overhead and unnecessary `lvextend` calls.
<!--
TODO: It would be nice if we could use a real session output, so we could test the examples
- During tests, save some outputs
-->
Changes in command line
-----------------------
* Report options (`--select STRING`, `--configreport CONFIG_REPORT`, `--logonly`)
are allowed only with `(pv|vg|lv)display -C|--columns`.
These **no longer work** without `-C|--columns` and were removed as they were not working properly anyway.
Other Changes
-------------
* Fix unlocking devices file only after all PVs are processed.
* Avoid creating system.devices when deleting entries.
* Fix existing issues with persistent reservations.
* Fix possible report output format inconsistencies while processing PVs.
* Allow report options for pv/vg/lvdisplay only if used with -C|--columns.
* Fix vgsplit failing to split a VG with RAID+integrity or cache with cachevol.
* Fix --lockopt handling in lvmlockd when --nolocking is used.
* Optimize dmeventd when remonitoring active devices.
"""]]
<!-- remove the pending tag on release, remove draft tag once editing is complete -->
[[!tag]]
<!--
For old releases add Release Timestamp like this, date from git show $COMMIT is fine.
[[!meta date="Tue Sep 09 14:19:37 2025 +0200"]]
-->

View File

@@ -4,5 +4,5 @@ This list is incomplete, only releases with a release-note are included.
For releases of stable branch 2.03 see [[index]].
[[!inline pages="release-notes/2.02.* and !*/template and !*/Discussion and !tagged(draft) and !tagged(pending)" limit=2 rootpage="release-notes"]]
[[!inline pages="release-notes/2.02.* and !*/template and !*/Discussion and !tagged(draft) and !tagged(pending)" rootpage="release-notes"]]

View File

@@ -579,7 +579,7 @@
/* Define to 1 to include code that uses lvmlockd IDM option. */
#undef LOCKDIDM_SUPPORT
/* Define to 1 to include code that uses lvmlockd sanlock option. */
/* Define version of sanlock. */
#undef LOCKDSANLOCK_SUPPORT
/* Define to 1 if 'lstat' dereferences a symlink specified with a trailing
@@ -598,6 +598,9 @@
/* Define to 1 to include code that uses lvmlockd. */
#undef LVMLOCKD_SUPPORT
/* Path to lvmpersist script. */
#undef LVMPERSIST_PATH
/* Path to lvmpolld pidfile. */
#undef LVMPOLLD_PIDFILE
@@ -633,6 +636,9 @@
/* Define to 1 to include code that uses dbus notification. */
#undef NOTIFYDBUS_SUPPORT
/* Use libnvme for WWID. */
#undef NVME_SUPPORT
/* Define to 1 to enable O_DIRECT support. */
#undef O_DIRECT_SUPPORT
@@ -660,6 +666,9 @@
/* Define to 1 to include the LVM readline shell. */
#undef READLINE_SUPPORT
/* Define to 1 to include code that uses sd_notify. */
#undef SD_NOTIFY_SUPPORT
/* Define to 1 to include built-in support for snapshots. */
#undef SNAPSHOT_INTERNAL

View File

@@ -43,6 +43,8 @@ SOURCES =\
device/filesystem.c \
device/online.c \
device/parse_vpd.c \
device/persist.c \
device/nvme.c \
device/dev_util.c \
display/display.c \
error/errseg.c \
@@ -142,7 +144,7 @@ LIB_STATIC = $(LIB_NAME).a
CFLOW_LIST = $(SOURCES)
CFLOW_LIST_TARGET = $(LIB_NAME).cflow
PROGS_CFLAGS = $(BLKID_CFLAGS) $(UDEV_CFLAGS)
PROGS_CFLAGS = $(BLKID_CFLAGS) $(LIBNVME_CFLAGS) $(UDEV_CFLAGS)
include $(top_builddir)/make.tmpl

View File

@@ -28,7 +28,6 @@
#include "lib/config/config.h"
#include "lib/metadata/segtype.h"
#include "lib/misc/sharedlib.h"
#include "lib/metadata/metadata.h"
#include "lib/misc/lvm-signal.h"
#include <limits.h>
@@ -1760,7 +1759,8 @@ int target_register_events(struct cmd_context *cmd, const char *dso, const struc
return_0;
if (!(dmevh = _create_dm_event_handler(cmd, uuid, dso, timeout,
DM_EVENT_ALL_ERRORS | (timeout ? DM_EVENT_TIMEOUT : 0))))
timeout ? DM_EVENT_ERROR_AND_TIMEOUT_MASK :
DM_EVENT_ALL_ERRORS)))
return_0;
r = set ? dm_event_register_handler(dmevh) : dm_event_unregister_handler(dmevh);

View File

@@ -197,6 +197,8 @@ int lv_raid_mismatch_count(const struct logical_volume *lv, uint64_t *cnt);
int lv_raid_sync_action(const struct logical_volume *lv, char **sync_action);
int lv_raid_message(const struct logical_volume *lv, const char *msg);
int lv_raid_status(const struct logical_volume *lv, struct lv_status_raid **status);
int lv_raid_clear_failed_devices(const struct logical_volume *lv);
int lv_raid_count_failed_devices(const struct logical_volume *lv, uint32_t *failed_cnt);
int lv_writecache_message(const struct logical_volume *lv, const char *msg);
int lv_cache_status(const struct logical_volume *cache_lv,
struct lv_status_cache **status);

View File

@@ -902,7 +902,7 @@ int devno_dm_uuid(struct cmd_context *cmd, int major, int minor,
const char *uuid;
int r = 0;
if (major != cmd->dev_types->device_mapper_major)
if (major != (int) cmd->dev_types->device_mapper_major)
return 0;
if (dm_devs_cache_use()) {
@@ -2014,7 +2014,7 @@ int dev_manager_thin_device_id(struct dev_manager *dm,
if (dm_get_next_target(dmt, NULL, &start, &length,
&target_type, &params)) {
log_error("More then one table line found for %s.",
log_error("More than one table line found for %s.",
display_lvname(lv));
goto out;
}
@@ -2067,7 +2067,7 @@ int dev_manager_vdo_pool_status(struct dev_manager *dm,
display_lvname(lv));
if (dm_get_next_target(dmt, NULL, &start, &length, &type, &params)) {
log_error("More then one table line found for %s.",
log_error("More than one table line found for %s.",
display_lvname(lv));
goto out;
}
@@ -2121,7 +2121,7 @@ int dev_manager_vdo_pool_size_config(struct dev_manager *dm,
display_lvname(lv));
if (dm_get_next_target(dmt, NULL, &start, &length, &type, &params)) {
log_error("More then one table line found for %s.",
log_error("More than one table line found for %s.",
display_lvname(lv));
goto out;
}
@@ -2773,9 +2773,10 @@ static int _add_cvol_subdev_to_dtree(struct dev_manager *dm, struct dm_tree *dtr
const struct logical_volume *pool_lv = lvseg->pool_lv;
struct dm_info info;
char *name ,*dlid;
union lvid lvid = { { lv->vg->id, _get_id_for_meta_or_data(lvseg, meta_or_data) } };
union lvid lvid = { .id = { lv->vg->id, _get_id_for_meta_or_data(lvseg, meta_or_data) } };
lvid.s[sizeof(lvid.id)] = 0;
if (!(dlid = dm_build_dm_uuid(mem, UUID_PREFIX, (const char *)&lvid.s, layer)))
if (!(dlid = dm_build_dm_uuid(mem, UUID_PREFIX, lvid.s, layer)))
return_0;
/* Name is actually not really needed here, but aids debugging... */
@@ -3426,9 +3427,10 @@ static int _add_new_cvol_subdev_to_dtree(struct dev_manager *dm,
const struct logical_volume *pool_lv = lvseg->pool_lv;
struct dm_tree_node *dnode;
char *dlid, *dlid_pool, *name;
union lvid lvid = { { lv->vg->id, _get_id_for_meta_or_data(lvseg, meta_or_data) } };
union lvid lvid = { .id = { lv->vg->id, _get_id_for_meta_or_data(lvseg, meta_or_data) } };
lvid.s[sizeof(lvid.id)] = 0;
if (!(dlid = dm_build_dm_uuid(dm->mem, UUID_PREFIX, (const char *)&lvid.s, layer)))
if (!(dlid = dm_build_dm_uuid(dm->mem, UUID_PREFIX, lvid.s, layer)))
return_0;
if (!(name = dm_build_dm_name(dm->mem, lv->vg->name, pool_lv->name, layer)))

View File

@@ -490,7 +490,11 @@ void fs_unlock(void)
{
/* Do not allow syncing device name with suspended devices */
if (!dm_get_suspended_counter()) {
log_debug_activation("Syncing device names");
if (!dm_udev_get_sync_support())
log_debug_activation("Not syncing device names (--noudevsync ? %d).",
dm_udev_get_checking());
else
log_debug_activation("Syncing device names");
/* Wait for all processed udev devices */
if (!dm_udev_wait(_fs_cookie))
stack;

View File

@@ -16,8 +16,12 @@
#ifndef _LVM_TARGETS_H
#define _LVM_TARGETS_H
#include <stddef.h>
#include <stdint.h>
struct dev_manager;
struct lv_segment;
struct dm_tree_node;
int compose_areas_line(struct dev_manager *dm, struct lv_segment *seg,
char *params, size_t paramsize, int *pos,

131
lib/cache/lvmcache.c vendored
View File

@@ -21,7 +21,6 @@
#include "lib/device/device_id.h"
#include "lib/locking/locking.h"
#include "lib/metadata/metadata.h"
#include "lib/mm/memlock.h"
#include "lib/format_text/format-text.h"
#include "lib/config/config.h"
#include "lib/filters/filter.h"
@@ -315,7 +314,7 @@ static struct lvmcache_vginfo *_vginfo_lookup(const char *vgname, const char *vg
if (vgid_arg) {
if ((vginfo = dm_hash_lookup(_vgid_hash, vgid))) {
if (vgname && strcmp(vginfo->vgname, vgname)) {
log_warn("WARNING: lookup found duplicate VGID %s for VGs %s and %s.", vgid, vginfo->vgname, vgname);
log_warn("WARNING: Lookup found duplicate VGID %s for VGs %s and %s.", vgid, vginfo->vgname, vgname);
if ((vginfo = dm_hash_lookup(_vgname_hash, vgname))) {
if (!memcmp(vginfo->vgid, vgid, ID_LEN))
return vginfo;
@@ -1891,7 +1890,7 @@ static int _lvmcache_update_vgname(struct cmd_context *cmd,
vginfo = lvmcache_vginfo_from_vgid(vgid);
if (vginfo && strcmp(vginfo->vgname, vgname)) {
log_warn("WARNING: fix duplicate VGID %s for VGs %s and %s (see vgchange -u).", vgid_dashed, vgname, vginfo->vgname);
log_warn("WARNING: Fix duplicate VGID %s for VGs %s and %s (see vgchange -u).", vgid_dashed, vgname, vginfo->vgname);
vginfo = lvmcache_vginfo_from_vgname(vgname, NULL);
if (vginfo && memcmp(vginfo->vgid, vgid, ID_LEN)) {
log_error("Ignoring %s with conflicting VG info %s %s.", dev_name(info->dev), vgid_dashed, vgname);
@@ -1954,7 +1953,7 @@ static int _lvmcache_update_vgname(struct cmd_context *cmd,
log_warn("WARNING: VG name %s is used by VGs %s and %s.",
vgname, vgid_dashed, other_dashed);
log_warn("Fix duplicate VG names with vgrename uuid, a device filter, or system IDs.");
log_warn("WARNING: Fix duplicate VG names with vgrename uuid, or vgrename --devices.");
}
if (!vginfo_is_allowed && !other_is_allowed) {
@@ -2097,12 +2096,17 @@ int lvmcache_update_vgname_and_id(struct cmd_context *cmd, struct lvmcache_info
vgid = vgname;
}
/* FIXME: remove this, it shouldn't be needed */
/* If PV without mdas is already in a real VG, don't make it orphan */
if (is_orphan_vg(vgname) && info->vginfo &&
mdas_empty_or_ignored(&info->mdas) &&
!is_orphan_vg(info->vginfo->vgname) && critical_section())
/*
* This happens when vgremove does pv_write to make a PV
* that was previously part of a VG into a new orphan.
* FIXME: change pv_write to not use or update lvmcache,
* which should only be updated by label_scan.
*/
if (is_orphan_vg(vgname) && info->vginfo && !is_orphan_vg(info->vginfo->vgname)) {
log_debug("lvmcache change %s to orphan from previous VG %s.",
dev_name(info->dev), info->vginfo->vgname);
return 1;
}
/*
* Creates a new vginfo struct for this vgname/vgid if none exists,
@@ -2223,7 +2227,7 @@ int lvmcache_update_vgname_and_id(struct cmd_context *cmd, struct lvmcache_info
*/
if ((vginfo->mda_size != vgsummary->mda_size) || (vginfo->mda_checksum != vgsummary->mda_checksum)) {
log_warn("WARNING: scan of VG %s from %s mda%d found mda_checksum %x mda_size %zu vs %x %zu",
log_warn("WARNING: Scan of VG %s from %s mda%d found mda_checksum %x mda_size %zu vs %x %zu.",
vgname, dev_name(info->dev), vgsummary->mda_num,
vgsummary->mda_checksum, vgsummary->mda_size,
vginfo->mda_checksum, vginfo->mda_size);
@@ -2265,7 +2269,7 @@ int lvmcache_update_vgname_and_id(struct cmd_context *cmd, struct lvmcache_info
* using the 'vg'.
*/
int lvmcache_update_vg_from_read(struct volume_group *vg, unsigned precommitted)
void lvmcache_update_vg_from_read(struct volume_group *vg, int *incorrect_pv_claim)
{
char pvid[ID_LEN + 1] __attribute__((aligned(8))) = { 0 };
char vgid[ID_LEN + 1] __attribute__((aligned(8))) = { 0 };
@@ -2285,9 +2289,11 @@ int lvmcache_update_vg_from_read(struct volume_group *vg, unsigned precommitted)
if (!(vginfo = lvmcache_vginfo_from_vgname(vg->name, vgid))) {
log_error(INTERNAL_ERROR "lvmcache_update_vg %s no vginfo", vg->name);
return 0;
return;
}
log_debug_cache("lvmcache_update_vg %s vginfo from metadata", vg->name);
/*
* The label scan doesn't know when a PV with old metadata has been
* removed from the VG. Now with the vg we can tell, so remove the
@@ -2306,7 +2312,7 @@ int lvmcache_update_vg_from_read(struct volume_group *vg, unsigned precommitted)
if (found)
continue;
log_warn("WARNING: outdated PV %s seqno %u has been removed in current VG %s seqno %u.",
log_warn("WARNING: Outdated PV %s seqno %u has been removed in current VG %s seqno %u.",
dev_name(info->dev), info->summary_seqno, vg->name, vginfo->seqno);
if (!_outdated_warning++)
@@ -2326,8 +2332,32 @@ int lvmcache_update_vg_from_read(struct volume_group *vg, unsigned precommitted)
continue;
}
log_debug_cache("lvmcache_update_vg %s for info %s",
vg->name, dev_name(info->dev));
/*
* If this PV info is already attached to a different VG, don't
* override that. The info/vginfo map a PV to a VG based on the
* metadata which appears on the PV itself. That has precedence
* over a different mapping of PV to another VG (the vg arg here)
* which is likely outdated metadata from some other device.
*/
if (info->vginfo && !is_orphan_vg(info->vginfo->vgname) &&
(strcmp(info->vginfo->vgname, vg->name) || memcmp(info->vginfo->vgid, &vg->id, ID_LEN))) {
char vgid_old[ID_LEN + 1] __attribute__((aligned(8))) = { 0 };
char vgid_new[ID_LEN + 1] __attribute__((aligned(8))) = { 0 };
memcpy(vgid_old, &vg->id, ID_LEN);
memcpy(vgid_new, info->vginfo->vgid, ID_LEN);
if (!strcmp(info->vginfo->vgname, vg->name))
log_warn("WARNING: PV %s %s belongs to VGID %s, ignoring claim from VGID %s (%s).",
dev_name(info->dev), pvid, vgid_new, vgid_old, vg->name);
else
log_warn("WARNING: PV %s %s belongs to VG %s, ignoring claim from VG %s.",
dev_name(info->dev), pvid, info->vginfo->vgname, vg->name);
pvl->pv->wrong_vg = 1;
*incorrect_pv_claim = 1;
continue;
}
log_debug_cache("lvmcache_update_vg %s for %s", vg->name, dev_name(info->dev));
/*
* FIXME: use a different function that just attaches info's that
@@ -2349,7 +2379,7 @@ int lvmcache_update_vg_from_read(struct volume_group *vg, unsigned precommitted)
* (since label_scan didn't know this without metadata.)
*/
dm_list_iterate_items(mda, &info->mdas) {
if (!mda_is_ignored(mda))
if (!_mda_is_ignored(mda))
continue;
log_debug("lvmcache_update_vg %s copy ignored mdas for %s", vg->name, dev_name(info->dev));
if (!lvmcache_fid_add_mdas_pv(info, vg->fid)) {
@@ -2359,8 +2389,6 @@ int lvmcache_update_vg_from_read(struct volume_group *vg, unsigned precommitted)
break;
}
}
return 1;
}
/*
@@ -3203,6 +3231,73 @@ bool lvmcache_is_outdated_dev(struct cmd_context *cmd,
return false;
}
/*
* Metadata is being processed which shows 'vg' containing 'pv'.
* Verify that this is consistent with the headers/metadata that
* were scanned from PV. The headers/metadata scanned from the
* actual PV could be different from what 'vg' metadata claims,
* if the 'vg' metadata is old/outdated.
*/
int lvmcache_verify_info_in_vg(struct volume_group *vg, struct lvmcache_info *info)
{
char vgid[ID_LEN + 1] __attribute__((aligned(8))) = { 0 };
memcpy(vgid, &vg->id, ID_LEN);
if (!info->dev) {
log_error(INTERNAL_ERROR "Verify PV info in %s: skip, no dev", vg->name);
return 1;
}
if (!info->dev->pvid[0]) {
log_debug("Verify PV %s in %s: uncertain, no pvid",
dev_name(info->dev), vg->name);
return 1;
}
if (!info->vginfo) {
log_debug("Verify PV %s %s in %s: uncertain, no vginfo",
info->dev->pvid, dev_name(info->dev), vg->name);
return 1;
}
if (strcmp(vg->name, info->vginfo->vgname)) {
log_debug("Verify PV %s %s in %s: fail, other VG %s",
info->dev->pvid, dev_name(info->dev), vg->name, info->vginfo->vgname);
return 0;
}
if (memcmp(vgid, info->vginfo->vgid, ID_LEN)) {
log_debug("Verify PV %s %s in %s: fail, other vgid %s",
info->dev->pvid, dev_name(info->dev), vg->name, info->vginfo->vgid);
return 0;
}
return 1;
}
int lvmcache_verify_pv_in_vg(struct volume_group *vg, struct physical_volume *pv)
{
struct lvmcache_info *info;
char pvid[ID_LEN + 1] __attribute__((aligned(8))) = { 0 };
memcpy(&pvid, &pv->id.uuid, ID_LEN);
if (!(info = lvmcache_info_from_pvid(pvid, NULL, 0))) {
log_debug("Verify PV %s in %s: skip, no info", pvid, vg->name);
return 1;
}
if (pv->dev != info->dev) {
log_debug("Verify PV %s in %s: skip, different devs", info->dev->pvid, vg->name);
return 1;
}
return lvmcache_verify_info_in_vg(vg, info);
}
const char *dev_filtered_reason(struct device *dev)
{
if (dev->filtered_flags & DEV_FILTERED_REGEX)

View File

@@ -83,7 +83,7 @@ void lvmcache_del_dev(struct device *dev);
/* Update things */
int lvmcache_update_vgname_and_id(struct cmd_context *cmd, struct lvmcache_info *info,
struct lvmcache_vgsummary *vgsummary);
int lvmcache_update_vg_from_read(struct volume_group *vg, unsigned precommitted);
void lvmcache_update_vg_from_read(struct volume_group *vg, int *incorrect_pv_claim);
void lvmcache_lock_vgname(const char *vgname, int read_only);
void lvmcache_unlock_vgname(const char *vgname);
@@ -98,7 +98,7 @@ struct lvmcache_info *lvmcache_info_from_pvid(const char *pvid, struct device *d
struct lvmcache_info *lvmcache_info_from_pv_id(const struct id *pv_id, struct device *dev, int valid_only);
const char *lvmcache_vgname_from_vgid(struct dm_pool *mem, const char *vgid);
const char *lvmcache_vgid_from_vgname(struct cmd_context *cmd, const char *vgname);
struct device *lvmcache_device_from_pv_id(struct cmd_context *cmd, const struct id *pv_id, uint64_t *label_sector);
struct device *lvmcache_device_from_pv_id(struct cmd_context *cmd, const struct id *pvid, uint64_t *label_sector);
const char *lvmcache_vgname_from_info(struct lvmcache_info *info);
const struct format_type *lvmcache_fmt_from_info(struct lvmcache_info *info);
@@ -190,6 +190,9 @@ void lvmcache_save_metadata_size(uint64_t val);
bool lvmcache_has_old_metadata(struct cmd_context *cmd, const char *vgname, const char *vgid, struct device *dev);
int lvmcache_verify_pv_in_vg(struct volume_group *vg, struct physical_volume *pv);
int lvmcache_verify_info_in_vg(struct volume_group *vg, struct lvmcache_info *info);
void lvmcache_get_outdated_devs(struct cmd_context *cmd,
const char *vgname, const char *vgid,
struct dm_list *devs);

View File

@@ -202,9 +202,7 @@ static int _settings_text_export(const struct lv_segment *seg,
}
static int _cache_pool_text_import(struct lv_segment *seg,
const struct dm_config_node *sn,
struct dm_hash_table *pv_hash __attribute__((unused)),
struct dm_hash_table *lv_hash)
const struct dm_config_node *sn)
{
struct logical_volume *data_lv, *meta_lv;
const char *str = NULL;
@@ -213,7 +211,7 @@ static int _cache_pool_text_import(struct lv_segment *seg,
return SEG_LOG_ERROR("Cache data not specified in");
if (!(str = dm_config_find_str(sn, "data", NULL)))
return SEG_LOG_ERROR("Cache data must be a string in");
if (!(data_lv = dm_hash_lookup(lv_hash, str)))
if (!(data_lv = find_lv(seg->lv->vg, str)))
return SEG_LOG_ERROR("Unknown logical volume %s specified for "
"cache data in", str);
@@ -221,7 +219,7 @@ static int _cache_pool_text_import(struct lv_segment *seg,
return SEG_LOG_ERROR("Cache metadata not specified in");
if (!(str = dm_config_find_str(sn, "metadata", NULL)))
return SEG_LOG_ERROR("Cache metadata must be a string in");
if (!(meta_lv = dm_hash_lookup(lv_hash, str)))
if (!(meta_lv = find_lv(seg->lv->vg, str)))
return SEG_LOG_ERROR("Unknown logical volume %s specified for "
"cache metadata in", str);
@@ -439,9 +437,7 @@ static const struct segtype_handler _cache_pool_ops = {
};
static int _cache_text_import(struct lv_segment *seg,
const struct dm_config_node *sn,
struct dm_hash_table *pv_hash __attribute__((unused)),
struct dm_hash_table *lv_hash)
const struct dm_config_node *sn)
{
struct logical_volume *pool_lv, *origin_lv;
const char *name;
@@ -451,7 +447,7 @@ static int _cache_text_import(struct lv_segment *seg,
return SEG_LOG_ERROR("cache_pool not specified in");
if (!(name = dm_config_find_str(sn, "cache_pool", NULL)))
return SEG_LOG_ERROR("cache_pool must be a string in");
if (!(pool_lv = dm_hash_lookup(lv_hash, name)))
if (!(pool_lv = find_lv(seg->lv->vg, name)))
return SEG_LOG_ERROR("Unknown logical volume %s specified for "
"cache_pool in", name);
@@ -459,7 +455,7 @@ static int _cache_text_import(struct lv_segment *seg,
return SEG_LOG_ERROR("Cache origin not specified in");
if (!(name = dm_config_find_str(sn, "origin", NULL)))
return SEG_LOG_ERROR("Cache origin must be a string in");
if (!(origin_lv = dm_hash_lookup(lv_hash, name)))
if (!(origin_lv = find_lv(seg->lv->vg, name)))
return SEG_LOG_ERROR("Unknown logical volume %s specified for "
"cache origin in", name);
if (!set_lv_segment_area_lv(seg, 0, origin_lv, 0, 0))

View File

@@ -82,7 +82,7 @@ const char *system_id_from_string(struct cmd_context *cmd, const char *str)
}
if (!strncmp(system_id, "localhost", 9)) {
log_warn("WARNING: system ID may not begin with the string \"localhost\".");
log_warn("WARNING: System ID may not begin with the string \"localhost\".");
return NULL;
}
@@ -658,8 +658,7 @@ static int _process_config(struct cmd_context *cmd)
{
mode_t old_umask;
const char *dev_ext_info_src = NULL;
const char *read_ahead;
const char *str;
const char *read_ahead, *validate_metadata;
struct stat st;
const struct dm_config_node *cn;
const struct dm_config_value *cv;
@@ -697,7 +696,7 @@ static int _process_config(struct cmd_context *cmd)
if (dev_ext_info_src &&
strcmp(dev_ext_info_src, "none") &&
strcmp(dev_ext_info_src, "udev")) {
log_warn("WARNING: unknown external device info source, using none.");
log_warn("WARNING: Unknown external device info source, using none.");
dev_ext_info_src = NULL;
}
@@ -705,7 +704,7 @@ static int _process_config(struct cmd_context *cmd)
if (udev_init_library_context()) {
init_external_device_info_source(DEV_EXT_UDEV);
} else {
log_warn("WARNING: failed to init udev for external device info, using none.");
log_warn("WARNING: Failed to init udev for external device info, using none.");
dev_ext_info_src = NULL;
}
}
@@ -721,7 +720,7 @@ static int _process_config(struct cmd_context *cmd)
}
if (*cmd->proc_dir && !dir_exists(cmd->proc_dir)) {
log_warn("WARNING: proc dir %s not found - some checks will be bypassed",
log_warn("WARNING: proc dir %s not found - some checks will be bypassed.",
cmd->proc_dir);
cmd->proc_dir[0] = '\0';
}
@@ -745,6 +744,15 @@ static int _process_config(struct cmd_context *cmd)
return 0;
}
cmd->vg_write_validates_vg = 1;
if ((validate_metadata = find_config_tree_str(cmd, config_validate_metadata_CFG, NULL))) {
if (!strcasecmp(validate_metadata, "none"))
cmd->vg_write_validates_vg = 0;
else if (strcasecmp(validate_metadata, "full"))
log_warn("WARNING: Ignoring unknown validate_metadata setting: %s.",
validate_metadata);
}
/*
* If udev is disabled using DM_DISABLE_UDEV environment
* variable, override existing config and hardcode these:
@@ -785,13 +793,13 @@ static int _process_config(struct cmd_context *cmd)
else if (strcmp(cmd->stripe_filler, "error") &&
strcmp(cmd->stripe_filler, "zero")) {
if (stat(cmd->stripe_filler, &st)) {
log_warn("WARNING: activation/missing_stripe_filler = \"%s\" "
log_warn("WARNING: activation/missing_stripe_filler = \"%s\"."
"is invalid,", cmd->stripe_filler);
log_warn(" stat failed: %s", strerror(errno));
log_warn("Falling back to \"error\" missing_stripe_filler.");
cmd->stripe_filler = "error";
} else if (!S_ISBLK(st.st_mode)) {
log_warn("WARNING: activation/missing_stripe_filler = \"%s\" "
log_warn("WARNING: activation/missing_stripe_filler = \"%s\"."
"is not a block device.", cmd->stripe_filler);
log_warn("Falling back to \"error\" missing_stripe_filler.");
cmd->stripe_filler = "error";
@@ -817,12 +825,6 @@ static int _process_config(struct cmd_context *cmd)
cmd->check_pv_dev_sizes = find_config_tree_bool(cmd, metadata_check_pv_device_sizes_CFG, NULL);
cmd->event_activation = find_config_tree_bool(cmd, global_event_activation_CFG, NULL);
if ((str = find_config_tree_str(cmd, global_vg_copy_internal_CFG, NULL))) {
if (!strcmp(str, "binary"))
cmd->vg_copy_binary = 1;
}
if (!process_profilable_config(cmd))
return_0;
@@ -1435,8 +1437,8 @@ static int _init_segtypes(struct cmd_context *cmd)
struct segment_type *segtype;
struct segtype_library seglib = { .cmd = cmd, .lib = NULL };
struct segment_type *(*init_segtype_array[])(struct cmd_context *cmd) = {
init_linear_segtype,
init_striped_segtype,
init_linear_segtype,
init_zero_segtype,
init_error_segtype,
/* disabled until needed init_free_segtype, */

View File

@@ -19,6 +19,8 @@
#include "lib/device/dev-cache.h"
#include "lib/device/dev-type.h"
#include "lib/commands/cmd_enum.h"
#include "lib/log/lvm-logging.h"
#include "lib/misc/lvm-string.h"
#include <limits.h>
@@ -71,7 +73,8 @@ struct cmd_context_initialized_parts {
};
struct cmd_report {
int log_only;
unsigned log_only:1;
unsigned lc_numeric_override:1;
dm_report_group_type_t report_group_type;
struct dm_report_group *report_group;
struct dm_report *log_rh;
@@ -163,6 +166,10 @@ struct cmd_context {
unsigned vg_read_print_access_error:1; /* print access errors from vg_read */
unsigned allow_mixed_block_sizes:1;
unsigned force_access_clustered:1;
unsigned lockd_creating_thin_pool:1;
unsigned lockd_creating_thin_volume:1;
unsigned lockd_created_thin_pool:1;
unsigned lockd_created_thin_volume:1;
unsigned lockd_gl_disable:1;
unsigned lockd_vg_disable:1;
unsigned lockd_lv_disable:1;
@@ -218,7 +225,8 @@ struct cmd_context {
unsigned device_ids_invalid:1;
unsigned device_ids_auto_import:1;
unsigned get_vgname_from_options:1; /* used by lvconvert */
unsigned vg_copy_binary:1;
unsigned vg_write_validates_vg:1;
unsigned disable_pr_required:1;
/*
* Devices and filtering.

View File

@@ -66,11 +66,16 @@ struct config_source {
* Map each ID to respective definition of the configuration item.
*/
static const struct cfg_def_item _cfg_def_items[CFG_COUNT + 1] = {
#define cfg_section(id, name, parent, flags, since_version, deprecated_since_version, deprecation_comment, comment) {id, parent, name, CFG_TYPE_SECTION, {0}, (flags), since_version, {0}, deprecated_since_version, deprecation_comment, comment},
#define cfg(id, name, parent, flags, type, default_value, since_version, unconfigured_value, deprecated_since_version, deprecation_comment, comment) {id, parent, name, type, {.v_##type = (default_value)}, (flags), since_version, {.v_UNCONFIGURED = (unconfigured_value)}, deprecated_since_version, deprecation_comment, comment},
#define cfg_runtime(id, name, parent, flags, type, since_version, deprecated_since_version, deprecation_comment, comment) {id, parent, name, type, {.fn_##type = get_default_##id}, (flags) | CFG_DEFAULT_RUN_TIME, since_version, {.fn_UNCONFIGURED = get_default_unconfigured_##id}, deprecated_since_version, (deprecation_comment), comment},
#define cfg_array(id, name, parent, flags, types, default_value, since_version, unconfigured_value, deprecated_since_version, deprecation_comment, comment) {id, parent, name, CFG_TYPE_ARRAY | (types), {.v_CFG_TYPE_STRING = (default_value)}, (flags), (since_version), {.v_UNCONFIGURED = (unconfigured_value)}, deprecated_since_version, deprecation_comment, comment},
#define cfg_array_runtime(id, name, parent, flags, types, since_version, deprecated_since_version, deprecation_comment, comment) {id, parent, name, CFG_TYPE_ARRAY | (types), {.fn_CFG_TYPE_STRING = get_default_##id}, (flags) | CFG_DEFAULT_RUN_TIME, (since_version), {.fn_UNCONFIGURED = get_default_unconfigured_##id}, deprecated_since_version, deprecation_comment, comment},
#define cfg_section(id, name, parent, flags, since_version, deprecated_since_version, deprecation_comment, comment)\
{id, parent, name, CFG_TYPE_SECTION, (flags), since_version, deprecated_since_version, {0}, {0}, deprecation_comment, comment},
#define cfg(id, name, parent, flags, type, default_value, since_version, unconfigured_value, deprecated_since_version, deprecation_comment, comment)\
{id, parent, name, type, (flags), since_version, deprecated_since_version, {.v_##type = (default_value)}, {.v_UNCONFIGURED = (unconfigured_value)}, deprecation_comment, comment},
#define cfg_runtime(id, name, parent, flags, type, since_version, deprecated_since_version, deprecation_comment, comment)\
{id, parent, name, type, (flags) | CFG_DEFAULT_RUN_TIME, since_version, deprecated_since_version, {.fn_##type = get_default_##id}, {.fn_UNCONFIGURED = get_default_unconfigured_##id}, (deprecation_comment), comment},
#define cfg_array(id, name, parent, flags, types, default_value, since_version, unconfigured_value, deprecated_since_version, deprecation_comment, comment)\
{id, parent, name, CFG_TYPE_ARRAY | (types), (flags), (since_version), deprecated_since_version, {.v_CFG_TYPE_STRING = (default_value)}, {.v_UNCONFIGURED = (unconfigured_value)}, deprecation_comment, comment},
#define cfg_array_runtime(id, name, parent, flags, types, since_version, deprecated_since_version, deprecation_comment, comment)\
{id, parent, name, CFG_TYPE_ARRAY | (types), (flags) | CFG_DEFAULT_RUN_TIME, (since_version), deprecated_since_version, {.fn_CFG_TYPE_STRING = get_default_##id}, {.fn_UNCONFIGURED = get_default_unconfigured_##id},deprecation_comment, comment},
#include "lib/config/config_settings.h"
#undef cfg_section
#undef cfg
@@ -103,7 +108,7 @@ static inline int _is_file_based_config_source(config_source_t source)
*/
struct dm_config_tree *config_open(config_source_t source,
const char *filename,
int unused)
int keep_open __attribute__((unused)))
{
struct dm_config_tree *cft = dm_config_create();
struct config_source *cs;
@@ -483,7 +488,7 @@ int override_config_tree_from_profile(struct cmd_context *cmd,
int config_file_read_fd(struct dm_config_tree *cft, struct device *dev, dev_io_reason_t reason,
off_t offset, size_t size, off_t offset2, size_t size2,
checksum_fn_t checksum_fn, uint32_t checksum,
int checksum_only, int no_dup_node_check)
int checksum_only, int no_dup_node_check, int only_pv_summary)
{
char namebuf[NAME_LEN + 1] __attribute__((aligned(8)));
int namelen = 0;
@@ -517,10 +522,11 @@ int config_file_read_fd(struct dm_config_tree *cft, struct device *dev, dev_io_r
/* Note: also used for lvm.conf to read all settings */
for (rsize = 0; rsize < size; rsize += sz) {
do {
/* coverity[overflow_sink] - only positive 'sz' is used */
sz = read(dev_fd(dev), buf + rsize, size - rsize);
} while ((sz < 0) && ((errno == EINTR) || (errno == EAGAIN)));
if (sz < 0) {
if (sz <= 0) {
log_sys_error("read", dev_name(dev));
goto out;
}
@@ -573,7 +579,10 @@ int config_file_read_fd(struct dm_config_tree *cft, struct device *dev, dev_io_r
if (!checksum_only) {
fe = fb + size + size2;
if (no_dup_node_check) {
if (!dm_config_parse_without_dup_node_check(cft, fb, fe))
if (only_pv_summary) {
if (!dm_config_parse_only_section(cft, fb, fe, "physical_volumes"))
goto_out;
} else if (!dm_config_parse_without_dup_node_check(cft, fb, fe))
goto_out;
} else {
if (!dm_config_parse(cft, fb, fe))
@@ -635,7 +644,7 @@ int config_file_read_from_file(struct dm_config_tree *cft)
cf->dev = &fake_dev;
r = config_file_read_fd(cft, cf->dev, DEV_IO_MDA_CONTENT, 0, (size_t) info.st_size, 0, 0,
(checksum_fn_t) NULL, 0, 0, 0);
(checksum_fn_t) NULL, 0, 0, 0, 0);
free((void*)alias->str);
free((void*)alias);
@@ -924,7 +933,7 @@ static int _check_value_differs_from_default(struct cft_check_handle *handle,
case DM_CFG_FLOAT:
f = v_def ? v_def->v.f
: cfg_def_get_default_value(handle->cmd, def, CFG_TYPE_FLOAT, NULL);
diff = fabs(f - v->v.f) < FLT_EPSILON;
diff = fabsf(f - v->v.f) < FLT_EPSILON;
break;
case DM_CFG_STRING:
/* string value can be a real string but it can also represent bool */
@@ -1933,11 +1942,13 @@ int config_write(struct dm_config_tree *cft,
.tree_spec = tree_spec,
.mem = cft->mem
};
int free_fp = 1;
int r = 1;
if (!file) {
baton.fp = stdout;
file = "stdout";
free_fp = 0;
} else if (!(baton.fp = fopen(file, "w"))) {
log_sys_error("open", file);
return 0;
@@ -1968,7 +1979,7 @@ int config_write(struct dm_config_tree *cft,
argv++;
}
if (baton.fp && baton.fp != stdout && dm_fclose(baton.fp)) {
if (free_fp && baton.fp && dm_fclose(baton.fp)) {
stack;
r = 0;
}

View File

@@ -134,11 +134,11 @@ typedef struct cfg_def_item {
int parent; /* ID of parent item */
const char *name; /* name of the item in configuration tree */
int type; /* configuration item type (bits of cfg_def_type_t) */
cfg_def_value_t default_value; /* default value (only for settings) */
uint16_t flags; /* configuration item definition flags */
uint16_t since_version; /* version this item appeared in */
cfg_def_unconfigured_value_t default_unconfigured_value; /* default value in terms of @FOO@, pre-configured (only for settings) */
uint16_t deprecated_since_version; /* version since this item is deprecated */
cfg_def_value_t default_value; /* default value (only for settings) */
cfg_def_unconfigured_value_t default_unconfigured_value; /* default value in terms of @FOO@, pre-configured (only for settings) */
const char *deprecation_comment; /* comment about reasons for deprecation and settings that supersede this one */
const char *comment; /* comment */
const char *file_preamble; /* comment text to use at the start of the file */
@@ -243,7 +243,7 @@ struct dm_config_tree *config_open(config_source_t source, const char *filename,
int config_file_read_fd(struct dm_config_tree *cft, struct device *dev, dev_io_reason_t reason,
off_t offset, size_t size, off_t offset2, size_t size2,
checksum_fn_t checksum_fn, uint32_t checksum,
int skip_parse, int no_dup_node_check);
int checksum_only, int no_dup_node_check, int only_pv_summary);
int config_file_read_from_file(struct dm_config_tree *cft);
struct dm_config_tree *config_file_open_and_read(const char *config_file, config_source_t source,
struct cmd_context *cmd);

View File

@@ -214,6 +214,16 @@ cfg(config_checks_CFG, "checks", config_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_
"without any warning (a message about the configuration key not being\n"
"found is issued in verbose mode only).\n")
cfg(config_validate_metadata_CFG, "validate_metadata", config_CFG_SECTION, CFG_DEFAULT_COMMENTED | CFG_ADVANCED, CFG_TYPE_STRING, DEFAULT_VALIDATE_METADATA, vsn(2, 3, 28), NULL, 0, NULL,
"Allows to select the level of validation after metadata transformation.\n"
"Validation takes extra CPU time to verify internal consistency.\n"
"Accepted values:\n"
" full\n"
" Do a full metadata validation before disk write.\n"
" none\n"
" Skip any checks (unrecommended, slightly faster).\n"
"#\n")
cfg(config_abort_on_errors_CFG, "abort_on_errors", config_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, 0, vsn(2,2,99), NULL, 0, NULL,
"Abort the LVM process if a configuration mismatch is found.\n")
@@ -671,7 +681,7 @@ cfg(allocation_thin_pool_metadata_require_separate_pvs_CFG, "thin_pool_metadata_
cfg(allocation_thin_pool_crop_metadata_CFG, "thin_pool_crop_metadata", allocation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_THIN_POOL_CROP_METADATA, vsn(2, 3, 12), NULL, 0, NULL,
"Older version of lvm2 cropped pool's metadata size to 15.81 GiB.\n"
"This is slightly less then the actual maximum 15.88 GiB.\n"
"This is slightly less than the actual maximum 15.88 GiB.\n"
"For compatibility with older version and use of cropped size set to 1.\n")
cfg(allocation_thin_pool_zero_CFG, "thin_pool_zero", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_THIN_POOL_ZERO, vsn(2, 2, 99), NULL, 0, NULL,
@@ -1322,6 +1332,10 @@ cfg(global_fsadm_executable_CFG, "fsadm_executable", global_CFG_SECTION, CFG_DEF
"The full path to the fsadm command.\n"
"LVM uses this command to help with lvresize -r operations.\n")
cfg(global_lvresize_fs_helper_executable_CFG, "lvresize_fs_helper_executable", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_LVRESIZE_FS_HELPER_PATH, vsn(2, 3, 33), "@LVRESIZE_FS_HELPER_PATH@", 0, NULL,
"The full path to the lvresize_fs_helper command.\n"
"LVM uses this command to help with filesystem operations during lvresize.\n")
cfg(global_system_id_source_CFG, "system_id_source", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_SYSTEM_ID_SOURCE, vsn(2, 2, 117), NULL, 0, NULL,
"The method LVM uses to set the local system ID.\n"
"Volume Groups can also be given a system ID (by vgcreate, vgchange,\n"
@@ -1387,13 +1401,6 @@ cfg(global_io_memory_size_CFG, "io_memory_size", global_CFG_SECTION, CFG_DEFAULT
"This value should usually not be decreased from the default; setting\n"
"it too low can result in lvm failing to read VGs.\n")
cfg(global_vg_copy_internal_CFG, "vg_copy_internal", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_VG_COPY_INTERNAL, vsn(2, 3, 27), NULL, 0, NULL,
"The method that lvm uses for internal VG structure copying.\n"
"\"binary\" copies between binary structures to improve performance\n"
"with large metadata (experimental.) \"text\" exports a binary\n"
"struct to text format, and reimports text to a new binary\n"
"structure (traditional.)\n")
cfg(activation_udev_sync_CFG, "udev_sync", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_UDEV_SYNC, vsn(2, 2, 51), NULL, 0, NULL,
"Use udev notifications to synchronize udev and LVM.\n"
"The --noudevsync option overrides this setting.\n"
@@ -2272,6 +2279,12 @@ cfg(local_system_id_CFG, "system_id", local_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_D
"system_id = \"host1\"\n"
"#\n")
cfg(local_pr_key_CFG, "pr_key", local_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, 0, vsn(2, 3, 32), NULL, 0, NULL,
"The local persistent reservation key in hexadecimal.\n"
"The value must be unique among all hosts using the same VG.\n"
"The max length is 16 hex characters (8 bytes), plus an optional\n"
"0x prefix. If pr_key is not set, host_id will be used to create a key.\n")
cfg_array(local_extra_system_ids_CFG, "extra_system_ids", local_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(2, 2, 117), NULL, 0, NULL,
"A list of extra VG system IDs the local host can access.\n"
"VGs with the system IDs listed here (in addition to the host's own\n"
@@ -2285,6 +2298,8 @@ cfg(local_host_id_CFG, "host_id", local_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_
"The sanlock host_id used by lvmlockd. This must be unique among all the hosts\n"
"using shared VGs with sanlock. Accepted values are 1-2000, except when sanlock_align_size\n"
"is configured to 1, 2 or 4, which correspond to max host_id values of 250, 500, or 1000.\n"
"Applicable only if LVM is compiled with support for lvmlockd+sanlock.\n")
"When using persistent reservations, lvm will generate a PR key from the host_id\n"
"if pr_key is not defined. All hosts using a sanlock shared VG with PR must use\n"
"the same approach for configuring their PR key (pr_key or host_id.)\n")
cfg(CFG_COUNT, NULL, root_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, 0, vsn(0, 0, 0), NULL, 0, NULL, NULL)

View File

@@ -33,6 +33,7 @@
#define DEFAULT_ARCHIVE_ENABLED 1
#define DEFAULT_BACKUP_ENABLED 1
#define DEFAULT_VALIDATE_METADATA "full" /* full | none */
#define DEFAULT_CACHE_FILE_PREFIX ""
@@ -191,6 +192,7 @@
#define DEFAULT_FSADM_PATH FSADM_PATH
#define DEFAULT_LVRESIZE_FS_HELPER_PATH LVRESIZE_FS_HELPER_PATH
#define DEFAULT_UMASK 0077
@@ -344,6 +346,4 @@
#define DEFAULT_DEVICESFILE_BACKUP_LIMIT 50
#define DEFAULT_VG_COPY_INTERNAL "binary"
#endif /* _LVM_DEFAULTS_H */

View File

@@ -16,7 +16,10 @@
#ifndef _LVM_BTREE_H
#define _LVM_BTREE_H
#include <stdint.h>
struct btree;
struct dm_pool;
struct btree *btree_create(struct dm_pool *mem);

View File

@@ -92,7 +92,7 @@ static void _cb_set_destroy(struct cb_set *cbs)
// never be in flight IO.
if (!dm_list_empty(&cbs->allocated)) {
// bail out
log_warn("WARNING: async io still in flight.");
log_warn("WARNING: Async io still in flight.");
return;
}

View File

@@ -64,7 +64,7 @@ struct block {
/*
* Ownership of engine passes. Engine will be destroyed even if this fails.
*/
struct bcache *bcache_create(sector_t block_size, unsigned nr_cache_blocks,
struct bcache *bcache_create(sector_t block_sectors, unsigned nr_cache_blocks,
struct io_engine *engine);
void bcache_destroy(struct bcache *cache);

View File

@@ -294,7 +294,8 @@ static int _add_alias(struct device *dev, const char *path, enum add_hash hash)
size_t path_len = strlen(path);
if (hash == REHASH)
radix_tree_remove(_cache.names, path, path_len);
if (!radix_tree_remove(_cache.names, path, path_len))
stack;
/* Is name already there? */
dm_list_iterate_items(strl, &dev->aliases)
@@ -406,7 +407,7 @@ out:
/* Change bit ordering for devno to generate more compact bTree */
static inline uint32_t _shuffle_devno(dev_t d)
{
return cpu_to_be32(d);
return htobe32(d);
//return (d & 0xff) << 24 | (d & 0xff00) << 8 | (d & 0xff0000) >> 8 | (d & 0xff000000) >> 24;
//return (d & 0xff000000) >> 24 | (d & 0xffff00) | ((d & 0xff) << 24);
//return (uint32_t) d;
@@ -696,7 +697,8 @@ void dev_cache_failed_path(struct device *dev, const char *path)
{
struct dm_str_list *strl;
radix_tree_remove(_cache.names, path, strlen(path));
if (!radix_tree_remove(_cache.names, path, strlen(path)))
stack;
dm_list_iterate_items(strl, &dev->aliases) {
if (!strcmp(strl->str, path)) {
@@ -869,7 +871,7 @@ static int _insert_dir(const char *dir)
if (bsearch(path + 5, _no_scan, DM_ARRAY_SIZE(_no_scan), sizeof(_no_scan[0]),
(int (*)(const void*, const void*))strcmp)) {
/* Skip insertion of directories that can't have block devices */
log_debug("Skipping \"%s\" (no block devices).", path);
log_debug_devs("Skipping \"%s\" (no block devices).", path);
return 1;
}
}
@@ -1159,12 +1161,12 @@ static int _insert(const char *path, const struct stat *info,
}
if (S_ISLNK(tinfo.st_mode)) {
log_debug_devs("%s: Symbolic link to directory", path);
log_debug_devs("Skipping \"%s\" (symbolic link to directory).", path);
return 1;
}
if (info->st_dev != _cache.st_dev) {
log_debug_devs("%s: Different filesystem in directory", path);
log_debug_devs("Skipping \"%s\" (different filesystem in directory).", path);
return 1;
}
@@ -1187,7 +1189,8 @@ static void _drop_all_aliases(struct device *dev)
dm_list_iterate_items_safe(strl, strl2, &dev->aliases) {
log_debug("Drop alias for %u:%u %s.", MAJOR(dev->dev), MINOR(dev->dev), strl->str);
radix_tree_remove(_cache.names, strl->str, strlen(strl->str));
if (!radix_tree_remove(_cache.names, strl->str, strlen(strl->str)))
stack;
dm_list_del(&strl->list);
}
}
@@ -1281,11 +1284,13 @@ void dm_devs_cache_destroy(void)
_cache.use_dm_devs_cache = 0;
if (_cache.dm_devnos) {
log_debug_cache("Destroying DM devno cache.");
radix_tree_destroy(_cache.dm_devnos);
_cache.dm_devnos = NULL;
}
if (_cache.dm_uuids) {
log_debug_cache("Destroying DM uuid cache.");
radix_tree_destroy(_cache.dm_uuids);
_cache.dm_uuids = NULL;
}
@@ -1293,23 +1298,68 @@ void dm_devs_cache_destroy(void)
dm_device_list_destroy(&_cache.dm_devs);
}
/*
* Updates cached trees with active DM devices.
*
* TODO:
* For large amount of active devices it might be useful
* to update existing trees - especially when there is high
* chance the set of active devices is nearly the same).
* However its not so trivial, so just make it a TODO.
* And do only an easy 1:1 match or full rebuild.
*/
int dm_devs_cache_update(void)
{
struct dm_active_device *dm_dev;
struct dm_active_device *dm_dev, *dm_dev_new;
unsigned devs_features;
uint32_t d;
struct dm_list *dm_devs_new, *l;
int cache_changed;
dm_devs_cache_destroy();
if (!get_dm_active_devices(NULL, &_cache.dm_devs, &devs_features))
if (!get_dm_active_devices(NULL, &dm_devs_new, &devs_features))
return 1;
if (!(devs_features & DM_DEVICE_LIST_HAS_UUID)) {
/* Cache unusable with older kernels without UUIDs in LIST */
dm_device_list_destroy(&_cache.dm_devs);
dm_device_list_destroy(&dm_devs_new);
return 1;
}
if (_cache.dm_devs) {
/* Compare existing cached list with a new one.
* When there is any mismatch, just rebuild whole cache */
if ((l = dm_list_first(dm_devs_new))) {
cache_changed = dm_list_empty(_cache.dm_devs); // 1 for empty cache and new list has entries */
dm_list_iterate_items(dm_dev, _cache.dm_devs) {
dm_dev_new = dm_list_item(l, struct dm_active_device);
if ((dm_dev->devno != dm_dev_new->devno) ||
strcmp(dm_dev->uuid, dm_dev_new->uuid)) {
log_debug_cache("Mismatching UUID or devno found %s %u:%u %s %u:%u.",
dm_dev->uuid, MAJOR(dm_dev->devno), MINOR(dm_dev->devno),
dm_dev_new->uuid, MAJOR(dm_dev_new->devno), MINOR(dm_dev_new->devno));
cache_changed = 1;
break;
}
if (!(l = dm_list_next(dm_devs_new, l))) {
if (dm_list_next(_cache.dm_devs, &dm_dev->list))
cache_changed = 1; /* old cached list still with entries */
break;
}
}
} else
cache_changed = 1;
if (!cache_changed) {
log_debug_cache("Preserving DM cache.");
dm_device_list_destroy(&dm_devs_new);
return 1;
}
dm_devs_cache_destroy();
}
_cache.dm_devs = dm_devs_new;
/* _cache.dm_devs entries are referenced by radix trees */
/* TODO: if _cache.dm_devs list is small, then skip the
@@ -1320,6 +1370,7 @@ int dm_devs_cache_update(void)
return_0; // FIXME
}
log_debug_cache("Creating DM cache for devno and uuid.");
/* Insert every active DM device into radix trees */
dm_list_iterate_items(dm_dev, _cache.dm_devs) {
d = _shuffle_devno(dm_dev->devno);
@@ -1572,7 +1623,8 @@ void dev_cache_verify_aliases(struct device *dev)
log_debug("Drop alias for %u:%u invalid path %s %u:%u.",
MAJOR(dev->dev), MINOR(dev->dev), strl->str,
MAJOR(st.st_rdev), MINOR(st.st_rdev));
radix_tree_remove(_cache.names, strl->str, strlen(strl->str));
if (!radix_tree_remove(_cache.names, strl->str, strlen(strl->str)))
stack;
dm_list_del(&strl->list);
}
}
@@ -1606,7 +1658,8 @@ static struct device *_dev_cache_get(struct cmd_context *cmd, const char *name,
log_debug("Device path %s is invalid for %u:%u %s.",
name, MAJOR(dev->dev), MINOR(dev->dev), dev_name(dev));
radix_tree_remove(_cache.names, name, strlen(name));
if (!radix_tree_remove(_cache.names, name, strlen(name)))
stack;
_remove_alias(dev, name);
@@ -1662,7 +1715,7 @@ static struct device *_dev_cache_get(struct cmd_context *cmd, const char *name,
* a warning to look for any other unknown cases.
*/
if (MAJOR(st.st_rdev) != cmd->dev_types->device_mapper_major) {
log_warn("WARNING: new device appeared %u:%u %s",
log_warn("WARNING: New device appeared %u:%u %s.",
MAJOR(st.st_rdev), (MINOR(st.st_rdev)), name);
}
#endif
@@ -1732,7 +1785,7 @@ static struct device *_dev_cache_get(struct cmd_context *cmd, const char *name,
* a warning to look for any other unknown cases.
*/
if (MAJOR(st.st_rdev) != cmd->dev_types->device_mapper_major) {
log_warn("WARNING: new device appeared %u:%u %s.",
log_warn("WARNING: New device appeared %u:%u %s.",
MAJOR(st.st_rdev), MINOR(st.st_rdev), name);
}
#endif
@@ -2331,7 +2384,7 @@ static char *_get_devname_from_devno(struct cmd_context *cmd, dev_t devno)
static const char _partitions[] = "/proc/partitions";
char path[PATH_MAX];
char devname[PATH_MAX] = { 0 };
char namebuf[NAME_LEN];
char namebuf[NAME_LEN + 1];
char line[1024];
unsigned major = MAJOR(devno);
unsigned minor = MINOR(devno);

View File

@@ -61,7 +61,7 @@ int dev_is_lvm1(struct device *dev, char *buf, int buflen)
uint32_t version;
int ret;
version = xlate16(pvd->version);
version = htole16(pvd->version);
if (pvd->id[0] == 'H' && pvd->id[1] == 'M' &&
(version == 1 || version == 2))
@@ -128,9 +128,9 @@ struct pool_disk {
};
#define CPIN_8(x, y, z) {memcpy((x), (y), (z));}
#define CPIN_16(x, y) {(x) = xlate16_be((y));}
#define CPIN_32(x, y) {(x) = xlate32_be((y));}
#define CPIN_64(x, y) {(x) = xlate64_be((y));}
#define CPIN_16(x, y) {(x) = htobe16((y));}
#define CPIN_32(x, y) {(x) = htobe32((y));}
#define CPIN_64(x, y) {(x) = htobe64((y));}
static void pool_label_in(struct pool_disk *pl, void *buf)
{

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