1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-04-07 14:50:46 +03:00

Compare commits

...

304 Commits

Author SHA1 Message Date
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 874a8ab4d02a59c5 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
e3f0af8f1fd7 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: 40b277ae1799fc7a2e3f38b0abebd81a8e3d1995
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 8425c1b468af0caf2e1e36d1eb1c1b399ee22489.

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 5b92ce741f6bcb9b3d3c19c0fc13b972f950c560),
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 5f71cebcbecc37b5291018da35b3efe9636bf6c3 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:
964012fdb924076e9ab97fabe00e759ddbf7c3bd
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 d106ac04ab34 ("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 83ae675f8df53010c984b78d0318d0d92d5ac83a.
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 acbeaa7a8d86acc0f0e3c04723d066d995f29fe5 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
330 changed files with 8383 additions and 4019 deletions

View File

@ -172,7 +172,7 @@ help:
@echo " lcov-dated Generate lcov with timedate suffix."
@echo " lcov-reset Reset lcov counters"
@echo " man Build man pages."
@echo " print-VARIABLE Resolve make variable."
@echo " print-VARIABLE Resolve make variable."
@echo " rpm Build rpm."
@echo " run-unit-test Run unit tests."
@echo " tags Generate c/etags."
@ -194,7 +194,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) (2024-11-04)
2.03.32(2)-git (2025-02-27)

View File

@ -1 +1 @@
1.02.202 (2024-11-04)
1.02.206-git (2025-02-27)

View File

@ -1,3 +1,50 @@
Version 2.03.32 -
==================
Lvconvert vdopool conversion propperly validates acceptable LVs.
Accept thin pool data LV as cachable 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.
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.

View File

@ -1,3 +1,20 @@
Version 1.02.206 -
===================
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.
@ -263,7 +280,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.17 -*- Autoconf -*-
# Copyright (C) 1996-2021 Free Software Foundation, Inc.
# Copyright (C) 1996-2024 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-2024 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-2024 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--;

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

@ -586,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

298
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 :
@ -12724,9 +12749,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 +12848,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 +13198,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 +13671,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,13 +13692,9 @@ 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
]
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to build notifydbus" >&5
@ -13459,10 +13703,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 +13797,6 @@ else
printf "%s\n" "yes" >&6; }
fi
fi
################################################################################
@ -13880,7 +14123,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 +14154,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 +14188,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 +14202,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')
@ -16564,6 +16829,7 @@ AIO_LIBS=${AIO_LIBS:--laio}
################################################################################
@ -17961,3 +18227,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

@ -217,6 +217,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])],
@ -1046,7 +1048,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 +1086,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 +1159,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,14 +1283,15 @@ 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_MSG_CHECKING([whether to build notifydbus])
@ -1246,9 +1299,9 @@ 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
@ -1938,6 +1991,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 +2129,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

@ -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

@ -12,6 +12,8 @@
#ifndef _LVM_CLOG_LOCAL_H
#define _LVM_CLOG_LOCAL_H
struct dm_ulog_request;
int init_local(void);
void cleanup_local(void);

View File

@ -268,7 +268,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;

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

@ -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

@ -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

@ -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))

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

@ -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

@ -97,8 +97,9 @@ 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);
(void) sscanf(line, "info=client pid=%u fd=%d pi=%d id=%u name=%"
DM_TO_STRING(MAX_NAME) "s",
&pid, &fd, &pi, &client_id, name);
clients[num_clients].client_id = client_id;
clients[num_clients].pid = pid;
@ -129,8 +130,11 @@ static void format_info_ls(char *line)
char lock_args[MAX_ARGS+1] = { 0 };
char lock_type[MAX_NAME+1] = { 0 };
(void) sscanf(line, "info=ls ls_name=%s vg_name=%s vg_uuid=%s vg_args=%s lm_type=%s",
ls_name, vg_name, vg_uuid, lock_args, lock_type);
(void) sscanf(line, "info=ls ls_name=%" DM_TO_STRING(MAX_NAME) "s vg_name=%"
DM_TO_STRING(MAX_NAME) "s vg_uuid=%" DM_TO_STRING(MAX_NAME)
"s vg_args=%" DM_TO_STRING(MAX_NAME) "s lm_type=%"
DM_TO_STRING(MAX_NAME) "s",
ls_name, vg_name, vg_uuid, lock_args, lock_type);
if (!first_ls)
printf("\n");
@ -150,8 +154,11 @@ 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);
(void) sscanf(line, "info=ls_action client_id=%u %"
DM_TO_STRING(MAX_NAME) "s %"
DM_TO_STRING(MAX_NAME) "s op=%"
DM_TO_STRING(MAX_NAME) "s",
&client_id, flags, version, op);
find_client_info(client_id, &pid, cl_name);
@ -166,8 +173,10 @@ static void format_info_r(char *line, char *r_name_out, char *r_type_out)
char sh_count[MAX_NAME+1] = { 0 };
uint32_t ver = 0;
(void) sscanf(line, "info=r name=%s type=%s mode=%s %s version=%u",
r_name, r_type, mode, sh_count, &ver);
(void) sscanf(line, "info=r name=%" DM_TO_STRING(MAX_NAME)
"s type=%3s mode=%3s %"
DM_TO_STRING(MAX_NAME) "s version=%u",
r_name, r_type, mode, sh_count, &ver);
strcpy(r_name_out, r_name);
strcpy(r_type_out, r_type);
@ -204,8 +213,9 @@ 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);
(void) sscanf(line, "info=lk mode=%3s version=%u %"
DM_TO_STRING(MAX_NAME) "s client_id=%u",
mode, &ver, flags, &client_id);
find_client_info(client_id, &pid, cl_name);
@ -240,8 +250,11 @@ 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);
(void) sscanf(line, "info=r_action client_id=%u %" DM_TO_STRING(MAX_NAME)
"s %" DM_TO_STRING(MAX_NAME) "s op=%" DM_TO_STRING(MAX_NAME)
"s rt=%3s mode=%3s %" DM_TO_STRING(MAX_NAME) "s %"
DM_TO_STRING(MAX_NAME) "s %" DM_TO_STRING(MAX_NAME) "s",
&client_id, flags, version, op, rt, mode, lm, result, lm_rv);
find_client_info(client_id, &pid, cl_name);

View File

@ -11,7 +11,7 @@
#include "tools/tool.h"
#include "libdaemon/client/daemon-io.h"
#include "daemon-server.h"
#include "libdaemon/server/daemon-server.h"
#include "lvm-version.h"
#include "daemons/lvmlockd/lvmlockd-client.h"
#include "device_mapper/misc/dm-ioctl.h"
@ -31,7 +31,7 @@
#include <sys/utsname.h>
#include <sys/un.h>
#ifdef USE_SD_NOTIFY
#ifdef SD_NOTIFY_SUPPORT
#include <systemd/sd-daemon.h>
#endif
@ -416,6 +416,7 @@ struct lockspace *alloc_lockspace(void)
INIT_LIST_HEAD(&ls->actions);
INIT_LIST_HEAD(&ls->resources);
INIT_LIST_HEAD(&ls->dispose);
pthread_mutex_init(&ls->mutex, NULL);
pthread_cond_init(&ls->cond, NULL);
return ls;
@ -754,7 +755,7 @@ static const char *rt_str(int x)
case LD_RT_LV:
return "lv";
default:
return ".";
return "";
};
}
@ -999,7 +1000,7 @@ static int read_adopt_file(struct list_head *vg_lockd)
memset(vg_uuid, 0, sizeof(vg_uuid));
memset(mode, 0, sizeof(mode));
if (sscanf(adopt_line, "LV: %64s %64s %s %7s %u",
if (sscanf(adopt_line, "LV: %64s %64s %64s %7s %u",
vg_uuid, r->name, r->lv_args, mode, &r->version) != 5) {
free_resource(r);
goto fail;
@ -1046,7 +1047,7 @@ fail:
static int lm_prepare_lockspace(struct lockspace *ls, struct action *act)
{
int rv;
int rv = -1;
if (ls->lm_type == LD_LM_DLM)
rv = lm_prepare_lockspace_dlm(ls);
@ -1054,8 +1055,6 @@ static int lm_prepare_lockspace(struct lockspace *ls, struct action *act)
rv = lm_prepare_lockspace_sanlock(ls);
else if (ls->lm_type == LD_LM_IDM)
rv = lm_prepare_lockspace_idm(ls);
else
return -1;
if (act)
act->lm_rv = rv;
@ -1064,7 +1063,7 @@ static int lm_prepare_lockspace(struct lockspace *ls, struct action *act)
static int lm_add_lockspace(struct lockspace *ls, struct action *act, int adopt_only, int adopt_ok, int nodelay)
{
int rv;
int rv = -1;
if (ls->lm_type == LD_LM_DLM)
rv = lm_add_lockspace_dlm(ls, adopt_only, adopt_ok);
@ -1072,8 +1071,6 @@ static int lm_add_lockspace(struct lockspace *ls, struct action *act, int adopt_
rv = lm_add_lockspace_sanlock(ls, adopt_only, adopt_ok, nodelay);
else if (ls->lm_type == LD_LM_IDM)
rv = lm_add_lockspace_idm(ls, adopt_only, adopt_ok);
else
return -1;
if (act)
act->lm_rv = rv;
@ -1082,7 +1079,7 @@ static int lm_add_lockspace(struct lockspace *ls, struct action *act, int adopt_
static int lm_rem_lockspace(struct lockspace *ls, struct action *act, int free_vg)
{
int rv;
int rv = -1;
if (ls->lm_type == LD_LM_DLM)
rv = lm_rem_lockspace_dlm(ls, free_vg);
@ -1090,18 +1087,30 @@ static int lm_rem_lockspace(struct lockspace *ls, struct action *act, int free_v
rv = lm_rem_lockspace_sanlock(ls, free_vg);
else if (ls->lm_type == LD_LM_IDM)
rv = lm_rem_lockspace_idm(ls, free_vg);
else
return -1;
if (act)
act->lm_rv = rv;
return rv;
}
static int lm_add_resource(struct lockspace *ls, struct resource *r)
{
int rv = -1;
if (ls->lm_type == LD_LM_DLM)
rv = lm_add_resource_dlm(ls, r, 0);
else if (ls->lm_type == LD_LM_SANLOCK)
rv = lm_add_resource_sanlock(ls, r);
else if (ls->lm_type == LD_LM_IDM)
rv = lm_add_resource_idm(ls, r);
return rv;
}
static int lm_lock(struct lockspace *ls, struct resource *r, int mode, struct action *act,
struct val_blk *vb_out, int *retry, int adopt_only, int adopt_ok)
{
int rv;
int rv = -1;
if (ls->lm_type == LD_LM_DLM)
rv = lm_lock_dlm(ls, r, mode, vb_out, adopt_only, adopt_ok);
@ -1110,8 +1119,6 @@ static int lm_lock(struct lockspace *ls, struct resource *r, int mode, struct ac
else if (ls->lm_type == LD_LM_IDM)
rv = lm_lock_idm(ls, r, mode, vb_out, act->lv_uuid,
&act->pvs, adopt_only, adopt_ok);
else
return -1;
if (act)
act->lm_rv = rv;
@ -1121,7 +1128,7 @@ static int lm_lock(struct lockspace *ls, struct resource *r, int mode, struct ac
static int lm_convert(struct lockspace *ls, struct resource *r,
int mode, struct action *act, uint32_t r_version)
{
int rv;
int rv = -1;
if (ls->lm_type == LD_LM_DLM)
rv = lm_convert_dlm(ls, r, mode, r_version);
@ -1129,8 +1136,6 @@ static int lm_convert(struct lockspace *ls, struct resource *r,
rv = lm_convert_sanlock(ls, r, mode, r_version);
else if (ls->lm_type == LD_LM_IDM)
rv = lm_convert_idm(ls, r, mode, r_version);
else
return -1;
if (act)
act->lm_rv = rv;
@ -1140,7 +1145,7 @@ static int lm_convert(struct lockspace *ls, struct resource *r,
static int lm_unlock(struct lockspace *ls, struct resource *r, struct action *act,
uint32_t r_version, uint32_t lmu_flags)
{
int rv;
int rv = -1;
if (ls->lm_type == LD_LM_DLM)
rv = lm_unlock_dlm(ls, r, r_version, lmu_flags);
@ -1148,8 +1153,6 @@ static int lm_unlock(struct lockspace *ls, struct resource *r, struct action *ac
rv = lm_unlock_sanlock(ls, r, r_version, lmu_flags);
else if (ls->lm_type == LD_LM_IDM)
rv = lm_unlock_idm(ls, r, r_version, lmu_flags);
else
return -1;
if (act)
act->lm_rv = rv;
@ -1678,20 +1681,32 @@ static int res_unlock(struct lockspace *ls, struct resource *r,
{
struct lock *lk;
uint32_t r_version;
int found_transient = 0;
int found_persistent = 0;
int rv;
if (act->flags & LD_AF_PERSISTENT) {
lk = find_lock_persistent(r);
if (lk)
goto do_unlock;
if (find_lock_client(r, act->client_id))
found_transient = 1;
} else {
lk = find_lock_client(r, act->client_id);
if (lk)
goto do_unlock;
if (find_lock_persistent(r))
found_persistent = 1;
}
if (act->op != LD_OP_CLOSE)
log_debug("%s:%s res_unlock cl %u no locks", ls->name, r->name, act->client_id);
if (act->op != LD_OP_CLOSE) {
if (found_transient)
log_debug("%s:%s res_unlock cl %u ENOENT (found transient)", ls->name, r->name, act->client_id);
else if (found_persistent)
log_debug("%s:%s res_unlock cl %u ENOENT (found persistent)", ls->name, r->name, act->client_id);
else
log_debug("%s:%s res_unlock cl %u ENOENT (no lock)", ls->name, r->name, act->client_id);
}
return -ENOENT;
do_unlock:
@ -1888,6 +1903,7 @@ static void res_process(struct lockspace *ls, struct resource *r,
{
struct action *act, *safe, *act_close;
struct lock *lk;
uint32_t unlock_by_client_id = 0;
int lm_retry;
int rv;
@ -1921,6 +1937,9 @@ static void res_process(struct lockspace *ls, struct resource *r,
if (rv == -ENOENT && (act->flags & LD_AF_UNLOCK_CANCEL))
rv = res_cancel(ls, r, act);
if (!rv && r->mode == LD_LK_UN)
unlock_by_client_id = act->client_id;
/*
* possible unlock results:
* 0: unlock succeeded
@ -1944,22 +1963,6 @@ static void res_process(struct lockspace *ls, struct resource *r,
res_cancel(ls, r, act_close);
}
/*
* handle freeing a lock for an lv that has been removed
*/
list_for_each_entry_safe(act, safe, &r->actions, list) {
if (act->op == LD_OP_FREE && act->rt == LD_RT_LV) {
log_debug("%s:%s free_lv", ls->name, r->name);
rv = free_lv(ls, r);
act->result = rv;
list_del(&act->list);
add_client_result(act);
goto r_free;
}
}
/*
* handle enable/disable
*/
@ -2103,6 +2106,7 @@ static void res_process(struct lockspace *ls, struct resource *r,
* be held for reading. If the T lock was sh, it would
* be converted to P ex. If the T/P modes matched, the
* lock could just be changed from T to P.
* Update: T->P is known to happen sometimes with LV locks.
*/
list_for_each_entry_safe(act, safe, &r->actions, list) {
@ -2121,6 +2125,7 @@ static void res_process(struct lockspace *ls, struct resource *r,
list_del(&act->list);
add_client_result(act);
} else {
log_debug("res_process %s change transient to persistent", r->name);
r->last_client_id = act->client_id;
lk->flags |= LD_LF_PERSISTENT;
lk->client_id = 0;
@ -2237,18 +2242,44 @@ static void res_process(struct lockspace *ls, struct resource *r,
}
}
/*
* In general, if the resource struct has no locks, no actions, and is
* unlocked, then it can be freed. (This is only needed for LV
* resources since LVs can be removed.) However, for lvremove (and
* vgremove, sometimes lvconvert), the command will send a free_lv op
* after unlocking. The free_lv op also needs the resource struct.
* So, rather than freeing it here, move the resource struct to the
* ls->dispose list. A free_lv op will find r on the dispose list, do
* free_lv, then free_resource. If the command closes its connection
* without doing free_lv (e.g. normal deactivation), then the structs
* that the client moved to the dispose list will all be freed when
* processing the OP_CLOSE for the client.
*/
if ((r->type == LD_RT_LV) && (r->mode == LD_LK_UN) &&
list_empty(&r->locks) && list_empty(&r->actions)) {
/* An implicit unlock of a transient lock. */
if (!unlock_by_client_id)
goto r_free;
log_debug("%s:%s will dispose for %u", ls->name, r->name, unlock_by_client_id);
list_del(&r->list);
r->dispose_client_id = unlock_by_client_id;
list_add(&r->list, &ls->dispose);
}
return;
r_free:
/* For the EUNATCH case it may be possible there are queued actions? */
list_for_each_entry_safe(act, safe, &r->actions, list) {
log_error("%s:%s res_process r_free cancel %s client %d",
log_error("%s:%s res_process r_free cancel %s client %u",
ls->name, r->name, op_str(act->op), act->client_id);
act->result = -ECANCELED;
list_del(&act->list);
add_client_result(act);
}
log_debug("%s:%s res_process free", ls->name, r->name);
log_debug("%s:%s res_process free_resource", ls->name, r->name);
lm_rem_resource(ls, r);
list_del(&r->list);
free_resource(r);
@ -2283,7 +2314,7 @@ static int for_each_lock(struct lockspace *ls, int locks_do)
return 0;
}
static int clear_locks(struct lockspace *ls, int free_vg, int drop_vg)
static void clear_locks(struct lockspace *ls, int free_vg, int drop_vg)
{
struct resource *r, *r_safe;
struct lock *lk, *lk_safe;
@ -2293,6 +2324,13 @@ static int clear_locks(struct lockspace *ls, int free_vg, int drop_vg)
int lk_count = 0;
int rv;
list_for_each_entry_safe(r, r_safe, &ls->dispose, list) {
log_debug("%s:%s clear_locks dispose free_resource", ls->name, r->name);
list_del(&r->list);
lm_rem_resource(ls, r);
free_resource(r);
}
list_for_each_entry_safe(r, r_safe, &ls->resources, list) {
lk_version = 0;
@ -2308,7 +2346,7 @@ static int clear_locks(struct lockspace *ls, int free_vg, int drop_vg)
if (lk->flags & LD_LF_PERSISTENT && !drop_vg)
log_error("%s:%s clear lock persistent", ls->name, r->name);
else
log_debug("%s:%s clear lock mode %s client %d", ls->name, r->name, mode_str(lk->mode), lk->client_id);
log_debug("%s:%s clear lock mode %s client %u", ls->name, r->name, mode_str(lk->mode), lk->client_id);
if (lk->version > lk_version)
lk_version = lk->version;
@ -2344,20 +2382,33 @@ static int clear_locks(struct lockspace *ls, int free_vg, int drop_vg)
}
list_for_each_entry_safe(act, act_safe, &r->actions, list) {
log_error("%s:%s clear_locks cancel %s client %d",
log_error("%s:%s clear_locks cancel %s client %u",
ls->name, r->name, op_str(act->op), act->client_id);
act->result = -ECANCELED;
list_del(&act->list);
add_client_result(act);
}
r_free:
log_debug("%s:%s free", ls->name, r->name);
log_debug("%s:%s clear_locks free_resource", ls->name, r->name);
lm_rem_resource(ls, r);
list_del(&r->list);
free_resource(r);
}
}
return lk_count;
static struct resource *find_dispose_act(struct lockspace *ls, struct action *act)
{
struct resource *r;
/* Only resources for unlocked LVs should exist on the dispose list. */
list_for_each_entry(r, &ls->dispose, list) {
if (r->type == LD_RT_LV && !strcmp(r->name, act->lv_uuid)) {
list_del(&r->list);
return r;
}
}
return NULL;
}
/*
@ -2496,6 +2547,7 @@ static void *lockspace_thread_main(void *arg_in)
int adopt_ok = 0;
int wait_flag = 0;
int nodelay = 0;
int nocreate;
int retry;
int rv;
@ -2725,10 +2777,64 @@ static void *lockspace_thread_main(void *arg_in)
continue;
}
if (act->op == LD_OP_FREE && act->rt == LD_RT_LV) {
list_del(&act->list);
r = find_dispose_act(ls, act); /* removes r from dispose list */
if (r) {
log_debug("%s:%s free_lv from dispose for %u", ls->name, r->name, act->client_id);
rv = free_lv(ls, r);
lm_rem_resource(ls, r);
free_resource(r);
act->result = rv;
add_client_result(act);
} else {
/* Happens when init_lv was called, but lock was never acquired. */
log_debug("%s:%s free_lv lock_args %s not found on dispose list",
ls->name, act->lv_uuid, act->lv_args);
if (!(r = alloc_resource())) {
rv = -ENOMEM;
} else {
dm_strncpy(r->name, act->lv_uuid, sizeof(r->name));
memcpy(r->lv_args, act->lv_args, MAX_ARGS);
r->type = LD_RT_LV;
r->mode = LD_LK_UN;
lm_add_resource(ls, r);
rv = free_lv(ls, r);
lm_rem_resource(ls, r);
free_resource(r);
}
act->result = rv;
add_client_result(act);
}
continue;
}
list_del(&act->list);
/* applies to all resources */
if (act->op == LD_OP_CLOSE) {
/*
* free any resources the client moved to
* ls->dispose after unlocking. Between the
* time the client unlocked the LV, and now,
* another client could have created a new
* struct resource on ls->resources for the
* same LV. This would not be a problem.
*/
list_for_each_entry_safe(r, r2, &ls->dispose, list) {
if (r->dispose_client_id == act->client_id) {
log_debug("%s:%s free_resource from dispose for %u",
ls->name, r->name, act->client_id);
list_del(&r->list);
lm_rem_resource(ls, r);
free_resource(r);
}
}
/*
* check all resources for transient locks the client
* was holding that should be automatically unlocked
*/
list_add(&act->list, &act_close);
continue;
}
@ -2741,10 +2847,12 @@ static void *lockspace_thread_main(void *arg_in)
* (This creates a new resource if the one named in
* the act is not found.)
*/
nocreate = (act->op == LD_OP_FREE) ||
((act->op == LD_OP_LOCK) && (act->mode == LD_LK_UN));
r = find_resource_act(ls, act, (act->op == LD_OP_FREE) ? 1 : 0);
r = find_resource_act(ls, act, nocreate);
if (!r) {
act->result = (act->op == LD_OP_FREE) ? -ENOENT : -ENOMEM;
act->result = nocreate ? -ENOENT : -ENOMEM;
add_client_result(act);
continue;
}
@ -2803,7 +2911,7 @@ out_rem:
log_debug("S %s clearing locks", ls->name);
(void) clear_locks(ls, free_vg, drop_vg);
clear_locks(ls, free_vg, drop_vg);
/*
* Tell any other hosts in the lockspace to leave it
@ -4073,9 +4181,9 @@ static int client_send_result(struct client *cl, struct action *act)
if (act->lv_args[0])
lv_args = act->lv_args;
log_debug("send %s[%d] cl %u %s %s rv %d vg_args %s lv_args %s",
log_debug("send %s[%d][%u] %s%s%s result %d vg_args %s lv_args %s",
cl->name[0] ? cl->name : "client", cl->pid, cl->id,
op_str(act->op), rt_str(act->rt),
op_str(act->op), act->rt ? "_" : "", rt_str(act->rt),
act->result, vg_args ? vg_args : "", lv_args ? lv_args : "");
res = daemon_reply_simple("OK",
@ -4089,9 +4197,9 @@ static int client_send_result(struct client *cl, struct action *act)
} else if (act->op == LD_OP_QUERY_LOCK) {
log_debug("send %s[%d] cl %u %s %s rv %d mode %d",
log_debug("send %s[%d][%u] %s%s%s result %d mode %d",
cl->name[0] ? cl->name : "client", cl->pid, cl->id,
op_str(act->op), rt_str(act->rt),
op_str(act->op), act->rt ? "_" : "", rt_str(act->rt),
act->result, act->mode);
res = daemon_reply_simple("OK",
@ -4119,7 +4227,7 @@ static int client_send_result(struct client *cl, struct action *act)
else
act->result = -EINVAL;
log_debug("send %s[%d] cl %u dump result %d dump_len %d",
log_debug("send %s[%d][%u] dump result %d dump_len %d",
cl->name[0] ? cl->name : "client", cl->pid, cl->id,
act->result, dump_len);
@ -4132,9 +4240,9 @@ static int client_send_result(struct client *cl, struct action *act)
* A normal reply.
*/
log_debug("send %s[%d] cl %u %s %s rv %d %s %s",
log_debug("send %s[%d][%u] %s%s%s result %d %s %s",
cl->name[0] ? cl->name : "client", cl->pid, cl->id,
op_mode_str(act->op, act->mode), rt_str(act->rt),
op_mode_str(act->op, act->mode), act->rt ? "_" : "", rt_str(act->rt),
act->result, (act->result == -ENOLS) ? "ENOLS" : "", result_flags);
res = daemon_reply_simple("OK",
@ -5066,9 +5174,16 @@ skip_pvs_path:
dm_config_destroy(req.cft);
buffer_destroy(&req.buffer);
log_debug("recv %s[%d] cl %u %s %s \"%s\" flags %x",
log_debug("recv %s[%d][%u] %s%s%s %s%s %s%s%s%s opts=%x",
cl->name[0] ? cl->name : "client", cl->pid, cl->id,
op_mode_str(act->op, act->mode), rt_str(act->rt), act->vg_name, opts);
op_mode_str(act->op, act->mode), act->rt ? "_" : "", rt_str(act->rt),
act->vg_name[0] ? "vg=" : "",
act->vg_name,
act->lv_name[0] || act->lv_uuid[0] ? "lv=" : "",
act->lv_name[0] ? act->lv_name : "",
act->lv_uuid[0] ? ":" : "",
act->lv_uuid[0] ? act->lv_uuid : "",
opts);
if (lm == LD_LM_DLM && !lm_support_dlm()) {
log_debug("dlm not supported");
@ -5524,6 +5639,9 @@ static void adopt_locks(void)
INIT_LIST_HEAD(&vg_lockd);
INIT_LIST_HEAD(&to_unlock);
if (daemon_test)
return;
/*
* Get list of lockspaces from currently running lock managers.
* Get list of shared VGs from file written by prior lvmlockd.
@ -6200,7 +6318,7 @@ static int main_loop(daemon_state *ds_arg)
setup_worker_thread();
setup_restart();
#ifdef USE_SD_NOTIFY
#ifdef SD_NOTIFY_SUPPORT
sd_notify(0, "READY=1");
#endif

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"
@ -169,8 +169,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 +363,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;

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;

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
@ -163,6 +166,7 @@ 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;
@ -212,6 +216,7 @@ struct lockspace {
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 */
};
/* val_blk version */
@ -278,15 +283,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 */
@ -397,6 +402,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 +426,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;
}
@ -512,6 +551,7 @@ int lm_rename_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_
int lm_prepare_lockspace_sanlock(struct lockspace *ls);
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);
@ -571,6 +611,11 @@ 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)
@ -649,6 +694,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 +740,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)

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"
@ -153,11 +153,11 @@ struct lm_sanlock {
};
struct rd_sanlock {
struct val_blk *vb;
union {
struct sanlk_resource rs;
char buf[sizeof(struct sanlk_resource) + sizeof(struct sanlk_disk)];
};
struct val_blk *vb;
};
struct sanlk_resourced {
@ -298,8 +298,8 @@ static int read_host_id_file(void)
*sep = '\0';
memset(key_str, 0, sizeof(key_str));
memset(val_str, 0, sizeof(val_str));
(void) sscanf(key, "%s", key_str);
(void) sscanf(val, "%s", val_str);
(void) sscanf(key, "%63s", key_str);
(void) sscanf(val, "%63s", val_str);
if (!strcmp(key_str, "host_id")) {
host_id = atoi(val_str);
@ -846,6 +846,11 @@ int lm_init_lv_sanlock(struct lockspace *ls, char *ls_name, char *vg_name, char
offset = align_size * LV_LOCK_BEGIN;
}
if (offset < (align_size * LV_LOCK_BEGIN)) {
log_error("S %s init_lv_san invalid offset %llu", ls_name, (unsigned long long)offset);
return -1;
}
strcpy_name_len(rd.rs.lockspace_name, ls_name, SANLK_NAME_LEN);
rd.rs.num_disks = 1;
memcpy(rd.rs.disks[0].path, disk_path, SANLK_PATH_LEN-1);
@ -1094,22 +1099,35 @@ int lm_rename_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_
int lm_free_lv_sanlock(struct lockspace *ls, struct resource *r)
{
struct rd_sanlock *rds = (struct rd_sanlock *)r->lm_data;
struct lm_sanlock *lms = (struct lm_sanlock *)ls->lm_data;
struct sanlk_resource *rs = &rds->rs;
uint64_t offset = rds->rs.disks[0].offset;
int rv;
log_debug("%s:%s free_lv_san", ls->name, r->name);
log_debug("%s:%s free_lv_san %llu", ls->name, r->name, (unsigned long long)offset);
if (daemon_test)
return 0;
strcpy_name_len(rs->name, "#unused", SANLK_NAME_LEN);
rv = sanlock_write_resource(rs, 0, 0, 0);
if (rv < 0) {
log_error("%s:%s free_lv_san write error %d",
ls->name, r->name, rv);
if (!offset) {
lock_lv_offset_from_args(r->lv_args, &offset);
rds->rs.disks[0].offset = offset;
log_debug("%s:%s free_lv_san lock_args offset %llu", ls->name, r->name, (unsigned long long)offset);
}
if (offset < (lms->align_size * LV_LOCK_BEGIN)) {
log_error("%s:%s free_lv_san invalid offset %llu",
ls->name, r->name, (unsigned long long)offset);
return -1;
}
rv = sanlock_write_resource(rs, 0, 0, 0);
if (rv < 0)
log_error("%s:%s free_lv_san %llu write error %d",
ls->name, r->name, (unsigned long long)offset, rv);
return rv;
}
@ -1734,7 +1752,7 @@ out:
return 0;
}
static int lm_add_resource_sanlock(struct lockspace *ls, struct resource *r)
int lm_add_resource_sanlock(struct lockspace *ls, struct resource *r)
{
struct lm_sanlock *lms = (struct lm_sanlock *)ls->lm_data;
struct rd_sanlock *rds = (struct rd_sanlock *)r->lm_data;

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

@ -191,7 +191,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 +1051,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 +1178,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 +1590,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 +1941,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);
@ -2081,7 +2081,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);
@ -2113,7 +2113,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);
}
}
@ -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;

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

@ -1461,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

@ -152,15 +152,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 +170,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 +541,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

@ -31,6 +31,7 @@
struct selection {
struct dm_pool *mem;
struct dm_pool *regex_mem;
struct selection_node *selection_root;
int add_new_fields;
};
@ -204,7 +205,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 +550,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 +592,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 +1415,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 +1758,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 +1857,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 +1921,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 +1969,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 +2043,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 +2086,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 +2123,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 +2816,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 +2881,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 +2896,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 +2912,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 +2987,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;
@ -3322,7 +3513,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 +3527,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 +3553,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 +3637,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 +3708,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 +3738,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 +3807,53 @@ 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);
s_arr_size = dm_list_size(&fs->value->v.l->str_list.list);
if (!(s_arr = malloc(sizeof(char *) * s_arr_size))) {
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 +3967,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 +3979,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);
@ -3863,7 +4115,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 +4148,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 +4160,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 */
@ -4092,7 +4343,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);

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;
@ -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)))

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;
@ -401,12 +401,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 +571,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

@ -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

@ -226,7 +226,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)) < (MAGIC_NUMBER_SIZE + sizeof(h))) {
if (read(fh, buffer, sizeof(buffer)) < (int)(MAGIC_NUMBER_SIZE + sizeof(h))) {
log_sys_debug("read", vdo_path);
goto err;
}
@ -270,7 +270,7 @@ bool dm_vdo_parse_logical_size(const char *vdo_path, uint64_t *logical_blocks)
goto err;
}
if (read(fh, buffer, sizeof(buffer)) < (sizeof(struct vdo_geometry_block) + sizeof(vn))) {
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]]

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

@ -15,6 +15,6 @@ Few bugfixes and a lot of speed improvements mainly for many LVs.
[[!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="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

@ -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

@ -633,6 +633,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 +663,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,7 @@ SOURCES =\
device/filesystem.c \
device/online.c \
device/parse_vpd.c \
device/nvme.c \
device/dev_util.c \
display/display.c \
error/errseg.c \
@ -142,7 +143,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

@ -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

@ -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,

121
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"
@ -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,
@ -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
@ -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
@ -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

@ -12,7 +12,7 @@
enum {
#define cmd(a, b) a ,
#include "cmds.h"
#include "include/cmds.h"
#undef cmd
};

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>
@ -163,6 +165,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;

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;
@ -520,7 +525,7 @@ int config_file_read_fd(struct dm_config_tree *cft, struct device *dev, dev_io_r
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;
}
@ -927,7 +932,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 */
@ -1936,11 +1941,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;
@ -1971,7 +1978,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 only_pv_summary);
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

@ -681,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,

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

@ -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

@ -871,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;
}
}
@ -1161,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;
}
@ -1314,7 +1314,7 @@ int dm_devs_cache_update(void)
unsigned devs_features;
uint32_t d;
struct dm_list *dm_devs_new, *l;
int cache_changed = 0;
int cache_changed;
if (!get_dm_active_devices(NULL, &dm_devs_new, &devs_features))
return 1;
@ -1329,6 +1329,7 @@ int dm_devs_cache_update(void)
/* 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) ||
@ -1394,8 +1395,6 @@ void dm_devs_cache_label_invalidate(struct cmd_context *cmd)
struct dm_active_device *dm_dev;
struct device *dev;
dm_devs_cache_update();
dm_list_iterate_items(dm_dev, _cache.dm_devs) {
if (dm_dev->uuid &&
strncmp(dm_dev->uuid, UUID_PREFIX, sizeof(UUID_PREFIX) - 1) == 0) {
@ -2385,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

@ -487,7 +487,7 @@ static int _dev_is_mpath_component_sysfs(struct cmd_context *cmd, struct device
*/
holder_name = de->d_name;
if (dm_snprintf(dm_dev_path, sizeof(dm_dev_path), "%s/%s", cmd->dev_dir, holder_name) < 0) {
if (dm_snprintf(dm_dev_path, sizeof(dm_dev_path), "%s%s", cmd->dev_dir, holder_name) < 0) {
log_warn("dm device path to check mpath is too long.");
continue;
}
@ -595,7 +595,7 @@ static int _dev_in_wwid_file(struct cmd_context *cmd, struct device *dev,
*/
lookup:
dm_list_iterate_items(dw, &dev->wwids) {
if (dw->type == 1 || dw->type == 2 || dw->type == 3)
if (dw->scsi_type == 1 || dw->scsi_type == 2 || dw->scsi_type == 3)
wwid = &dw->id[4];
else
wwid = dw->id;
@ -615,7 +615,7 @@ lookup:
goto lookup;
if (!(dev->flags & DEV_ADDED_SYS_WWID) && dev_read_sys_wwid(cmd, dev, idbuf, sizeof(idbuf), &dw)) {
if (dw->type == 1 || dw->type == 2 || dw->type == 3)
if (dw->scsi_type == 1 || dw->scsi_type == 2 || dw->scsi_type == 3)
wwid = &dw->id[4];
else
wwid = dw->id;
@ -642,7 +642,7 @@ int dev_is_mpath_component(struct cmd_context *cmd, struct device *dev, dev_t *h
/*
* multipath only uses SCSI or NVME devices
*/
if (!major_is_scsi_device(dt, MAJOR(dev->dev)) && !dev_is_nvme(dt, dev))
if (!major_is_scsi_device(dt, MAJOR(dev->dev)) && !dev_is_nvme(dev))
return 0;
/*

View File

@ -16,6 +16,7 @@
#include "lib/misc/lib.h"
#include "lib/device/dev-type.h"
#include "lib/device/device-types.h"
#include "lib/device/filesystem.h"
#include "lib/mm/xlate.h"
#include "lib/config/config.h"
#include "lib/metadata/metadata.h"
@ -23,6 +24,7 @@
#include "lib/label/label.h"
#include "lib/commands/toolcontext.h"
#include "lib/activate/activate.h"
#include "lib/display/display.h"
#include "device_mapper/misc/dm-ioctl.h"
#ifdef BLKID_WIPING_SUPPORT
@ -46,7 +48,7 @@
* is excessive and unnecessary compared to just comparing /dev/name*.
*/
int dev_is_nvme(struct dev_types *dt, struct device *dev)
int dev_is_nvme(struct device *dev)
{
return (dev->flags & DEV_IS_NVME) ? 1 : 0;
}
@ -106,7 +108,7 @@ int dev_is_used_by_active_lv(struct cmd_context *cmd, struct device *dev, int *u
* from this name, create path "/dev/dm-1" to run stat on.
*/
if (dm_snprintf(dm_dev_path, sizeof(dm_dev_path), "%s/%s", cmd->dev_dir, holder_name) < 0)
if (dm_snprintf(dm_dev_path, sizeof(dm_dev_path), "%s%s", cmd->dev_dir, holder_name) < 0)
continue;
/*
@ -562,7 +564,7 @@ static int _is_partitionable(struct dev_types *dt, struct device *dev)
_loop_is_with_partscan(dev))
return 1;
if (dev_is_nvme(dt, dev)) {
if (dev_is_nvme(dev)) {
/* If this dev is already a partition then it's not partitionable. */
if (_has_sys_partition(dev))
return 0;
@ -790,7 +792,7 @@ int dev_get_primary_dev(struct dev_types *dt, struct device *dev, dev_t *result)
* block dev types that have their own major number, so
* the calculation based on minor number doesn't work.
*/
if (dev_is_nvme(dt, dev))
if (dev_is_nvme(dev))
goto sys_partition;
/*
@ -1378,6 +1380,22 @@ static unsigned long _dev_topology_attribute(struct dev_types *dt,
return result;
}
static unsigned long _dev_topology_attribute_4k(struct dev_types *dt,
const char *attribute,
struct device *dev,
unsigned long default_value)
{
unsigned long result = _dev_topology_attribute(dt, attribute, dev, default_value);
if ((result > 1) && (result & 0x3)) {
log_warn("WARNING: Ignoring %s = %lu for device %s (not divisible by 4KiB).",
attribute, result << SECTOR_SHIFT, dev_name(dev));
result = 8;
}
return result;
}
unsigned long dev_alignment_offset(struct dev_types *dt, struct device *dev)
{
return _dev_topology_attribute(dt, "alignment_offset", dev, 0UL);
@ -1385,12 +1403,12 @@ unsigned long dev_alignment_offset(struct dev_types *dt, struct device *dev)
unsigned long dev_minimum_io_size(struct dev_types *dt, struct device *dev)
{
return _dev_topology_attribute(dt, "queue/minimum_io_size", dev, 0UL);
return _dev_topology_attribute_4k(dt, "queue/minimum_io_size", dev, 0UL);
}
unsigned long dev_optimal_io_size(struct dev_types *dt, struct device *dev)
{
return _dev_topology_attribute(dt, "queue/optimal_io_size", dev, 0UL);
return _dev_topology_attribute_4k(dt, "queue/optimal_io_size", dev, 0UL);
}
unsigned long dev_discard_max_bytes(struct dev_types *dt, struct device *dev)

View File

@ -16,9 +16,10 @@
#define _LVM_DEV_TYPE_H
#include "lib/device/device.h"
#include "lib/display/display.h"
#include "lib/metadata/metadata-exported.h"
#include "lib/label/label.h"
#include "lib/device/filesystem.h"
struct fs_info;
#define NUMBER_OF_MAJORS 4096
@ -58,10 +59,10 @@ const char *dev_subsystem_name(struct dev_types *dt, struct device *dev);
int major_is_scsi_device(struct dev_types *dt, int major);
/* Signature/superblock recognition with position returned where found. */
int dev_is_md_component(struct cmd_context *cmd, struct device *dev, uint64_t *sb, int full);
int dev_is_mpath_component(struct cmd_context *cmd, struct device *dev, dev_t *mpath_devno);
int dev_is_swap(struct cmd_context *cmd, struct device *dev, uint64_t *signature, int full);
int dev_is_luks(struct cmd_context *cmd, struct device *dev, uint64_t *signature, int full);
int dev_is_md_component(struct cmd_context *cmd, struct device *dev, uint64_t *offset_found, int full);
int dev_is_mpath_component(struct cmd_context *cmd, struct device *dev, dev_t *holder_devno);
int dev_is_swap(struct cmd_context *cmd, struct device *dev, uint64_t *offset_found, int full);
int dev_is_luks(struct cmd_context *cmd, struct device *dev, uint64_t *offset_found, int full);
int dasd_is_cdl_formatted(struct device *dev);
const char *dev_mpath_component_wwid(struct cmd_context *cmd, struct device *dev);
@ -98,7 +99,7 @@ int dev_is_rotational(struct dev_types *dt, struct device *dev);
int dev_is_pmem(struct dev_types *dt, struct device *dev);
int dev_is_nvme(struct dev_types *dt, struct device *dev);
int dev_is_nvme(struct device *dev);
int dev_is_lv(struct cmd_context *cmd, struct device *dev);

View File

@ -16,11 +16,11 @@
#include "lib/misc/lib.h"
#include "lib/device/device.h"
int device_id_list_remove(struct dm_list *list, struct device *dev)
int device_id_list_remove(struct dm_list *devices, struct device *dev)
{
struct device_id_list *dil;
dm_list_iterate_items(dil, list) {
dm_list_iterate_items(dil, devices) {
if (dil->dev == dev) {
dm_list_del(&dil->list);
return 1;
@ -29,22 +29,22 @@ int device_id_list_remove(struct dm_list *list, struct device *dev)
return 0;
}
struct device_id_list *device_id_list_find_dev(struct dm_list *list, struct device *dev)
struct device_id_list *device_id_list_find_dev(struct dm_list *devices, struct device *dev)
{
struct device_id_list *dil;
dm_list_iterate_items(dil, list) {
dm_list_iterate_items(dil, devices) {
if (dil->dev == dev)
return dil;
}
return NULL;
}
int device_list_remove(struct dm_list *list, struct device *dev)
int device_list_remove(struct dm_list *devices, struct device *dev)
{
struct device_list *devl;
dm_list_iterate_items(devl, list) {
dm_list_iterate_items(devl, devices) {
if (devl->dev == dev) {
dm_list_del(&devl->list);
return 1;
@ -53,11 +53,11 @@ int device_list_remove(struct dm_list *list, struct device *dev)
return 0;
}
struct device_list *device_list_find_dev(struct dm_list *list, struct device *dev)
struct device_list *device_list_find_dev(struct dm_list *devices, struct device *dev)
{
struct device_list *devl;
dm_list_iterate_items(devl, list) {
dm_list_iterate_items(devl, devices) {
if (devl->dev == dev)
return devl;
}

View File

@ -13,6 +13,11 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef LIB_DEVICE_DEVICE_TYPES_H
#define LIB_DEVICE_DEVICE_TYPES_H
#include <stdint.h>
typedef struct {
const char name[15];
const int8_t max_partitions;
@ -65,5 +70,8 @@ static const dev_known_type_t _dev_known_types[] = {
{"nvme", 64, "NVM Express"},
{"zvol", 16, "ZFS Zvols"},
{"VxDMP", 16, "Veritas Dynamic Multipathing"},
{"zram", 1, "zram block device"},
{"", 0, ""}
};
#endif

View File

@ -16,8 +16,10 @@
#ifndef _LVM_DEVICE_H
#define _LVM_DEVICE_H
#include "base/data-struct/list.h"
#include "lib/uuid/uuid.h"
#include <stdint.h>
#include <fcntl.h>
#define DEV_REGULAR 0x00000002 /* Regular file? */
@ -41,6 +43,8 @@
#define DEV_MATCHED_USE_ID 0x00080000 /* matched an entry from cmd->use_devices */
#define DEV_SCAN_FOUND_NOLABEL 0x00100000 /* label_scan read, passed filters, but no lvm label */
#define DEV_SCAN_NOT_READ 0x00200000 /* label_scan not able to read dev */
#define DEV_ADDED_NVME_WWIDS 0x00400000 /* wwids have been ready from libnvme */
#define DEV_UPDATE_USE_ID 0x00800000 /* update system.devices entry to use preferred wwid */
/*
* Support for external device info.
@ -70,8 +74,12 @@ struct dev_ext {
#define DEV_ID_TYPE_WWID_NAA 9
#define DEV_ID_TYPE_WWID_EUI 10
#define DEV_ID_TYPE_WWID_T10 11
/* reserve 12 for "scsi name string" if we decide to add that */
#define DEV_ID_TYPE_NVME_EUI64 13
#define DEV_ID_TYPE_NVME_NGUID 14
#define DEV_ID_TYPE_NVME_UUID 15
/* Max length of WWID_NAA, WWID_EUI, WWID_T10 */
/* Max length of SCSI or NVME WWID */
#define DEV_WWID_SIZE 128
/*
@ -79,12 +87,14 @@ struct dev_ext {
* /sys/dev/block/%d:%d/device/wwid
* /sys/dev/block/%d:%d/wwid
* /sys/dev/block/%d:%d/device/vpd_pg83
* or libnvme
*/
struct dev_wwid {
struct dm_list list; /* dev->wwids */
int type; /* 1,2,3 for NAA,EUI,T10 */
char id[DEV_WWID_SIZE]; /* includes prefix naa.,eui.,t10. */
struct dm_list list; /* dev->wwids */
uint16_t scsi_type; /* 1,2,3 for SCSI NAA,EUI,T10 */
uint16_t nvme_type; /* 1,2,3 for NVME EUI64,NGUID,UUID */
char id[DEV_WWID_SIZE]; /* includes prefix e.g. naa.,eui.,t10. */
};
/*

View File

@ -14,8 +14,6 @@
#include "base/memory/zalloc.h"
#include "lib/misc/lib.h"
#include "lib/commands/toolcontext.h"
#include "lib/device/device.h"
#include "lib/device/device_id.h"
#include "lib/device/dev-type.h"
#include "lib/label/label.h"
@ -26,6 +24,7 @@
#include "lib/datastruct/str_list.h"
#include "lib/metadata/metadata-exported.h"
#include "lib/activate/activate.h"
#include "lib/display/display.h"
#include "device_mapper/misc/dm-ioctl.h"
#include <sys/stat.h>
@ -568,7 +567,7 @@ static int _dev_has_lvmlv_uuid(struct cmd_context *cmd, struct device *dev, char
* The numbers 1,2,3 for NAA,EUI,T10 are part of the standard
* and are used in the vpd data.
*/
static int _wwid_type_num(char *id)
static int _scsi_wwid_type_num(char *id)
{
if (!strncmp(id, "naa.", 4))
return 3;
@ -580,9 +579,9 @@ static int _wwid_type_num(char *id)
return 0; /* any unrecognized, non-standard prefix */
}
int wwid_type_to_idtype(int wwid_type)
int scsi_type_to_idtype(int scsi_type)
{
switch (wwid_type) {
switch (scsi_type) {
case 3: return DEV_ID_TYPE_WWID_NAA;
case 2: return DEV_ID_TYPE_WWID_EUI;
case 1: return DEV_ID_TYPE_WWID_T10;
@ -591,7 +590,7 @@ int wwid_type_to_idtype(int wwid_type)
}
}
int idtype_to_wwid_type(int idtype)
int idtype_to_scsi_type(int idtype)
{
switch (idtype) {
case DEV_ID_TYPE_WWID_NAA: return 3;
@ -602,6 +601,45 @@ int idtype_to_wwid_type(int idtype)
}
}
/*
* libnvme only returns the standard identifiers UUID/NGUID/EUI64
* sysfs wwid file will return "nvme." identifier when one of the
* others is not available.
*/
static int _nvme_wwid_type_num(char *id)
{
if (!strncmp(id, "uuid.", 5))
return 3; /* UUID is 16 bytes */
else if (!strncmp(id, "eui.", 4)) {
if (strlen(id) > 15)
return 2; /* NGUID is 16 bytes */
return 1; /* EUI64 is 8 bytes */
}
return 0; /* any other prefix, including "nvme.", which must come from sysfs wwid file */
}
int nvme_type_to_idtype(int nvme_type)
{
switch (nvme_type) {
case 3: return DEV_ID_TYPE_NVME_UUID;
case 2: return DEV_ID_TYPE_NVME_NGUID;
case 1: return DEV_ID_TYPE_NVME_EUI64;
case 0: return DEV_ID_TYPE_SYS_WWID;
default: return -1;
}
}
int idtype_to_nvme_type(int idtype)
{
switch (idtype) {
case DEV_ID_TYPE_NVME_UUID: return 3;
case DEV_ID_TYPE_NVME_NGUID: return 2;
case DEV_ID_TYPE_NVME_EUI64: return 1;
case DEV_ID_TYPE_SYS_WWID: return 0;
default: return -1;
}
}
void free_wwids(struct dm_list *ids)
{
struct dev_wwid *dw, *safe;
@ -620,22 +658,41 @@ void free_wwids(struct dm_list *ids)
* in /etc/multipath/wwids.
*/
struct dev_wwid *dev_add_wwid(char *id, int id_type, struct dm_list *ids)
struct dev_wwid *dev_add_wwid(char *id, int dw_type, int is_nvme, struct dm_list *ids)
{
struct dev_wwid *dw;
uint16_t scsi_type = 0;
uint16_t nvme_type = 0;
if (!id_type)
id_type = _wwid_type_num(id);
if (is_nvme)
nvme_type = dw_type ?: _nvme_wwid_type_num(id);
else
scsi_type = dw_type ?: _scsi_wwid_type_num(id);
/* nvme_type/scsi_type will be 0 for any sysfs wwid string that
doesn't begin with a prefix recognized by lvm, e.g. that
comes from sysfs wwid. */
if (!(dw = zalloc(sizeof(*dw))))
return_NULL;
/* Copy id string with upto DEV_WWID_SIZE characters */
dm_strncpy(dw->id, id, sizeof(dw->id));
dw->type = id_type;
dw->scsi_type = scsi_type;
dw->nvme_type = nvme_type;
dm_list_add(ids, &dw->list);
return dw;
}
struct dev_wwid *dev_add_scsi_wwid(char *id, int dw_type, struct dm_list *ids)
{
return dev_add_wwid(id, dw_type, 0, ids);
}
struct dev_wwid *dev_add_nvme_wwid(char *id, int dw_type, struct dm_list *ids)
{
return dev_add_wwid(id, dw_type, 1, ids);
}
#define VPD_SIZE 4096
int dev_read_vpd_wwids(struct cmd_context *cmd, struct device *dev)
@ -693,9 +750,13 @@ int dev_read_sys_wwid(struct cmd_context *cmd, struct device *dev,
else
format_general_id((const char *)buf, sizeof(buf), (unsigned char *)outbuf, outbufsize);
/* We don't currently add the sysfs wwid to dev->wwids for nvme, it's not needed. */
if (dev_is_nvme(dev))
return 1;
/* Note, if wwids are also read from vpd, this same wwid will be added again. */
if (!(dw = dev_add_wwid(buf, 0, &dev->wwids)))
if (!(dw = dev_add_wwid(buf, 0, dev_is_nvme(dev), &dev->wwids)))
return_0;
if (dw_out)
*dw_out = dw;
@ -809,7 +870,17 @@ char *device_id_system_read(struct cmd_context *cmd, struct device *dev, uint16_
if (!(dev->flags & DEV_ADDED_VPD_WWIDS))
dev_read_vpd_wwids(cmd, dev);
dm_list_iterate_items(dw, &dev->wwids) {
if (idtype_to_wwid_type(idtype) == dw->type)
if (idtype_to_scsi_type(idtype) == dw->scsi_type)
return strdup(dw->id);
}
return NULL;
case DEV_ID_TYPE_NVME_EUI64:
case DEV_ID_TYPE_NVME_NGUID:
case DEV_ID_TYPE_NVME_UUID:
if (!(dev->flags & DEV_ADDED_NVME_WWIDS))
dev_read_nvme_wwids(dev);
dm_list_iterate_items(dw, &dev->wwids) {
if (idtype_to_nvme_type(idtype) == dw->nvme_type)
return strdup(dw->id);
}
return NULL;
@ -823,6 +894,9 @@ char *device_id_system_read(struct cmd_context *cmd, struct device *dev, uint16_
*/
if ((idtype != DEV_ID_TYPE_SYS_WWID) &&
(idtype != DEV_ID_TYPE_SYS_SERIAL) &&
(idtype != DEV_ID_TYPE_NVME_EUI64) &&
(idtype != DEV_ID_TYPE_NVME_NGUID) &&
(idtype != DEV_ID_TYPE_NVME_UUID) &&
(idtype != DEV_ID_TYPE_WWID_NAA) &&
(idtype != DEV_ID_TYPE_WWID_EUI) &&
(idtype != DEV_ID_TYPE_WWID_T10)) {
@ -1043,6 +1117,9 @@ static const char _dev_id_types[][16] = {
[DEV_ID_TYPE_WWID_NAA] = "wwid_naa",
[DEV_ID_TYPE_WWID_EUI] = "wwid_eui",
[DEV_ID_TYPE_WWID_T10] = "wwid_t10",
[DEV_ID_TYPE_NVME_EUI64] = "nvme_eui64",
[DEV_ID_TYPE_NVME_NGUID] = "nvme_nguid",
[DEV_ID_TYPE_NVME_UUID] = "nvme_uuid",
};
static int _is_idtype(uint16_t idtype) {
@ -1107,6 +1184,17 @@ static const char *_dev_idname(struct device *dev, uint16_t idtype)
return NULL;
}
static struct dev_id *get_dev_id(struct device *dev, uint16_t idtype)
{
struct dev_id *id;
dm_list_iterate_items(id, &dev->ids) {
if (id->idtype == idtype)
return id;
}
return NULL;
}
static int _dev_has_id(struct device *dev, uint16_t idtype, const char *idname)
{
struct dev_id *id;
@ -1343,12 +1431,20 @@ int device_ids_read(struct cmd_context *cmd)
return ret;
}
#define BACKUP_NAME_LEN 35
#define BACKUP_NAME_SIZE BACKUP_NAME_LEN+1 /* +1 null byte */
/*
* backup files with version 1-9999 use a 4 digit suffix:
* 31 chars + 4 chars (zero padded counter) + null byte
*
* backup files with version >9999:
* 31 chars + 5+ chars (uint32 counter, not zero padded, up to 10 chars) + null byte
*/
#define BACKUP_NAME_SIZE 48 /* larger than the longest backup file name */
static int _filter_backup_files(const struct dirent *de)
{
if (strlen(de->d_name) != BACKUP_NAME_LEN)
int len = strlen(de->d_name);
if (len < 35 || len > BACKUP_NAME_SIZE-1)
return 0;
if (strncmp(de->d_name, "system.devices-", 15))
return 0;
@ -1372,6 +1468,7 @@ static void devices_file_backup(struct cmd_context *cmd, char *fc, char *fb, tim
uint32_t low_date = 0, low_time = 0, low_count = 0;
uint32_t de_date, de_time, de_count;
unsigned int backup_limit = 0, backup_count = 0, remove_count;
int namelen;
int sort_count;
int dir_fd;
int i;
@ -1392,10 +1489,21 @@ static void devices_file_backup(struct cmd_context *cmd, char *fc, char *fb, tim
tm = localtime(tp);
strftime(datetime_str, sizeof(datetime_str), "%Y%m%d.%H%M%S", tm);
/* system.devices-YYYYMMDD.HHMMSS.000N (fixed length 35) */
if (dm_snprintf(path, sizeof(path), "%s/devices/backup/system.devices-%s.%04u",
cmd->system_dir, datetime_str, df_counter) < 0)
goto_out;
/* arbitrary max for devicesfile_backup_limit setting */
if (backup_limit > 5000)
backup_limit = 5000;
if (df_counter < 10000) {
/* system.devices-YYYYMMDD.HHMMSS.NNNN (fixed length 35, uses 4 digit zero padded suffix) */
if (dm_snprintf(path, sizeof(path), "%s/devices/backup/system.devices-%s.%04u",
cmd->system_dir, datetime_str, df_counter) < 0)
goto_out;
} else {
/* system.devices-YYYYMMDD.HHMMSS.NNNNN... (variable length, suffix has no fixed width) */
if (dm_snprintf(path, sizeof(path), "%s/devices/backup/system.devices-%s.%u",
cmd->system_dir, datetime_str, df_counter) < 0)
goto_out;
}
if (!(fp = fopen(path, "w+"))) {
log_warn("WARNING: Failed to create backup file %s", path);
@ -1433,7 +1541,10 @@ static void devices_file_backup(struct cmd_context *cmd, char *fc, char *fb, tim
while ((de = readdir(dir))) {
if (de->d_name[0] == '.')
continue;
if (strlen(de->d_name) != BACKUP_NAME_LEN)
namelen = strlen(de->d_name);
if (namelen < 35 || namelen > BACKUP_NAME_SIZE-1)
continue;
memset(de_date_str, 0, sizeof(de_date_str));
@ -1441,16 +1552,22 @@ static void devices_file_backup(struct cmd_context *cmd, char *fc, char *fb, tim
memset(de_count_str, 0, sizeof(de_count_str));
/*
* Save the oldest backup file name.
* system.devices-YYYYMMDD.HHMMSS.NNNN
* Save the oldest backup file name:
*
* backup files with version 1-9999 have 4 digit suffix:
* system.devices-YYYYMMDD.HHMMSS.NNNN
* 12345678901234567890123456789012345 (len 35)
* date YYYYMMDD is 8 chars 16-23
* time HHMMSS is 6 chars 25-30
* count NNNN is 4 chars 32-35
*
* backup files with version >9999 have
* non-zero-padded variable length suffix:
* system.devices-YYYYMMDD.HHMMSS.NNNNN...
*/
memcpy(de_date_str, de->d_name+15, 8);
memcpy(de_time_str, de->d_name+24, 6);
memcpy(de_count_str, de->d_name+31, 4);
memcpy(de_count_str, de->d_name+31, namelen - 31);
de_date = (uint32_t)strtoul(de_date_str, NULL, 10);
de_time = (uint32_t)strtoul(de_time_str, NULL, 10);
@ -1488,7 +1605,7 @@ static void devices_file_backup(struct cmd_context *cmd, char *fc, char *fb, tim
/* Remove the n oldest files by sorting system.devices-*. */
setlocale(LC_COLLATE, "C"); /* Avoid sorting by locales */
sort_count = scandir(dirpath, &namelist, _filter_backup_files, alphasort);
sort_count = scandir(dirpath, &namelist, _filter_backup_files, versionsort);
setlocale(LC_COLLATE, "");
if (sort_count < 0) {
log_warn("WARNING: Failed to sort backup devices files.");
@ -1508,6 +1625,7 @@ static void devices_file_backup(struct cmd_context *cmd, char *fc, char *fb, tim
free(namelist[i]);
}
free(namelist);
out:
if (fp && fclose(fp))
stack;
@ -2564,33 +2682,63 @@ static int _match_du_to_dev(struct cmd_context *cmd, struct dev_use *du, struct
*/
/*
* SCSI:
* Make the du match this device if the dev has a vpd_pg83 wwid
* that matches du->idname, even if the sysfs wwid for dev did
* not match the du->idname. This could happen if sysfs changes
* which wwid it reports (there are often multiple), or if lvm in
* the future selects a sys_wwid value from vpd_pg83 data rather
* than from the sysfs wwid.
*
* TODO: update the df entry IDTYPE somewhere?
*
* NVME:
* For some nvme drives (faulty hw, flagged with quirk), the sysfs wwid
* file changed to reporting a new/correct wwid. The du->idname may
* still have the wwid from the old sysfs wwid, so we need to look
* at the old wwids that can be found from libnvme.
*
* device_ids_validate updates system.devices to use the latest value
* from sysfs wwid.
*
* In future, we could limit dev_read_nvme_wwids() to only devices
* that have the quirk flag (indicating a bad wwid had been used.)
* dev_has_nvme_quirk() checks a flag in a newly exposed sysfs file.
* If that sysfs file doesn't exist because of an older kernel, then
* the function returns -1. When the quirk file exists and says 0,
* then the device hasn't changed its reported sys_wwid value, and
* we don't need to check libnvme for other wwids that the dev
* might have displayed in the past.
*/
if (du->idtype == DEV_ID_TYPE_SYS_WWID) {
struct dev_wwid *dw;
if (!(dev->flags & DEV_ADDED_VPD_WWIDS))
if (!(dev->flags & DEV_ADDED_VPD_WWIDS) && !dev_is_nvme(dev))
dev_read_vpd_wwids(cmd, dev);
if (!(dev->flags & DEV_ADDED_NVME_WWIDS) && dev_is_nvme(dev))
dev_read_nvme_wwids(dev);
dm_list_iterate_items(dw, &dev->wwids) {
if (!strcmp(dw->id, du_idname)) {
if (!(id = zalloc(sizeof(struct dev_id))))
return_0;
/* wwid types are 1,2,3 and idtypes are DEV_ID_TYPE_ */
id->idtype = wwid_type_to_idtype(dw->type);
/* scsi/nvme types are 1,2,3 and idtypes are DEV_ID_TYPE_ */
if (dev_is_nvme(dev))
id->idtype = nvme_type_to_idtype(dw->nvme_type);
else
id->idtype = scsi_type_to_idtype(dw->scsi_type);
id->idname = strdup(dw->id);
dm_list_add(&dev->ids, &id->list);
du->dev = dev;
dev->id = id;
dev->flags |= DEV_MATCHED_USE_ID;
log_debug("Match %s %s to %s: using vpd_pg83 %s %s",
/* update system.devices with sysfs wwid value since IDTYPE=sys_wwid */
/* FIXME: also do this for scsi */
if (dev_is_nvme(dev))
dev->flags |= DEV_UPDATE_USE_ID;
log_debug("Match %s %s to %s: using extra %s %s",
idtype_to_str(du->idtype), du_idname, dev_name(dev),
idtype_to_str(id->idtype), id->idname ?: ".");
du->idtype = id->idtype;
@ -2939,6 +3087,31 @@ void device_ids_validate(struct cmd_context *cmd, struct dm_list *scanned_devs,
du->dev ? dev_name(du->dev) : "not set");
}
/*
* Replace old wwid with new value displayed by sysfs wwid.
*/
dm_list_iterate_items(du, &cmd->use_devices) {
if (!du->dev)
continue;
if (!(du->dev->flags & DEV_UPDATE_USE_ID))
continue;
if ((id = get_dev_id(du->dev, DEV_ID_TYPE_SYS_WWID)) && id->idname) {
log_debug("Validate %s %s PVID %s on %s: replace old wwid with %s",
idtype_to_str(du->idtype), du->idname ?: ".", du->pvid ?: ".",
dev_name(du->dev), id->idname);
if (!(tmpdup = strdup(id->idname)))
continue;
free(du->idname);
du->idtype = DEV_ID_TYPE_SYS_WWID;
du->idname = tmpdup;
du->dev->id = id;
update_file = 1;
} else {
log_warn("Device %s PVID %s is using only old wwid %s.",
dev_name(du->dev), du->pvid ?: ".", du->idname ?: ".");
}
}
/*
* Validate entries with proper device id types.
* idname is the authority for pairing du and dev.

View File

@ -16,10 +16,13 @@
#ifndef _LVM_DEVICE_ID_H
#define _LVM_DEVICE_ID_H
#include "lib/commands/toolcontext.h"
#include "lib/device/device.h"
void free_du(struct dev_use *du);
void free_dus(struct dm_list *list);
void free_dus(struct dm_list *dus);
void free_did(struct dev_id *did);
void free_dids(struct dm_list *list);
void free_dids(struct dm_list *ids);
const char *idtype_to_str(uint16_t idtype);
uint16_t idtype_from_str(const char *str);
const char *dev_idtype_for_metadata(struct cmd_context *cmd, struct device *dev);
@ -69,11 +72,16 @@ int read_sys_block_binary(struct cmd_context *cmd, struct device *dev,
int dev_has_mpath_uuid(struct cmd_context *cmd, struct device *dev, char **idname_out);
int wwid_type_to_idtype(int wwid_type);
int idtype_to_wwid_type(int idtype);
int scsi_type_to_idtype(int scsi_type);
int nvme_type_to_idtype(int nvme_type);
int idtype_to_scsi_type(int idtype);
int idtype_to_nvme_type(int idtype);
void free_wwids(struct dm_list *ids);
struct dev_wwid *dev_add_wwid(char *id, int id_type, struct dm_list *ids);
struct dev_wwid *dev_add_wwid(char *id, int dw_type, int is_nvme, struct dm_list *ids);
struct dev_wwid *dev_add_scsi_wwid(char *id, int dw_type, struct dm_list *ids);
struct dev_wwid *dev_add_nvme_wwid(char *id, int dw_type, struct dm_list *ids);
int dev_read_vpd_wwids(struct cmd_context *cmd, struct device *dev);
void dev_read_nvme_wwids(struct device *dev);
int dev_read_sys_wwid(struct cmd_context *cmd, struct device *dev,
char *buf, int bufsize, struct dev_wwid **dw_out);

View File

@ -14,9 +14,9 @@
#include "base/memory/zalloc.h"
#include "lib/misc/lib.h"
#include "lib/commands/toolcontext.h"
#include "lib/device/device.h"
#include "lib/device/dev-type.h"
#include "lib/device/filesystem.h"
#include "lib/display/display.h"
#include "lib/misc/lvm-exec.h"
#include "lib/activate/dev_manager.h"
@ -239,9 +239,9 @@ int fs_mount_state_is_misnamed(struct cmd_context *cmd, struct logical_volume *l
{
FILE *fp;
char proc_line[PATH_MAX];
char proc_fstype[FSTYPE_MAX];
char proc_devpath[PATH_MAX];
char proc_mntpath[PATH_MAX];
char proc_fstype[FSTYPE_MAX + 1];
char proc_devpath[PATH_MAX + 1];
char proc_mntpath[PATH_MAX + 1];
char mtab_mntpath[PATH_MAX] = { 0 };
char dm_devpath[PATH_MAX];
char tmp_path[PATH_MAX];
@ -327,7 +327,7 @@ int fs_mount_state_is_misnamed(struct cmd_context *cmd, struct logical_volume *l
if (sscanf(proc_line, "%"
DM_TO_STRING(PATH_MAX) "s %"
DM_TO_STRING(PATH_MAX) "s %"
DM_TO_STRING(PATH_MAX) "s", proc_devpath, proc_mntpath, proc_fstype) != 3)
DM_TO_STRING(FSTYPE_MAX) "s", proc_devpath, proc_mntpath, proc_fstype) != 3)
continue;
if (strcmp(fstype, proc_fstype))
continue;
@ -375,8 +375,7 @@ int fs_mount_state_is_misnamed(struct cmd_context *cmd, struct logical_volume *l
#define FS_CMD_MAX_ARGS 16
int crypt_resize_script(struct cmd_context *cmd, struct logical_volume *lv, struct fs_info *fsi,
uint64_t newsize_bytes_fs)
int crypt_resize_script(struct cmd_context *cmd, struct logical_volume *lv, struct fs_info *fsi)
{
char crypt_path[PATH_MAX];
char newsize_str[16] = { 0 };
@ -384,7 +383,7 @@ int crypt_resize_script(struct cmd_context *cmd, struct logical_volume *lv, stru
int args = 0;
int status;
if (dm_snprintf(newsize_str, sizeof(newsize_str), "%llu", (unsigned long long)newsize_bytes_fs) < 0)
if (dm_snprintf(newsize_str, sizeof(newsize_str), "%llu", (unsigned long long)fsi->new_size_bytes) < 0)
return_0;
if (dm_snprintf(crypt_path, sizeof(crypt_path), "/dev/dm-%u", MINOR(fsi->crypt_devt)) < 0)
@ -420,12 +419,11 @@ int crypt_resize_script(struct cmd_context *cmd, struct logical_volume *lv, stru
* if needs_crypt
* cryptsetup resize --size $newsize_sectors $cryptpath
*
* Note: when a crypt layer is included, newsize_bytes_fs is smaller
* Note: when a crypt layer is included, new_size_bytes is smaller
* than newsize_bytes_lv because of the crypt header.
*/
int fs_reduce_script(struct cmd_context *cmd, struct logical_volume *lv, struct fs_info *fsi,
uint64_t newsize_bytes_fs, char *fsmode)
int fs_reduce_script(struct cmd_context *cmd, struct logical_volume *lv, struct fs_info *fsi, char *fsmode)
{
char lv_path[PATH_MAX];
char crypt_path[PATH_MAX];
@ -435,7 +433,7 @@ int fs_reduce_script(struct cmd_context *cmd, struct logical_volume *lv, struct
int args = 0;
int status;
if (dm_snprintf(newsize_str, sizeof(newsize_str), "%llu", (unsigned long long)newsize_bytes_fs) < 0)
if (dm_snprintf(newsize_str, sizeof(newsize_str), "%llu", (unsigned long long)fsi->new_size_bytes) < 0)
return_0;
if (dm_snprintf(lv_path, PATH_MAX, "%s%s/%s", lv->vg->cmd->dev_dir, lv->vg->name, lv->name) < 0)
@ -448,7 +446,7 @@ int fs_reduce_script(struct cmd_context *cmd, struct logical_volume *lv, struct
argv[++args] = "--lvpath";
argv[++args] = lv_path;
if (newsize_bytes_fs) {
if (fsi->new_size_bytes) {
argv[++args] = "--newsizebytes";
argv[++args] = newsize_str;
}
@ -484,8 +482,8 @@ int fs_reduce_script(struct cmd_context *cmd, struct logical_volume *lv, struct
devpath = fsi->needs_crypt ? crypt_path : (char *)display_lvname(lv);
log_print_unless_silent("Reducing file system %s to %s (%llu bytes) on %s...",
fsi->fstype, display_size(cmd, newsize_bytes_fs/512),
(unsigned long long)newsize_bytes_fs, devpath);
fsi->fstype, display_size(cmd, fsi->new_size_bytes/512),
(unsigned long long)fsi->new_size_bytes, devpath);
if (!exec_cmd(cmd, argv, &status, 1)) {
log_error("Failed to reduce file system with lvresize_fs_helper.");
@ -513,12 +511,12 @@ int fs_reduce_script(struct cmd_context *cmd, struct logical_volume *lv, struct
* if $fstype == "xfs"
* xfs_growfs $devpath
*
* Note: when a crypt layer is included, newsize_bytes_fs is smaller
* Note: when a crypt layer is included, new_size_bytes is smaller
* than newsize_bytes_lv because of the crypt header.
*/
int fs_extend_script(struct cmd_context *cmd, struct logical_volume *lv, struct fs_info *fsi,
uint64_t newsize_bytes_fs, char *fsmode)
char *fsmode)
{
char lv_path[PATH_MAX];
char crypt_path[PATH_MAX];
@ -569,8 +567,8 @@ int fs_extend_script(struct cmd_context *cmd, struct logical_volume *lv, struct
devpath = fsi->needs_crypt ? crypt_path : (char *)display_lvname(lv);
log_print_unless_silent("Extending file system %s to %s (%llu bytes) on %s...",
fsi->fstype, display_size(cmd, newsize_bytes_fs/512),
(unsigned long long)newsize_bytes_fs, devpath);
fsi->fstype, display_size(cmd, fsi->new_size_bytes/512),
(unsigned long long)fsi->new_size_bytes, devpath);
if (!exec_cmd(cmd, argv, &status, 1)) {
log_error("Failed to extend file system with lvresize_fs_helper.");

View File

@ -15,6 +15,9 @@
#ifndef _FILESYSTEM_H
#define _FILESYSTEM_H
#include "lib/commands/toolcontext.h"
#include "lib/device/device.h"
#define FSTYPE_MAX 16
struct fs_info {
@ -26,6 +29,7 @@ struct fs_info {
uint32_t crypt_offset_bytes; /* offset in bytes of crypt data on LV */
dev_t crypt_devt; /* dm-crypt device between the LV and FS */
uint64_t crypt_dev_size_bytes;
uint64_t new_size_bytes;
unsigned nofs:1;
unsigned unmounted:1;
@ -42,12 +46,9 @@ struct fs_info {
int fs_get_info(struct cmd_context *cmd, struct logical_volume *lv,
struct fs_info *fsi, int include_mount);
int fs_extend_script(struct cmd_context *cmd, struct logical_volume *lv, struct fs_info *fsi,
uint64_t newsize_bytes, char *fsmode);
int fs_reduce_script(struct cmd_context *cmd, struct logical_volume *lv, struct fs_info *fsi,
uint64_t newsize_bytes, char *fsmode);
int crypt_resize_script(struct cmd_context *cmd, struct logical_volume *lv, struct fs_info *fsi,
uint64_t newsize_bytes_fs);
int fs_extend_script(struct cmd_context *cmd, struct logical_volume *lv, struct fs_info *fsi, char *fsmode);
int fs_reduce_script(struct cmd_context *cmd, struct logical_volume *lv, struct fs_info *fsi, char *fsmode);
int crypt_resize_script(struct cmd_context *cmd, struct logical_volume *lv, struct fs_info *fsi);
int fs_mount_state_is_misnamed(struct cmd_context *cmd, struct logical_volume *lv, char *lv_path, char *fstype);
int lv_crypt_is_active(struct cmd_context *cmd, char *lv_path);

274
lib/device/nvme.c Normal file
View File

@ -0,0 +1,274 @@
/*
* Copyright (C) 2024 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "base/memory/zalloc.h"
#include "lib/misc/lib.h"
#include "lib/commands/toolcontext.h"
#include "lib/device/device.h"
#include "lib/device/device_id.h"
#include "lib/mm/xlate.h"
#include <stdio.h>
#include <unistd.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <inttypes.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <limits.h>
#include <dirent.h>
#include <errno.h>
#include <stdbool.h>
#include <assert.h>
#ifdef NVME_SUPPORT
#include <libnvme.h>
static int iszero(unsigned char *d, size_t n)
{
size_t i;
for (i = 0; i < n; ++i) {
if (d[i])
return 0;
}
return 1;
}
static void _save_uuid(struct device *dev, unsigned char *uuid)
{
char idname[DEV_WWID_SIZE] = {0};
int max, pos, num, i;
max = sizeof(idname);
pos = 0;
num = snprintf(idname + pos, max - pos, "uuid.");
if (num >= max - pos)
goto bad;
pos += num;
for (i = 0; i < NVME_UUID_LEN; ++i) {
num = snprintf(idname + pos, max - pos, "%02x", uuid[i]);
if (num >= max - pos)
goto bad;
pos += num;
if (i == 3 || i == 5 || i == 7 || i == 9) {
num = snprintf(idname + pos, max - pos, "-");
if (num >= max - pos)
goto bad;
pos += num;
}
}
idname[DEV_WWID_SIZE-1] = '\0';
dev_add_nvme_wwid(idname, 3, &dev->wwids);
return;
bad:
log_debug("dev_read_nvme_wwids ignore invalid uuid %s for %s", uuid, dev_name(dev));
}
static void _save_nguid(struct device *dev, unsigned char *nguid)
{
char idname[DEV_WWID_SIZE] = {0};
int max, pos, num, i;
max = sizeof(idname);
pos = 0;
num = snprintf(idname + pos, max - pos, "eui.");
if (num >= max - pos)
goto bad;
pos += num;
for (i = 0; i < 16; ++i) {
num = snprintf(idname + pos, max - pos, "%02x", nguid[i]);
if (num >= max - pos)
goto bad;
pos += num;
}
idname[DEV_WWID_SIZE-1] = '\0';
dev_add_nvme_wwid(idname, 2, &dev->wwids);
return;
bad:
log_debug("dev_read_nvme_wwids ignore invalid nguid %s for %s", nguid, dev_name(dev));
}
static void _save_eui64(struct device *dev, unsigned char *eui64)
{
char idname[DEV_WWID_SIZE] = {0};
int max, pos, num, i;
max = sizeof(idname);
pos = 0;
num = snprintf(idname + pos, max - pos, "eui.");
if (num >= max - pos)
goto bad;
pos += num;
for (i = 0; i < 8; ++i) {
num = snprintf(idname + pos, max - pos, "%02x", eui64[i]);
if (num >= max - pos)
goto bad;
pos += num;
}
idname[DEV_WWID_SIZE-1] = '\0';
dev_add_nvme_wwid(idname, 1, &dev->wwids);
return;
bad:
log_debug("dev_read_nvme_wwids ignore invalid eui64 %s for %s", eui64, dev_name(dev));
}
#define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S))
static void *_nvme_alloc(size_t len)
{
size_t _len = ROUND_UP(len, 0x1000);
void *p;
if (posix_memalign((void *)&p, getpagesize(), _len))
return NULL;
memset(p, 0, _len);
return p;
}
void dev_read_nvme_wwids(struct device *dev)
{
const char *devpath;
unsigned char *data = NULL;
struct nvme_id_ns *ns = NULL;
struct nvme_id_ctrl *ctrl_id = NULL;
unsigned char nguid[16] = {0};
unsigned char eui64[8] = {0};
unsigned char uuid[NVME_UUID_LEN] = {0};
uint32_t nsid = 0;
int fd, i, len;
dev->flags |= DEV_ADDED_NVME_WWIDS;
/* shouldn't happen */
if (dm_list_empty(&dev->aliases))
return;
devpath = dev_name(dev);
if ((fd = open(devpath, O_RDONLY)) < 0) {
log_debug("dev_read_nvme_wwids cannot open %s", devpath);
return;
}
if (nvme_get_nsid(fd, &nsid)) {
log_print("dev_read_nvme_wwids nvme_get_nsid error %d %s", errno, devpath);
goto out;
}
if (!(ns = _nvme_alloc(sizeof(*ns))))
goto_out;
if (nvme_identify_ns(fd, nsid, ns)) {
log_debug("dev_read_nvme_wwids nvme_identify_ns error %d %s", errno, devpath);
goto out;
}
memcpy(nguid, ns->nguid, 16);
memcpy(eui64, ns->eui64, 8);
if (!iszero(nguid, 16))
_save_nguid(dev, nguid);
if (!iszero(eui64, 8))
_save_eui64(dev, eui64);
if (!(ctrl_id = _nvme_alloc(sizeof(struct nvme_id_ctrl))))
goto_out;
/* Avoid using nvme_identify_ns_descs before ver 1.3. */
if (!nvme_identify_ctrl(fd, ctrl_id)) {
if (le32_to_cpu(ctrl_id->ver) < 0x10300)
goto_out;
}
if (!(data = _nvme_alloc(NVME_IDENTIFY_DATA_SIZE)))
goto_out;
if (nvme_identify_ns_descs(fd, nsid, (struct nvme_ns_id_desc *)data)) {
log_debug("dev_read_nvme_wwids nvme_identify_ns_descs error %d %s", errno, devpath);
goto out;
}
for (i = 0; i < NVME_IDENTIFY_DATA_SIZE; i += len) {
struct nvme_ns_id_desc *cur = (struct nvme_ns_id_desc *)(data + i);
if (cur->nidl == 0)
break;
memset(eui64, 0, sizeof(eui64));
memset(nguid, 0, sizeof(nguid));
memset(uuid, 0, sizeof(uuid));
switch (cur->nidt) {
case NVME_NIDT_EUI64:
memcpy(eui64, data + i + sizeof(*cur), sizeof(eui64));
len = sizeof(eui64);
break;
case NVME_NIDT_NGUID:
memcpy(nguid, data + i + sizeof(*cur), sizeof(nguid));
len = sizeof(nguid);
break;
case NVME_NIDT_UUID:
memcpy(uuid, data + i + sizeof(*cur), NVME_UUID_LEN);
len = sizeof(uuid);
break;
case NVME_NIDT_CSI:
len = 1;
break;
default:
len = cur->nidl;
break;
}
len += sizeof(*cur);
if (!iszero(uuid, NVME_UUID_LEN))
_save_uuid(dev, uuid);
else if (!iszero(nguid, 16))
_save_nguid(dev, nguid);
else if (!iszero(eui64, 8))
_save_eui64(dev, eui64);
}
out:
free(ctrl_id);
free(ns);
free(data);
if (close(fd))
log_sys_debug("close", devpath);
}
#else
void dev_read_nvme_wwids(struct device *dev)
{
}
#endif

View File

@ -14,9 +14,8 @@
#include "base/memory/zalloc.h"
#include "lib/misc/lib.h"
#include "lib/commands/toolcontext.h"
#include "lib/device/device.h"
#include "lib/device/online.h"
#include "lib/config/defaults.h"
#include <dirent.h>

View File

@ -15,6 +15,9 @@
#ifndef _ONLINE_H
#define _ONLINE_H
#include "lib/commands/toolcontext.h"
#include "lib/device/device.h"
struct pv_online {
struct dm_list list;
struct device *dev;

View File

@ -177,7 +177,7 @@ int parse_vpd_ids(const unsigned char *vpd_data, int vpd_datalen, struct dm_list
break;
if (id_size >= ID_BUFSIZE)
id_size = ID_BUFSIZE - 1;
dev_add_wwid(id, 1, ids);
dev_add_scsi_wwid(id, 1, ids);
break;
case 0x2:
/* EUI-64 */
@ -203,7 +203,7 @@ int parse_vpd_ids(const unsigned char *vpd_data, int vpd_datalen, struct dm_list
break;
if (id_size >= ID_BUFSIZE)
id_size = ID_BUFSIZE - 1;
dev_add_wwid(id, 2, ids);
dev_add_scsi_wwid(id, 2, ids);
break;
case 0x3:
/* NAA */
@ -225,7 +225,7 @@ int parse_vpd_ids(const unsigned char *vpd_data, int vpd_datalen, struct dm_list
break;
if (id_size >= ID_BUFSIZE)
id_size = ID_BUFSIZE - 1;
dev_add_wwid(id, 3, ids);
dev_add_scsi_wwid(id, 3, ids);
break;
case 0x8:
/* SCSI name string */
@ -257,7 +257,7 @@ int parse_vpd_ids(const unsigned char *vpd_data, int vpd_datalen, struct dm_list
for (i = 0; i < strlen(id); i++)
id[i] = tolower(id[i]);
}
dev_add_wwid(id, type, ids);
dev_add_scsi_wwid(id, type, ids);
break;
default:
break;

View File

@ -934,13 +934,13 @@ void display_name_error(name_error_t name_error)
char yes_no_prompt(const char *prompt, ...)
{
/* Lowercase Yes/No strings */
static const char _yes[] = "yes";
static const char _no[] = "no";
char buf[12] = { 0 };
static const char _yes[sizeof(buf)] = "yes";
static const char _no[sizeof(buf)] = "no";
const char *answer = NULL;
int c = silent_mode() ? EOF : 0;
int ret = 0, sig = 0;
unsigned i = 0;
char buf[12];
va_list ap;
sigint_allow();

View File

@ -17,7 +17,6 @@
#include "base/data-struct/radix-tree.h"
#include "lib/misc/lib.h"
#include "lib/filters/filter.h"
#include "lib/config/config.h"
struct pfilter {
struct radix_tree *devices;
@ -74,7 +73,7 @@ static void _persistent_filter_wipe(struct cmd_context *cmd, struct dev_filter *
_init_hash(pf);
} else {
dm_list_iterate_items(sl, &dev->aliases)
radix_tree_remove(pf->devices, sl->str, strlen(sl->str));
(void) radix_tree_remove(pf->devices, sl->str, strlen(sl->str));
}
}

View File

@ -15,6 +15,7 @@
#include "base/memory/zalloc.h"
#include "lib/misc/lib.h"
#include "lib/filters/filter.h"
#include "lib/config/config.h"
#include "lib/activate/activate.h"
static const char _too_small_to_hold_pv_msg[] = "Too small to hold a PV";

View File

@ -27,7 +27,7 @@ struct dev_filter *md_filter_create(struct cmd_context *cmd, struct dev_types *d
struct dev_filter *fwraid_filter_create(struct dev_types *dt);
struct dev_filter *mpath_filter_create(struct dev_types *dt);
struct dev_filter *partitioned_filter_create(struct dev_types *dt);
struct dev_filter *persistent_filter_create(struct dev_types *dt, struct dev_filter *f);
struct dev_filter *persistent_filter_create(struct dev_types *dt, struct dev_filter *real);
struct dev_filter *sysfs_filter_create(const char *sysfs_dir);
struct dev_filter *signature_filter_create(struct dev_types *dt);
struct dev_filter *deviceid_filter_create(struct cmd_context *cmd);

View File

@ -219,7 +219,7 @@ static void _remove_expired(const char *dir, const char *vgname,
sum /= 1024 * 1024;
if (sum > 128 || archives_size > 8192)
log_print_unless_silent("Consider pruning %s VG archive with more then %u MiB in %u files (see archiving settings in lvm.conf).",
log_print_unless_silent("Consider pruning %s VG archive with more than %u MiB in %u files (see archiving settings in lvm.conf).",
vgname, (unsigned)sum, archives_size);
}

View File

@ -70,7 +70,7 @@ int print_segtype_lvflags(char *buffer, size_t size, uint64_t status);
int read_lvflags(uint64_t *status, const char *flags_str);
int text_vg_export_file(struct volume_group *vg, const char *desc, FILE *fp);
size_t text_vg_export_raw(struct volume_group *vg, const char *desc, char **buf, uint32_t *alloc_size);
size_t text_vg_export_raw(struct volume_group *vg, const char *desc, char **buf, uint32_t *buf_size);
struct volume_group *text_read_metadata_file(struct format_instance *fid,
const char *file,
time_t *when, char **desc);

View File

@ -16,6 +16,8 @@
#ifndef _LVM_TEXT_EXPORT_H
#define _LVM_TEXT_EXPORT_H
#include <stdint.h>
#define outsize(args...) do {if (!out_size(args)) return_0;} while (0)
#define outhint(args...) do {if (!out_hint(args)) return_0;} while (0)
#define outfc(args...) do {if (!out_text_with_comment(args)) return_0;} while (0)

View File

@ -21,6 +21,7 @@
struct dm_hash_table;
struct lv_segment;
struct dm_config_node;
struct dm_config_value;
int text_import_areas(struct lv_segment *seg, const struct dm_config_node *sn,
const struct dm_config_value *cv, uint64_t status);

View File

@ -141,7 +141,6 @@
#include "lib/misc/crc.h"
#include "lib/cache/lvmcache.h"
#include "lib/device/bcache.h"
#include "lib/commands/toolcontext.h"
#include "lib/activate/activate.h"
#include "lib/label/hints.h"
#include "lib/device/dev-type.h"

View File

@ -15,6 +15,8 @@
#ifndef _LVM_HINTS_H
#define _LVM_HINTS_H
#include "lib/commands/toolcontext.h"
struct hint {
struct dm_list list;
dev_t devt;

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