1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-10-25 03:33:16 +03:00

Compare commits

...

1232 Commits

Author SHA1 Message Date
Marian Csontos
c8b7a765cb pre-release 2.03.36 2025-10-24 18:21:25 +02:00
Marian Csontos
8e1f326d82 CI: fix regexp filtering out some unstable tests 2025-10-24 18:08:40 +02:00
Zdenek Kabelac
a1ea879c31 coverity: add annotation for intentional single-iteration pattern
Add coverity[unreachable] annotation to suppress false positive
warning about unreachable loop increment when using dm_list_iterate_items()
with immediate break to get the first item from a list.
2025-10-24 17:21:02 +02:00
Zdenek Kabelac
51f80dc0a9 cleanup: simplify getting first poll_idls item
Use dm_list_iterate_items() with immediate break to get the first
item from the list, then check for NULL explicitly. This is clearer
than using dm_list_empty() followed by dm_list_item(dm_list_first()),
and helps static analyzers like Coverity understand that we're
properly checking for the NULL case.

Add coverity annotation to suppress unreachable code warning for
the intentional single-iteration pattern.

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-24 17:21:02 +02:00
Zdenek Kabelac
8f7f91fdf9 dmeventd: fix thread state transition when reusing from grace period
Threads reused from grace period should transition directly to
DM_THREAD_RUNNING state, not DM_THREAD_REGISTERING. The REGISTERING
state is only for newly created threads during initial registration.
If the thread would finish in this state, we might miss to
unregister device.

Set processing flag to prevent race conditions with timeout thread
signaling during the transition. Update comments to reflect the
correct state flow.

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-24 17:21:02 +02:00
Zdenek Kabelac
83a49e3cbf WHATS_NEW: update 2025-10-23 20:15:30 +02:00
Zdenek Kabelac
d105bfb5ad cleanup: consistent chunk_size_calc_policy naming
Rename symbols to use consistent and generic naming:
- thin_chunk_size_calc_policy -> chunk_size_calc_policy
- chunk_size_calc_method -> chunk_size_calc_policy
- THIN_CHUNK_SIZE_CALC_METHOD_* -> CHUNK_SIZE_CALC_POLICY_*

Change type from int to unsigned since these are flag values.

Introduce CHUNK_SIZE_CALC_POLICY_UNSELECTED (0x00) to replace
bare 0 value with meaningful define.

This removes the "THIN_" prefix since the policy applies to both
thin and cache pools, and uses "policy" consistently throughout
to match the config setting name (thin_pool_chunk_size_policy).

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-23 20:15:30 +02:00
Zdenek Kabelac
620cc808d1 pool: initialize chunk_size_calc_method in update functions
Fix uninitialized variable bug causing valgrind warnings when
converting LVs to pools with user-specified --chunksize.

The update_thin_pool_params() and update_cache_pool_params()
functions only initialized chunk_size_calc_method in the code
path that calculates default chunk size from profile settings.
When users specified --chunksize, this output parameter remained
uninitialized and was later used in a conditional check in
recalculate_pool_chunk_size_with_dev_hints(), triggering valgrind:
"Conditional jump or move depends on uninitialised value(s)"

Fix by initializing chunk_size_calc_method to 0 at the start of
both functions. A value of 0 indicates chunk size was user-specified
or should not be recalculated from device hints.

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-23 20:15:30 +02:00
Marian Csontos
9c1a632dc8 doc: Update release-notes. 2025-10-23 19:47:53 +02:00
Marian Csontos
c50557996d CI: fix job status 2025-10-23 19:47:53 +02:00
Zdenek Kabelac
1cf6e5492b test: simplify
Reduce number of calls - when used with valgrind testing,
extra commands take quite some extra time - as simple workaround
just use single command for the change.
2025-10-22 23:52:08 +02:00
Zdenek Kabelac
18b0e82e23 test: add --yes to lvreduce
On older systems with need to always pass --yes for reduction
even when there is no fs.
2025-10-22 23:52:08 +02:00
Zdenek Kabelac
09e760b0ef dmeventd: reorder cleanup of pid file
Move the removal of DMEVENTD_PIDFILE after unlinking FIFO files
to prevent the exiting daemon from unlinking FIFO files that were just
created by a newly started daemon instance.

Race condition scenario (before this fix):
1. Old daemon exits, atexit() calls _remove_files_on_exit()
2. PID file is unlinked first
3. Client detects PID change via _wait_for_new_pid() and starts new daemon
4. New daemon creates its FIFO files via mkfifo()
5. Old daemon (still in atexit) then unlinks FIFO files
6. New daemon's FIFOs are destroyed before it can use them

By removing the PID file last, we ensure that when clients detect the PID
file is gone (or changed), the old daemon has already cleaned up its FIFOs
and won't interfere with files created by the new instance.
2025-10-22 23:50:47 +02:00
Zdenek Kabelac
c7fd0d3001 WHATS_NEW: update 2025-10-22 17:24:41 +02:00
Zdenek Kabelac
090444e450 test: check raid allocation failure
Regression test for https://issues.redhat.com/browse/RHEL-116884

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-22 17:23:59 +02:00
Zdenek Kabelac
d2715e01f5 lv_manip: detect insufficient space for RAID with split metadata
When approx_alloc reduces allocation and we have RAID/mirror with
split metadata (alloc_and_split_meta), verify that we allocated at
least 1 extent per data area.

If total_area_len < area_count, the integer division during parallel
area allocation (area_len = max_to_allocate / ah->area_multiple) results
in area_len=0 for individual data areas. This causes those areas to be
skipped (empty allocation), creating RAID image LVs with no segments.

This create invalid metadata with LVs without segments.

Example:
- Need 52 extents total (4 data areas x 13 extents)
- Metadata allocated: 4 extents (4 rmeta x 1 extent each)
- Only 1 extent remains for data
- Result: area_len = 1/4 = 0, all data areas get empty allocation

Fix by failing allocation early with clear error message instead of
creating corrupted RAID LVs that trigger internal errors.

Resolves: https://issues.redhat.com/browse/RHEL-116884

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-22 17:19:34 +02:00
Zdenek Kabelac
a4d5c8ee9a WHATS_NEW: update 2025-10-21 22:23:29 +02:00
Zdenek Kabelac
356074fd61 test: hide line for success
Dont clutter output when there is no error.
2025-10-21 22:21:30 +02:00
Zdenek Kabelac
0f6cbb9ee7 test: wait_pvmove_lv_ready handles -real
Since now our pvmove LV is adding suffix - strip it for search
in lvmpolld dumped output where pvmove LV is stored without
this suffix in it database.
2025-10-21 22:21:30 +02:00
Zdenek Kabelac
99b85e7e4a dmeventd: simplify grace period wake-up path
Fix race when reusing thread in grace period.

Remove unnecessary code after grace period wait that performed redundant
operations already handled by _update_events() or pointless operations
for threads about to terminate.

The grace period wait occurs inside a while(thread->events) loop. After
the wait completes, control returns to the loop condition check, making
post-wait operations unnecessary:

Scenario 1 - Woken by registration (_update_events called):
  - _update_events() sets thread->events to non-zero
  - Moves thread to active registry via _thread_used()
  - Sets thread->status (to DM_THREAD_REGISTERING to trigger re-registration)
  - Signals the condition variable
  - _register_for_event() then calls _register_for_timeout() which resets
    next_time to give thread fresh timeout period (thanks to patch 1)
  - Loop continues with events != 0, thread resumes monitoring

Post-wait code was redundant - everything already done by _update_events()
and subsequent _register_for_timeout() call.

Scenario 2 - Natural timeout (grace period expired):
  - thread->events remains 0 (no new registration)
  - Loop condition while(thread->events) becomes false
  - Loop exits, thread terminates
  - Cleanup handler processes thread from unused registry

Post-wait code was pointless - thread exits immediately anyway, moving it
to active registry serves no purpose.

Removed operations:
- _unlock_mutex()/_lock_mutex() cycle (eliminates potential race window)
- Timeout reset via direct next_time assignment (now handled by
  _register_for_timeout() thanks to patch 1)
- Unconditional _thread_used() call (now handled by _update_events() when
  actually needed)

Added to _update_events():
When waking thread from grace period, now explicitly:
- Moves thread to active registry before signaling (fixes race where
  GET_REGISTERED_DEVICE queries could fail to find just-registered device)
- Sets status to DM_THREAD_REGISTERING (triggers re-registration flow)
- Comments explain both wake-up scenarios

Benefits:
- Simpler, clearer code flow
- Keeps _global_mutex locked throughout (safer, no unlock/relock)
- Timeout reset via proper API (_register_for_timeout) not direct assignment
- Fixes race condition where registered device appears unregistered briefly

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-21 22:21:30 +02:00
Zdenek Kabelac
dd479229f3 dmeventd: wake grace period threads on daemon exit
When dmeventd is exiting (_exit_now is set), _cleanup_unused_threads()
needs to wake threads waiting in grace period so they can check the exit
flag and terminate fast and cleanly.

Without this, threads in grace period would continue waiting up to the
full grace period duration (default 10 seconds) before their condition
wait times out and they check _exit_now. This delays daemon shutdown.

Changes:
- In _cleanup_unused_threads(), detect threads in DM_THREAD_GRACE_PERIOD state
- If daemon is exiting, signal their grace_cond to wake them immediately
- Break to check again on next cleanup round (thread should transition to DONE)
2025-10-21 22:21:30 +02:00
Zdenek Kabelac
ecb9d8ef25 dmeventd: refactor time handling and timeout registration
Extract time retrieval logic into _get_curr_time() helper function that
consistently uses clock_gettime(CLOCK_REALTIME) when available, falling
back to time(NULL). This centralizes time handling and makes it more
maintainable.

More importantly, change _register_for_timeout() to always update
thread->next_time, not only when initially adding to the timeout registry.

This behavioral change enables resetting the timeout for threads being
reused from grace period. When a thread in grace period is woken for new
registration, calling _register_for_timeout() will now give it a fresh
timeout period, ensuring the timeout fires at the correct interval after
resuming monitoring (not based on stale next_time from previous cycle).

This is preparation for grace period wake-up path simplification in
subsequent commits.
2025-10-21 22:21:30 +02:00
David Teigland
a945c93d42 lvmlockd: allow vgchange locktype without global lock
In vgchange --locktype, if the global lock request fails, continue
with the command without it.  An example in which this is necessary
is vgchange --locktype sanlock vg, where there are no other sanlock
VGs available containing a global lock.
2025-10-21 14:16:24 -05:00
David Teigland
83f3921705 lvmlockd: allow lvchange refresh on lvmlock LV 2025-10-21 09:37:14 -05:00
Zdenek Kabelac
74d2962b12 WHATS_NEW: update 2025-10-17 13:43:03 +02:00
Zdenek Kabelac
1f9c62a410 doc: remove obsolete file
This daemon was dropped long time ago...
2025-10-17 13:43:03 +02:00
Zdenek Kabelac
588e12408f test: update excluded kernels 2025-10-17 13:43:03 +02:00
Zdenek Kabelac
652d65af18 codespell: typos
Fix typos in new messages and doc.
2025-10-17 13:43:03 +02:00
Zdenek Kabelac
284627f811 radix_tree: eliminate node16 to node4 degradation
Remove _degrade_to_n4() function and the node16 -> node4 degradation path
during removal operations. Instead, only free node16 when it becomes
completely empty. Lookup performance is identical.
Allocation overhead is removed with very low waste of memory since
this degradation case is rare in practice.
2025-10-17 13:43:03 +02:00
Zdenek Kabelac
e2afc0ec20 radix-tree: optimize memory allocation overhead
Replace zalloc() with malloc() for structures where all fields are
explicitly initialized. This avoids unnecessary zeroing of memory
that will be immediately overwritten.
2025-10-17 13:43:03 +02:00
Zdenek Kabelac
0626a1708e pvmove: use -real suffix for UUID
Start using -real suffix for pvmove UUID. Use of suffix makes
volume invisible for udev even after restart and udev database
reinitialization.

We could possibly use -pvmove suffix - however this would require
unessary extra code and also we would need to -pvmove within
its lvname or add another code we use for seek of orphan -real
volumes to seek also for -pvmove.

So for now keeping it simple and stay with -real which does not
require to store different pvmove LV names in metadata.
2025-10-17 13:43:03 +02:00
David Teigland
18959c825b lvmlockd: deactivate internal lvmlock LV if lock start fails 2025-10-16 14:23:59 -05:00
Zdenek Kabelac
cb9badd391 WHATS_NEW: update 2025-10-16 14:32:10 +02:00
Zdenek Kabelac
08833b6d1a test: update to catch raid issue
If we are checking raid after the pvmove is finished,
raid could have actully 'revive' itself - so test
after table reload was not capturing the failed leg.
2025-10-16 14:30:14 +02:00
Zdenek Kabelac
65d2e7a6b5 test: pvmove segmentation 2025-10-16 14:30:14 +02:00
Zdenek Kabelac
48015ecb3c libdm: deptree: cancel delay_resume for new children when parent is inactive
When preloading children of an inactive parent node (other than root),
cancel the delay_resume_if_new flag to allow immediate resume of new devices.

This fixes a specific issue with pvmove operations on RAID devices where:

1. The RAID logical volume has not been instantiated yet (inactive parent)
2. A pvmove device needs to be created for one of the RAID legs
3. The RAID table requires the leg LV to be active before loading
4. Therefore, the pvmove device must be resumed immediately, not delayed

Background:
When both RAID and pvmove devices are being created from scratch,
the pvmove device can be started immediately without leaking direct
access to the PV - all I/O goes through appropriate targets from the start.

However, if the RAID device is already active, we can only preload the
new pvmove table. In that case, a full suspend must occur before resuming
the new table, ensuring all I/O continues through the existing table
until the resume point.
2025-10-16 14:30:14 +02:00
Zdenek Kabelac
89183b0a06 revert "libdm: fix pvmove preload for complex devices"
This reverts commit 8afdfebc47.
2025-10-16 14:30:11 +02:00
Zdenek Kabelac
0b398da71c revert "libdm: drop propagation of delay_resume_if_new"
This reverts commit bfb9a9e9b1.
So a different solution can be applied as backportable patch.
2025-10-16 14:29:45 +02:00
Zdenek Kabelac
00aa072284 pvmove: segment large moves
Introduce splitting of large segments before building the temporary pvmove
mirror layer, limiting the size of each mirrored chunk according to the
configuration setting `allocation/pvmove_max_segment_size_mb` (in MiB).

Details:
- Add helper `_split_large_segments_for_pvmove()` in `lib/metadata/lv_manip.c`.
  The helper is invoked at the start of `insert_layer_for_segments_on_pv()`
  when `status & PVMOVE` is set.
- Read the limit via `allocation_pvmove_max_segment_size_mb_CFG`.
  A value of 0 disables splitting (default behavior unchanged).
- Convert the limit from MiB to extents based on the VG extent size,
  ensure at least 1 extent, and align the limit to a whole stripe
  (`seg->area_count`).
- For segments on the specified PV, split at LE boundaries using
  `lv_split_segment()` so that each chunk is <= the aligned limit.

Benefits:
- Avoid excessively large single mirror operations during pvmove.
- Shorter activation windows and more frequent metadata checkpoints.
- Improved responsiveness and progress reporting for large moves.

Note:
- This uses the config added separately in `allocation/pvmove_max_segment_size_mb`;
  when unset (0), behavior is unchanged.
2025-10-16 14:29:03 +02:00
Zdenek Kabelac
fd13a02f4e config: add allocation/pvmove_max_segment_size_mb
Introduce a new configuration setting `allocation/pvmove_max_segment_size_mb`
that limits the maximum size (in MiB) of a segment mirrored at once during
pvmove.
2025-10-16 14:29:03 +02:00
David Teigland
a813ef476e test: integrity-imeta-segs use ext4 2025-10-14 10:49:27 -05:00
David Teigland
724747d772 integrity: allow creating imeta with more than one segment
The imeta LV is already permitted to have more than one segment when
extending, so there's no reason to prevent this in the initial state.
2025-10-13 14:50:52 -05:00
Zdenek Kabelac
e2f59bce4e test: replace large test data
Replace large static test data inclusion with algorithmic generation.

The test_bcache_scenario3() function included a ~1600-line
static test case file (rt_case1.c)
2025-10-13 12:50:16 +02:00
Zdenek Kabelac
9745e4ecf9 debug: remove obsolete comment
Obsoleted comment with recent commit 61c2cc0c89.
2025-10-13 12:50:16 +02:00
Zdenek Kabelac
ec25b4b28c cov: ensure list is initialized
Make obvious to Coverity that our dm_list here after full safe
iteration is equal to the initilized list.
2025-10-13 12:50:16 +02:00
Zdenek Kabelac
d991c7c5c2 coverity: improve static analysis models
Improvements to Coverity modeling file to enable better
static analysis of LVM2 code.

1. Improve first_seg()/last_seg()/find_config_tree_str()/
   find_config_tree_str_allow_empty() - now models that these never
   return NULL.

New Models Added:
2. dm_pool_alloc/zalloc/strdup/strndup - Core allocation functions
   - Models that allocation can fail (returns NULL)
   - Tracks uninitialized vs zeroed memory
   - Detects negative size arguments
   - Properly models string null-termination

3. dm_malloc/zalloc/free wrappers - Standard allocation wrappers
   - Resource tracking for leak detection
   - Allocation failure modeling

4. dm_list operations - List manipulation functions
   - Models that operations don't fail for valid inputs
   - Catches NULL pointer programming errors
2025-10-13 12:50:16 +02:00
Marian Csontos
a34b925fc8 CI: Run the reboot job always 2025-10-13 11:17:13 +02:00
David Teigland
b9837dd5e7 integrity: minor cleanup
add a couple minor code changes from reverted commit
cdf57ddfa4
2025-10-10 12:13:53 -05:00
Zdenek Kabelac
ec1ae7c871 WHATS_NEW: updates 2025-10-08 13:56:31 +02:00
Zdenek Kabelac
212ec87c16 cov: widen to 64bit arithmetic 2025-10-08 13:47:40 +02:00
Zdenek Kabelac
eaa1581a02 cov: reset result on error path 2025-10-08 13:47:40 +02:00
Zdenek Kabelac
dc51f3aa6c cov: driver_version checks version buffer
Call for driver_version(NULL, 0) needs check for version != NULL.
2025-10-08 13:47:40 +02:00
Zdenek Kabelac
68e6c3e06c cov: initialize variables 2025-10-08 13:47:40 +02:00
Zdenek Kabelac
72c32c52b4 cov: use proper memory release function
Allocated mda buffer needs to be released with dm_pool_free() in this
error path.
2025-10-08 13:47:40 +02:00
Zdenek Kabelac
f1a11acbe8 debug: trace failure
Function persist_vgremove_after() currently cannot fail.

Trace failure from _run_stop() and lock_global() calls.
2025-10-08 13:47:40 +02:00
Zdenek Kabelac
f8a05b1c7e metadata: add _validate_tags() helper
Consolidate identical tag validation pattern that appeared 3 times
in vg_validate() for VG tags, PV tags, and LV tags.

The pattern involved iterating through tag lists, calling validate_tag(),
and logging INTERNAL_ERROR messages with specific context.

No functional change.
2025-10-08 13:47:22 +02:00
Zdenek Kabelac
63db8d2957 mirror: add _cleanup_failed_mirrored_log() helper
Extract the complex mirrored log cleanup logic from _remove_mirror_images()
into a dedicated helper function.

No functional change.
2025-10-08 13:46:36 +02:00
Zdenek Kabelac
832029d464 mirror: add _validate_mirror_segments() helper
Extract common validation logic for checking if all segments in an LV
are mirrored and optionally have required status bits set.

This pattern appeared in remove_mirrors_from_segments() and could be
reused elsewhere for consistent validation.

No functional change.
2025-10-08 13:46:36 +02:00
Zdenek Kabelac
6d88b76eaf mirror: add _add_lv_to_list() helper function
Consolidate repeated pattern of allocating lv_list structure
and adding it to a list. This pattern appeared in 4 places
with slight variations in error handling and memory pool usage.

No functional change.
2025-10-08 13:46:36 +02:00
Zdenek Kabelac
9d58c71055 pvmove: use is_striped condition 2025-10-08 13:46:36 +02:00
Zdenek Kabelac
f83b49ab22 pvmove: remove unused _pvmove_is_exclusive() function
The _pvmove_is_exclusive() function always returned 0 and was never
modified to do anything else, making it dead code.

Replace the function call with direct assignment exclusive = 0;
and remove the unused function definition.

This simplifies the code without changing behavior since the function
was effectively a no-op that always returned the same value.
2025-10-08 13:46:36 +02:00
Zdenek Kabelac
61c2cc0c89 pvmove: simplification of RAID sibling PV removal
Replace string parsing in _remove_sibling_pvs_from_trim_list()
with direct structural access using LVM's existing infrastructure.

This eliminates all string manipulation and leverages seg_lv/seg_metalv
accessors for robust sibling detection.
2025-10-08 13:46:36 +02:00
Zdenek Kabelac
2b632d5f3a bcache: do not call io_destroy in forked process 2025-10-08 13:46:36 +02:00
Jason Owen
875571cc81 tools: add cache promotions/demotions to report
dm-cache devices keep track of how many times a block is promoted to or
demoted from the cache[1]. The `lvdisplay` tool knows how to display
this information, so the framework for looking it up is in place
already, but `lvs` did not use it.

Add two new columns `cache_promotions` and `cache_demotions` to expose
this information via `lvs`.

[1] https://docs.kernel.org/admin-guide/device-mapper/cache.html#status
2025-10-08 13:46:36 +02:00
David Teigland
8784b7f64b persist: use a prefix in the key file
key: 0xabc123
which makes it easier to add other lines in the future.
2025-10-07 12:48:24 -05:00
Marian Csontos
80afbd98ec CI: reboot VMs running gitlab-runner after tests 2025-10-07 16:16:45 +02:00
David Teigland
64fad1d1da persist: do not use pr_key config setting for sanlock VGs v2
Use only hostid-based PR keys for sanlock VGs.
This will be required for PR-based recovery with sanlock.

Changes how persist_start() is used to update an existing key.
Previously, the updated key was passed to persist_start as if
it was the local pr_key setting.  It's now passed as a separate
parameter.

This also fixes an incorrect warning in vgchange --persist check
when checking a hostid-based key while the lockspace is stopped.
2025-10-06 13:13:11 -05:00
David Teigland
5893794a19 Revert "persist: do not use pr_key config setting for sanlock VGs"
This reverts commit 038af21fa1.
2025-10-06 12:48:00 -05:00
David Teigland
038af21fa1 persist: do not use pr_key config setting for sanlock VGs
Use only hostid-based PR keys for sanlock VGs.
This will be required for PR-based recovery with sanlock.
2025-10-06 09:46:03 -05:00
Zdenek Kabelac
92b782042e revert "polldaemon: drop caches before daemonizing"
This reverts commit 8a704063ed.
Not the right way to fix this issue - needs different solution.
2025-10-03 15:28:22 +02:00
Zdenek Kabelac
dd712ac746 test: shorten lvconvert
Test doesn't need to be there for 100second - shorten timeout.
Normally this is not an issue if the background process does not
have an output, but if the output is enabled, it may block exit.
2025-10-02 22:55:26 +02:00
Zdenek Kabelac
8a704063ed polldaemon: drop caches before daemonizing
Droping cache after fork just make our internal bcache confused.
So droping early.
2025-10-02 22:55:26 +02:00
Zdenek Kabelac
bfb9a9e9b1 libdm: drop propagation of delay_resume_if_new
When we disable 'delay' for pvmove as not useful, whole propagation
becomes useless - so drop it for now until we have better plan.

Previous patch was not working well for some snapshot construction.
2025-10-02 22:55:26 +02:00
Zdenek Kabelac
8af25bd23a WHATS_NEW: update 2025-10-02 16:37:31 +02:00
Zdenek Kabelac
c4c301488e test: more excluded kernels 2025-10-02 16:36:22 +02:00
Zdenek Kabelac
a62dfdfbe2 test: raid restart 2025-10-02 16:36:22 +02:00
Zdenek Kabelac
95ecb6e57e clean: sort suffixes alphabetically
Just list suffixes 1 per line here.
2025-10-02 16:36:22 +02:00
Zdenek Kabelac
8afdfebc47 libdm: fix pvmove preload for complex devices
Change delay_resume_if_new propagation from "> 1" to "!= 1" to ensure
devices are resumed when required by parent devices. This specifically
fixes issues where RAID devices using legs that are being pvmoved need
their preloaded legs resumed before the RAID device itself is preloaded.

The fix ensures pvmove operations start when needed by parent devices,
even though this means pvmove begins before metadata commit. This is
acceptable since pvmove mirrors to previously unallocated extents.
2025-10-02 16:36:17 +02:00
Zdenek Kabelac
42e3a8705e integrity: fix activation race during setup
Add synchronization after deactivate_lv() to prevent races between
deactivation and subsequent activation using the same udev cookie.

This ensures proper ordering when wiping prepared integrity metadata
devices during RAID integrity setup, affecting both active and inactive
code paths.
2025-10-02 16:36:17 +02:00
David Teigland
c73c6e0b6a Revert "integrity: proper rounding for sizes"
This reverts commit cdf57ddfa4.
2025-09-29 11:48:50 -05:00
David Teigland
bacd71d338 persist: fix vgremove key check
Fix commit ab1405034d
"persist: vgremove should check for other keys"

which counted keys without eliminating the duplicates
that are reported for mpath devices, so vgremove would
report multiple registered keys for a single host using
an mpath device.
2025-09-29 11:03:46 -05:00
Zdenek Kabelac
ac673c35c8 WHATS_NEW: update 2025-09-29 15:54:38 +02:00
Zdenek Kabelac
f1732e0188 tests: continue with next filesystem
If the kernel fails to mount - continue with next fs.
(i.e kernel no longer supports reiserfs, but tools can be still there).
2025-09-29 15:45:35 +02:00
Zdenek Kabelac
c0e64cc295 tests: add tuned to checked services
Running tuned will change device properties in parallel so i.e.
setting read_ahead will not work as expected.
2025-09-29 15:45:35 +02:00
Zdenek Kabelac
35b01ec1e9 cov: initialize variables
Address Coverity static analysis warnings by initializing variables
that could theoretically be used uninitialized in edge cases:

While these uninitialized uses are unlikely to occur in practice due to
the surrounding logic, explicit initialization eliminates potential static
analysis warnings.
2025-09-29 15:45:35 +02:00
Zdenek Kabelac
dd7d4b1bf6 gcc: make variable initialized 2025-09-29 15:45:35 +02:00
Zdenek Kabelac
6f1ab66a0a cov: check for no patterns 2025-09-29 15:45:35 +02:00
Zdenek Kabelac
a68958cb15 cov: use checked pr_op pointer
Directly assign pr_op pointer and at the same time
use its checked value.
2025-09-29 15:45:35 +02:00
Zdenek Kabelac
fa741cab7f cov: check result 2025-09-29 15:45:35 +02:00
Zdenek Kabelac
132495d4bb cov: check resulting values 2025-09-29 15:45:35 +02:00
Zdenek Kabelac
f38400afd7 cov: raise MAX_FILTERS
After adding filter MAX_FILTERS might have been too small
if all filters would be applied.
2025-09-29 15:45:35 +02:00
Zdenek Kabelac
c15069ba67 debug: fix error message
Extent is correct here.
2025-09-29 15:45:35 +02:00
Zdenek Kabelac
516cd06296 display: add helper display_mb_size
Add function to simplify printing number that are stored
in MiB units that we use in couple places.
Avoids adding multiplication to sector units...
2025-09-29 15:45:35 +02:00
Zdenek Kabelac
0f4d9a2d5b vdo: extract magic numbers as named constant
Replace scattered magic numbers throughout VDO code with
descriptive named constants to improve code maintainability.
2025-09-29 15:45:35 +02:00
Zdenek Kabelac
c33233cb88 integrity: fix adding integrity to RAID
Fix several issues in integrity addition to RAID logical volumes and
improve error handling and cleanup:

Synchronization and activation fixes:
- Add sync_local_dev_names() before LV activation to handle potential
  udev deactivation in-flight from metadata device wiping
- Consolidate deactivate_lv() calls to avoid code duplication in
  _set_integrity_block_size() error path

Missing segment relationship:
- Add missing add_seg_to_segs_using_this_lv() call for imeta LV to
  properly establish segment relationships

Enhanced error recovery:
- Improve error path cleanup in case integrity addition fails
2025-09-29 15:45:35 +02:00
Zdenek Kabelac
cdf57ddfa4 integrity: proper rounding for sizes 2025-09-29 15:18:01 +02:00
Zdenek Kabelac
2538fa9b0f integrity: add some basic lvdisplay support
Print _iorig and _imeta for integrity LVs.
Print "on" for RAIDs with integrity.
2025-09-29 15:18:01 +02:00
Zdenek Kabelac
9247dd4afb integrity: lv_raid_has_integrity accepts const 2025-09-29 15:18:01 +02:00
Zdenek Kabelac
51b891cdc3 integrity: use suffix -real for iorig and imeta
Add private -real suffix for active _iorig and _imeta volumes.

TODO: ATM we will keep using "-real" suffix also for raid leg with integrity.
      Better fit would be i.e. "-integ" suffix for such LV, but this
      requires more complicated table manipulation as we would need
      to also change the raid leg name, so leave this for later...
      Usage of "-real" suffix to keep raid leg private is already better
      than previous state.
2025-09-29 15:13:05 +02:00
Zdenek Kabelac
031c59b14a integrity: add segment validation
Add some more validation checks for integrity segments.
2025-09-29 14:47:47 +02:00
Zdenek Kabelac
cff439265c integrity: drop use of origin pointer for integrity
Integrity segment is not using 'origin' anywhere and every code
is now using seg_lv(seg, 0) to reach origin LV from Integrity segment.
So do not set this pointer to any value for integrity segment.

Also for lv_origin_lv() presence of origin is already made by
validation - integrity must have origin defined.
2025-09-29 10:53:13 +02:00
Zdenek Kabelac
d54b1fecc1 integrity: fix ordering during integrity removal
Reorder integrity cleanup operations to ensure proper LV state before
device suspension. Move layer removal and visibility changes to occur
before the first metadata write, so that _iorig and _imeta LVs are
already marked as public and visible during suspend/resume operations.

This prevents issues where the device mapper operations occur on LVs
that are still marked as internal components rather than proper public
LVs ready for removal.

Note: this code had not set ->origin used in other places,
but it's going to be replaced with use of seg_lv().
2025-09-28 15:37:40 +02:00
Zdenek Kabelac
3dd0175b02 integrity: refactor lv_is_integrity_origin
Extract common integrity origin detection logic into new helper function
lv_integrity_from_origin() to eliminate code duplication:

- Add lv_integrity_from_origin() that returns the integrity LV for a given origin
- Refactor lv_is_integrity_origin() to use the new helper function
- Replace duplicate logic in lv_raid_integrity_image_in_sync() with helper call
- Consolidate multiple condition checks into single if statement
- Replace direct seg->origin access with seg_lv(seg, 0) for consistency

The seg_lv(seg, 0) approach is preferred throughout the codebase as it
provides a consistent interface to access the origin LV from segments.
2025-09-28 15:37:40 +02:00
Zdenek Kabelac
a1434f0283 raid: fix -real suffix for external origins
With recent change to use -real suffices for raid/mirror legs,
we need to take special care for devices that already use -real
suffix normally - patchset missed check for external origins.

Also avoid even creating UUID for these LVs in _lv_info_real().
2025-09-25 15:33:11 +02:00
Zdenek Kabelac
69c8540514 WHATS_NEW: update 2025-09-25 13:23:04 +02:00
Zdenek Kabelac
74e9c7c174 mirror: add -real suffix for mirrors
Extend "-real" suffix handling to mirror operations, similar to RAID
functionality for managing internal-to-public LV transitions.

- Add reactivation logic in _split_mirror_images() to update UUIDs
- Enable "real" suffix for mirror images and logs in build_dm_uuid()
- Detect temporary mirror sync layers using MIRROR_SYNC_LAYER pattern
- Force deactivate/activate cycle to transition from private to public UUID

This ensures mirror split operations properly transition split LVs from
internal components with private UUIDs to public LVs with correct UUIDs.
2025-09-25 13:23:04 +02:00
Zdenek Kabelac
0ef47b8960 raid_manip: reactivate after split to update UUID
After RAID leg split operations, the resulting LV becomes public but
retains its private "-real" UUID suffix from when it was an internal
component. Since active device mapper devices cannot change their UUID,
the split LV must be deactivated and reactivated to acquire the proper
public UUID.

Add reactivation logic to lv_raid_split() and lv_raid_split_and_track()
that handles both shared and non-shared volume groups, ensuring split
LVs are properly transitioned from internal to public state.
2025-09-25 13:23:04 +02:00
Zdenek Kabelac
1cef87bb3b raid: add -real suffix handling for internal LVs
Add support for managing RAID internal LVs that use "-real" suffix
during transitions from internal components to public LVs.

- Add _lv_info_real() to detect orphan devices with private UUIDs
- Add _lv_adjust_real_uuid() to handle UUID mismatches in device tree
- Use "real" suffix for non-visible RAID images and metadata in build_dm_uuid()
- Integrate checks into activation and device manager code paths

This handles edge cases where RAID leg splits leave public devices active
with private "-real" UUIDs, requiring explicit reactivation.

Note: RAID image and metadata gets "-real" suffix only when it is marked
as not visible LV in lvm2 metadata as there is also a public activation
of these devices.
2025-09-25 13:23:04 +02:00
Zdenek Kabelac
d6620e2347 dev_manager: helper function to set UUID suffixes
Add _set_optional_uuid_suffixes() helper to reduce code duplication
when calling dm_tree_set_optional_uuid_suffixes() with the global
_uuid_suffix_list.
2025-09-25 13:23:04 +02:00
Zdenek Kabelac
0f63bb505a metadata: lv_is_linear/striped needs only const 2025-09-25 13:23:04 +02:00
Zdenek Kabelac
088311e76b memlock: add [aio] into skiped regions
Stay away of locking aio memory regions.
2025-09-25 13:22:44 +02:00
David Teigland
71640d9731 persist: check key generation
vgchange --persist check was getting the key generation and
the sanlock generation, but wasn't actually comparing them
to warn about a mismatch.
2025-09-24 13:43:34 -05:00
David Teigland
f15d948720 man lvmlockd: updates
Major rewrite of the beginning description/setup/introduction.
2025-09-23 11:19:13 -05:00
Zdenek Kabelac
d73b1ecf4b make: generate 2025-09-20 14:37:58 +02:00
Zdenek Kabelac
6016b2a7e4 commands: enusure stable sorting result
When options do have same name, use it's enum
as secondary key.
2025-09-20 14:36:28 +02:00
Zdenek Kabelac
9d9bb26fd5 commands: preserve any_ro_count
Previous patch unintentionally mixed these options
together while sorting.
2025-09-20 14:36:28 +02:00
David Teigland
5036e067e1 lvmpersist: fix hex digit key check
was incorrectly checking for a-z rather than a-f.
2025-09-19 14:21:11 -05:00
David Teigland
14cd96573f lvmpersist: run sg_turs to clear unit attention errors
Sometimes sg_persist/mpathpersist commands will fail if the
device returns a Unit Attention, e.g. if the host's last
registration was cleared.  Run sg_turs on each scsi/mpath
device at the start of each command to clear any UA errors.
This is simpler than adding code to retry commands throughout
the script if they happen to hit a UA error.
2025-09-19 12:43:37 -05:00
Zdenek Kabelac
622d222b1f make: generate 2025-09-19 14:49:41 +02:00
Zdenek Kabelac
095fb7eff8 test: update lisf of unusable kernels for raid resize 2025-09-19 14:48:46 +02:00
Zdenek Kabelac
5a367077d5 dmeventd: use define for mirror sync layer
Use existing define, just in case someone would have ever changed it.
2025-09-19 14:46:52 +02:00
Zdenek Kabelac
04cb7f742a command: add validation and sorting for args.h
Add comprehensive validation to ensure args.h option definitions follow
the established sorting rules:
1. Options without short options - sorted alphabetically
2. Alias options (without descriptions) - sorted alphabetically
3. Options with short options - sorted by uppercase symbol with
   lowercase variants first, then by long option name

Changes include:
- Enhanced validation logic in _find_lvm_command_enum() to check args.h
  ordering during MAN_PAGE_GENERATOR builds
- Improved error messages showing which entries violate sorting rules
- Added _sort_opt_args() function to sort optional/required option args
  for consistent man page and help generation output
- Fixed validation flag handling to properly report multiple errors

This ensures the args.h reorganization from the previous commit is
maintained and prevents future ordering regressions that could affect
code maintainability and generated documentation consistency.
2025-09-19 14:46:28 +02:00
Zdenek Kabelac
a8f1e2a83d args: sort by rules
tools: reorganize args.h argument definitions by sorting rules

Reorganize argument definitions in args.h to follow consistent sorting:
1. Options without short options - sorted alphabetically
2. Alias options (unadvertised, no description)
3. Options with short options - sorted by uppercase symbol
   with lowercase variants first, then by long option name

This improves code organization and maintainability by establishing
a clear, documented ordering for LVM command line argument definitions.

No functional changes - only reordering of existing argument definitions.

Also note there should never be a command using 2 options with the same
short option symbol
2025-09-19 14:46:28 +02:00
David Teigland
687b1a780f persist: support --setpersist in vgcreate
Previously, setpersist was only supported in vgchange
on an existing VG.  The PR is acquired exclusively before
the devices are modified, and in the case of a shared
VG the PR is subsequently changed to a shared mode.
2025-09-17 15:46:54 -05:00
David Teigland
57bf48c058 persist: use vgid in the key file name
adding a new helper function to create key file path.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Before this patch:

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

With this patch applied:

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

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

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

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

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

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

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

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

For example:

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

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

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

With this patch applied:

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

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

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

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

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

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

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

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

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

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

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

Before this patch:

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

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

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

With this patch applied:

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

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

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

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

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

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

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

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

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

Before this patch:

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

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

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

With this patch applied:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Example:

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

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

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

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

With this patch applied:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

And finaly fixing invalid bash scripting logic since:

test && TRUE || FALSE

is not bash equivalent of:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

The annotations address the following false positives:

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

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

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

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

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

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

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

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

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

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

Changes:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

This commit fixes the following compiler error.

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

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

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

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

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

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

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

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

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

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

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

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

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

This improves consistency and follows man page conventions.

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

This ensures consistent company name formatting across all man pages.

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

These changes improve grammatical correctness, consistency, and readability.

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

These changes improve grammatical correctness and consistency.

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

These changes improve documentation clarity and correctness.

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

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

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

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

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

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

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

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

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

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

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

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

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

No functional change.

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

LOCKDSANLOCK_SUPPORT is not defined is the build
is not enabled.

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

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

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

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

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

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

Reformat lines to fit in 80 columns.

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

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

Use .MT .ME for emails.

Use .UR .UE. for URL.

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

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

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

Correct some small typographical rendering issues.

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

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

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

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

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

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

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

Use 'short_ops' loop to avoid duplicating code.

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

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

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

man: generator use macros for options

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  With -vvv:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

-.-.

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

503:.B \-\-units \c

-.-

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

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

-.-.

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

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

-.-.

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

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

-.-.

Wrong distance between sentences in the input file.

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

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

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

-.-.

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

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

-.-.

Use thousand markers to make large numbers easy to read

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

-.-.

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

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

-.-.

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

.-.

Additionally:

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

-.-

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

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

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

-.-

Generally:

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

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

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

-.-.

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

-.-.

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

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

-.-.

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

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

-.-.

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

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

-.-.

Wrong distance between sentences in the input file.

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

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

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

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

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

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

-.-.

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

-.-.

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

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

-.-.

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

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

FIXME:

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

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

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

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

These symbols:

dm_bitset_parse_list@@DM_1_02_138
and dm_tree_node_size_changed@Base

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

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

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

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

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

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

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

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

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

Also ignore unexecuted blocks warnings with 'gcov'.

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

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

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

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

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

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

Fix by capturing this missed case and update cache properly.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Now we can separately describe:

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

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

Also reorder some messages when doing teardown of devices.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  - stripes is different from 1

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

But this is not correct in all cases, because:

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

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

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

     C) if stripe_size = 0, executed
       (correct)

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

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

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

  The D) ends up with errors like:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

**
check_lv_segments_incomplete_vg()

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

**
check_lv_segments_complete_vg()

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

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

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

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

It would be likely better to not copy these strings at all
and derefence it from the original string however that
needs futher changes in the code base.
2024-10-22 19:36:00 +02:00
Zdenek Kabelac
b185578321 crc: add newer zlib code
This code is faster when calculating crc32 checksum for larger
block areas. There is also SIMD variant present in the code,
however ATM the influence on performance of lvm2 is not that big..
2024-10-22 19:36:00 +02:00
Zdenek Kabelac
f55c949410 crc: move static table
Move static table upward in the code so it can be shared with
another 'crc' implementation.
2024-10-22 19:36:00 +02:00
Zdenek Kabelac
d07e273aff lvmlockd: drop return 1 from void function
When compiling code without lvmlockd, the void function
lockd_free_lv_after_updatei()  should not return any value.
2024-10-22 19:15:55 +02:00
Peter Rajnoha
e96d6b7442 lv_manip: fall back to direct zeroing on any BLKZEROOUT ioctl failure
When BLKZEROOUT ioctl fails, it should not stop us from trying the direct
zeroing as a fallback action, since this is an optimization only.
We should be able to continue with new LV creation if we succeed
with that direct fallback then.

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

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

Before the fix:

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

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

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

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

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

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

(The lock for lv1 is gone, so nothing can be done with it.)
2024-10-16 13:18:14 -05:00
Peter Rajnoha
8e3db44036 device_id: fix segfault if devices file has PVID=. 2024-10-15 10:58:16 +02:00
Peter Rajnoha
317fae4024 dev-type: detect mixed dos partition with gpt's PMBR
Detect when we have mixed dos partition with gpt's PMBR partition.

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

For example:

  ❯  fdisk -l /dev/sdc

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

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

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

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

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

Actually found with codespell.

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

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

Before:

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

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

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

After:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Introduce:
dev_cache_update_dm_devs
dev_cache_get_dm_dev_by_devno
dev_cache_get_dm_dev_by_uuid

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

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

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

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

One line of cat /dev/kmsg is like:

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

If CONFIG_PRINTK_CALLER is off:

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

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

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

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

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

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

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

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

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

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

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

Adapt the only bcache user ATM for API change.

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

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

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

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

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

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

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

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

Also strlen(_cache.dev_dir) just once.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

This closes some race window in testing.
2024-04-19 23:56:16 +02:00
904 changed files with 55065 additions and 28367 deletions

7
.gitignore vendored
View File

@@ -45,6 +45,12 @@ make.tmpl
coverity/coverity_model.xml
/.cache/
/compile_commands.json
/doc/.ikiwiki
/public
/libdm/.symver_check
daemons/clvmd
@@ -52,7 +58,6 @@ daemons/dmfilemapd
daemons/lvmetad/
tools/man-generator
tools/man-generator.c
test/.lib-dir-stamp
test/.tests-stamp

View File

@@ -1,6 +1,7 @@
stages:
- approve
- test
- post
approve1:
stage: approve
@@ -16,6 +17,23 @@ approve1:
- when: on_success
allow_failure: false
pages:
image: elecnix/ikiwiki
stage: test
script:
- ikiwiki --setup ikiwiki.setup --libdir themes/ikistrap/lib
artifacts:
paths:
- public
only:
refs:
- main
changes:
- doc/**/*
- ikiwiki.setup
# TODO:
# - check results of autoreconf and make generate - may need additional commit
# - we need a particular setup (rawhide OR latest supported fedora?)
@@ -75,9 +93,9 @@ test-job:
- rm -rf /dev/shm/lvm2-test
- cut -d' ' -f2 test/results/list | sort | uniq -c
# Filter artifacts - keep only logs from tests which are not pass
- cd test/results && rm $(grep 'passed$' list | cut -d' ' -f1 | sed -e 's|/|_|g' -e 's|.*|\0.txt|')
- (cd test/results && rm $(grep 'passed$' list | cut -d' ' -f1 | sed -e 's|/|_|g' -e 's|.*|\0.txt|'))
# TODO: Keep a list of known failures, and translate into regexp - or simply use python...
- if grep failed test/results/list | grep -v '\\\(dbustest\|lvconvert-mirror\)\.sh' | sort; then false; else true; fi
- if grep failed test/results/list | grep -v '\(dbustest\|lvconvert-mirror\)\.sh' | sort; then false; else true; fi
rules:
# Filter only safe repositories, or user in developers:
# NOTE: Already done in approve stage, may be more caution than necessary
@@ -85,3 +103,25 @@ test-job:
when: manual
- when: on_success
# reboot must be configured to let runner finish cleanly while not accepting new jobs
# NOTE: If this causes warnings, gitlab-runner needs to be configured to be stopped using SIGQUIT
# See: https://docs.gitlab.com/runner/commands/#gitlab-runner-stop-doesnt-shut-down-gracefully
# NOTE: It should be possible to use after_script in test job, which runs
# before artifacts collection, but reboot may be too eager to stop the job
# while collecting artifacts
# NOTE: What would happen when there are multiple jobs in the queue for each
# tag? Could the tests run first and reboot only after them? I think so!
reboot:
stage: post
parallel:
matrix:
- TAG: rhel8
- TAG: rhel9
tags:
- ${TAG}
timeout: 1m
script:
- reboot
allow_failure: true
when: always

View File

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

2
README
View File

@@ -1,7 +1,5 @@
This tree contains the LVM2 and device-mapper tools and libraries.
This is development branch, for stable 2.02 release see stable-2.02 branch.
For more information about LVM2 read the changelog in the WHATS_NEW file.
Installation instructions are in INSTALL.

View File

@@ -21,6 +21,11 @@ You MUST disable (or mask) any LVM daemons:
- clvmd
- cmirrord
Some lvm.conf options should be set:
- global/event_activation = 0
- activation/monitoring = 0
For running cluster tests, we are using singlenode locking. Pass
`--with-clvmd=singlenode` to configure.

View File

@@ -1 +1 @@
2.03.24(2)-git (2023-11-21)
2.03.36(2) (2025-10-24)

View File

@@ -1 +1 @@
1.02.198-git (2023-11-21)
1.02.210 (2025-10-24)

324
WHATS_NEW
View File

@@ -1,7 +1,171 @@
Version 2.03.24 -
==================
Version 2.03.36 - 24th October 2025
===================================
Fix uninitialized chunk_size_calc_policy in pool parameter functions.
Fix approximate allocation for Raid with insufficient extents.
Fix race in dmeventd remonitoring optimization (2.03.35).
Use -real suffix for pvmove UUID.
Add support pvmove segmentation allocation/pvmove_max_segmentation_size_mb.
Allow creating _imeta with multiple segments.
Fix driver_version() accepts NULL version buffer pointer.
Fix invalid free() call in error path of _add_metadata_area_to_pv().
Avoid destroying aio context in forked process.
Add lvs -o cache_promotions,cache_promotions fields.
Update pvmove logic when moving i.e. raid legs.
Display integrity info in lvdisplay.
Increase storage size for internal filter chain.
Add helper function display_mb_size().
Enhance code for adding and removing integrity to RAID volumes.
Add code for basic validation of integrity segment.
Use -real private suffix for integrity origin and meta volumes.
Use -real private suffix for mirror and raid legs.
Detect and use existing XFS quota mount options for lvresize --fs resize.
Version 2.03.35 - 09th September 2025
=====================================
Fix unlocking devices file only after all PVs are processed.
Avoid creating system.devices when deleting entries.
Fix existing issues with persistent reservations.
Fix possible report output format inconsistencies while processing PVs.
Allow report options for pv/vg/lvdisplay only if used with -C|--columns.
Fix vgsplit failing to split a VG with RAID+integrity or cache with cachevol.
Fix --lockopt handling in lvmlockd when --nolocking is used.
Optimize dmeventd when remonitoring active devices.
Version 2.03.34 - 30th July 2025
================================
Support dmeventd restart when there are no monitored devices.
Dmeventd no longer calls 'action commands' on removed devices.
Fix reader of VDO metadata on 32bit architecture.
Fix lvmdevices --deldev/--delpvid to error out if devices file not writeable.
Fix lvresize corruption in LV->crypt->FS stack if near crypt min size limit.
Enhanced lvresize -r support for btrfs.
Use glibc standard functions htoX, Xtoh functions for endian conversion.
Fix structure copying within sanlock's release_rename().
Fix autoactivation on top of loop dev PVs to trigger once for change uevents.
Add lvmlockd --lockopt repair to reinitialize corrupted sanlock leases.
Fix support for lvcreate -T --setautoactivation.
Add lvm.conf global/lvresize_fs_helper_executable.
Enable lvm to use persistent reservations on a VG.
Version 2.03.33 - 27th June 2025
================================
Various spelling, grammar, formatting, test, and build script improvements.
Override LC_NUMERIC locale if unsuitable for json_std report format.
Repair raid arrays with transiently lost devices.
Version 2.03.32 - 05th May 2025
===============================
Lvconvert vdopool conversion properly validates acceptable LVs.
Accept thin pool data LV as cacheable LV.
Allow using zram block devices (likely for testing).
Fix lvresize when resizing COW snapshots already covering origin.
Fix lvmdbusd read of executed lvm commands output.
Fix construction of DM UUID for cachevol _cdata and _cmeta devices.
Ignore PV claims from old metadata when then PV belongs to a new VG.
Fix integrity metadata rounding.
Accept --autobackup option in pvresize.
Version 2.03.31 - 27th February 2025
====================================
Reduce 'mandoc -T lint' reported issues for man pages.
Restore support for LVM_SUPPRESS_FD_WARNINGS (2.03.24).
Fix uncache and split cache restoring original state of volume.
Extend use of lockopt skip to more scenarios.
Enhance error path resolving in polling code.
Disallow shared activation of LV with CoW snapshot.
Fix lvmlockd use in lvremove of CoW snapshot, VDO pool, and uncache.
Improve mirror split with opened temporary volumes.
Improve pvmove finish with opened temporary volumes.
Fix backup limit for devices file, handle over 10,000 files.
Ignore reported optimal_io_size not divisible by 4096.
Fix busy-loop in config reading when read returned 0.
Fix DM cache preserving logic (2.03.28).
Improve use of lvmlockd for usecases involving thin volumes and pools.
Version 2.03.30 - 14th January 2025
===================================
Lvresize reports origin vdo volume cannot be resized.
Support setting reserved_memory|stack of --config cmdline.
Fix support for disabling memory locking (2.03.27).
Do not extend an LV if FS resize unsupported and '--fs resize' used.
Prevent leftover temporary device when converting in use volume to a pool.
lvconvert detects early volume in use when converting it to a pool.
Handle NVMe with quirk changed WWID not matching WWID in devices file.
Version 2.03.29 - 09th December 2024
====================================
Configure --enable/disable-sd-notify to control lvmlockd build with sd-notify.
Allow test mode when lvmlockd is built without dlm support.
Add a note about RAID + integrity synchronization to lvmraid(7) man page.
Add a function for running lvconvert --repair on RAID LVs to lvmdbusd.
Improve option section of man pages for listing commands ({pv,lv,vg}{s,display}).
Fix renaming of raid sub LVs when converting a volume to raid (2.03.28).
Fix segfault/VG write error for raid LV lvextend -i|--stripes -I|--stripesize.
Revert ignore -i|--stripes, -I|--stripesize for lvextend on raid0 LV (2.03.27).
Version 2.03.28 - 04th November 2024
====================================
Use radix_tree to lookup for UUID within committed metadata.
Use radix_tree to lookup LV list entry within VG struct.
Introduce setting config/validate_metadata = full | none.
Restore fs resize call for lvresize -r on the same size LV (2.03.17).
Correct off-by-one devicesfile backup counting.
Replace use of dm_hash with radix_tree for lv names and uuids.
Refactor vg_validate with uniq_insert and better use of CPU caches.
Add radix_tree_uniq_insert.
Update DM cache when taking next VG lock instead of dropping it.
Generate json string id only for json reporting.
For vgsummary use new API call dm_config_parse_only_section().
Use radix_tree for PV names mapping.
Split check_lv_segment into separate _in/complete_vg variant.
Use find_lv instead of find_lv_in_vg when possible.
Do a mirror fixup only when mirrors with logs are imported.
Add faster crc32 calculation from zlib code for x86_64.
Fall back to direct zeroing if BLKZEROOUT fails during new LV initialization.
Version 2.03.27 - 02nd October 2024
===================================
Fix swap device size detection using blkid for lvresize/lvreduce/lvextend.
Detect GPT partition table and pass partition filter if no partitions defined.
Add global/sanlock_align_size option to configure sanlock lease size.
Disable mem locking when activation/reserved_stack or reserved_memory is 0.
Fix locking issues in lvmlockd leaving thin pool locked.
Deprecate vdo settings vdo_write_policy and vdo_write_policy.
Lots of typo fixes across lvm2 code base (codespell).
Corrected integrity parameter interleave_sectors for DM table line.
Ignore -i|--stripes, -I|--stripesize for lvextend on raid0 LV, like raid10.
Do not accept duplicate device names for pvcreate.
Version 2.03.26 - 23rd August 2024
==================================
Fix internal error reported by pvmove on a VG with single PV.
Also accept --mknodes --refresh for vgscan.
Fix vgmknodes --refresh to wait for udev before checking /dev content.
Use log/report_command_log=1 config setting by default for JSON output format.
Fix unreleased memory pools on RAID lvextend.
Add --integritysettings option to manipulate dm-integrity settings.
Version 2.03.25 - 12nd July 2024
================================
Utilize more radix_tree instead of dm_hash and btree.
Refactor DM uuid caching from device_mapper directory.
Enhance checking for DM uuid device.
Fix lvm shell command completion on tab key (2.03.24).
Avoid lockd_vg call to lvmlockd for local VGs.
Allow forced change of locktype from none.
Handle OPTIONS defined in /etc/sysconfig/lvmlockd.
Version 2.03.24 - 16th May 2024
===============================
Lvconvert supports VDO options for thin-pool with vdo conversion.
Improve placement to .data.rel.ro and .rodata sections.
Fix support for -y and -W when creating thinpool with vdo.
Better support for runtime valgrind detection.
Allow command interruption when communicating with dmeventd.
Fix resize of VDO volume used for thin pool data volume.
Use -Wl,-z,now and -Wl,--as-needed for compilation by default.
Require 3.7 as minimal version for sanlock.
Share code for closing opened desriptors on program startup.
Share code for closing opened descriptors on program startup.
Fix memleak in lvmcache.
Add configure --with-default-event-activation=ON setting.
Fix return value from reporter function when hitting internal error.
@@ -45,7 +209,7 @@ Version 2.03.23 - 21st November 2023
Support PV lists with thin lvconvert.
Fix support for lvm_import_vdo with SCSI VDO volumes.
Fix locking issue leading to hanging concurrent vgchange --refresh.
Recognize lvm.conf report/headings=2 for full column names in report headings.
Recognise lvm.conf report/headings=2 for full column names in report headings.
Add --headings none|abbrev|full cmd line option to set report headings type.
Fix conversion to thin pool using lvmlockd.
Fix conversion from thick into thin volume using lvmlockd.
@@ -115,6 +279,7 @@ Version 2.03.17 - 10th November 2022
Switch to use mallinfo2 and use it only with glibc.
Error out in lvm shell if using a cmd argument not supported in the shell.
Fix lvm shell's lastlog command to report previous pre-command failures.
Keep libaio locked in memory in critical section.
Extend VDO and VDOPOOL without flushing and locking fs.
Add --valuesonly option to lvmconfig to print only values without keys.
Updates configure with recent autoconf tooling.
@@ -134,7 +299,7 @@ Version 2.03.16 - 18th May 2022
--deldev.
Display writecache block size with lvs -o writecache_block_size.
Improve cachesettings description in man lvmcache.
Fix lossing of delete message on thin-pool extension.
Fix losing of delete message on thin-pool extension.
Version 2.03.15 - 07th February 2022
====================================
@@ -221,7 +386,7 @@ Version 2.03.12 - 07th May 2021
Fix problem with unbound variable usage within fsadm.
Fix IMSM MD RAID detection on 4k devices.
Check for presence of VDO target before starting any conversion.
Support metatadata profiles with volume VDO pool conversions.
Support metadata profiles with volume VDO pool conversions.
Support -Zn for conversion of already formatted VDO pools.
Avoid removing LVs on error path of lvconvert during creation volumes.
Fix crashing lvdisplay when thin volume was waiting for merge.
@@ -252,7 +417,7 @@ Version 2.03.11 - 08th January 2021
Enhance error handling for fsadm and handle correct fsck result.
Dmeventd lvm plugin ignores higher reserved_stack lvm.conf values.
Support using BLKZEROOUT for clearing devices.
Support interruption when wipping LVs.
Support interruption when wiping LVs.
Support interruption for bcache waiting.
Fix bcache when device has too many failing writes.
Fix bcache waiting for IO completion with failing disks.
@@ -379,7 +544,7 @@ Version 2.03.03 - 07th June 2019
Ignore foreign and shared PVs for pvscan online files.
Add config setting to control fields in debug file and verbose output.
Add command[pid] and timestamp to debug file and verbose output.
Fix missing growth of _pmsmare volume when extending _tmeta volume.
Fix missing growth of _pmspare volume when extending _tmeta volume.
Automatically grow thin metadata, when thin data gets too big.
Add synchronization with udev before removing cached devices.
Add support for caching VDO LVs and VDOPOOL LVs.
@@ -392,14 +557,14 @@ Version 2.03.03 - 07th June 2019
Change scan_lvs default to 0 so LVs are not scanned for PVs.
Thin-pool selects power-of-2 chunk size by default.
Cache selects power-of-2 chunk size by default.
Support reszing for VDOPoolLV and VDOLV.
Support resizing for VDOPoolLV and VDOLV.
Improve -lXXX%VG modifier which improves cache segment estimation.
Ensure migration_threshold for cache is at least 8 chunks.
Restore missing man info lvcreate --zero for thin-pools.
Drop misleadning comment for metadata minimum_io_size for VDO segment.
Drop misleading comment for metadata minimum_io_size for VDO segment.
Add device hints to reduce scanning.
Introduce LVM_SUPPRESS_SYSLOG to suppress syslog usage by generator.
Fix generator quering lvmconfig unpresent config option.
Fix generator querying lvmconfig unpresent config option.
Fix memleak on bcache error path code.
Fix missing unlock on lvm2 dmeventd plugin error path initialization.
Improve Makefile dependency tracking.
@@ -461,7 +626,7 @@ Version 2.02.178-rc1 - 24th May 2018
--with-cache switch for ./configure has been removed.
Include new unit-test framework and unit tests.
Extend validation of region_size for mirror segment.
Reload whole device stack when reinitilizing mirror log.
Reload whole device stack when reinitializing mirror log.
Mirrors without monitoring are WARNING and not blocking on error.
Detect too big region_size with clustered mirrors.
Fix evaluation of maximal region size for mirror log.
@@ -506,7 +671,7 @@ Version 2.02.178-rc1 - 24th May 2018
Restore pvmove support for wide-clustered active volumes (2.02.177).
Avoid non-exclusive activation of exclusive segment types.
Fix trimming sibling PVs when doing a pvmove of raid subLVs.
Preserve exclusive activation during thin snaphost merge.
Preserve exclusive activation during thin snapshot merge.
Avoid exceeding array bounds in allocation tag processing.
Add --lockopt to common options and add option to skip selected locks.
@@ -522,7 +687,7 @@ Version 2.02.177 - 18th December 2017
Fix lvmlockd to use pool lock when accessing _tmeta volume.
Report expected sanlock_convert errors only when retries fail.
Avoid blocking in sanlock_convert on SH to EX lock conversion.
Deactivate missing raid LV legs (_rimage_X-missing_Y_Z) on decativation.
Deactivate missing raid LV legs (_rimage_X-missing_Y_Z) on deactivation.
Skip read-modify-write when entire block is replaced.
Categorise I/O with reason annotations in debug messages.
Allow extending of raid LVs created with --nosync after a failed repair.
@@ -544,7 +709,7 @@ Version 2.02.177 - 18th December 2017
Check raid reshape flags in vg_validate().
Add support for pvmove of cache and snapshot origins.
Avoid using precommitted metadata for suspending pvmove tree.
Ehnance pvmove locking.
Enhance pvmove locking.
Deactivate activated LVs on error path when pvmove activation fails.
Add "io" to log/debug_classes for logging low-level I/O.
Eliminate redundant nested VG metadata in VG struct.
@@ -634,13 +799,13 @@ Version 2.02.173 - 20th July 2017
Version 2.02.172 - 28th June 2017
=================================
Add missing NULL to argv array when spliting cmdline arguments.
Add missing NULL to argv array when splitting cmdline arguments.
Add display_percent helper function for printing percent values.
lvconvert --repair handles failing raid legs (present but marked 'D'ead).
Do not lvdisplay --maps unset settings of cache pool.
Fix lvdisplay --maps for cache pool without policy settings.
Support aborting of flushing cache LV.
Reenable conversion of data and metadata thin-pool volumes to raid.
Re-enable conversion of data and metadata thin-pool volumes to raid.
Improve raid status reporting with lvs.
No longer necessary to '--force' a repair for RAID1.
Linear to RAID1 upconverts now use "recover" sync action, not "resync".
@@ -708,7 +873,7 @@ Version 2.02.169 - 28th March 2017
Support cache segment with configurable metadata format.
Add allocation/cache_metadata_format profilable settings.
Use function cache_set_params() for both lvcreate and lvconvert.
Skip rounding on cache chunk size boudary when create cache LV.
Skip rounding on cache chunk size boundary when create cache LV.
Improve cache_set_params support for chunk_size selection.
Fix metadata profile allocation/cache_[mode|policy] setting.
Fix missing support for using allocation/cache_pool_chunk_size setting.
@@ -758,8 +923,8 @@ Version 2.02.169 - 28th March 2017
Extend metadata validation of external origin LV use count.
Fix dm table when the last user of active external origin is removed.
Improve reported lvs status for active external origin volume.
Fix table load for splitted RAID LV and require explicit activation.
Always active splitted RAID LV exclusively locally.
Fix table load for split RAID LV and require explicit activation.
Always active split RAID LV exclusively locally.
Do not use LV RAID status bit for segment status.
Check segtype directly instead of checking RAID in segment status.
Reusing exiting code for raid image removal.
@@ -822,7 +987,7 @@ Version 2.02.166 - 26th September 2016
Use --alloc normal for mirror logs even if the mimages were stricter.
Use O_DIRECT to gather metadata in lvmdump.
Ignore creation_time when checking for matching metadata for lvmetad.
Fix possible NULL pointer derefence when checking for monitoring.
Fix possible NULL pointer dereference when checking for monitoring.
Add lvmreport(7) man page.
Don't install lvmraid(7) man page when raid excluded. (2.02.165)
Report 0% as dirty (copy%) for cache without any used block.
@@ -862,7 +1027,7 @@ Version 2.02.164 - 15th August 2016
Version 2.02.163 - 10th August 2016
===================================
Add profile for lvmdbusd which uses lvm shell json report output.
Restrict in-command modification of some parms in lvm shell.
Restrict in-command modification of some params in lvm shell.
Apply LVM_COMMAND_PROFILE early for lvm shell.
Refactor reporting so lvm shell log report collects whole of cmd execution.
Support LVM_*_FD envvars to redirect output to file descriptors.
@@ -1015,11 +1180,11 @@ Version 2.02.152 - 30th April 2016
==================================
Use any inherited tags when wiping metadata sub LVs to ensure activation.
Add str_list_wipe.
Improve support for interrupting procesing of volumes during lvchange.
Improve support for interrupting processing of volumes during lvchange.
Use failed command return code when lvchanging read-only volume.
Show creation transaction_id and zeroing state of pool with thin volume.
Stop checking for dm_cache_mq policy with cache target 1.9 (alias to smq).
Check first /sys/module/dm_* dir existance before using modprobe.
Check first /sys/module/dm_* dir existence before using modprobe.
Remove mpath from 10-dm.rules, superseded by 11-dm-mpath.rules (mpath>=0.6.0).
Version 2.02.151 - 23rd April 2016
@@ -1044,7 +1209,7 @@ Version 2.02.150 - 9th April 2016
=================================
Avoid using flushing dm status ioctl when checking for usable DM device.
Check for devices without LVM- uuid prefix only with kernels < 3.X.
Reuse %FREE size aproximation with lvcreate -l%PVS thin-pool.
Reuse %FREE size approximation with lvcreate -l%PVS thin-pool.
Allow the lvmdump directory to exist already provided it is empty.
Show lvconverted percentage with 2 decimal digits.
Fix regression in suspend when repairing --type mirror (2.02.133).
@@ -1121,7 +1286,7 @@ Version 2.02.143 - 21st February 2016
Fix error path when sending thin-pool message fails in update_pool_lv().
Support reporting CheckNeeded and Fail state for thin-pool and thin LV.
For failing thin-pool and thin volume correctly report percentage as INVALID.
Report -1, not 'unkown' for lv_{snapshot_invalid,merge_failed} with --binary.
Report -1, not 'unknown' for lv_{snapshot_invalid,merge_failed} with --binary.
Add configure --enable-dbus-service for an LVM D-Bus service.
Replace configure --enable-python_bindings with python2 and python3 versions.
If PV belongs to some VG and metadata missing, skip it if system ID is used.
@@ -1150,7 +1315,7 @@ Version 2.02.141 - 25th January 2016
Restore support for command breaking in process_each_lv_in_vg() (2.02.118).
Use correct mempool when process_each_lv_in_vg() (2.02.118).
Fix lvm.8 man to show again prohibited suffixes.
Fix configure to set proper use_blkid_wiping if autodetected as disabled.
Fix configure to set proper use_blkid_wiping if autodetection as disabled.
Initialise udev in clvmd for use in device scanning. (2.02.116)
Add seg_le_ranges report field for common format when displaying seg devices.
Honour report/list_item_separator for seg_metadata_le_ranges report field.
@@ -1300,7 +1465,7 @@ Version 2.02.129 - 26th August 2015
Fix shared library generation to stop exporting internal functions.(2.02.120)
Accept --cachemode with lvconvert.
Fix and improve reporting properties of cache-pool.
Enable usage of --cachepolicy and --cachesetting with lvconvert.
Enable usage of --cachepolicy and --cachesettings with lvconvert.
Don't allow to reduce size of thin-pool metadata.
Fix debug buffer overflows in cmirrord logging.
Add --foreground and --help to cmirrord.
@@ -1457,7 +1622,7 @@ Version 2.02.119 - 2nd May 2015
Add --enable-halvm and --disable-halvm options to lvmconf script.
Add --services, --mirrorservice and --startstopservices option to lvmconf.
Use proper default value of global/use_lvmetad when processing lvmconf script.
Respect allocation/cling_tag_list during intial contiguous allocation.
Respect allocation/cling_tag_list during initial contiguous allocation.
Add A_PARTITION_BY_TAGS set when allocated areas should not share tags.
Make changes persist with python addTag/removeTag.
Set correct vgid when updating cache when writing PV metadata.
@@ -1535,7 +1700,7 @@ Version 2.02.116 - 30th January 2015
Scan pools in for_each_sub_lv() and add for_each_sub_lv_except_pools().
Fix lvm2app lvm_lv_get_property return value for fields with info/status ioctl.
Fix lvm2app regression in lvm_lv_get_attr causing unknown values (2.02.115).
Set default cache_mode to writehrough when missing in metadata.
Set default cache_mode to writethrough when missing in metadata.
Preserve chunk size with repair and metadata swap of a thin pool.
Fix raid --splitmirror 1 functionality (2.02.112).
Fix tree preload to handle splitting raid images.
@@ -1601,13 +1766,13 @@ Version 2.02.112 - 11th November 2014
Properly report error when taking snapshot of any cache type LV.
Add basic thread debugging messages to dmeventd.
Include threads being shutdown in dmeventd device registration responses.
Inital support for external users of thin pools based on transaction_id.
Initial support for external users of thin pools based on transaction_id.
Report some basic percentage info for cache pools.
Introduce size_mb_arg_with_percent() for advanced size arg reading.
Add extra support for '.' as decimal point in size args.
Add configure parameters for default segment type choices.
Add global/sparse_segtype_default setting to use thin for --type sparse.
Update and correct lvcreate and lvcovert man pages.
Update and correct lvcreate and lvconvert man pages.
Mark pools and snapshots as unzeroable volumes.
Check for zeroing of volume after segment type is fully detected.
Better support for persistent major and minor options with lvcreate.
@@ -1660,7 +1825,7 @@ Version 2.02.112 - 11th November 2014
Support DEBUG_MEMLOCK to trap unsupported mmap usage.
Enable cache segment type by default.
Ensure only supported volume types are used with cache segments.
Fix inablility to specify cachemode when 'lvconvert'ing to cache-pool.
Fix inability to specify cachemode when 'lvconvert'ing to cache-pool.
Grab cluster lock for active LVs when setting clustered attribute.
Use va_copy to properly pass va_list through functions.
Add function to detect rotational devices.
@@ -1728,7 +1893,7 @@ Version 2.02.108 - 23rd July 2014
Enhance lvconvert thin, thinpool, cache and cachepool command line support.
Display 'C' only for cache and cache-pool target types in lvs.
Prompt for confirmation before change LV into a snapshot exception store.
Return proper error codes for some failing lvconvert funtions.
Return proper error codes for some failing lvconvert functions.
Add initial code to use cache tools (cache_check|dump|repair|restore).
Support lvdisplay --maps for raid.
Add --activationmode degraded to activate degraded raid volumes by default.
@@ -1747,7 +1912,7 @@ Version 2.02.108 - 23rd July 2014
Support lvremove -ff to remove thin volumes from broken thin pools.
Require --yes to skip raid repair prompt.
Change makefile %.d generation to handle filename changes without make clean.
Fix use of buildir in make pofile.
Fix use of builddir in make pofile.
Enhance private volumes UUIDs with suffixed for easier detection.
Do not use reserved _[tc]meta volumes for temporary LVs.
Leave backup pool metadata with _meta%d suffix instead of reserved _tmeta%d.
@@ -1852,7 +2017,7 @@ Version 2.02.106 - 10th April 2014
Include 'lvm dumpconfig --type missing' and '--type diff' output to lvmdump.
Return failure when specifying negative size for pvresize.
Fix memory corruption in cmd context refresh if clvmd leaks opened device.
Reinitialise lvmcache properly on fork to fix premature polldaemon exit.
Reinitialize lvmcache properly on fork to fix premature polldaemon exit.
Add 'lvm dumpconfig --type diff' to show differences from defaults.
Fix swap signature detection for devices smaller then 2MB.
Use dm_malloc function in clvmd.c.
@@ -1879,7 +2044,7 @@ Version 2.02.106 - 10th April 2014
Don't print an error and accept empty value for global/thin_disabled_features.
Update API for internal function build_dm_uuid().
Do not try to check empty pool with scheduled messages.
Fix return value in pool_has_message() when quering for any message.
Fix return value in pool_has_message() when querying for any message.
Cleanup all client resources on clvmd exit.
Use dm_zalloc to clear members of clvmd client struct.
Use BLKID_CFLAGS when compiling with blkid support.
@@ -1921,7 +2086,7 @@ Version 2.02.106 - 10th April 2014
Fix test when checking target version for available thin features.
Detect thin feature external_origin_extend and limit extend when missing.
Rename internal pool_can_resize_metadata() to thin_pool_feature_supported().
Issue error if libbblkid detects signature and fails to return offset/length.
Issue error if libblkid detects signature and fails to return offset/length.
Update autoconf config.guess/sub to 2014-01-01.
Online thin pool metadata resize requires 1.10 kernel thin pool target.
@@ -1994,7 +2159,7 @@ Version 2.02.104 - 13th November 2013
=====================================
Workaround VG refresh race during autoactivation by retrying the refresh.
Handle failures in temporary mirror used when adding images to mirrors.
Fix and improve logic for implicitely exclusive activations.
Fix and improve logic for implicitly exclusive activations.
Return success when LV cannot be activated because of volume_list filter.
Return proper error state for remote exclusive activation.
Fix missing lvmetad scan for PVs found on MD partitions.
@@ -2157,11 +2322,11 @@ Version 2.02.99 - 24th July 2013
Add support for persistent flagging of LVs to be skipped during activation.
Add --type profilable to lvm dumpconfig to show profilable config settings.
Add --mergedconfig to lvm dumpconfig for merged --config/--profile/lvm.conf.
Relase memory and unblock signals in lock_vol error path.
Release memory and unblock signals in lock_vol error path.
Define LVM2_* command errors in lvm2cmd.h and use in dmeventd plugins.
Move errors.h to tools dir.
Add man page entries for profile configuration and related options.
Improve error loging when user tries to interrupt commands.
Improve error logging when user tries to interrupt commands.
Rename _swap_lv to _swap_lv_identifiers and move to allow an additional user.
Rename snapshot segment returning methods from find_*_cow to find_*_snapshot.
liblvm/python API: Additions: PV create/removal/resize/listing
@@ -2362,7 +2527,7 @@ Version 2.02.98 - 15th October 2012
Do not start dmeventd for lvchange --resync when monitoring is off.
Remove pvscan --cache from lvm2-lvmetad init script.
Remove ExecStartPost with pvscan --cache from lvm2-lvmetad.service.
Report invalid percentage for property snap_percent of non-snaphot LVs.
Report invalid percentage for property snap_percent of non-snapshot LVs.
Disallow conversion of thin LVs to mirrors.
Fix lvm2api data_percent reporting for thin volumes.
Do not allow RAID LVs in a clustered volume group.
@@ -2412,7 +2577,7 @@ Version 2.02.98 - 15th October 2012
Version 2.02.97 - 7th August 2012
=================================
Improve documention of allocation policies in lvm.8.
Improve documentation of allocation policies in lvm.8.
Increase limit for major:minor to 4095:1048575 when using -My option.
Add make install_systemd_generators.
Add generator for lvm2 activation systemd units.
@@ -2496,7 +2661,7 @@ Version 2.02.96 - 8th June 2012
Check for buffer overwrite in get_cluster_type() in clvmd.
Fix global/detect_internal_vg_cache_corruption config check.
Update lcov Makefile target to support all dmeventd plugins.
Fix initializiation of thin monitoring. (2.02.92)
Fix initialization of thin monitoring. (2.02.92)
Cope with improperly formatted device numbers in /proc/devices. (2.02.91)
Exit if LISTEN_PID environment variable incorrect in lvmetad systemd handover.
Use pvscan --cache instead of vgscan in lvmetad scripts.
@@ -2509,7 +2674,7 @@ Version 2.02.96 - 8th June 2012
Add --with-thin-check configure option for path to thin_check.
Fix error message when pvmove LV activation fails with name already in use.
Better structure layout for device_info in dev_subsystem_name().
Change message severity for creation of VG over uninitialised devices.
Change message severity for creation of VG over uninitialized devices.
Fix error path for failed toolcontext creation.
Detect lvm binary path in lvmetad udev rules.
Don't unlink socket on lvmetad shutdown if instantiated from systemd.
@@ -2544,7 +2709,7 @@ Version 2.02.94 - 3rd March 2012
Add some close() and dev_close() error path backtraces.
Set stdin/stdout/stderr to /dev/null for polldaemon.
Limit the max size of processed clvmd message to ~8KB.
Do not send uninitialised bytes in cluster error reply messages.
Do not send uninitialized bytes in cluster error reply messages.
Use unsigned type for bitmask instead of enum type for lvm properties.
Add missing cleanup of excl_uuid hash on some exit paths of clvmd.
Check for existence of vg_name in _format1/_pool_vg_read().
@@ -2617,7 +2782,7 @@ Version 2.02.91 - 12th February 2012
Version 2.02.90 - 1st February 2012
===================================
sync_local_dev_names before (re)activating mirror log for initialisation.
sync_local_dev_names before (re)activating mirror log for initialization.
Disable partial activation for thin LVs and LVs with all missing segments.
Do not print warning for pv_min_size between 512KB and 2MB.
Clean up systemd unit ordering and requirements.
@@ -2636,7 +2801,7 @@ Version 2.02.89 - 26th January 2012
Add data_percent and metadata_percent for thin pools to lvs -v.
Add data_lv & metadata_lv fields to lvs for thin pools.
Add data_percent & pool_lv fields to lvs for thin volumes.
Rename origin_only parm to use_layer for lv_info and use with thin LVs.
Rename origin_only param to use_layer for lv_info and use with thin LVs.
Add lv_thin_pool_transaction_id to read the transaction_id value.
Use {suspend,resume}_origin_only when up-converting RAID, as mirrors do.
Always add RAID metadata LVs to deptree (even when origin_only is set).
@@ -2666,7 +2831,7 @@ Version 2.02.89 - 26th January 2012
Add _dev_init to initialize common struct device members.
Always zalloc struct device during initialization.
Fix missing thread list manipulation protection in dmeventd.
Do not derefence lv pointer in _percent_run() function before NULL check.
Do not dereference lv pointer in _percent_run() function before NULL check.
Allow empty strings for description and creation_host config fields.
Issue deprecation warning when removing last lvm1-format snapshot.
Reinstate support for snapshot removal with lvm1 format. (2.02.86)
@@ -2737,11 +2902,11 @@ Version 2.02.89 - 26th January 2012
Change vg_revert to void and remove superfluous calls after failed vg_commit.
Use execvp for CLVMD restart to preserve environment settings.
Restart CLVMD with same cluster manager.
Fix log_error() usage in raid and unknown segtype initialisation.
Fix log_error() usage in raid and unknown segtype initialization.
Improve testing Makefile.
Fix install_ocf make target when srcdir != builddir. (2.02.80)
Support env vars LVM_CLVMD_BINARY and LVM_BINARY in clvmd.
Fix restart of clvmd (preserve exlusive locks). (2.02.64)
Fix restart of clvmd (preserve exclusive locks). (2.02.64)
Add 'Volume Type' lv_attr characters for RAID and RAID_IMAGE.
Add activation/retry_deactivation to lvm.conf to retry deactivation of an LV.
Replace open_count check with holders/mounted_fs check on lvremove path.
@@ -2807,13 +2972,13 @@ Version 2.02.87 - 12th August 2011
Cache and share generated VG structs.
Fix possible format instance memory leaks and premature releases in _vg_read.
Suppress locking error messages in monitoring init scripts.
If pipe in clvmd fails return busy instead of using uninitialised descriptors.
If pipe in clvmd fails return busy instead of using uninitialized descriptors.
Add ability to reduce the number of mirrors in raid1 arrays to lvconvert.
Add dmeventd plugin for raid.
Replace free_vg with release_vg and move it to vg.c.
Remove INCONSISTENT_VG flag from the code.
Remove lock from cache in _lock_vol even if unlock fails.
Initialise clvmd locks before lvm context to avoid open descriptor leaks.
Initialize clvmd locks before lvm context to avoid open descriptor leaks.
Remove obsolete gulm clvmd cluster locking support.
Suppress low-level locking errors and warnings while using --sysinit.
Remove unused inconsistent_seqno variable in _vg_read().
@@ -2886,7 +3051,7 @@ Version 2.02.85 - 29th April 2011
Issue discards on lvremove and lvreduce etc. if enabled and supported.
Add seg_pe_ranges and devices fields to liblvm.
Fix incorrect tests for dm_snprintf() failure.
Fix some unmatching sign comparation gcc warnings in the code.
Fix some unmatching sign comparison gcc warnings in the code.
Support lv_extend() on empty LVs.
Avoid regenerating cache content when exported VG buffer is unchanged.
Extend the set of memory regions that are not locked to memory.
@@ -2912,7 +3077,7 @@ Version 2.02.85 - 29th April 2011
Use only vg_set_fid and new pv_set_fid fn to assign the format instance.
Make create_text_context fn static and move it inside create_instance fn.
Add mem and ref_count fields to struct format_instance for own mempool use.
Use new alloc_fid fn for common format instance initialisation.
Use new alloc_fid fn for common format instance initialization.
Optimise _get_token() and _eat_space().
Add _lv_postorder_vg() to improve efficiency for all LVs in VG.
Add gdbinit script for debugging.
@@ -2921,10 +3086,10 @@ Version 2.02.85 - 29th April 2011
Avoid possible endless loop in _free_vginfo when 4 or more VGs have same name.
Use empty string instead of /dev// for LV path when there's no VG.
Don't allocate unused VG mempool in _pvsegs_sub_single.
Do not send uninitialised bytes in local clvmd messages.
Do not send uninitialized bytes in local clvmd messages.
Support --help option for clvmd and return error for unknown option.
Avoid reading freed memory when printing LV segment type.
Fix syslog initialisation in clvmd to respect lvm.conf setting.
Fix syslog initialization in clvmd to respect lvm.conf setting.
Fix possible overflow in maximum stripe size and physical extent size.
Improve pvremove error message when PV belongs to a VG.
Extend normal policy to allow mirror logs on same PVs as images if necessary.
@@ -2938,7 +3103,7 @@ Version 2.02.85 - 29th April 2011
Restructure existing pv_setup and pv_write and add pv_initialise.
Add internal interface to support adding and removing metadata areas.
Allow internal indexing of metadata areas (PV id + mda order).
Generalise internal format_instance infrastrusture for PV and VG use.
Generalise internal format_instance infrastructure for PV and VG use.
Handle decimal digits with --units instead of ignoring them silently.
Fix remaining warnings and compile with -Wpointer-arith.
Fix gcc warnings for unused variables and const casts.
@@ -2952,7 +3117,7 @@ Version 2.02.85 - 29th April 2011
Make pv_min_size configurable and increase to 2048KB to exclude floppy drives.
Add find_config_tree_int64 to read 64-bit ints from config.
Ensure resuming exclusive cluster mirror continues to use local mirror target.
Clear temporary postorder LV status flags to allow re-use with same LV struct.
Clear temporary postorder LV status flags to allow reuse with same LV struct.
Remove invalid snapshot umount mesg which floods syslog from dmeventd plugin.
Add extended examples to pvmove man page.
Support LVM_TEST_DEVDIR env var for private /dev during testing.
@@ -3007,7 +3172,7 @@ Version 2.02.80 - 10th January 2011
Speed up command processing by caching resolved config tree.
Pass config_tree to renamed function import_vg_from_config_tree().
Detect NULL handle in get_property().
Fix superfluous /usr in ocf_scriptdir instalation path.
Fix superfluous /usr in ocf_scriptdir installation path.
Add --with-ocfdir configurable option.
Add aclocal.m4 (for pkgconfig).
Fix memory leak in persistent filter creation error path.
@@ -3039,7 +3204,7 @@ Version 2.02.79 - 20th December 2010
Add copy_percent and snap_percent to liblvm.
Enhance vg_validate to ensure integrity of LV and PV structs referenced.
Enhance vg_validate to check composition of pvmove LVs.
Create /var/run/lvm directory during clvmd initialisation if missing.
Create /var/run/lvm directory during clvmd initialization if missing.
Use new dm_prepare_selinux_context instead of dm_set_selinux_context.
Avoid revalidating the label cache immediately after scanning.
Support scanning for a single VG in independent mdas.
@@ -3336,7 +3501,7 @@ Version 2.02.67 - 4th June 2010
Avoid selecting names under /dev/block if there is an alternative.
Update clustered log kernel module name to log-userspace for 2.6.31 onwards.
Add replicators' LVs to dtree for activation.
Supress activation message if there is a missing replicator VG.
Suppress activation message if there is a missing replicator VG.
Fix scripts/relpath.awk to work in mawk
Extend lock_vol to check for missing replicator VGs first.
Update _process_one_vg and process_each_lv_in_vg to populate cmd_vg.
@@ -3387,7 +3552,7 @@ Version 2.02.65 - 17th May 2010
Version 2.02.64 - 30th April 2010
=================================
Avoid pointless initialisation when the 'version' command is run directly.
Avoid pointless initialization when the 'version' command is run directly.
Fix memory leak for invalid regex pattern input.
Display invalid regex pattern for filter configuration in case of error.
Remove no-longer-used arg_ptr_value.
@@ -3546,7 +3711,7 @@ Version 2.02.60 - 23rd January 2010
Disable memory debugging if dmeventd is configured. (Not thread-safe.)
Fix first log message prefix in syslog for dmeventd plugins.
Fix exported symbols names for dmeventd lvm2 wrapper plugin.
Make failed locking initialisation messages more descriptive.
Make failed locking initialization messages more descriptive.
Version 2.02.59 - 21st January 2010
===================================
@@ -3562,7 +3727,7 @@ Version 2.02.59 - 21st January 2010
Fix detection of completed snapshot merge.
Add Red Hat cmirror initscript (unfinished).
Add cmirrord man page (incomplete).
Make cluster log communication structures architecture independant.
Make cluster log communication structures architecture independent.
Fix cluster log in-memory bitmap handling.
Improve snapshot merge metadata import validation.
Improve target type compatibility checking in _percent_run().
@@ -3638,7 +3803,7 @@ Version 2.02.57 - 12th January 2010
Impose limit of 8 mirror images to match the in-kernel kcopyd restriction.
Use locking_type 3 (compiled in) for lvmconf --enable-cluster.
Remove list.c and list.h with no-longer-used dm_list macros and functions.
Log failure type and recognise type 'F' (flush) in dmeventd mirror plugin.
Log failure type and recognize type 'F' (flush) in dmeventd mirror plugin.
Extend internal PV/VG/LV/segment status variables from 32-bit to 64-bit.
Version 2.02.56 - 24th November 2009
@@ -3676,14 +3841,14 @@ Version 2.02.54 - 26th October 2009
Fix clvmd segfault when refresh_toolcontext fails.
Remember to clear 'global lock held during cache refresh' state after use.
Use udev flags support in LVM and apply various fixes to udev rules.
Delay announcing mirror monitoring to syslog until initialisation succeeded.
Delay announcing mirror monitoring to syslog until initialization succeeded.
Handle metadata with unknown segment types more gracefully.
Set default owner and group to null.
Add dmeventd.static to the build.
Disable realtime support code by default.
Make clvmd return 0 on success rather than 1.
Add --pvmetadatacopies for pvcreate, vgcreate, vgextend, vgconvert.
Add implict pvcreate support to vgcreate and vgextend.
Add implicit pvcreate support to vgcreate and vgextend.
Correct example.conf to indicate that lvm2 not lvm1 is the default format.
Remove an unused stray LVM1_SUPPORT ifdef.
Only include selinux libs in libdevmapper.pc when selinux build enabled.
@@ -3863,7 +4028,7 @@ Version 2.02.48 - 30th June 2009
Reinstate partial activation support in clustered mode. (2.02.40)
Allow metadata correction even when PVs are missing.
Use 'lvm lvresize' instead of 'lvresize' in fsadm.
Do not use '-n' realine option in fsadm for busybox compatiblity.
Do not use '-n' realine option in fsadm for busybox compatibility.
Add vg_lock_newname() library function for vgrename, vgsplit and vgcreate.
Round up requested readahead to at least one page and print warning.
Try to repair vg before actual vgremove when force flag provided.
@@ -3924,7 +4089,7 @@ Version 2.02.46 - 21st May 2009
Fix first_seg() call for empty segment list.
Add install_lvm2 makefile target to install only the LVM2 components.
Reject missing PVs from allocation in toollib.
Fix PV datalignment for values starting prior to MDA area. (2.02.45)
Fix PV dataalignment for values starting prior to MDA area. (2.02.45)
Add sparse devices: lvcreate -s --virtualoriginsize (hidden zero origin).
Fix minimum width of devices column in reports.
Add lvs origin_size field.
@@ -3997,7 +4162,7 @@ Version 2.02.45 - 3rd March 2009
Separate PV label attributes which do not need parse metadata when reporting.
Remove external dependency on the 'cut' command from fsadm.
Fix pvs segfault when pv mda attributes requested for not available PV.
Add fsadm support for reszing ext4 filesysystems.
Add fsadm support for resizing ext4 filesystems.
Move locking_type reading inside init_locking().
Rename get_vgs() to get_vgnames() and clarify related error messages.
Allow clvmd to be built with all cluster managers & select one on cmdline.
@@ -4174,7 +4339,7 @@ Version 2.02.37 - 6th June 2008
Refactor some vginfo manipulation code.
Add assertions to trap deprecated P_ and V_ lock usage.
Add missing mutex around clvmd lvmcache_drop_metadata library call.
Fix uninitialised mutex in clvmd if all daemons are not running at startup.
Fix uninitialized mutex in clvmd if all daemons are not running at startup.
Avoid using DLM locks with LCK_CACHE type P_ lock requests.
When asked to drop cached committed VG metadata, invalidate cached PV labels.
Drop metadata cache before writing precommitted metadata instead of after.
@@ -4221,7 +4386,7 @@ Version 2.02.34 - 10th April 2008
Mention default --clustered setting in vgcreate man page.
Add config file overrides to clvmd when it reads the active LVs list.
Fix vgreduce to use vg_split_mdas to check sufficient mdas remain.
Add (empty) orphan VGs to lvmcache during initialisation.
Add (empty) orphan VGs to lvmcache during initialization.
Fix orphan VG name used for format_pool.
Create a fid for internal orphan VGs.
Update lvmcache VG lock state for all locking types now.
@@ -4239,7 +4404,7 @@ Version 2.02.34 - 10th April 2008
Fix redundant lvresize message if vg doesn't exist.
Fix another allocation bug with clvmd and large node IDs.
Add find_lv_in_lv_list() and find_pv_in_pv_list().
Fix uninitialised variable in clvmd that could cause odd hangs.
Fix uninitialized variable in clvmd that could cause odd hangs.
Add vgmerge tests.
Add pvseg_is_allocated() for identifying a PV segment allocated to a LV.
Add list_move() for moving elements from one list to another.
@@ -4247,7 +4412,7 @@ Version 2.02.34 - 10th April 2008
Correct command name in lvmdiskscan man page.
clvmd no longer crashes if it sees nodeids over 50.
Fix potential deadlock in clvmd thread handling.
Refactor text format initialisation into _init_text_import.
Refactor text format initialization into _init_text_import.
Escape double quotes and backslashes in external metadata and config data.
Add functions for escaping double quotes in strings.
Rename count_chars_len to count_chars.
@@ -4297,7 +4462,7 @@ Version 2.02.31 - 19th January 2008
Version 2.02.30 - 17th January 2008
===================================
Set default readahead to twice maximium stripe size.
Set default readahead to twice maximum stripe size.
Reinstate VG extent size and stripe size defaults (halved). (2.02.29)
Add lists of stacked LV segments using each LV to the internal metadata.
Change vgsplit -l (for unimplemented --list) into --maxlogicalvolumes.
@@ -4669,7 +4834,7 @@ Version 2.02.11 - 12th October 2006
Capture error messages in clvmd and pass them back to the user.
Remove unused #defines from filter-md.c.
Make clvmd restart init script wait until clvmd has died before starting it.
Add -R to clvmd which tells running clvmds to reload their device cache.
Add -R to clvmd which tells running clvmd to reload their device cache.
Add LV column to reports listing kernel modules needed for activation.
Show available fields if report given invalid field. (e.g. lvs -o list)
Add timestamp functions with --disable-realtime configure option.
@@ -4996,7 +5161,7 @@ Version 2.01.08 - 22nd March 2005
Improve detection of external changes affecting internal cache.
Add 'already in device cache' debug message.
Add -a to pvdisplay -C.
Avoid rmdir opendir error messsages when dir was already removed.
Avoid rmdir opendir error messages when dir was already removed.
Tighten signal handlers.
Avoid some compiler warnings.
Additional rename failure error message.
@@ -5227,7 +5392,7 @@ Version 2.00.17 - 20 June 2004
fsadm support for fsck and resizing - needs testing.
Add read-only GFS pool support.
Add lvm2create_initrd script from http://poochiereds.net/svn/lvm2/
Fix rounding of large diplayed sizes.
Fix rounding of large displayed sizes.
Suppress decimal point when using units of sectors/bytes.
Additional kernel target checks before pvmove & snapshot creation.
Add i2o_block.
@@ -5443,3 +5608,4 @@ Display output. Some metadata information cannot yet be displayed.
Recovery tools to salvage "lost" metadata directly from the disks:
but we hope the new format will mean such tools are hardly ever needed!

View File

@@ -1,5 +1,54 @@
Version 1.02.198 -
===================
Version 1.02.210 - 24th October 2025
====================================
Version 1.02.209 - 09th September 2025
======================================
Version 1.02.208 - 30th July 2025
=================================
Version 1.02.207 - 27th June 2025
=================================
Escape the escape character itself on JSON report format output.
Fail dm_report_group_create if radix char from locale unsuitable for JSON_STD.
Version 1.02.206 - 05th May 2025
================================
Add support for using regex in selection criteria for string lists.
Fix string list selection when using [<item> || <item> ...].
Version 1.02.205 - 27th February 2025
=====================================
Restore missing symbol dm_tree_node_size_changed@Base (1.02.175).
Restore missing symbol dm_bitset_parse_list@@DM_1_02_138 (1.02.175).
Version 1.02.204 - 14th January 2025
====================================
Create /dev/disk/by-diskseq/<DISKSEQ> symlink for public DM devices.
Version 1.02.203 - 09th December 2024
=====================================
Version 1.02.202 - 04th November 2024
=====================================
Introduce dm_config_parse_only_section to stop parsing after section.
For shorter string use on stack buffers when generating sections.
Enhance dm_config tokenizer.
Version 1.02.201 - 02nd October 2024
====================================
Cleanup udev sync semaphore if dm_{udev_create,task_set}_cookie fails.
Improve error messages on failed udev cookie create/inc/dec operation.
Version 1.02.200 - 23rd August 2024
===================================
Version 1.02.199 - 12nd July 2024
=================================
Version 1.02.198 - 16th May 2024
================================
Fix static only compilation of libdevmapper.a and dmsetup tool.
Use better code for closing opened descriptors when starting dmeventd.
Correct dmeventd -R for systemd environment.
Restart of dmeventd -R checks pid file to detect running dmeventd first.
@@ -81,7 +130,7 @@ Version 1.02.173 - 09th August 2020
Version 1.02.171 - 26th March 2020
==================================
Try to remove all created devices on dm preload tree error path.
Fix dm_list interators with gcc 10 optimization (-ftree-pta).
Fix dm_list iterators with gcc 10 optimization (-ftree-pta).
Dmeventd handles timer without looping on short intervals.
Version 1.02.169 - 11th February 2020
@@ -112,7 +161,7 @@ Version 1.02.155 - 18th December 2018
=====================================
Include correct internal header inside libdm list.c.
Enhance ioctl flattening and add parameters only when needed.
Add DM_DEVICE_ARM_POLL for API completness matching kernel.
Add DM_DEVICE_ARM_POLL for API completeness matching kernel.
Do not add parameters for RESUME with DM_DEVICE_CREATE dm task.
Fix dmstats report printing no output.
@@ -141,7 +190,7 @@ Version 1.02.147-rc1 - 24th May 2018
Reuse uname() result for mirror target.
Recognize also mounted btrfs through dm_device_has_mounted_fs().
Add missing log_error() into dm_stats_populate() returning 0.
Avoid calling dm_stats_populat() for DM devices without any stats regions.
Avoid calling dm_stats_populate() for DM devices without any stats regions.
Support DM_DEBUG_WITH_LINE_NUMBERS envvar for debug msg with source:line.
Configured command for thin pool threshold handling gets whole environment.
Fix tests for failing dm_snprintf() in stats code.
@@ -190,7 +239,7 @@ Version 1.02.141 - 28th June 2017
Add dm_percent_to_round_float for adjusted percentage rounding.
Reset array with dead rimage devices once raid gets in sync.
Drop unneeded --config option from raid dmeventd plugin.
dm_get_status_raid() handle better some incosistent md statuses.
dm_get_status_raid() handle better some inconsistent md statuses.
Accept truncated files in calls to dm_stats_update_regions_from_fd().
Restore Warning by 5% increment when thin-pool is over 80% (1.02.138).
@@ -245,7 +294,7 @@ Version 1.02.136 - 5th November 2016
Still produce output when dmsetup dependency tree building finds dev missing.
Check and report pthread_sigmask() failure in dmeventd.
Check mem alloc fail in _canonicalize_field_ids().
Use unsigned math when checking more then 31 legs of raid.
Use unsigned math when checking more than 31 legs of raid.
Fix 'dmstats delete' with dmsetup older than v1.02.129
Fix stats walk segfault with dmsetup older than v1.02.129
@@ -385,7 +434,7 @@ Version 1.02.112 - 28th November 2015
=====================================
Show error message when trying to create unsupported raid type.
Improve preloading sequence of an active thin-pool target.
Drop extra space from cache target line to fix unneded table reloads.
Drop extra space from cache target line to fix unneeded table reloads.
Version 1.02.111 - 23rd November 2015
=====================================
@@ -400,7 +449,7 @@ Version 1.02.110 - 30th October 2015
Disable thin monitoring plugin when it fails too often (>10 times).
Fix/restore parsing of empty field '-' when processing dmeventd event.
Enhance dm_tree_node_size_changed() to recognize size reduction.
Support exit on idle for dmenventd (1 hour).
Support exit on idle for dmeventd (1 hour).
Add support to allow unmonitor device from plugin itself.
New design for thread co-operation in dmeventd.
Dmeventd read device status with 'noflush'.
@@ -573,7 +622,7 @@ Version 1.02.93 - 21st January 2015
Version 1.02.92 - 24th November 2014
====================================
Fix memory corruption with sorting empty string lists (1.02.86).
Fix man dmsetup.8 syntax warning of Groff
Fix man dmsetup.8 syntax warning of Groff.
Accept unquoted strings and / in place of {} when parsing configs.
Version 1.02.91 - 11th November 2014
@@ -592,7 +641,7 @@ Version 1.02.90 - 1st September 2014
Version 1.02.89 - 26th August 2014
==================================
Improve libdevmapper-event select() error handling.
Add extra check for matching transation_id after message submitting.
Add extra check for matching transaction_id after message submitting.
Add dm_report_field_string_list_unsorted for str. list report without sorting.
Support --deferred with dmsetup remove to defer removal of open devices.
Update dm-ioctl.h to include DM_DEFERRED_REMOVE flag.
@@ -679,7 +728,7 @@ Version 1.02.82 - 4th October 2013
Version 1.02.81 - 23rd September 2013
=====================================
Tidy dmeventd fifo initialisation.
Tidy dmeventd fifo initialization.
Version 1.02.80 - 20th September 2013
=====================================
@@ -704,7 +753,7 @@ Version 1.02.78 - 24th July 2013
Always return success on dmeventd -V command call.
Fix parsing of 64bit snapshot status in dmeventd snapshot plugin.
Add dm_get_status_snapshot() for parsing snapshot status.
Detecte mounted fs also via reading /proc/self/mountinfo.
Detect mounted fs also via reading /proc/self/mountinfo.
Add dm_mountinfo_read() for parsing /proc/self/mountinfo.
Report error for nonexisting devices in dmeventd communication.
Prevent double free error after dmeventd call of _fill_device_data().
@@ -801,7 +850,7 @@ Version 1.02.71 - 20th February 2012
Add "watch" rule to 13-dm-disk.rules.
Detect failing fifo and skip 20s retry communication period.
Add DM_DEFAULT_NAME_MANGLING_MODE environment variable as an override.
Add dm_lib_init to automatically initialise device-mapper library on load.
Add dm_lib_init to automatically initialize device-mapper library on load.
Replace any '\' char with '\\' in dm table specification on input.
Add mangle command to dmsetup to provide renaming to correct mangled form.
Add 'mangled_name' and 'unmangled_name' fields to dmsetup info -c -o.
@@ -895,7 +944,7 @@ Version 1.02.66 - 12th August 2011
Fix memory leak in dmsetup _message() memory allocation error path.
Use new oom killer adjustment interface (oom_score_adj) when available.
Add systemd unit files for dmeventd.
Fix read-only identical table reload supression.
Fix read-only identical table reload suppression.
Version 1.02.65 - 8th July 2011
===============================
@@ -910,7 +959,7 @@ Version 1.02.65 - 8th July 2011
Add dm_get_suspended_counter() for number of devs in suspended state by lib.
Fix "all" report field prefix matching to include label fields with pv_all.
Delay resuming new preloaded mirror devices with core logs in deptree code.
Accept new kernel version 3 uname formats in initialisation.
Accept new kernel version 3 uname formats in initialization.
Version 1.02.64 - 29th April 2011
==================================
@@ -924,7 +973,7 @@ Version 1.02.64 - 29th April 2011
Improve stack debug reporting in dm_task_create().
Fallback to control node creation only if node doesn't exist yet.
Change dm_hash binary functions to take void *key instead of char *.
Fix uninitialised memory use with empty params in _reload_with_suppression_v4.
Fix uninitialized memory use with empty params in _reload_with_suppression_v4.
Lower severity of selabel_lookup and matchpathcon failure to log_debug.
Add test for failed allocation from dm_task_set_uuid() in dmeventd.
Add dm_event_get_version to dmeventd for use with -R.
@@ -1093,7 +1142,7 @@ Version 1.02.44 - 15th February 2010
Version 1.02.43 - 21st January 2010
===================================
Remove bitset, hash and pool headers superceded by libdevmapper.h.
Remove bitset, hash and pool headers superseded by libdevmapper.h.
Fix off-by-one error causing bad cluster mirror table construction.
Version 1.02.42 - 14th January 2010
@@ -1217,7 +1266,7 @@ Version 1.02.27 - 25th June 2008
Version 1.02.26 - 6th June 2008
===============================
Initialise params buffer to empty string in _emit_segment.
Initialize params buffer to empty string in _emit_segment.
Skip add_dev_node when ioctls disabled.
Make dm_hash_iter safe against deletion.
Accept a NULL pointer to dm_free silently.
@@ -1273,7 +1322,7 @@ Version 1.02.20 - 15th June 2007
Version 1.02.19 - 27th April 2007
=================================
Standardise protective include file #defines.
Standardize protective include file #defines.
Add regex functions to library.
Avoid trailing separator in reports when there are hidden sort fields.
Fix segfault in 'dmsetup status' without --showkeys against crypt target.
@@ -1304,7 +1353,7 @@ Version 1.02.16 - 25th January 2007
Streamline dm_report_field_* interface.
Add cmdline debug & version options to dmeventd.
Add DM_LIB_VERSION definition to configure.h.
Suppress 'Unrecognised field' error if report field is 'help'.
Suppress 'Unrecognized field' error if report field is 'help'.
Add --separator and --sort to dmsetup (unused).
Make alignment flag optional when specifying report fields.
@@ -1553,3 +1602,4 @@ Version 1.00.08 - 27 Feb 2004
Updated README/INSTALL to reflect move to sources.redhat.com.
Updated autoconf files to 2003-06-17.

61
aclocal.m4 vendored
View File

@@ -1,6 +1,6 @@
# generated automatically by aclocal 1.16.5 -*- Autoconf -*-
# generated automatically by aclocal 1.18.1 -*- Autoconf -*-
# Copyright (C) 1996-2021 Free Software Foundation, Inc.
# Copyright (C) 1996-2025 Free Software Foundation, Inc.
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -117,8 +117,8 @@ m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1,
[m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])])
])dnl PKG_PREREQ
dnl PKG_PROG_PKG_CONFIG([MIN-VERSION])
dnl ----------------------------------
dnl PKG_PROG_PKG_CONFIG([MIN-VERSION], [ACTION-IF-NOT-FOUND])
dnl ---------------------------------------------------------
dnl Since: 0.16
dnl
dnl Search for the pkg-config tool and set the PKG_CONFIG variable to
@@ -126,6 +126,12 @@ dnl first found in the path. Checks that the version of pkg-config found
dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is
dnl used since that's the first version where most current features of
dnl pkg-config existed.
dnl
dnl If pkg-config is not found or older than specified, it will result
dnl in an empty PKG_CONFIG variable. To avoid widespread issues with
dnl scripts not checking it, ACTION-IF-NOT-FOUND defaults to aborting.
dnl You can specify [PKG_CONFIG=false] as an action instead, which would
dnl result in pkg-config tests failing, but no bogus error messages.
AC_DEFUN([PKG_PROG_PKG_CONFIG],
[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$])
@@ -146,6 +152,9 @@ if test -n "$PKG_CONFIG"; then
AC_MSG_RESULT([no])
PKG_CONFIG=""
fi
fi
if test -z "$PKG_CONFIG"; then
m4_default([$2], [AC_MSG_ERROR([pkg-config not found])])
fi[]dnl
])dnl PKG_PROG_PKG_CONFIG
@@ -413,7 +422,7 @@ AS_IF([test "$AS_TR_SH([with_]m4_tolower([$1]))" = "yes"],
[AC_DEFINE([HAVE_][$1], 1, [Enable ]m4_tolower([$1])[ support])])
])dnl PKG_HAVE_DEFINE_WITH_MODULES
# Copyright (C) 1999-2021 Free Software Foundation, Inc.
# Copyright (C) 1999-2025 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -447,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])
@@ -644,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],
@@ -664,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')
@@ -694,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],
@@ -706,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')
@@ -757,7 +792,7 @@ for i in list(range(0, 4)): minverhex = (minverhex << 8) + minver[[i]]
sys.exit(sys.hexversion < minverhex)"
AS_IF([AM_RUN_LOG([$1 -c "$prog"])], [$3], [$4])])
# Copyright (C) 2001-2021 Free Software Foundation, Inc.
# Copyright (C) 2001-2025 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,

View File

@@ -35,6 +35,6 @@ $(BASE_TARGET): $(BASE_OBJECTS)
$(Q) $(RM) $@
$(Q) $(AR) rsv $@ $(BASE_OBJECTS) > /dev/null
ifeq ("$(DEPENDS)","yes")
ifeq ("$(USE_TRACKING)","yes")
-include $(BASE_DEPENDS)
endif

View File

@@ -30,10 +30,10 @@ struct dm_hash_table {
unsigned num_nodes;
unsigned num_hint;
unsigned mask_slots; /* (slots - 1) -> used as hash mask */
unsigned collisions; /* Collissions of hash keys */
unsigned collisions; /* Collisions of hash keys */
unsigned search; /* How many keys were searched */
unsigned found; /* How many nodes were found */
unsigned same_hash; /* Was there a colision with same masked hash and len ? */
unsigned same_hash; /* Was there a collision with same masked hash and len ? */
struct dm_hash_node **slots;
};
@@ -41,7 +41,7 @@ struct dm_hash_table {
static unsigned _hash(const void *key, unsigned len)
{
/* Permutation of the Integers 0 through 255 */
static unsigned char _nums[] = {
static const unsigned char _nums[] = {
1, 14, 110, 25, 97, 174, 132, 119, 138, 170, 125, 118, 27, 233, 140, 51,
87, 197, 177, 107, 234, 169, 56, 68, 30, 7, 173, 73, 188, 40, 36, 65,
49, 213, 104, 190, 57, 211, 148, 223, 48, 115, 15, 2, 67, 186, 210, 28,
@@ -348,7 +348,7 @@ int dm_hash_insert_allow_multiple(struct dm_hash_table *t, const char *key,
/*
* Look through multiple entries with the same key for one that has a
* matching val and return that. If none have maching val, return NULL.
* matching val and return that. If none have matching val, return NULL.
*/
void *dm_hash_lookup_with_val(struct dm_hash_table *t, const char *key,
const void *val, uint32_t val_len)

View File

@@ -19,6 +19,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
//----------------------------------------------------------------
@@ -69,7 +70,7 @@ struct node48 {
};
struct node256 {
uint32_t nr_entries;
uint32_t nr_entries;
struct value values[256];
};
@@ -99,7 +100,7 @@ struct radix_tree *radix_tree_create(radix_value_dtr dtr, void *dtr_context)
static inline void _dtr(struct radix_tree *rt, union radix_value v)
{
if (rt->dtr)
rt->dtr(rt->dtr_context, v);
rt->dtr(rt->dtr_context, v);
}
// Returns the number of values removed
@@ -118,8 +119,8 @@ static unsigned _free_node(struct radix_tree *rt, struct value v)
break;
case VALUE:
_dtr(rt, v.value);
nr = 1;
_dtr(rt, v.value);
nr = 1;
break;
case VALUE_CHAIN:
@@ -178,9 +179,9 @@ unsigned radix_tree_size(struct radix_tree *rt)
return rt->nr_entries;
}
static bool _insert(struct radix_tree *rt, struct value *v, uint8_t *kb, uint8_t *ke, union radix_value rv);
static bool _insert(struct radix_tree *rt, struct value *v, const uint8_t *kb, const uint8_t *ke, union radix_value rv);
static bool _insert_unset(struct radix_tree *rt, struct value *v, uint8_t *kb, uint8_t *ke, union radix_value rv)
static bool _insert_unset(struct radix_tree *rt, struct value *v, const uint8_t *kb, const uint8_t *ke, union radix_value rv)
{
unsigned len = ke - kb;
@@ -190,8 +191,8 @@ static bool _insert_unset(struct radix_tree *rt, struct value *v, uint8_t *kb, u
v->value = rv;
rt->nr_entries++;
} else {
// prefix -> value
struct prefix_chain *pc = zalloc(sizeof(*pc) + len);
// prefix -> value (all fields explicitly initialized)
struct prefix_chain *pc = malloc(sizeof(*pc) + len);
if (!pc)
return false;
@@ -207,7 +208,7 @@ static bool _insert_unset(struct radix_tree *rt, struct value *v, uint8_t *kb, u
return true;
}
static bool _insert_value(struct radix_tree *rt, struct value *v, uint8_t *kb, uint8_t *ke, union radix_value rv)
static bool _insert_value(struct radix_tree *rt, struct value *v, const uint8_t *kb, const uint8_t *ke, union radix_value rv)
{
unsigned len = ke - kb;
@@ -234,7 +235,7 @@ static bool _insert_value(struct radix_tree *rt, struct value *v, uint8_t *kb, u
return true;
}
static bool _insert_value_chain(struct radix_tree *rt, struct value *v, uint8_t *kb, uint8_t *ke, union radix_value rv)
static bool _insert_value_chain(struct radix_tree *rt, struct value *v, const uint8_t *kb, const uint8_t *ke, union radix_value rv)
{
struct value_chain *vc = v->value.ptr;
return _insert(rt, &vc->child, kb, ke, rv);
@@ -248,7 +249,7 @@ static unsigned min(unsigned lhs, unsigned rhs)
return rhs;
}
static bool _insert_prefix_chain(struct radix_tree *rt, struct value *v, uint8_t *kb, uint8_t *ke, union radix_value rv)
static bool _insert_prefix_chain(struct radix_tree *rt, struct value *v, const uint8_t *kb, const uint8_t *ke, union radix_value rv)
{
struct prefix_chain *pc = v->value.ptr;
@@ -266,7 +267,8 @@ static bool _insert_prefix_chain(struct radix_tree *rt, struct value *v, uint8_t
if (kb[i] != pc->prefix[i])
break;
if (!(pc2 = zalloc(sizeof(*pc2) + pc->len - i)))
// All fields of pc2 are explicitly initialized
if (!(pc2 = malloc(sizeof(*pc2) + pc->len - i)))
return false;
pc2->len = pc->len - i;
memmove(pc2->prefix, pc->prefix + i, pc2->len);
@@ -278,7 +280,7 @@ static bool _insert_prefix_chain(struct radix_tree *rt, struct value *v, uint8_t
pc->len = i;
if (!_insert(rt, &pc->child, kb + i, ke, rv)) {
free(pc2);
free(pc->child.value.ptr);
return false;
}
@@ -292,6 +294,7 @@ static bool _insert_prefix_chain(struct radix_tree *rt, struct value *v, uint8_t
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--;
@@ -313,7 +316,7 @@ static bool _insert_prefix_chain(struct radix_tree *rt, struct value *v, uint8_t
return true;
}
static bool _insert_node4(struct radix_tree *rt, struct value *v, uint8_t *kb, uint8_t *ke, union radix_value rv)
static bool _insert_node4(struct radix_tree *rt, struct value *v, const uint8_t *kb, const uint8_t *ke, union radix_value rv)
{
struct node4 *n4 = v->value.ptr;
if (n4->nr_entries == 4) {
@@ -343,7 +346,7 @@ static bool _insert_node4(struct radix_tree *rt, struct value *v, uint8_t *kb, u
return true;
}
static bool _insert_node16(struct radix_tree *rt, struct value *v, uint8_t *kb, uint8_t *ke, union radix_value rv)
static bool _insert_node16(struct radix_tree *rt, struct value *v, const uint8_t *kb, const uint8_t *ke, union radix_value rv)
{
struct node16 *n16 = v->value.ptr;
@@ -382,7 +385,7 @@ static bool _insert_node16(struct radix_tree *rt, struct value *v, uint8_t *kb,
return true;
}
static bool _insert_node48(struct radix_tree *rt, struct value *v, uint8_t *kb, uint8_t *ke, union radix_value rv)
static bool _insert_node48(struct radix_tree *rt, struct value *v, const uint8_t *kb, const uint8_t *ke, union radix_value rv)
{
struct node48 *n48 = v->value.ptr;
if (n48->nr_entries == 48) {
@@ -417,20 +420,20 @@ static bool _insert_node48(struct radix_tree *rt, struct value *v, uint8_t *kb,
return true;
}
static bool _insert_node256(struct radix_tree *rt, struct value *v, uint8_t *kb, uint8_t *ke, union radix_value rv)
static bool _insert_node256(struct radix_tree *rt, struct value *v, const uint8_t *kb, const uint8_t *ke, union radix_value rv)
{
struct node256 *n256 = v->value.ptr;
bool r, was_unset = n256->values[*kb].type == UNSET;
r = _insert(rt, n256->values + *kb, kb + 1, ke, rv);
if (r && was_unset)
n256->nr_entries++;
n256->nr_entries++;
return r;
}
// FIXME: the tree should not be touched if insert fails (eg, OOM)
static bool _insert(struct radix_tree *rt, struct value *v, uint8_t *kb, uint8_t *ke, union radix_value rv)
static bool _insert(struct radix_tree *rt, struct value *v, const uint8_t *kb, const uint8_t *ke, union radix_value rv)
{
if (kb == ke) {
if (v->type == UNSET) {
@@ -442,7 +445,8 @@ static bool _insert(struct radix_tree *rt, struct value *v, uint8_t *kb, uint8_t
v->value = rv;
} else {
struct value_chain *vc = zalloc(sizeof(*vc));
// All fields explicitly initialized
struct value_chain *vc = malloc(sizeof(*vc));
if (!vc)
return false;
@@ -487,10 +491,10 @@ static bool _insert(struct radix_tree *rt, struct value *v, uint8_t *kb, uint8_t
struct lookup_result {
struct value *v;
uint8_t *kb;
const uint8_t *kb;
};
static struct lookup_result _lookup_prefix(struct value *v, uint8_t *kb, uint8_t *ke)
static struct lookup_result _lookup_prefix(struct value *v, const uint8_t *kb, const uint8_t *ke)
{
unsigned i;
struct value_chain *vc;
@@ -500,7 +504,7 @@ static struct lookup_result _lookup_prefix(struct value *v, uint8_t *kb, uint8_t
struct node48 *n48;
struct node256 *n256;
if (kb == ke)
if (kb == ke || !kb) /* extra check for !kb for coverity */
return (struct lookup_result) {.v = v, .kb = kb};
switch (v->type) {
@@ -555,45 +559,38 @@ static struct lookup_result _lookup_prefix(struct value *v, uint8_t *kb, uint8_t
return (struct lookup_result) {.v = v, .kb = kb};
}
bool radix_tree_insert(struct radix_tree *rt, uint8_t *kb, uint8_t *ke, union radix_value rv)
bool radix_tree_insert(struct radix_tree *rt, const void *key, size_t keylen, union radix_value rv)
{
const uint8_t *kb = key;
const uint8_t *ke = kb + keylen;
struct lookup_result lr = _lookup_prefix(&rt->root, kb, ke);
return _insert(rt, lr.v, lr.kb, ke, rv);
}
// Note the degrade functions also free the original node.
static void _degrade_to_n4(struct node16 *n16, struct value *result)
int radix_tree_uniq_insert(struct radix_tree *rt, const void *key, size_t keylen, union radix_value rv)
{
struct node4 *n4 = zalloc(sizeof(*n4));
assert(n4 != NULL);
n4->nr_entries = n16->nr_entries;
memcpy(n4->keys, n16->keys, n16->nr_entries * sizeof(*n4->keys));
memcpy(n4->values, n16->values, n16->nr_entries * sizeof(*n4->values));
free(n16);
result->type = NODE4;
result->value.ptr = n4;
unsigned entries = rt->nr_entries;
return radix_tree_insert(rt, key, keylen, rv) ?
((entries != rt->nr_entries) ? 1 : -1) : 0;
}
static void _degrade_to_n16(struct node48 *n48, struct value *result)
{
unsigned i, count = 0;
struct node16 *n16 = zalloc(sizeof(*n16));
struct node16 *n16 = zalloc(sizeof(*n16));
assert(n16 != NULL);
n16->nr_entries = n48->nr_entries;
for (i = 0; i < 256; i++) {
if (n48->keys[i] < 48) {
n16->keys[count] = i;
n16->values[count] = n48->values[n48->keys[i]];
count++;
}
}
n16->nr_entries = n48->nr_entries;
for (i = 0; i < 256; i++) {
if (n48->keys[i] < 48) {
n16->keys[count] = i;
n16->values[count] = n48->values[n48->keys[i]];
count++;
}
}
free(n48);
free(n48);
result->type = NODE16;
result->value.ptr = n16;
@@ -601,13 +598,13 @@ static void _degrade_to_n16(struct node48 *n48, struct value *result)
static void _degrade_to_n48(struct node256 *n256, struct value *result)
{
unsigned i, count = 0;
struct node48 *n48 = zalloc(sizeof(*n48));
unsigned i, count = 0;
struct node48 *n48 = zalloc(sizeof(*n48));
assert(n48 != NULL);
n48->nr_entries = n256->nr_entries;
for (i = 0; i < 256; i++) {
n48->nr_entries = n256->nr_entries;
for (i = 0; i < 256; i++) {
if (n256->values[i].type == UNSET)
n48->keys[i] = 48;
@@ -616,9 +613,9 @@ static void _degrade_to_n48(struct node256 *n256, struct value *result)
n48->values[count] = n256->values[i];
count++;
}
}
}
free(n256);
free(n256);
result->type = NODE48;
result->value.ptr = n48;
@@ -632,14 +629,14 @@ static void _erase_elt(void *array, size_t obj_size, unsigned count, unsigned id
return;
memmove(((uint8_t *) array) + (obj_size * idx),
((uint8_t *) array) + (obj_size * (idx + 1)),
obj_size * (count - idx - 1));
((uint8_t *) array) + (obj_size * (idx + 1)),
obj_size * (count - idx - 1));
// Zero the now unused last elt (set's v.type to UNSET)
memset(((uint8_t *) array) + (count - 1) * obj_size, 0, obj_size);
}
static bool _remove(struct radix_tree *rt, struct value *root, uint8_t *kb, uint8_t *ke)
static bool _remove(struct radix_tree *rt, struct value *root, const uint8_t *kb, const uint8_t *ke)
{
bool r;
unsigned i, j;
@@ -651,27 +648,28 @@ static bool _remove(struct radix_tree *rt, struct value *root, uint8_t *kb, uint
struct node256 *n256;
if (kb == ke) {
if (root->type == VALUE) {
root->type = UNSET;
_dtr(rt, root->value);
return true;
if (root->type == VALUE) {
root->type = UNSET;
_dtr(rt, root->value);
return true;
} else if (root->type == VALUE_CHAIN) {
} else if (root->type == VALUE_CHAIN) {
// Free value_chain after copying child out
vc = root->value.ptr;
_dtr(rt, vc->value);
memcpy(root, &vc->child, sizeof(*root));
*root = vc->child;
free(vc);
return true;
} else
} else
return false;
}
switch (root->type) {
case UNSET:
case VALUE:
// this is a value for a prefix of the key
return false;
// this is a value for a prefix of the key
return false;
case VALUE_CHAIN:
vc = root->value.ptr;
@@ -686,11 +684,11 @@ static bool _remove(struct radix_tree *rt, struct value *root, uint8_t *kb, uint
case PREFIX_CHAIN:
pc = root->value.ptr;
if (ke - kb < pc->len)
return false;
return false;
for (i = 0; i < pc->len; i++)
if (kb[i] != pc->prefix[i])
return false;
return false;
r = _remove(rt, &pc->child, kb + pc->len, ke);
if (r && pc->child.type == UNSET) {
@@ -705,12 +703,12 @@ static bool _remove(struct radix_tree *rt, struct value *root, uint8_t *kb, uint
if (n4->keys[i] == *kb) {
r = _remove(rt, n4->values + i, kb + 1, ke);
if (r && n4->values[i].type == UNSET) {
if (i < n4->nr_entries) {
_erase_elt(n4->keys, sizeof(*n4->keys), n4->nr_entries, i);
_erase_elt(n4->values, sizeof(*n4->values), n4->nr_entries, i);
}
if (i < n4->nr_entries) {
_erase_elt(n4->keys, sizeof(*n4->keys), n4->nr_entries, i);
_erase_elt(n4->values, sizeof(*n4->values), n4->nr_entries, i);
}
n4->nr_entries--;
n4->nr_entries--;
if (!n4->nr_entries) {
free(n4);
root->type = UNSET;
@@ -722,19 +720,20 @@ static bool _remove(struct radix_tree *rt, struct value *root, uint8_t *kb, uint
return false;
case NODE16:
n16 = root->value.ptr;
n16 = root->value.ptr;
for (i = 0; i < n16->nr_entries; i++) {
if (n16->keys[i] == *kb) {
r = _remove(rt, n16->values + i, kb + 1, ke);
if (r && n16->values[i].type == UNSET) {
if (i < n16->nr_entries) {
_erase_elt(n16->keys, sizeof(*n16->keys), n16->nr_entries, i);
_erase_elt(n16->values, sizeof(*n16->values), n16->nr_entries, i);
}
if (i < n16->nr_entries) {
_erase_elt(n16->keys, sizeof(*n16->keys), n16->nr_entries, i);
_erase_elt(n16->values, sizeof(*n16->values), n16->nr_entries, i);
}
n16->nr_entries--;
if (n16->nr_entries <= 4) {
_degrade_to_n4(n16, root);
n16->nr_entries--;
if (!n16->nr_entries) {
free(n16);
root->type = UNSET;
}
}
return r;
@@ -746,18 +745,18 @@ static bool _remove(struct radix_tree *rt, struct value *root, uint8_t *kb, uint
n48 = root->value.ptr;
i = n48->keys[*kb];
if (i < 48) {
r = _remove(rt, n48->values + i, kb + 1, ke);
if (r && n48->values[i].type == UNSET) {
n48->keys[*kb] = 48;
for (j = 0; j < 256; j++)
if (n48->keys[j] < 48 && n48->keys[j] > i)
n48->keys[j]--;
r = _remove(rt, n48->values + i, kb + 1, ke);
if (r && n48->values[i].type == UNSET) {
n48->keys[*kb] = 48;
for (j = 0; j < 256; j++)
if (n48->keys[j] < 48 && n48->keys[j] > i)
n48->keys[j]--;
_erase_elt(n48->values, sizeof(*n48->values), n48->nr_entries, i);
n48->nr_entries--;
if (n48->nr_entries <= 16)
_degrade_to_n16(n48, root);
}
return r;
_degrade_to_n16(n48, root);
}
return r;
}
return false;
@@ -767,7 +766,7 @@ static bool _remove(struct radix_tree *rt, struct value *root, uint8_t *kb, uint
if (r && n256->values[*kb].type == UNSET) {
n256->nr_entries--;
if (n256->nr_entries <= 48)
_degrade_to_n48(n256, root);
_degrade_to_n48(n256, root);
}
return r;
}
@@ -775,11 +774,14 @@ static bool _remove(struct radix_tree *rt, struct value *root, uint8_t *kb, uint
return false;
}
bool radix_tree_remove(struct radix_tree *rt, uint8_t *key_begin, uint8_t *key_end)
bool radix_tree_remove(struct radix_tree *rt, const void *key, size_t keylen)
{
if (_remove(rt, &rt->root, key_begin, key_end)) {
rt->nr_entries--;
return true;
const uint8_t *kb = key;
const uint8_t *ke = kb + keylen;
if (_remove(rt, &rt->root, kb, ke)) {
rt->nr_entries--;
return true;
}
return false;
@@ -787,25 +789,25 @@ bool radix_tree_remove(struct radix_tree *rt, uint8_t *key_begin, uint8_t *key_e
//----------------------------------------------------------------
static bool _prefix_chain_matches(struct lookup_result *lr, uint8_t *ke)
static bool _prefix_chain_matches(const struct lookup_result *lr, const uint8_t *ke)
{
// It's possible the top node is a prefix chain, and
// the remaining key matches part of it.
if (lr->v->type == PREFIX_CHAIN) {
unsigned i, rlen = ke - lr->kb;
struct prefix_chain *pc = lr->v->value.ptr;
if (rlen < pc->len) {
for (i = 0; i < rlen; i++)
if (pc->prefix[i] != lr->kb[i])
return false;
return true;
// It's possible the top node is a prefix chain, and
// the remaining key matches part of it.
if (lr->v->type == PREFIX_CHAIN) {
unsigned i, rlen = ke - lr->kb;
const struct prefix_chain *pc = lr->v->value.ptr;
if (rlen < pc->len) {
for (i = 0; i < rlen; i++)
if (pc->prefix[i] != lr->kb[i])
return false;
return true;
}
}
}
return false;
return false;
}
static bool _remove_subtree(struct radix_tree *rt, struct value *root, uint8_t *kb, uint8_t *ke, unsigned *count)
static bool _remove_subtree(struct radix_tree *rt, struct value *root, const uint8_t *kb, const uint8_t *ke, unsigned *count)
{
bool r;
unsigned i, j, len;
@@ -826,7 +828,7 @@ static bool _remove_subtree(struct radix_tree *rt, struct value *root, uint8_t *
case UNSET:
case VALUE:
// No entries with the given prefix
return true;
return true;
case VALUE_CHAIN:
vc = root->value.ptr;
@@ -843,7 +845,7 @@ static bool _remove_subtree(struct radix_tree *rt, struct value *root, uint8_t *
len = min(pc->len, ke - kb);
for (i = 0; i < len; i++)
if (kb[i] != pc->prefix[i])
return true;
return true;
r = _remove_subtree(rt, &pc->child, len < pc->len ? ke : (kb + pc->len), ke, count);
if (r && pc->child.type == UNSET) {
@@ -858,12 +860,12 @@ static bool _remove_subtree(struct radix_tree *rt, struct value *root, uint8_t *
if (n4->keys[i] == *kb) {
r = _remove_subtree(rt, n4->values + i, kb + 1, ke, count);
if (r && n4->values[i].type == UNSET) {
if (i < n4->nr_entries) {
_erase_elt(n4->keys, sizeof(*n4->keys), n4->nr_entries, i);
_erase_elt(n4->values, sizeof(*n4->values), n4->nr_entries, i);
}
if (i < n4->nr_entries) {
_erase_elt(n4->keys, sizeof(*n4->keys), n4->nr_entries, i);
_erase_elt(n4->values, sizeof(*n4->values), n4->nr_entries, i);
}
n4->nr_entries--;
n4->nr_entries--;
if (!n4->nr_entries) {
free(n4);
root->type = UNSET;
@@ -875,19 +877,21 @@ static bool _remove_subtree(struct radix_tree *rt, struct value *root, uint8_t *
return true;
case NODE16:
n16 = root->value.ptr;
n16 = root->value.ptr;
for (i = 0; i < n16->nr_entries; i++) {
if (n16->keys[i] == *kb) {
r = _remove_subtree(rt, n16->values + i, kb + 1, ke, count);
if (r && n16->values[i].type == UNSET) {
if (i < n16->nr_entries) {
_erase_elt(n16->keys, sizeof(*n16->keys), n16->nr_entries, i);
_erase_elt(n16->values, sizeof(*n16->values), n16->nr_entries, i);
}
if (i < n16->nr_entries) {
_erase_elt(n16->keys, sizeof(*n16->keys), n16->nr_entries, i);
_erase_elt(n16->values, sizeof(*n16->values), n16->nr_entries, i);
}
n16->nr_entries--;
if (n16->nr_entries <= 4)
_degrade_to_n4(n16, root);
n16->nr_entries--;
if (!n16->nr_entries) {
free(n16);
root->type = UNSET;
}
}
return r;
}
@@ -898,18 +902,18 @@ static bool _remove_subtree(struct radix_tree *rt, struct value *root, uint8_t *
n48 = root->value.ptr;
i = n48->keys[*kb];
if (i < 48) {
r = _remove_subtree(rt, n48->values + i, kb + 1, ke, count);
if (r && n48->values[i].type == UNSET) {
n48->keys[*kb] = 48;
for (j = 0; j < 256; j++)
if (n48->keys[j] < 48 && n48->keys[j] > i)
n48->keys[j]--;
r = _remove_subtree(rt, n48->values + i, kb + 1, ke, count);
if (r && n48->values[i].type == UNSET) {
n48->keys[*kb] = 48;
for (j = 0; j < 256; j++)
if (n48->keys[j] < 48 && n48->keys[j] > i)
n48->keys[j]--;
_erase_elt(n48->values, sizeof(*n48->values), n48->nr_entries, i);
n48->nr_entries--;
if (n48->nr_entries <= 16)
_degrade_to_n16(n48, root);
}
return r;
_degrade_to_n16(n48, root);
}
return r;
}
return true;
@@ -922,7 +926,7 @@ static bool _remove_subtree(struct radix_tree *rt, struct value *root, uint8_t *
if (r && n256->values[*kb].type == UNSET) {
n256->nr_entries--;
if (n256->nr_entries <= 48)
_degrade_to_n48(n256, root);
_degrade_to_n48(n256, root);
}
return r;
}
@@ -931,11 +935,13 @@ static bool _remove_subtree(struct radix_tree *rt, struct value *root, uint8_t *
return false;
}
unsigned radix_tree_remove_prefix(struct radix_tree *rt, uint8_t *kb, uint8_t *ke)
unsigned radix_tree_remove_prefix(struct radix_tree *rt, const void *prefix, size_t prefix_len)
{
unsigned count = 0;
const uint8_t *kb = prefix;
const uint8_t *ke = kb + prefix_len;
unsigned count = 0;
if (_remove_subtree(rt, &rt->root, kb, ke, &count))
if (_remove_subtree(rt, &rt->root, kb, ke, &count))
rt->nr_entries -= count;
return count;
@@ -943,9 +949,11 @@ unsigned radix_tree_remove_prefix(struct radix_tree *rt, uint8_t *kb, uint8_t *k
//----------------------------------------------------------------
bool radix_tree_lookup(struct radix_tree *rt,
uint8_t *kb, uint8_t *ke, union radix_value *result)
bool radix_tree_lookup(struct radix_tree *rt, const void *key, size_t keylen,
union radix_value *result)
{
const uint8_t *kb = key;
const uint8_t *ke = kb + keylen;
struct value_chain *vc;
struct lookup_result lr = _lookup_prefix(&rt->root, kb, ke);
if (lr.kb == ke) {
@@ -968,58 +976,58 @@ bool radix_tree_lookup(struct radix_tree *rt,
}
// FIXME: build up the keys too
static bool _iterate(struct value *v, struct radix_tree_iterator *it)
static bool _iterate(struct radix_tree_iterator *it, const struct value *v)
{
unsigned i;
struct value_chain *vc;
struct prefix_chain *pc;
struct node4 *n4;
struct node16 *n16;
struct node48 *n48;
struct node256 *n256;
const struct value_chain *vc;
const struct prefix_chain *pc;
const struct node4 *n4;
const struct node16 *n16;
const struct node48 *n48;
const struct node256 *n256;
switch (v->type) {
case UNSET:
// can't happen
// can't happen
break;
case VALUE:
return it->visit(it, NULL, NULL, v->value);
return it->visit(it, NULL, 0, v->value);
case VALUE_CHAIN:
vc = v->value.ptr;
return it->visit(it, NULL, NULL, vc->value) && _iterate(&vc->child, it);
return it->visit(it, NULL, 0, vc->value) && _iterate(it, &vc->child);
case PREFIX_CHAIN:
pc = v->value.ptr;
return _iterate(&pc->child, it);
return _iterate(it, &pc->child);
case NODE4:
n4 = (struct node4 *) v->value.ptr;
n4 = (const struct node4 *) v->value.ptr;
for (i = 0; i < n4->nr_entries; i++)
if (!_iterate(n4->values + i, it))
return false;
return true;
if (!_iterate(it, n4->values + i))
return false;
return true;
case NODE16:
n16 = (struct node16 *) v->value.ptr;
n16 = (const struct node16 *) v->value.ptr;
for (i = 0; i < n16->nr_entries; i++)
if (!_iterate(n16->values + i, it))
return false;
if (!_iterate(it, n16->values + i))
return false;
return true;
case NODE48:
n48 = (struct node48 *) v->value.ptr;
n48 = (const struct node48 *) v->value.ptr;
for (i = 0; i < n48->nr_entries; i++)
if (!_iterate(n48->values + i, it))
return false;
if (!_iterate(it, n48->values + i))
return false;
return true;
case NODE256:
n256 = (struct node256 *) v->value.ptr;
n256 = (const struct node256 *) v->value.ptr;
for (i = 0; i < 256; i++)
if (n256->values[i].type != UNSET && !_iterate(n256->values + i, it))
return false;
if (n256->values[i].type != UNSET && !_iterate(it, n256->values + i))
return false;
return true;
}
@@ -1027,12 +1035,14 @@ static bool _iterate(struct value *v, struct radix_tree_iterator *it)
return false;
}
void radix_tree_iterate(struct radix_tree *rt, uint8_t *kb, uint8_t *ke,
struct radix_tree_iterator *it)
void radix_tree_iterate(struct radix_tree *rt, const void *key, size_t keylen,
struct radix_tree_iterator *it)
{
const uint8_t *kb = key;
const uint8_t *ke = kb + keylen;
struct lookup_result lr = _lookup_prefix(&rt->root, kb, ke);
if (lr.kb == ke || _prefix_chain_matches(&lr, ke))
(void) _iterate(lr.v, it);
(void) _iterate(it, lr.v);
}
//----------------------------------------------------------------
@@ -1130,7 +1140,7 @@ static bool _check_nodes(struct value *v, unsigned *count)
if (ncount != n48->nr_entries) {
fprintf(stderr, "incorrect number of entries in n48, n48->nr_entries = %u, actual = %u\n",
n48->nr_entries, ncount);
n48->nr_entries, ncount);
return false;
}
@@ -1166,7 +1176,7 @@ static bool _check_nodes(struct value *v, unsigned *count)
if (ncount != n256->nr_entries) {
fprintf(stderr, "incorrect number of entries in n256, n256->nr_entries = %u, actual = %u\n",
n256->nr_entries, ncount);
n256->nr_entries, ncount);
return false;
}
@@ -1189,7 +1199,7 @@ bool radix_tree_is_well_formed(struct radix_tree *rt)
if (rt->nr_entries != count) {
fprintf(stderr, "incorrect entry count: rt->nr_entries = %u, actual = %u\n",
rt->nr_entries, count);
rt->nr_entries, count);
return false;
}
@@ -1207,6 +1217,7 @@ static void _dump(FILE *out, struct value v, unsigned indent)
struct node16 *n16;
struct node48 *n48;
struct node256 *n256;
unsigned printable;
if (v.type == UNSET)
return;
@@ -1231,9 +1242,22 @@ static void _dump(FILE *out, struct value v, unsigned indent)
case PREFIX_CHAIN:
pc = v.value.ptr;
fprintf(out, "<prefix: ");
fprintf(out, "<prefix(%u): ", pc->len);
printable = 1;
for (i = 0; i < pc->len; i++)
fprintf(out, "%x.", (unsigned) *(pc->prefix + i));
if (!isprint(pc->prefix[i])) {
printable = 0;
break;
}
if (printable)
fputc('"', out);
for (i = 0; i < pc->len; i++)
if (printable)
fprintf(out, "%c", pc->prefix[i]);
else
fprintf(out, "%02x.", (unsigned) *(pc->prefix + i));
if (printable)
fputc('"', out);
fprintf(out, ">\n");
_dump(out, pc->child, indent + 1);
break;
@@ -1242,7 +1266,7 @@ static void _dump(FILE *out, struct value v, unsigned indent)
n4 = v.value.ptr;
fprintf(out, "<n4: ");
for (i = 0; i < n4->nr_entries; i++)
fprintf(out, "%x ", (unsigned) n4->keys[i]);
fprintf(out, "%02x ", (unsigned) n4->keys[i]);
fprintf(out, ">\n");
for (i = 0; i < n4->nr_entries; i++)
@@ -1253,7 +1277,7 @@ static void _dump(FILE *out, struct value v, unsigned indent)
n16 = v.value.ptr;
fprintf(out, "<n16: ");
for (i = 0; i < n16->nr_entries; i++)
fprintf(out, "%x ", (unsigned) n16->keys[i]);
fprintf(out, "%02x ", (unsigned) n16->keys[i]);
fprintf(out, ">\n");
for (i = 0; i < n16->nr_entries; i++)
@@ -1265,7 +1289,7 @@ static void _dump(FILE *out, struct value v, unsigned indent)
fprintf(out, "<n48: ");
for (i = 0; i < 256; i++)
if (n48->keys[i] < 48)
fprintf(out, "%x ", i);
fprintf(out, "%02x ", i);
fprintf(out, ">\n");
for (i = 0; i < n48->nr_entries; i++) {
@@ -1279,7 +1303,7 @@ static void _dump(FILE *out, struct value v, unsigned indent)
fprintf(out, "<n256: ");
for (i = 0; i < 256; i++)
if (n256->values[i].type != UNSET)
fprintf(out, "%x ", i);
fprintf(out, "%02x ", i);
fprintf(out, ">\n");
for (i = 0; i < 256; i++)

View File

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

View File

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

View File

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

View File

@@ -36,6 +36,19 @@ config {
# This configuration option has an automatic default value.
# checks = 1
# Configuration option config/validate_metadata.
# Allows to select the level of validation after metadata transformation.
# Validation takes extra CPU time to verify internal consistency.
# Accepted values:
# full
# Do a full metadata validation before disk write.
# none
# Skip any checks (unrecommended, slightly faster).
#
# This configuration option is advanced.
# This configuration option has an automatic default value.
# validate_metadata = "full"
# Configuration option config/abort_on_errors.
# Abort the LVM process if a configuration mismatch is found.
# This configuration option has an automatic default value.
@@ -122,7 +135,7 @@ devices {
# Configuration option devices/use_devicesfile.
# Enable or disable the use of a devices file.
# When enabled, lvm will only use devices that
# are lised in the devices file. A devices file will
# are listed in the devices file. A devices file will
# be used, regardless of this setting, when the --devicesfile
# option is set to a specific file name.
# This configuration option has an automatic default value.
@@ -562,10 +575,21 @@ allocation {
# Configuration option allocation/cache_pool_max_chunks.
# The maximum number of chunks in a cache pool.
# For cache target v1.9 the recommended maximumm is 1000000 chunks.
# For cache target v1.9 the recommended maximum is 1000000 chunks.
# Using cache pool with more chunks may degrade cache performance.
# This configuration option does not have a default value defined.
# Configuration option allocation/pvmove_max_segment_size_mb.
# Maximum size in MiB of segments to mirror at once during pvmove.
# When pvmove needs to move large segments, it will split them into
# smaller chunks of this size, mirror each chunk, and update metadata
# between chunks. This prevents mirroring excessively large amounts
# of data at once. A value of 0 (default) means no limit - the entire
# segment will be mirrored at once. Setting this to e.g. 10240 will
# limit each mirroring operation to 10GiB chunks.
# This configuration option has an automatic default value.
# pvmove_max_segment_size_mb = 0
# Configuration option allocation/thin_pool_metadata_require_separate_pvs.
# Thin pool metadata and data will always use different PVs.
# This configuration option has an automatic default value.
@@ -573,7 +597,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
@@ -646,13 +670,6 @@ allocation {
# This configuration option has an automatic default value.
# vdo_use_deduplication = 1
# Configuration option allocation/vdo_use_metadata_hints.
# Enables or disables whether VDO volume should tag its latency-critical
# writes with the REQ_SYNC flag. Some device mapper targets such as dm-raid5
# process writes with this flag at a higher priority.
# This configuration option has an automatic default value.
# vdo_use_metadata_hints = 1
# Configuration option allocation/vdo_minimum_io_size.
# The minimum IO size for VDO volume to accept, in bytes.
# Valid values are 512 or 4096. The recommended value is 4096.
@@ -751,19 +768,6 @@ allocation {
# This configuration option has an automatic default value.
# vdo_physical_threads = 1
# Configuration option allocation/vdo_write_policy.
# Specifies the write policy:
# auto - VDO will check the storage device and determine whether it supports flushes.
# If it does, VDO will run in async mode, otherwise it will run in sync mode.
# sync - Writes are acknowledged only after data is stably written.
# This policy is not supported if the underlying storage is not also synchronous.
# async - Writes are acknowledged after data has been cached for writing to stable storage.
# Data which has not been flushed is not guaranteed to persist in this mode.
# async-unsafe - Writes are handled like 'async' but there is no guarantee of the atomicity async provides.
# This mode should only be used for better performance when atomicity is not required.
# This configuration option has an automatic default value.
# vdo_write_policy = "auto"
# Configuration option allocation/vdo_max_discard.
# Specified the maximum size of discard bio accepted, in 4096 byte blocks.
# I/O requests to a VDO volume are normally split into 4096-byte blocks,
@@ -801,6 +805,9 @@ log {
# to define fields to display and sort fields for the log report.
# You can also use log/command_log_selection to define selection
# criteria used each time the log is reported.
# Note that if report/output_format (or --reportformat command line
# option) is set to json or json_std, then log/report_command_log=1
# is default.
# This configuration option has an automatic default value.
# report_command_log = 0
@@ -830,8 +837,9 @@ log {
# define selection criteria for log report on command line directly
# using <lvm command> --configreport log -S <selection criteria>
# which has precedence over log/command_log_selection setting.
# For more information about selection criteria in general, see
# lvm(8) man page.
# To make all the command log lines visible, use "all" value
# for the command log selection. For more information about selection
# criteria in general, see lvmreport(7) man page.
# This configuration option has an automatic default value.
# command_log_selection = "!(log_type=status && message=success)"
@@ -1208,6 +1216,16 @@ global {
# This configuration option has an automatic default value.
# sanlock_lv_extend = 256
# Configuration option global/sanlock_align_size.
# The sanlock lease size in MiB to use on disks with a 4K sector size.
# Possible values are 1,2,4,8. The default is 8, which supports up to
# 2000 hosts (and max host_id 2000.) Smaller values support smaller
# numbers of max hosts (and max host_ids): 250, 500, 1000, 2000 for
# lease sizes 1,2,4,8. Disks with 512 byte sectors always use 1MiB
# leases and support 2000 hosts, and are not affected by this setting.
# This configuration option has an automatic default value.
# sanlock_align_size = 8
# Configuration option global/lvmlockctl_kill_command.
# The command that lvmlockctl --kill should use to force LVs offline.
# The lvmlockctl --kill command is run when a shared VG has lost
@@ -1372,6 +1390,12 @@ global {
# This configuration option has an automatic default value.
# fsadm_executable = "@FSADM_PATH@"
# Configuration option global/lvresize_fs_helper_executable.
# The full path to the lvresize_fs_helper command.
# LVM uses this command to help with filesystem operations during lvresize.
# This configuration option has an automatic default value.
# lvresize_fs_helper_executable = "@LVRESIZE_FS_HELPER_PATH@"
# Configuration option global/system_id_source.
# The method LVM uses to set the local system ID.
# Volume Groups can also be given a system ID (by vgcreate, vgchange,
@@ -1511,12 +1535,14 @@ activation {
# Configuration option activation/reserved_stack.
# Stack size in KiB to reserve for use while devices are suspended.
# Insufficient reserve risks I/O deadlock during device suspension.
# Value 0 disables memory locking.
# This configuration option has an automatic default value.
# reserved_stack = 64
# Configuration option activation/reserved_memory.
# Memory size in KiB to reserve for use while devices are suspended.
# Insufficient reserve risks I/O deadlock during device suspension.
# Value 0 disables memory locking.
# This configuration option has an automatic default value.
# reserved_memory = 8192
@@ -1865,7 +1891,7 @@ activation {
# uses are present. Other PVs in the Volume Group may be missing.
# degraded
# Like complete, but additionally RAID LVs of segment type raid1,
# raid4, raid5, radid6 and raid10 will be activated if there is no
# raid4, raid5, raid6 and raid10 will be activated if there is no
# data loss, i.e. they have sufficient redundancy to present the
# entire addressable range of the Logical Volume.
# partial
@@ -1989,7 +2015,7 @@ report {
# If there is more than one report per command, then the format
# is applied for all reports. You can also change output format
# directly on command line using --reportformat option which
# has precedence over log/output_format setting.
# has precedence over report/output_format setting.
# Accepted values:
# basic
# Original format with columns and rows. If there is more than
@@ -2003,6 +2029,7 @@ report {
# - it does not use double quotes around numeric values,
# - it uses 'null' for undefined numeric values,
# - it prints string list as proper JSON array of strings instead of a single string.
# Note that if json or json_std output format is used, then log/command_log_report=1 is default.
# This configuration option has an automatic default value.
# output_format = "basic"
@@ -2125,7 +2152,7 @@ report {
# %F
# Equivalent to %Y-%m-%d (the ISO 8601 date format).
# %G
# The ISO 8601 week-based year with century as adecimal number.
# The ISO 8601 week-based year with century as a decimal number.
# The 4-digit year corresponding to the ISO week number (see %V).
# This has the same format and value as %Y, except that if the
# ISO week number belongs to the previous or next year, that year

View File

@@ -38,6 +38,14 @@ local {
# This configuration option has an automatic default value.
# system_id = ""
# Configuration option local/pr_key.
# The local persistent reservation key in hexadecimal.
# The value must be unique among all hosts using the same VG.
# The max length is 16 hex characters (8 bytes), plus an optional
# 0x prefix. If pr_key is not set, host_id will be used to create a key.
# This configuration option has an automatic default value.
# pr_key = ""
# Configuration option local/extra_system_ids.
# A list of extra VG system IDs the local host can access.
# VGs with the system IDs listed here (in addition to the host's own
@@ -49,9 +57,12 @@ local {
# This configuration option does not have a default value defined.
# Configuration option local/host_id.
# The lvmlockd sanlock host_id.
# This must be unique among all hosts, and must be between 1 and 2000.
# Applicable only if LVM is compiled with lockd support
# The sanlock host_id used by lvmlockd. This must be unique among all the hosts
# using shared VGs with sanlock. Accepted values are 1-2000, except when sanlock_align_size
# is configured to 1, 2 or 4, which correspond to max host_id values of 250, 500, or 1000.
# When using persistent reservations, lvm will generate a PR key from the host_id
# if pr_key is not defined. All hosts using a sanlock shared VG with PR must use
# the same approach for configuring their PR key (pr_key or host_id.)
# This configuration option has an automatic default value.
# host_id = 0
}

View File

@@ -4,7 +4,6 @@
allocation {
vdo_use_compression=1
vdo_use_deduplication=1
vdo_use_metadata_hints=1
vdo_minimum_io_size=4096
vdo_block_map_cache_size_mb=128
vdo_block_map_period=16380
@@ -18,6 +17,5 @@ allocation {
vdo_hash_zone_threads=1
vdo_logical_threads=1
vdo_physical_threads=1
vdo_write_policy="auto"
vdo_max_discard=1
}

337
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
@@ -3761,7 +3776,7 @@ case "$host_os" in #(
LVMIMPORTVDO="no"
BLKDEACTIVATE="no" ;; #(
*) :
CLDFLAGS="${CLDFLAGS-"$LDFLAGS"}" ;;
;;
esac
################################################################################
@@ -9065,9 +9080,9 @@ printf "%s\n" "$ac_cv_flag_HAVE_PIE" >&6; }
ac_save_LDFLAGS=$LDFLAGS
LDFLAGS=-Wl,-z,relro,-z,now
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -Wl,-z,relro,-z,now ld flags" >&5
printf %s "checking whether $CC accepts -Wl,-z,relro,-z,now ld flags... " >&6; }
LDFLAGS=-Wl,-z,relro,-z,now,-z,pack-relative-relocs,--as-needed
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -Wl,-z,relro,-z,now,-z,pack-relative-relocs,--as-needed ld flags" >&5
printf %s "checking whether $CC accepts -Wl,-z,relro,-z,now,-z,pack-relative-relocs,--as-needed ld flags... " >&6; }
if test ${ac_cv_flag_HAVE_FULL_RELRO+y}
then :
printf %s "(cached) " >&6
@@ -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 :
@@ -10929,7 +10954,7 @@ printf "%s\n" "#define VDO_FORMAT_CMD \"$VDO_FORMAT_CMD\"" >>confdefs.h
#
# Do we need to use the API??
# Do we want to link lvm2 with a big library for vdoformatting ?
# Do we want to link lvm2 with a big library for VDO formatting ?
#
#AC_ARG_WITH(vdo-include,
# AS_HELP_STRING([--with-vdo-include=PATH],
@@ -11286,6 +11311,9 @@ printf "%s\n" "no" >&6; }
PKG_CONFIG=""
fi
fi
if test -z "$PKG_CONFIG"; then
as_fn_error $? "pkg-config not found" "$LINENO" 5
fi
if test "$BUILD_CMIRRORD" = "yes" && test "$HAVE_CPG" != "yes"
then :
@@ -11577,7 +11605,7 @@ printf "%s\n" "#define GNU_SYMVER 1" >>confdefs.h
case "$host_os" in #(
linux*) :
CLDFLAGS="${CLDFLAGS-"$LDFLAGS"} -Wl,--version-script,.export.sym"
CLDFLAGS="-Wl,--version-script,.export.sym"
LDDEPS="$LDDEPS .export.sym" ;; #(
*) :
;;
@@ -12146,6 +12174,23 @@ printf "%s\n" "$BUILD_LOCKDSANLOCK" >&6; }
if test "$BUILD_LOCKDSANLOCK" = "yes"
then :
LOCKDSANLOCK_SUPPORT=370
if test -n "$PKG_CONFIG" && \
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsanlock_client >= 4.0.0\""; } >&5
($PKG_CONFIG --exists --print-errors "libsanlock_client >= 4.0.0") 2>&5
ac_status=$?
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
LOCKDSANLOCK_SUPPORT=400
fi
if test -n "$PKG_CONFIG" && \
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsanlock_client >= 4.1.0\""; } >&5
($PKG_CONFIG --exists --print-errors "libsanlock_client >= 4.1.0") 2>&5
ac_status=$?
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
LOCKDSANLOCK_SUPPORT=410
fi
pkg_failed=no
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for libsanlock_client >= 3.7.0" >&5
@@ -12238,7 +12283,7 @@ printf "%s\n" "yes" >&6; }
BUILD_LVMLOCKD="yes"
fi
printf "%s\n" "#define LOCKDSANLOCK_SUPPORT 1" >>confdefs.h
printf "%s\n" "#define LOCKDSANLOCK_SUPPORT $LOCKDSANLOCK_SUPPORT" >>confdefs.h
fi
@@ -12721,9 +12766,18 @@ SYSTEMD_MIN_VERSION=0
NOTIFYDBUS_SUPPORT="no"
SYSTEMD_JOURNAL_SUPPORT="no"
APP_MACHINEID_SUPPORT="no"
SD_NOTIFY_SUPPORT="no"
if test "$with_systemd" = "yes"
then :
if test -n "$PKG_CONFIG" && \
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"systemd >= 218\""; } >&5
($PKG_CONFIG --exists --print-errors "systemd >= 218") 2>&5
ac_status=$?
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
SYSTEMD_MIN_VERSION=218 SD_NOTIFY_SUPPORT="maybe"
fi
if test -n "$PKG_CONFIG" && \
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"systemd >= 221\""; } >&5
($PKG_CONFIG --exists --print-errors "systemd >= 221") 2>&5
ac_status=$?
@@ -12811,6 +12865,41 @@ printf "%s\n" "#define APP_MACHINEID_SUPPORT 1" >>confdefs.h
fi
################################################################################
if test "$SD_NOTIFY_SUPPORT" != "no"
then :
ac_fn_c_check_header_compile "$LINENO" "systemd/sd-daemon.h" "ac_cv_header_systemd_sd_daemon_h" "$ac_includes_default"
if test "x$ac_cv_header_systemd_sd_daemon_h" = xyes
then :
SD_NOTIFY_SUPPORT="yes"
else case e in #(
e) SD_NOTIFY_SUPPORT="no" ;;
esac
fi
fi
# Check whether --enable-sd-notify was given.
if test ${enable_sd_notify+y}
then :
enableval=$enable_sd_notify; if test "$enableval" = "yes" && test "$SD_NOTIFY_SUPPORT" = "no"
then :
as_fn_error $? "--enable-sd-notify requires systemd/sd-daemon.h. (--with-systemd=$with_systemd)" "$LINENO" 5
fi
SD_NOTIFY_SUPPORT=$enableval
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to enable to sd_notify" >&5
printf %s "checking whether to enable to sd_notify... " >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $SD_NOTIFY_SUPPORT" >&5
printf "%s\n" "$SD_NOTIFY_SUPPORT" >&6; }
if test "$SD_NOTIFY_SUPPORT" = "yes"
then :
printf "%s\n" "#define SD_NOTIFY_SUPPORT 1" >>confdefs.h
fi
################################################################################
# Check whether --with-systemd-run was given.
@@ -13126,6 +13215,181 @@ printf "%s\n" "$BLKID_WIPING" >&6; }
printf "%s\n" "#define DEFAULT_USE_BLKID_WIPING $DEFAULT_USE_BLKID_WIPING" >>confdefs.h
################################################################################
# Check whether --enable-nvme-wwid was given.
if test ${enable_nvme_wwid+y}
then :
enableval=$enable_nvme_wwid; NVME_WWID=$enableval
else case e in #(
e) if test "$with_libnvme" = "yes"
then :
NVME_WWID="maybe"
else case e in #(
e) NVME_WWID="no" ;;
esac
fi ;;
esac
fi
# ATM NVME_WWID is the only user of libnvme, so skip checking for libnvme when disabled
if test "$NVME_WWID" = "no"
then :
with_libnvme="no"
fi
if test "$with_libnvme" = "yes"
then :
pkg_failed=no
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for libnvme >= 1.4" >&5
printf %s "checking for libnvme >= 1.4... " >&6; }
if test -n "$LIBNVME_CFLAGS"; then
pkg_cv_LIBNVME_CFLAGS="$LIBNVME_CFLAGS"
elif test -n "$PKG_CONFIG"; then
if test -n "$PKG_CONFIG" && \
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libnvme >= 1.4\""; } >&5
($PKG_CONFIG --exists --print-errors "libnvme >= 1.4") 2>&5
ac_status=$?
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
pkg_cv_LIBNVME_CFLAGS=`$PKG_CONFIG --cflags "libnvme >= 1.4" 2>/dev/null`
test "x$?" != "x0" && pkg_failed=yes
else
pkg_failed=yes
fi
else
pkg_failed=untried
fi
if test -n "$LIBNVME_LIBS"; then
pkg_cv_LIBNVME_LIBS="$LIBNVME_LIBS"
elif test -n "$PKG_CONFIG"; then
if test -n "$PKG_CONFIG" && \
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libnvme >= 1.4\""; } >&5
($PKG_CONFIG --exists --print-errors "libnvme >= 1.4") 2>&5
ac_status=$?
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
pkg_cv_LIBNVME_LIBS=`$PKG_CONFIG --libs "libnvme >= 1.4" 2>/dev/null`
test "x$?" != "x0" && pkg_failed=yes
else
pkg_failed=yes
fi
else
pkg_failed=untried
fi
if test $pkg_failed = yes; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
_pkg_short_errors_supported=yes
else
_pkg_short_errors_supported=no
fi
if test $_pkg_short_errors_supported = yes; then
LIBNVME_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libnvme >= 1.4" 2>&1`
else
LIBNVME_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libnvme >= 1.4" 2>&1`
fi
# Put the nasty error message in config.log where it belongs
echo "$LIBNVME_PKG_ERRORS" >&5
if test "$NVME_WWID" = "yes"
then :
NVME_WWID="error"
else case e in #(
e) NVME_WWID="no" ;;
esac
fi
elif test $pkg_failed = untried; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
if test "$NVME_WWID" = "yes"
then :
NVME_WWID="error"
else case e in #(
e) NVME_WWID="no" ;;
esac
fi
else
LIBNVME_CFLAGS=$pkg_cv_LIBNVME_CFLAGS
LIBNVME_LIBS=$pkg_cv_LIBNVME_LIBS
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
printf "%s\n" "yes" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for NVME_NIDT_CSI in libnvme.h" >&5
printf %s "checking for NVME_NIDT_CSI in libnvme.h... " >&6; }
if test ${ac_cv_have_libnvme_csi+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <libnvme.h>
const int a = NVME_NIDT_CSI;
int
main (void)
{
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
ac_cv_have_libnvme_csi="yes"
else case e in #(
e) ac_cv_have_libnvme_csi="no" ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_libnvme_csi" >&5
printf "%s\n" "$ac_cv_have_libnvme_csi" >&6; }
if test "$NVME_WWID" != "no"
then :
if test $ac_cv_have_libnvme_csi = yes
then :
NVME_WWID="yes"
printf "%s\n" "#define NVME_SUPPORT 1" >>confdefs.h
else case e in #(
e) NVME_WWID="error" ;;
esac
fi
fi
fi
else case e in #(
e) if test "$NVME_WWID" = "yes"
then :
NVME_WWID="error"
fi ;;
esac
fi
if test "$NVME_WWID" = "error"
then :
as_fn_error $? "--enable-nvme-wwid requires libnvme library >= 1.1. (--with-libnvme=$with_libnvme)" "$LINENO" 5
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to use libnvme for alternate WWIDs" >&5
printf %s "checking whether to use libnvme for alternate WWIDs... " >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $NVME_WWID" >&5
printf "%s\n" "$NVME_WWID" >&6; }
################################################################################
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to enable synchronization with udev processing" >&5
printf %s "checking whether to enable synchronization with udev processing... " >&6; }
@@ -13424,7 +13688,11 @@ printf "%s\n" "$BUILD_LVMDBUSD" >&6; }
# Check whether --enable-notify-dbus was given.
if test ${enable_notify_dbus+y}
then :
enableval=$enable_notify_dbus; NOTIFYDBUS_SUPPORT=$enableval
enableval=$enable_notify_dbus; if test "enableval" = "yes" && test "$NOTIFYDBUS_SUPPORT" = "no"
then :
as_fn_error $? "--enable-notify-dbus requires systemd >= 221. (--with-systemd=$with_systemd)" "$LINENO" 5
fi
NOTIFYDBUS_SUPPORT=$enableval
fi
@@ -13441,10 +13709,6 @@ fi
if test "$NOTIFYDBUS_SUPPORT" = "yes"
then :
if test "$SYSTEMD_MIN_VERSION" -lt 221
then :
as_fn_error $? "--enable-notify-dbus requires systemd >= 221. (--with-systemd=$with_systemd)" "$LINENO" 5
fi
printf "%s\n" "#define NOTIFYDBUS_SUPPORT 1" >>confdefs.h
@@ -13456,10 +13720,10 @@ printf %s "checking whether to build notifydbus... " >&6; }
printf "%s\n" "$NOTIFYDBUS_SUPPORT" >&6; }
################################################################################
if test "$NOTIFYDBUS_SUPPORT" = "yes" || test "$SYSTEMD_JOURNAL_SUPPORT" = "yes" || test "$APP_MACHINEID_SUPPORT" = "yes"
if test "$NOTIFYDBUS_SUPPORT" = "yes" || test "$SYSTEMD_JOURNAL_SUPPORT" = "yes" ||
test "$APP_MACHINEID_SUPPORT" = "yes" || test "$SD_NOTIFY_SUPPORT" = "yes"
then :
pkg_failed=no
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for libsystemd" >&5
printf %s "checking for libsystemd... " >&6; }
@@ -13550,7 +13814,6 @@ else
printf "%s\n" "yes" >&6; }
fi
fi
################################################################################
@@ -13877,7 +14140,21 @@ try:
if python_implementation() == 'CPython' and sys.version[:3] == '2.7':
can_use_sysconfig = 0
except ImportError:
pass"
pass" # end of am_python_setup_sysconfig
# More repeated code, for figuring out the installation scheme to use.
am_python_setup_scheme="if hasattr(sysconfig, 'get_default_scheme'):
scheme = sysconfig.get_default_scheme()
else:
scheme = sysconfig._get_default_scheme()
if scheme == 'posix_local':
if '$am_py_prefix' == '/usr':
scheme = 'deb_system' # should only happen during Debian package builds
else:
# Debian's default scheme installs to /usr/local/ but we want to
# follow the prefix, as we always have.
# See bugs#54412, #64837, et al.
scheme = 'posix_prefix'" # end of am_python_setup_scheme
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON script directory (pythondir)" >&5
@@ -13894,7 +14171,11 @@ else case e in #(
am_cv_python_pythondir=`$PYTHON -c "
$am_python_setup_sysconfig
if can_use_sysconfig:
sitedir = sysconfig.get_path('purelib', vars={'base':'$am_py_prefix'})
try:
$am_python_setup_scheme
sitedir = sysconfig.get_path('purelib', scheme, vars={'base':'$am_py_prefix'})
except:
sitedir = sysconfig.get_path('purelib', vars={'base':'$am_py_prefix'})
else:
from distutils import sysconfig
sitedir = sysconfig.get_python_lib(0, 0, prefix='$am_py_prefix')
@@ -13924,7 +14205,7 @@ printf "%s\n" "$am_cv_python_pythondir" >&6; }
pkgpythondir=\${pythondir}/$PACKAGE
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON extension module directory (pyexecdir)" >&5
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON extension module directory (pyexecdir)" >&5
printf %s "checking for $am_display_PYTHON extension module directory (pyexecdir)... " >&6; }
if test ${am_cv_python_pyexecdir+y}
then :
@@ -13938,7 +14219,11 @@ else case e in #(
am_cv_python_pyexecdir=`$PYTHON -c "
$am_python_setup_sysconfig
if can_use_sysconfig:
sitedir = sysconfig.get_path('platlib', vars={'platbase':'$am_py_exec_prefix'})
try:
$am_python_setup_scheme
sitedir = sysconfig.get_path('platlib', scheme, vars={'platbase':'$am_py_exec_prefix'})
except:
sitedir = sysconfig.get_path('platlib', vars={'platbase':'$am_py_exec_prefix'})
else:
from distutils import sysconfig
sitedir = sysconfig.get_python_lib(1, 0, prefix='$am_py_exec_prefix')
@@ -14287,7 +14572,7 @@ printf %s "checking whether to compile liblvm2cmd.so... " >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CMDLIB" >&5
printf "%s\n" "$CMDLIB" >&6; }
if test "$CMDLIB" == "yes" && test "$SHARED_LINK" = "no"
if test "$CMDLIB" = "yes" && test "$SHARED_LINK" = "no"
then :
as_fn_error $? "--enable-cmdlib requires dynamic linking." "$LINENO" 5
fi
@@ -16218,6 +16503,11 @@ LVRESIZE_FS_HELPER_PATH="$LIBEXECDIR/lvresize_fs_helper"
printf "%s\n" "#define LVRESIZE_FS_HELPER_PATH \"$LVRESIZE_FS_HELPER_PATH\"" >>confdefs.h
LVMPERSIST_PATH="$SBINDIR/lvmpersist"
printf "%s\n" "#define LVMPERSIST_PATH \"$LVMPERSIST_PATH\"" >>confdefs.h
################################################################################
# Check whether --with-dmeventd-pidfile was given.
@@ -16561,6 +16851,7 @@ AIO_LIBS=${AIO_LIBS:--laio}
################################################################################
@@ -17958,3 +18249,9 @@ then :
printf "%s\n" "$as_me: WARNING: Building D-Bus support without D-Bus notifications!" >&2;}
fi
if test "$BUILD_LVMLOCKD" = "yes" && test "$SD_NOTIFY_SUPPORT" = "no"
then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Building lvmlockd without sd-notify support may block!" >&5
printf "%s\n" "$as_me: WARNING: Building lvmlockd without sd-notify support may block!" >&2;}
fi

View File

@@ -1,4 +1,3 @@
###############################################################################
## Copyright (C) 2000-2004 Sistina Software, Inc. All rights reserved.
## Copyright (C) 2004-2023 Red Hat, Inc. All rights reserved.
##
@@ -20,7 +19,7 @@ AC_CONFIG_SRCDIR([lib/device/dev-cache.h])
AC_CONFIG_HEADERS([include/configure.h])
################################################################################
dnl -- Setup the directory where autoconf has auxilary files
dnl -- Setup the directory where autoconf has auxiliary files
AC_CONFIG_AUX_DIR(autoconf)
################################################################################
@@ -57,7 +56,7 @@ AS_CASE(["$host_os"],
FSADM="no"
LVMIMPORTVDO="no"
BLKDEACTIVATE="no"],
[CLDFLAGS="${CLDFLAGS-"$LDFLAGS"}"])
[])
################################################################################
dnl -- Checks for programs.
@@ -199,7 +198,7 @@ AC_MSG_RESULT([$SHARED_LINK])
dnl -- Check if compiler/linker supports PIE and RELRO
AC_TRY_CCFLAG([-pie], [HAVE_PIE], [], [])
AC_SUBST(HAVE_PIE)
AC_TRY_LDFLAGS([-Wl,-z,relro,-z,now], [HAVE_FULL_RELRO], [], [])
AC_TRY_LDFLAGS([-Wl,-z,relro,-z,now,-z,pack-relative-relocs,--as-needed], [HAVE_FULL_RELRO], [], [])
AC_SUBST(HAVE_FULL_RELRO)
################################################################################
@@ -217,6 +216,8 @@ test "$exec_prefix" = "NONE" && exec_prefix='${prefix}'
AC_ARG_WITH(blkid, [AS_HELP_STRING([--without-blkid], [do not build with blkid library])],
[], with_blkid="yes")
AC_ARG_WITH(libnvme, [AS_HELP_STRING([--without-libnvme], [do not build with libnvme library])],
[], with_libnvme="yes")
AC_ARG_WITH(systemd, [AS_HELP_STRING([--without-systemd], [do not build with systemd library])],
[], with_systemd="yes")
AC_ARG_WITH(udev, [AS_HELP_STRING([--without-udev], [do not build with udev library])],
@@ -656,7 +657,7 @@ AC_DEFINE_UNQUOTED([VDO_FORMAT_CMD], ["$VDO_FORMAT_CMD"],
[The path to 'vdoformat', if available.])
#
# Do we need to use the API??
# Do we want to link lvm2 with a big library for vdoformatting ?
# Do we want to link lvm2 with a big library for VDO formatting ?
#
#AC_ARG_WITH(vdo-include,
# AS_HELP_STRING([--with-vdo-include=PATH],
@@ -836,7 +837,7 @@ AS_IF([test "$GCC" = "yes" && test "$symvers" = "gnu"], [
[Define to use GNU versioning in the shared library.])
AS_CASE(["$host_os"],
[linux*], [
CLDFLAGS="${CLDFLAGS-"$LDFLAGS"} -Wl,--version-script,.export.sym"
CLDFLAGS="-Wl,--version-script,.export.sym"
LDDEPS="$LDDEPS .export.sym"])
])
@@ -933,8 +934,11 @@ AC_MSG_RESULT([$BUILD_LOCKDSANLOCK])
dnl -- Look for sanlock libraries
AS_IF([test "$BUILD_LOCKDSANLOCK" = "yes"], [
LOCKDSANLOCK_SUPPORT=370
PKG_CHECK_EXISTS(libsanlock_client >= 4.0.0, [LOCKDSANLOCK_SUPPORT=400])
PKG_CHECK_EXISTS(libsanlock_client >= 4.1.0, [LOCKDSANLOCK_SUPPORT=410])
PKG_CHECK_MODULES(LIBSANLOCKCLIENT, libsanlock_client >= 3.7.0, [BUILD_LVMLOCKD="yes"])
AC_DEFINE([LOCKDSANLOCK_SUPPORT], 1, [Define to 1 to include code that uses lvmlockd sanlock option.])
AC_DEFINE_UNQUOTED([LOCKDSANLOCK_SUPPORT], [$LOCKDSANLOCK_SUPPORT], [Define version of sanlock.])
])
################################################################################
@@ -952,7 +956,7 @@ AS_IF([test "$BUILD_LOCKDDLM" = "yes"], [
AC_DEFINE([LOCKDDLM_SUPPORT], 1, [Define to 1 to include code that uses lvmlockd dlm option.])
AS_CASE(["$LIBDLM_LIBS"],
[*lpthread*], [
dnl -- pkg-congig for libdlm_lt may give us libdlm with libpthread
dnl -- pkg-config for libdlm_lt may give us libdlm with libpthread
AC_MSG_RESULT([replacing pkg-config --libs libdlm_lt "$LIBDLM_LIBS" with... -ldlm_lt])
LIBDLM_LIBS="${LIBDLM_LIBS%%ldlm*}ldlm_lt"])
])
@@ -1046,7 +1050,9 @@ SYSTEMD_MIN_VERSION=0
NOTIFYDBUS_SUPPORT="no"
SYSTEMD_JOURNAL_SUPPORT="no"
APP_MACHINEID_SUPPORT="no"
SD_NOTIFY_SUPPORT="no"
AS_IF([test "$with_systemd" = "yes"],
PKG_CHECK_EXISTS(systemd >= 218, [SYSTEMD_MIN_VERSION=218 SD_NOTIFY_SUPPORT="maybe"])
PKG_CHECK_EXISTS(systemd >= 221, [SYSTEMD_MIN_VERSION=221 NOTIFYDBUS_SUPPORT="maybe" SYSTEMD_JOURNAL_SUPPORT="maybe"])
PKG_CHECK_EXISTS(systemd >= 234, [SYSTEMD_MIN_VERSION=234 APP_MACHINEID_SUPPORT="maybe"]))
@@ -1082,6 +1088,22 @@ AC_MSG_RESULT([$APP_MACHINEID_SUPPORT])
AS_IF([test "$APP_MACHINEID_SUPPORT" = "yes"],
AC_DEFINE([APP_MACHINEID_SUPPORT], 1, [Define to 1 to include code that uses libsystemd machine-id apis.]))
################################################################################
dnl -- Build with sd_notify when the header file sd-daemon.h is present
AS_IF([test "$SD_NOTIFY_SUPPORT" != "no"],
AC_CHECK_HEADER([systemd/sd-daemon.h], [SD_NOTIFY_SUPPORT="yes"], [SD_NOTIFY_SUPPORT="no"]))
AC_ARG_ENABLE(sd-notify,
AS_HELP_STRING([--disable-sd-notify],
[disable LVM sd_notify]),
AS_IF([test "$enableval" = "yes" && test "$SD_NOTIFY_SUPPORT" = "no"],
AC_MSG_ERROR([--enable-sd-notify requires systemd/sd-daemon.h. (--with-systemd=$with_systemd)]))
SD_NOTIFY_SUPPORT=$enableval, [])
AC_MSG_CHECKING([whether to enable to sd_notify])
AC_MSG_RESULT([$SD_NOTIFY_SUPPORT])
AS_IF([test "$SD_NOTIFY_SUPPORT" = "yes"],
AC_DEFINE([SD_NOTIFY_SUPPORT], 1, [Define to 1 to include code that uses sd_notify.]))
################################################################################
dnl -- Support override for systemd-run path if they need to (NixOS builds)
AC_ARG_WITH(systemd-run,
@@ -1139,6 +1161,38 @@ AC_MSG_RESULT([$BLKID_WIPING])
AC_DEFINE_UNQUOTED(DEFAULT_USE_BLKID_WIPING, [$DEFAULT_USE_BLKID_WIPING],
[Use blkid wiping by default.])
################################################################################
dnl -- Enable nvme alternate WWID via libnvme
AC_ARG_ENABLE(nvme-wwid,
AS_HELP_STRING([--disable-nvme-wwid],
[do not use libnvme to detect alternate WWIDs]),
NVME_WWID=$enableval,
[AS_IF([test "$with_libnvme" = "yes"], [NVME_WWID="maybe"], [NVME_WWID="no"])])
# ATM NVME_WWID is the only user of libnvme, so skip checking for libnvme when disabled
AS_IF([test "$NVME_WWID" = "no"], [with_libnvme="no"])
AS_IF([test "$with_libnvme" = "yes"], [
PKG_CHECK_MODULES([LIBNVME], [libnvme >= 1.4], [
AC_CACHE_CHECK([for NVME_NIDT_CSI in libnvme.h],
[ac_cv_have_libnvme_csi],
[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include <libnvme.h>
const int a = NVME_NIDT_CSI;
])], [ac_cv_have_libnvme_csi="yes"], [ac_cv_have_libnvme_csi="no"])])
AS_IF([test "$NVME_WWID" != "no"], [
AC_IF_YES(ac_cv_have_libnvme_csi, [NVME_WWID="yes"
AC_DEFINE(NVME_SUPPORT, 1, [Use libnvme for WWID.])],
[NVME_WWID="error"])])
], [AS_IF([test "$NVME_WWID" = "yes"], [NVME_WWID="error"], [NVME_WWID="no"])])
], [AS_IF([test "$NVME_WWID" = "yes"], [NVME_WWID="error"])])
AS_IF([test "$NVME_WWID" = "error"],
[AC_MSG_ERROR([--enable-nvme-wwid requires libnvme library >= 1.1. (--with-libnvme=$with_libnvme)])])
AC_MSG_CHECKING([whether to use libnvme for alternate WWIDs])
AC_MSG_RESULT([$NVME_WWID])
################################################################################
dnl -- Enable udev synchronization
AC_MSG_CHECKING([whether to enable synchronization with udev processing])
@@ -1231,24 +1285,25 @@ AC_MSG_RESULT([$BUILD_LVMDBUSD])
dnl -- Build notifydbus
AC_ARG_ENABLE(notify-dbus,
[AS_HELP_STRING([--enable-notify-dbus], [enable LVM notification using dbus])],
[NOTIFYDBUS_SUPPORT=$enableval])
[AS_IF([test "enableval" = "yes" && test "$NOTIFYDBUS_SUPPORT" = "no"],
[AC_MSG_ERROR([--enable-notify-dbus requires systemd >= 221. (--with-systemd=$with_systemd)])])
NOTIFYDBUS_SUPPORT=$enableval])
AS_IF([test "$NOTIFYDBUS_SUPPORT" = "maybe"],
[AS_IF([test "$BUILD_LVMDBUSD" = "yes"], [NOTIFYDBUS_SUPPORT="yes"], [NOTIFYDBUS_SUPPORT="no"])])
[AS_IF([test "$BUILD_LVMDBUSD" = "yes"],
[NOTIFYDBUS_SUPPORT="yes"], [NOTIFYDBUS_SUPPORT="no"])])
AS_IF([test "$NOTIFYDBUS_SUPPORT" = "yes"],
[AS_IF([test "$SYSTEMD_MIN_VERSION" -lt 221],
[AC_MSG_ERROR([--enable-notify-dbus requires systemd >= 221. (--with-systemd=$with_systemd)])])
AC_DEFINE([NOTIFYDBUS_SUPPORT], 1, [Define to 1 to include code that uses dbus notification.])])
[AC_DEFINE([NOTIFYDBUS_SUPPORT], 1, [Define to 1 to include code that uses dbus notification.])])
AC_MSG_CHECKING([whether to build notifydbus])
AC_MSG_RESULT([$NOTIFYDBUS_SUPPORT])
################################################################################
dnl -- Look for libsystemd libraries if needed
AS_IF([test "$NOTIFYDBUS_SUPPORT" = "yes" || test "$SYSTEMD_JOURNAL_SUPPORT" = "yes" || test "$APP_MACHINEID_SUPPORT" = "yes"], [
PKG_CHECK_MODULES(LIBSYSTEMD, [libsystemd])
])
AS_IF([test "$NOTIFYDBUS_SUPPORT" = "yes" || test "$SYSTEMD_JOURNAL_SUPPORT" = "yes" ||
test "$APP_MACHINEID_SUPPORT" = "yes" || test "$SD_NOTIFY_SUPPORT" = "yes"],
[PKG_CHECK_MODULES(LIBSYSTEMD, [libsystemd])])
################################################################################
dnl -- Enable Python dbus library
@@ -1341,7 +1396,7 @@ AS_IF([test "$CMDLIB" != "yes"], [CMDLIB="no" LVM2CMD_LIB=], [LVM2CMD_LIB="-llvm
AC_MSG_CHECKING([whether to compile liblvm2cmd.so])
AC_MSG_RESULT([$CMDLIB])
AS_IF([test "$CMDLIB" == "yes" && test "$SHARED_LINK" = "no"],
AS_IF([test "$CMDLIB" = "yes" && test "$SHARED_LINK" = "no"],
[AC_MSG_ERROR([--enable-cmdlib requires dynamic linking.])])
@@ -1717,6 +1772,9 @@ LIBEXECDIR="$(eval echo $(eval echo $libexecdir))"
LVRESIZE_FS_HELPER_PATH="$LIBEXECDIR/lvresize_fs_helper"
AC_DEFINE_UNQUOTED(LVRESIZE_FS_HELPER_PATH, ["$LVRESIZE_FS_HELPER_PATH"], [Path to lvresize_fs_helper script.])
LVMPERSIST_PATH="$SBINDIR/lvmpersist"
AC_DEFINE_UNQUOTED(LVMPERSIST_PATH, ["$LVMPERSIST_PATH"], [Path to lvmpersist script.])
################################################################################
dnl -- dmeventd pidfile and executable path
AC_ARG_WITH(dmeventd-pidfile,
@@ -1938,6 +1996,7 @@ AC_SUBST(PYTHON3)
AC_SUBST(PYTHON3DIR)
AC_SUBST(RT_LIBS)
AC_SUBST(SBINDIR)
AC_SUBST(SD_NOTIFY_SUPPORT)
AC_SUBST(SELINUX_LIBS)
AC_SUBST(SELINUX_PC)
AC_SUBST(SELINUX_STATIC_LIBS)
@@ -2075,3 +2134,6 @@ AS_IF([test "$ODIRECT" != "yes"],
AS_IF([test "$BUILD_LVMDBUSD" = "yes" && test "$NOTIFYDBUS_SUPPORT" = "no"],
[AC_MSG_WARN([Building D-Bus support without D-Bus notifications!])])
AS_IF([test "$BUILD_LVMLOCKD" = "yes" && test "$SD_NOTIFY_SUPPORT" = "no"],
[AC_MSG_WARN([Building lvmlockd without sd-notify support may block!])])

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2015 Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2025 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
@@ -21,128 +21,295 @@
* compile (using outdir 'cov'):
* cov-build --dir=cov make CC=gcc
*
* analyze (agressively, using 'cov')
* analyze (aggressively, using 'cov')
* cov-analyze --dir cov --wait-for-license --hfa --concurrency --enable-fnptr --enable-constraint-fpp --security --all --aggressiveness-level=high --field-offset-escape --user-model-file=coverity/coverity_model.xml
*
* generate html output (to 'html' from 'cov'):
* cov-format-errors --dir cov --html-output html
*/
/* Define NULL for Coverity modeling */
#define NULL ((void *)0)
/* Forward declarations */
struct lv_segment;
struct logical_volume;
struct segment_type;
struct cmd_context;
struct profile;
struct dm_pool;
struct dm_list;
/*
* These functions never return NULL for valid LVs with segments
*/
struct lv_segment *first_seg(const struct logical_volume *lv)
{
return ((struct lv_segment **)lv)[0];
struct lv_segment *seg;
/* Model: assume lv is valid and has at least one segment */
if (lv) {
__coverity_read_pointee__(lv);
return seg;
}
__coverity_panic__(); /* Should never happen in valid code */
}
struct lv_segment *last_seg(const struct logical_volume *lv)
{
return ((struct lv_segment **)lv)[0];
}
struct lv_segment *seg;
const char *find_config_tree_str(struct cmd_context *cmd, int id, struct profile *profile)
{
return "STRING";
}
/*
struct logical_volume *origin_from_cow(const struct logical_volume *lv)
{
if (lv)
return lv;
if (lv) {
__coverity_read_pointee__(lv);
return seg;
}
__coverity_panic__();
}
*/
/* simple_memccpy() from glibc */
void *memccpy(void *dest, const void *src, int c, size_t n)
{
const char *s = src;
char *d = dest;
while (n-- > 0)
if ((*d++ = *s++) == (char) c)
return d;
return 0;
}
/*
* 2 lines bellow needs to be placed in coverity/config/user_nodefs.h
* Not sure about any other way.
* Without them, coverity shows warning since x86 system header files
* are using inline assembly to reset fdset
*/
//#nodef FD_ZERO model_FD_ZERO
//void model_FD_ZERO(void *fdset);
void model_FD_ZERO(void *fdset)
{
unsigned i;
for (i = 0; i < 1024 / 8 / sizeof(long); ++i)
((long*)fdset)[i] = 0;
}
/* Resent Coverity reports quite weird errors... */
int *__errno_location(void)
{
}
const unsigned short **__ctype_b_loc (void)
{
}
/*
* Added extra pointer check to not need these models,
* for now just keep then in file
*/
/*
struct cmd_context;
struct profile;
const char *find_config_tree_str(struct cmd_context *cmd, int id, struct profile *profile)
{
return "text";
char *str;
__coverity_read_pointee__(cmd);
if (str)
return str;
__coverity_panic__();
}
const char *find_config_tree_str_allow_empty(struct cmd_context *cmd, int id, struct profile *profile)
{
return "text";
}
*/
char *str;
/*
* Until fixed coverity case# 00531860:
* A FORWARD_NULL false positive on a recursive function call
*
* model also these functions:
*/
/*
const struct dm_config_node;
const struct dm_config_node *find_config_tree_array(struct cmd_context *cmd, int id, struct profile *profile)
__coverity_read_pointee__(cmd);
if (str)
return str;
__coverity_panic__();
}
struct segment_type *init_unknown_segtype(struct cmd_context *cmd, const char *name)
{
const struct dm_config_node *cn;
struct segment_type *seg_type;
return cn;
__coverity_read_pointee__(cmd);
__coverity_read_pointee__(name);
if (seg_type)
return seg_type;
__coverity_panic__();
}
const struct dm_config_node *find_config_tree_node(struct cmd_context *cmd, int id, struct profile *profile)
/* simple_memccpy() from glibc */
void *memccpy(void *dest, const void *src, int c, unsigned long n)
{
const struct dm_config_node *cn;
int success;
return cn;
__coverity_negative_sink__(n);
__coverity_negative_sink__(c);
__coverity_tainted_data_transitive__(dest, src);
__coverity_write_buffer_bytes__(dest, n);
if (!success)
return NULL;
return dest;
}
int find_config_tree_bool(struct cmd_context *cmd, int id, struct profile *profile)
/* dm_pool_alloc - can return NULL on allocation failure */
void *dm_pool_alloc(struct dm_pool *p, unsigned long s)
{
int b;
void *ptr;
int success;
return b;
if (!p) {
__coverity_panic__();
}
__coverity_negative_sink__(s); /* Catch negative sizes */
if (!success)
return NULL;
ptr = __coverity_alloc__(s);
/* Mark as escaped - pool memory doesn't need individual free */
__coverity_escape__(ptr);
return ptr;
}
/* dm_pool_zalloc - allocates and zeros */
void *dm_pool_zalloc(struct dm_pool *p, unsigned long s)
{
void *ptr;
int success;
if (!p) {
__coverity_panic__();
}
__coverity_negative_sink__(s); /* Catch negative sizes */
if (!success)
return NULL;
ptr = __coverity_alloc__(s);
__coverity_writeall0__(ptr); /* Memory is zeroed */
/* Mark as escaped - pool memory doesn't need individual free */
__coverity_escape__(ptr);
return ptr;
}
/* dm_pool_strdup - duplicates string in pool */
char *dm_pool_strdup(struct dm_pool *p, const char *str)
{
char *ptr;
unsigned long size;
int success;
if (!p || !str) {
__coverity_panic__();
}
__coverity_string_null_sink__(str); /* str must be null-terminated */
__coverity_string_size_sink__(str); /* Coverity tracks the size */
if (!success)
return NULL;
/* Allocate symbolic size - Coverity will track this appropriately */
ptr = __coverity_alloc__(size);
__coverity_tainted_data_transitive__(ptr, str);
/* Mark as escaped - pool memory doesn't need individual free */
__coverity_escape__(ptr);
return ptr;
}
/* dm_pool_strndup - duplicates up to n characters */
char *dm_pool_strndup(struct dm_pool *p, const char *str, unsigned long n)
{
char *ptr;
int success;
if (!p) {
__coverity_panic__();
}
__coverity_string_size_source__(str);
__coverity_negative_sink__(n);
if (!success)
return NULL;
ptr = __coverity_alloc__(n + 1);
__coverity_tainted_data_transitive__(ptr, str);
__coverity_string_null_copy__(ptr, str, n);
/* Mark as escaped - pool memory doesn't need individual free */
__coverity_escape__(ptr);
return ptr;
}
/* dm_pool_free - frees memory back to the pool */
void dm_pool_free(struct dm_pool *p, void *ptr)
{
if (!p || !ptr) {
__coverity_panic__();
}
}
void dm_pool_empty(struct dm_pool *p)
{
if (!p) {
__coverity_panic__();
}
}
/* dm_malloc - standard malloc wrapper */
void *dm_malloc_wrapper(unsigned long s, const char *file, int line)
{
void *ptr;
int success;
__coverity_negative_sink__(s);
if (!success)
return NULL;
ptr = __coverity_alloc__(s);
__coverity_mark_as_afm_allocated__(ptr, AFM_free);
return ptr;
}
/* dm_zalloc - standard calloc wrapper */
void *dm_zalloc_wrapper(unsigned long s, const char *file, int line)
{
void *ptr;
int success;
__coverity_negative_sink__(s);
if (!success)
return NULL;
ptr = __coverity_alloc__(s);
__coverity_mark_as_afm_allocated__(ptr, AFM_free);
__coverity_writeall0__(ptr);
return ptr;
}
/* dm_free - standard free wrapper */
void dm_free_wrapper(void *ptr, const char *file, int line)
{
if (ptr) {
__coverity_free__(ptr);
}
}
/* dm_list_init - initializes a list head */
void dm_list_init(struct dm_list *head)
{
if (head) {
__coverity_writeall__(head);
}
}
/* dm_list_empty - checks if list is empty (never fails) */
int dm_list_empty(const struct dm_list *head)
{
int is_empty;
if (head)
return is_empty;
__coverity_panic__();
}
/* dm_list_add - adds to list (never fails) */
void dm_list_add(struct dm_list *head, struct dm_list *elem)
{
if (!head || !elem) {
__coverity_panic__();
}
/* Modification happens, but no failure */
__coverity_writeall__(head);
__coverity_writeall__(elem);
__coverity_escape__(elem);
}
*/

View File

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

View File

@@ -197,7 +197,7 @@ int cluster_send(struct clog_request *rq)
iov.iov_base = rq;
iov.iov_len = sizeof(struct clog_request) + rq->u_rq.data_size;
rq->u.version[0] = xlate64(CLOG_TFR_VERSION);
rq->u.version[0] = htole64(CLOG_TFR_VERSION);
rq->u.version[1] = CLOG_TFR_VERSION;
r = clog_request_to_network(rq);
@@ -279,7 +279,7 @@ static int handle_cluster_request(struct clog_cpg *entry __attribute__((unused))
* With resumes, we only handle our own.
* Resume is a special case that requires
* local action (to set up CPG), followed by
* a cluster action to co-ordinate reading
* a cluster action to coordinate reading
* the disk and checkpointing
*/
if (tmp->u_rq.request_type == DM_ULOG_RESUME) {

View File

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

View File

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

View File

@@ -254,7 +254,7 @@ static int read_log(struct log_c *lc)
bitset_size = lc->region_count / 8;
bitset_size += (lc->region_count % 8) ? 1 : 0;
/* 'lc->clean_bits + 1' becasue dm_bitset_t leads with a uint32_t */
/* 'lc->clean_bits + 1' because dm_bitset_t leads with a uint32_t */
memcpy(lc->clean_bits + 1, (char *)lc->disk_buffer + 1024, bitset_size);
return 0;
@@ -281,7 +281,7 @@ static int write_log(struct log_c *lc)
bitset_size = lc->region_count / 8;
bitset_size += (lc->region_count % 8) ? 1 : 0;
/* 'lc->clean_bits + 1' becasue dm_bitset_t leads with a uint32_t */
/* 'lc->clean_bits + 1' because dm_bitset_t leads with a uint32_t */
memcpy((char *)lc->disk_buffer + 1024, lc->clean_bits + 1, bitset_size);
if (rw_log(lc, 1)) {
@@ -380,8 +380,8 @@ static int _clog_ctr(char *uuid, uint64_t luid,
int disk_log;
char disk_path[PATH_MAX] = { 0 };
int unlink_path = 0;
long page_size;
int pages;
long ps;
size_t pages, page_size;
/* If core log request, then argv[0] will be region_size */
if (!strtoll(argv[0], &p, 0) || *p) {
@@ -488,14 +488,15 @@ static int _clog_ctr(char *uuid, uint64_t luid,
lc->sync_count = (log_sync == NOSYNC) ? region_count : 0;
if (disk_log) {
if ((page_size = sysconf(_SC_PAGESIZE)) < 0) {
if (((ps = sysconf(_SC_PAGESIZE)) <= 0) ||
(ps > (1 << 24))) {
LOG_ERROR("Unable to read pagesize: %s",
strerror(errno));
r = errno;
goto fail;
}
pages = *(lc->clean_bits) / page_size;
pages += *(lc->clean_bits) % page_size ? 1 : 0;
page_size = (size_t)ps;
pages = (*(lc->clean_bits) + page_size - 1) / page_size;
pages += 1; /* for header */
r = open(disk_path, O_RDWR | O_DIRECT);
@@ -927,7 +928,7 @@ int local_resume(struct dm_ulog_request *rq)
*
* Since this value doesn't change, the kernel
* should not need to talk to server to get this
* The function is here for completness
* The function is here for completeness
*
* Returns: 0 on success, -EXXX on failure
*/
@@ -1018,7 +1019,7 @@ static int clog_in_sync(struct dm_ulog_request *rq)
* happen for reads is that additional read attempts may be
* taken.
*
* Futher investigation may be required to determine if there are
* Further investigation may be required to determine if there are
* similar possible outcomes when the mirror is in the process of
* recovering. In that case, lc->in_sync would not have been set
* yet.

View File

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

View File

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

View File

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

View File

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

View File

@@ -27,16 +27,15 @@
#include <dlfcn.h>
#include <pthread.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <signal.h>
#include <arpa/inet.h> /* for htonl, ntohl */
#include <fcntl.h> /* for musl libc */
#include <unistd.h>
#include <syslog.h>
#include <sys/utsname.h>
#ifdef __linux__
/*
@@ -94,6 +93,10 @@ static const size_t THREAD_STACK_SIZE = 300 * 1024;
/* Default idle exit timeout 1 hour (in seconds) */
static const time_t DMEVENTD_IDLE_EXIT_TIMEOUT = 60 * 60;
/* Default grace period for thread cleanup 10 seconds */
#define DMEVENTD_DEFAULT_GRACE_PERIOD 10
static int _grace_period = DMEVENTD_DEFAULT_GRACE_PERIOD;
static int _systemd_activation = 0;
static int _foreground = 0;
static time_t _idle_since = 0;
@@ -202,7 +205,7 @@ struct message_data {
char *dso_name; /* Name of DSO. */
char *device_uuid; /* Mapped device path. */
char *events_str; /* Events string as fetched from message. */
enum dm_event_mask events_field; /* Events bitfield. */
unsigned events_field; /* Events bitfield. */
uint32_t timeout_secs;
char *timeout_str;
struct dm_event_daemon_message *msg; /* Pointer to message buffer. */
@@ -211,7 +214,8 @@ struct message_data {
/* There are three states a thread can attain. */
enum {
DM_THREAD_REGISTERING, /* Registering, transitions to RUNNING */
DM_THREAD_RUNNING, /* Working on events, transitions to DONE */
DM_THREAD_RUNNING, /* Working on events, transitions to GRACE or DONE */
DM_THREAD_GRACE_PERIOD, /* Thread awaits reuse for a grace period */
DM_THREAD_DONE /* Terminated and cleanup is pending */
};
@@ -235,12 +239,15 @@ struct thread_status {
} device;
int processing; /* Set when event is being processed */
int status; /* See DM_THREAD_{REGISTERING,RUNNING,DONE} */
int status; /* See DM_THREAD_{REGISTERING,RUNNING,GRACE_PERIOD,DONE} */
int events; /* bitfield for event filter. */
int current_events; /* bitfield for occured events. */
int current_events; /* bitfield for occurred events. */
struct dm_task *wait_task;
int pending; /* Set when event filter change is pending */
int used; /* Count thread reusage (for debugging) */
pthread_cond_t grace_cond; /* Condition variable for grace period wait */
uint64_t inode; /* Device path inode of monitored volume */
time_t next_time;
uint32_t timeout;
struct dm_list timeout_list;
@@ -270,7 +277,7 @@ static void _free_dso_data(struct dso_data *data)
static struct dso_data *_alloc_dso_data(struct message_data *data)
{
struct dso_data *ret = (typeof(ret)) zalloc(sizeof(*ret));
struct dso_data *ret = (__typeof__(ret)) zalloc(sizeof(*ret));
if (!ret)
return_NULL;
@@ -397,11 +404,17 @@ static void _free_thread_status(struct thread_status *thread)
_lib_put(thread->dso_data);
if (thread->wait_task)
dm_task_destroy(thread->wait_task);
/* Clean up grace period condition variable */
pthread_cond_destroy(&thread->grace_cond);
free(thread->device.uuid);
free(thread->device.name);
free(thread);
}
static int _lock_mutex(void);
static int _unlock_mutex(void);
/* Note: events_field must not be 0, ensured by caller */
static struct thread_status *_alloc_thread_status(const struct message_data *data,
struct dso_data *dso_data)
@@ -429,7 +442,13 @@ static struct thread_status *_alloc_thread_status(const struct message_data *dat
if (!(thread->device.name = strdup(data->device_uuid)))
goto_out;
/* runs ioctl and may register lvm2 pluging */
/* Initialize grace period condition variable */
if (pthread_cond_init(&thread->grace_cond, NULL)) {
log_error("Failed to initialize grace period condition variable.");
goto_out;
}
/* runs ioctl and may register lvm2 plugin */
thread->processing = 1;
thread->status = DM_THREAD_REGISTERING;
@@ -522,7 +541,7 @@ static int _fetch_string(char **ptr, char **src, const int delimiter)
*p = delimiter;
*src = p;
}
(*src)++; /* Skip delmiter, next field */
(*src)++; /* Skip delimiter, next field */
} else if ((len = strlen(*src))) {
/* No delimiter, item ends with '\0' */
if (!(*ptr = strdup(*src))) {
@@ -608,11 +627,14 @@ static int _fill_device_data(struct thread_status *ts)
if (!dm_task_run(dmt))
goto fail;
free(ts->device.name);
if (!(ts->device.name = strdup(dm_task_get_name(dmt))))
if (!dm_task_get_info(dmt, &dmi))
goto fail;
if (!dm_task_get_info(dmt, &dmi))
if (!dmi.exists)
goto fail;
free(ts->device.name);
if (!(ts->device.name = strdup(dm_task_get_name(dmt))))
goto fail;
ts->device.major = dmi.major;
@@ -628,9 +650,9 @@ fail:
static struct dm_task *_get_device_status(struct thread_status *ts)
{
struct dm_task *dmt = dm_task_create(DM_DEVICE_STATUS);
struct dm_task *dmt;
if (!dmt)
if (!(dmt = dm_task_create(DM_DEVICE_STATUS)))
return_NULL;
if (!dm_task_set_uuid(dmt, ts->device.uuid)) {
@@ -650,6 +672,60 @@ static struct dm_task *_get_device_status(struct thread_status *ts)
return dmt;
}
static uint64_t _get_device_inode(struct thread_status *ts)
{
static int _kernel_major = -1;
struct utsname uts;
struct stat buf;
char path[PATH_MAX];
/* Get kernel version to determine path format */
if (_kernel_major < 0) {
_kernel_major = 0;
if (uname(&uts))
log_sys_debug("uname", "");
else if (sscanf(uts.release, "%d", &_kernel_major) != 1)
log_debug("Cannot parse kernel version from %s.", uts.release);
}
if (_kernel_major >= 3) {
/* Use sysfs path with major:minor format for modern kernels */
if (dm_snprintf(path, sizeof(path), "%sdev/block/%d:%d",
dm_sysfs_dir(), ts->device.major, ts->device.minor) < 0)
return_0;
} else {
/* Use /dev/mapper/name device path for kernel version <3.
* Older kernels do not change inode numbers for devices!
* Relies on correct files in /dev/mapper directory.
*/
if (dm_snprintf(path, sizeof(path), "%s/%s",
dm_dir(), ts->device.name) < 0)
return_0;
}
if (stat(path, &buf) < 0) {
log_sys_debug("stat", path);
if (_kernel_major >= 3)
return 0;
/* Since monitoring is not synchronized with udev
* symlink may not exists, so also try /dev/dm-X */
if (dm_snprintf(path, sizeof(path), "%s/../dm-%d",
dm_dir(), ts->device.minor) < 0)
return_0;
if (stat(path, &buf) < 0) {
log_sys_debug("stat", path);
return 0;
}
}
log_debug("Device %s with inode %" PRIu64 " (kernel %d).",
path, (uint64_t) buf.st_ino, _kernel_major);
return (uint64_t) buf.st_ino;
}
/*
* Find an existing thread for a device.
*
@@ -666,6 +742,22 @@ static struct thread_status *_lookup_thread_status(struct message_data *data)
return NULL;
}
static struct thread_status *_lookup_grace_thread_status(struct message_data *data)
{
struct thread_status *thread;
dm_list_iterate_items(thread, &_thread_registry_unused)
if ((thread->status == DM_THREAD_GRACE_PERIOD) &&
!strcmp(data->device_uuid, thread->device.uuid) &&
!strcmp(data->dso_name, thread->dso_data->dso_name) &&
(thread->inode == _get_device_inode(thread))) {
DEBUGLOG("Found reusable thread %x in grace period.",(int)thread->thread);
return thread;
}
return NULL;
}
static int _get_status(struct message_data *message_data)
{
struct dm_event_daemon_message *msg = message_data->msg;
@@ -682,9 +774,15 @@ static int _get_status(struct message_data *message_data)
return -EINVAL;
_lock_mutex();
count = dm_list_size(&_thread_registry);
if (!(count = dm_list_size(&_thread_registry))) {
_unlock_mutex();
ret = 0; /* no monitored devices */
goto out;
}
buffers = alloca(sizeof(char*) * count);
dm_list_iterate_items(thread, &_thread_registry) {
/* coverity[overflow_sink] - only positive 'current' is used */
if ((current = dm_asprintf(buffers + i, "0:%d %s %s %u %" PRIu32 ";",
i, thread->dso_data->dso_name,
thread->device.uuid, thread->events,
@@ -693,6 +791,7 @@ static int _get_status(struct message_data *message_data)
goto out;
}
++i;
/* coverity[overflow] - only positive 'current' is used */
size += current; /* count with trailing '\0' */
}
_unlock_mutex();
@@ -757,11 +856,26 @@ static void _exit_timeout(void *unused __attribute__((unused)))
pthread_mutex_unlock(&_timeout_mutex);
}
static time_t _get_curr_time(void)
{
#ifdef HAVE_REALTIME
struct timespec real_time;
if (clock_gettime(CLOCK_REALTIME, &real_time) == 0)
/* 10ms back to the future */
return real_time.tv_sec + ((real_time.tv_nsec > (1000000000 - 10000000)) ? 1 : 0);
/* fallback to time() */
log_sys_debug("clock_gettime", "");
#endif
return time(NULL);
}
/* Wake up monitor threads every so often. */
static void *_timeout_thread(void *unused __attribute__((unused)))
{
struct thread_status *thread;
struct timespec timeout, real_time;
struct timespec timeout;
time_t curr_time;
int ret;
@@ -772,22 +886,17 @@ static void *_timeout_thread(void *unused __attribute__((unused)))
while (!dm_list_empty(&_timeout_registry)) {
timeout.tv_sec = 0;
timeout.tv_nsec = 0;
#ifndef HAVE_REALTIME
curr_time = time(NULL);
#else
if (clock_gettime(CLOCK_REALTIME, &real_time)) {
log_error("Failed to read clock_gettime().");
break;
}
/* 10ms back to the future */
curr_time = real_time.tv_sec + ((real_time.tv_nsec > (1000000000 - 10000000)) ? 1 : 0);
#endif
curr_time = _get_curr_time();
dm_list_iterate_items_gen(thread, &_timeout_registry, timeout_list) {
if (thread->next_time <= curr_time) {
thread->next_time = curr_time + thread->timeout;
_lock_mutex();
if (thread->processing) {
if (thread->status != DM_THREAD_RUNNING) {
/* Skip wake up of non running thread (i.e. in grace period) */
log_debug("Skipping SIGALRM to non running Thr %x for timeout.",
(int) thread->thread);
} else if (thread->processing) {
/* Cannot signal processing monitoring thread */
log_debug("Skipping SIGALRM to processing Thr %x for timeout.",
(int) thread->thread);
@@ -806,8 +915,8 @@ static void *_timeout_thread(void *unused __attribute__((unused)))
timeout.tv_sec = thread->next_time;
}
pthread_cond_timedwait(&_timeout_cond, &_timeout_mutex,
&timeout);
(void) pthread_cond_timedwait(&_timeout_cond, &_timeout_mutex,
&timeout);
}
DEBUGLOG("Timeout thread finished.");
@@ -823,12 +932,13 @@ static int _register_for_timeout(struct thread_status *thread)
pthread_mutex_lock(&_timeout_mutex);
if (dm_list_empty(&thread->timeout_list)) {
thread->next_time = time(NULL) + thread->timeout;
dm_list_add(&_timeout_registry, &thread->timeout_list);
if (_timeout_running)
pthread_cond_signal(&_timeout_cond);
}
thread->next_time = _get_curr_time() + thread->timeout;
if (!_timeout_running &&
!(ret = _pthread_create_smallstack(NULL, _timeout_thread, NULL)))
_timeout_running = 1;
@@ -874,6 +984,43 @@ enum {
DM_WAIT_FATAL
};
/* Reset pending signal for a task/thread */
static int _reset_pending_signal(int signal)
{
sigset_t prev_mask, mask;
struct sigaction prev_act, act = { .sa_handler = SIG_IGN };
sigemptyset(&act.sa_mask);
sigemptyset(&prev_mask);
sigemptyset(&mask);
sigaddset(&mask, signal);
if (pthread_sigmask(SIG_SETMASK, &mask, &prev_mask) != 0) {
log_sys_error("pthread_sigmask", "ignore signal");
return 0; /* What better */
}
if (sigaction(signal, &act, &prev_act) < 0) {
log_sys_error("sigaction", "ignore signal");
return 0;
}
if (sigaction(signal, &prev_act, NULL) < 0) {
log_sys_error("sigaction", "restore signal");
return 0;
}
/* And also restore the process's original sigmask */
if (pthread_sigmask(SIG_SETMASK, &prev_mask, NULL) < 0) {
log_sys_error("pthread_sigmask", "restore signal");
return 0;
}
return 1;
}
/* Wait on a device until an event occurs. */
static int _event_wait(struct thread_status *thread)
{
@@ -896,6 +1043,9 @@ static int _event_wait(struct thread_status *thread)
}
if (dm_task_run(thread->wait_task)) {
/* Recheck device info whether is still exists */
if (!_fill_device_data(thread))
goto disappeared; /* device is gone... */
thread->current_events |= DM_EVENT_DEVICE_ERROR;
ret = DM_WAIT_INTR;
/* Update event_nr */
@@ -904,6 +1054,7 @@ static int _event_wait(struct thread_status *thread)
} else {
switch (dm_task_get_errno(thread->wait_task)) {
case ENXIO:
disappeared:
log_error("%s disappeared, detaching.",
thread->device.name);
ret = DM_WAIT_FATAL;
@@ -960,7 +1111,8 @@ static void _do_process_event(struct thread_status *thread)
if (!task)
log_error("Lost event in Thr %x.", (int)thread->thread);
else {
thread->dso_data->process_event(task, thread->current_events, &(thread->dso_private));
thread->dso_data->process_event(task, (enum dm_event_mask) thread->current_events,
&(thread->dso_private));
if (task != thread->wait_task)
dm_task_destroy(task);
}
@@ -972,6 +1124,12 @@ static void _thread_unused(struct thread_status *thread)
LINK(thread, &_thread_registry_unused);
}
static void _thread_used(struct thread_status *thread)
{
UNLINK_THREAD(thread);
LINK_THREAD(thread);
}
/* Thread cleanup handler to unregister device. */
static void _monitor_unregister(void *arg)
{
@@ -1008,32 +1166,11 @@ static void _monitor_unregister(void *arg)
kill(getpid(), SIGINT);
}
/* Device monitoring thread. */
static void *_monitor_thread(void *arg)
static int _monitor_events(struct thread_status *thread)
{
struct thread_status *thread = arg;
int ret;
int ret = 0;
sigset_t pendmask;
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
pthread_cleanup_push(_monitor_unregister, thread);
if (!_fill_device_data(thread)) {
log_error("Failed to fill device data for %s.", thread->device.uuid);
_lock_mutex();
goto out;
}
if (!_do_register_device(thread)) {
log_error("Failed to register device %s.", thread->device.name);
_lock_mutex();
goto out;
}
_lock_mutex();
thread->status = DM_THREAD_RUNNING;
thread->processing = 0;
/* Loop awaiting/analyzing device events. */
while (thread->events) {
@@ -1079,6 +1216,102 @@ static void *_monitor_thread(void *arg)
break;
}
}
return ret;
}
/* Thread awaits condition wake up for a grace period */
static void _monitor_grace_period_wait(struct thread_status *thread)
{
struct timespec grace_timeout = { .tv_sec = _get_curr_time() + _grace_period };
DEBUGLOG("Thread %x entering grace period for %d seconds.",
(int)thread->thread, _grace_period);
/* Wait on per-thread condition variable with global mutex */
while (!_exit_now && !thread->events &&
(ETIMEDOUT != pthread_cond_timedwait(&thread->grace_cond,
&_global_mutex, &grace_timeout)))
/* Waiting */;
DEBUGLOG("Thread %x wakeup grace period.", (int)thread->thread);
}
/* Device monitoring thread. */
static void *_monitor_thread(void *arg)
{
struct thread_status *thread = arg;
int ret;
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
pthread_cleanup_push(_monitor_unregister, thread);
if (!_fill_device_data(thread)) {
log_error("Failed to fill device data for %s.", thread->device.uuid);
_lock_mutex();
goto out;
}
/* Now with resolved major:minor store also device inode */
thread->inode = _get_device_inode(thread);
if (!_do_register_device(thread)) {
log_error("Failed to register device %s.", thread->device.name);
_lock_mutex();
goto out;
}
_lock_mutex();
/* Main monitoring loop with grace period support */
while (thread->events) {
DEBUGLOG("Monitoring %s with Thr %x (events: %x, used: %d).",
thread->device.name, (int)thread->thread,
thread->events, thread->used);
thread->status = DM_THREAD_RUNNING;
thread->processing = 0;
thread->used++;
ret = _monitor_events(thread);
/* No grace period when set to 0
* or there were left some processing events which is an error state
* or there is on going exit
* or there was fatal error while waiting for some event */
if (!_grace_period || thread->events || _exit_now || (ret == DM_WAIT_FATAL))
break;
/* Before restarting event loop reset any pending SIGALRM signal */
if (!_reset_pending_signal(SIGALRM)) {
stack;
break; /* Something is wrong... */
}
thread->current_events = 0;
thread->status = DM_THREAD_GRACE_PERIOD; /* No events - enter grace period */
_thread_unused(thread);
DEBUGLOG("Gracing %s with Thr %x (events: %x, used: %d).",
thread->device.name, (int)thread->thread,
thread->events, thread->used);
_monitor_grace_period_wait(thread);
/*
* Grace period wait completed - two possible wake-up scenarios:
*
* 1) Woken by _update_events() (new registration reusing this thread):
* - thread->events is non-zero and thread is moved to active registry
* - Status is set DM_THREAD_RUNNING
* - _register_for_timeout() resets next_time for fresh timeout
* - Loop continues (events != 0)
*
* 2) Natural timeout (grace period expired with no new registration):
* - thread->events is still 0 and loop exits
* - Thread terminates via cleanup handler
* - Thread remains in unused registry for _cleanup_unused_threads()
*/
}
out:
/* ';' fixes gcc compilation problem with older pthread macros
* "label at end of compound statement" */
@@ -1107,6 +1340,35 @@ static int _update_events(struct thread_status *thread, int events)
thread->events = events;
thread->pending = DM_EVENT_REGISTRATION_PENDING;
/* Wake up thread waiting in grace period for new registration or exit */
if ((events || _exit_now) && (thread->status == DM_THREAD_GRACE_PERIOD)) {
DEBUGLOG("Waking up thread %x waiting in grace period (events=%x).",
(int)thread->thread, events);
/*
* Move thread back to active registry NOW, before signaling.
* This is critical to avoid race condition.
* Moves thread to active registry and signals thread
* Client queries GET_REGISTERED_DEVICE - FOUND immediately
*/
_thread_used(thread);
/* Set status to RUNNING and processing to 1. */
thread->status = DM_THREAD_RUNNING;
thread->processing = 1; /* No signaling */
/*
* Signal the per-thread condition variable while holding _global_mutex.
* Thread will wake from _monitor_grace_period_wait(), check events != 0,
* and continue the monitoring loop.
*
* Note: Timeout reset happens after _update_events() returns, when
* _register_for_event() calls _register_for_timeout() to give the
* reused thread a fresh timeout period.
*/
pthread_cond_signal(&thread->grace_cond);
return 0;
}
/* Only non-processing threads can be notified */
if (!thread->processing) {
DEBUGLOG("Sending SIGALRM to wakeup Thr %x.", (int)thread->thread);
@@ -1121,9 +1383,7 @@ static int _update_events(struct thread_status *thread, int events)
}
}
/* Threads with no events has to be moved to unused */
if (!thread->events)
_thread_unused(thread);
/* Threads with no events will enter grace period in their main loop */
return -ret;
}
@@ -1225,7 +1485,8 @@ static int _register_for_event(struct message_data *message_data)
_lock_mutex();
if ((thread = _lookup_thread_status(message_data))) {
if ((thread = _lookup_thread_status(message_data)) ||
(thread = _lookup_grace_thread_status(message_data))) {
/* OR event # into events bitfield. */
ret = _update_events(thread, (thread->events | message_data->events_field));
} else {
@@ -1339,11 +1600,13 @@ static int _get_registered_dev(struct message_data *message_data, int next)
/*
* If we didn't get a match, try the threads waiting to be deleted.
* Threads in grace period are skipped.
* FIXME Do something similar if 'next' is set.
*/
if (!hit && !next)
dm_list_iterate_items(thread, &_thread_registry_unused)
if (_want_registered_device(message_data->dso_name,
if ((thread->status != DM_THREAD_GRACE_PERIOD) &&
_want_registered_device(message_data->dso_name,
message_data->device_uuid, thread)) {
hit = thread;
goto reg;
@@ -1428,8 +1691,8 @@ static int _open_fifo(const char *path)
{
struct stat st;
int fd = -1;
/*
/*
* FIXME Explicitly verify the code's requirement that path is secure:
* - All parent directories owned by root without group/other write access unless sticky.
*/
@@ -1443,7 +1706,8 @@ static int _open_fifo(const char *path)
} else if (!S_ISFIFO(st.st_mode) || st.st_uid ||
(st.st_mode & (S_IEXEC | S_IRWXG | S_IRWXO))) {
log_warn("WARNING: %s has wrong attributes: Replacing.", path);
if (unlink(path)) {
/* coverity[toctou] don't care, path is going to be recreated */
if (unlink(path) && (errno != ENOENT)) {
log_sys_error("unlink", path);
return -1;
}
@@ -1451,6 +1715,7 @@ static int _open_fifo(const char *path)
/* Create fifo. */
(void) dm_prepare_selinux_context(path, S_IFIFO);
/* coverity[toctou] revalidating things again */
if ((mkfifo(path, 0600) == -1) && errno != EEXIST) {
log_sys_error("mkfifo", path);
(void) dm_prepare_selinux_context(NULL, 0);
@@ -1716,8 +1981,8 @@ static void _process_request(struct dm_event_fifos *fifos)
free(msg.data);
if (cmd == DM_EVENT_CMD_DIE) {
_exit_now = DM_SCHEDULED_EXIT; /* No grace period */
_unregister_all_threads();
_exit_now = DM_SCHEDULED_EXIT;
log_info("dmeventd exiting for restart.");
}
}
@@ -1751,6 +2016,13 @@ static void _cleanup_unused_threads(void)
if (thread->processing)
break; /* cleanup on the next round */
if (thread->status == DM_THREAD_GRACE_PERIOD) {
/* Wake-up thread in grace period */
if (_exit_now)
pthread_cond_signal(&thread->grace_cond);
break;
}
/* Signal possibly sleeping thread */
ret = pthread_kill(thread->thread, SIGALRM);
if (!ret || (ret != ESRCH))
@@ -1931,9 +2203,6 @@ out:
static void _remove_files_on_exit(void)
{
if (unlink(DMEVENTD_PIDFILE) && (errno != ENOENT))
log_sys_debug("unlink", DMEVENTD_PIDFILE);
if (!_systemd_activation) {
if (unlink(DM_EVENT_FIFO_CLIENT) && (errno != ENOENT))
log_sys_debug("unlink", DM_EVENT_FIFO_CLIENT);
@@ -1941,11 +2210,14 @@ static void _remove_files_on_exit(void)
if (unlink(DM_EVENT_FIFO_SERVER) && (errno != ENOENT))
log_sys_debug("unlink", DM_EVENT_FIFO_SERVER);
}
if (unlink(DMEVENTD_PIDFILE) && (errno != ENOENT))
log_sys_debug("unlink", DMEVENTD_PIDFILE);
}
static void _daemonize(void)
{
int child_status;
int child_status, null_fd;
pid_t pid;
struct timeval tval;
sigset_t my_sigset;
@@ -2000,19 +2272,26 @@ static void _daemonize(void)
daemon_close_stray_fds("dmeventd", 0, -1, &custom_fds);
/* coverity[leaked_handle] dont't care */
if ((open("/dev/null", O_RDONLY) < 0) ||
(open("/dev/null", O_WRONLY) < 0) ||
(open("/dev/null", O_WRONLY) < 0))
if ((null_fd = open("/dev/null", O_RDWR)) < 0)
exit(EXIT_DESC_OPEN_FAILURE);
if ((dup2(null_fd, STDIN_FILENO) == -1) ||
(dup2(null_fd, STDOUT_FILENO) == -1) ||
(dup2(null_fd, STDERR_FILENO) == -1))
exit(EXIT_DESC_OPEN_FAILURE);
if ((null_fd > STDERR_FILENO) && close(null_fd))
exit(EXIT_DESC_CLOSE_FAILURE);
setsid();
/* coverity[leaked_handle] 'null_fd' handle is not leaking */
}
static int _reinstate_registrations(struct dm_event_fifos *fifos)
{
static const char _failed_parsing_msg[] = "Failed to parse existing event registration.\n";
static const char *_delim = " ";
static const char _delim[] = " ";
struct dm_event_daemon_message msg = { 0 };
char *endp, *dso_name, *dev_name, *mask, *timeout;
unsigned long mask_value, timeout_value;
@@ -2243,16 +2522,18 @@ bad:
static void _usage(char *prog, FILE *file)
{
fprintf(file, "Usage:\n"
"%s [-d [-d [-d]]] [-e path] [-f] [-h] [i] [-l] [-R] [-V] [-?]\n\n"
"%s [-d [-d [-d]]] [-e path] [-g seconds] [-f] [-h] [i] [-l] [-R] [-V] [-?]\n\n"
" -d Log debug messages to syslog (-d, -dd, -ddd)\n"
" -e Select a file path checked on exit\n"
" -g Grace period for thread cleanup (0-300 seconds, default: %d)\n"
" -f Don't fork, run in the foreground\n"
" -h Show this help information\n"
" -i Query running instance of dmeventd for info\n"
" -l Log to stdout,stderr instead of syslog\n"
" -? Show this help information on stderr\n"
" -R Restart dmeventd\n"
" -V Show version of dmeventd\n\n", prog);
" -V Show version of dmeventd\n\n", prog,
_grace_period);
}
int main(int argc, char *argv[])
@@ -2272,7 +2553,7 @@ int main(int argc, char *argv[])
optopt = optind = opterr = 0;
optarg = (char*) "";
while ((opt = getopt(argc, argv, ":?e:fhiVdlR")) != EOF) {
while ((opt = getopt(argc, argv, ":?e:g:fhiVdlR")) != EOF) {
switch (opt) {
case 'h':
_usage(argv[0], stdout);
@@ -2293,6 +2574,13 @@ int main(int argc, char *argv[])
}
_exit_on=optarg;
break;
case 'g':
_grace_period = atoi(optarg);
if (_grace_period < 0 || _grace_period > 300) {
fprintf(stderr, "dmeventd: grace period must be between 0 and 300 seconds.\n");
return EXIT_FAILURE;
}
break;
case 'f':
_foreground++;
break;

View File

@@ -15,6 +15,8 @@
#ifndef __DMEVENTD_DOT_H__
#define __DMEVENTD_DOT_H__
#include <stdint.h>
/* FIXME This stuff must be configurable. */
#define DM_EVENT_FIFO_CLIENT DEFAULT_DM_RUN_DIR "/dmeventd-client"
@@ -68,7 +70,7 @@ struct dm_event_fifos {
int daemon_talk(struct dm_event_fifos *fifos,
struct dm_event_daemon_message *msg, int cmd,
const char *dso_name, const char *dev_name,
enum dm_event_mask evmask, uint32_t timeout);
unsigned evmask, uint32_t timeout);
int init_fifos(struct dm_event_fifos *fifos);
void fini_fifos(struct dm_event_fifos *fifos);
int dm_event_get_version(struct dm_event_fifos *fifos, int *version);

View File

@@ -352,7 +352,7 @@ static int _daemon_write(struct dm_event_fifos *fifos,
int daemon_talk(struct dm_event_fifos *fifos,
struct dm_event_daemon_message *msg, int cmd,
const char *dso_name, const char *dev_name,
enum dm_event_mask evmask, uint32_t timeout)
unsigned evmask, uint32_t timeout)
{
int msg_size;
memset(msg, 0, sizeof(*msg));
@@ -400,25 +400,16 @@ int daemon_talk(struct dm_event_fifos *fifos,
return (int32_t) msg->cmd;
}
/*
* start_daemon
* Check for usable client fifo file
*
* This function forks off a process (dmeventd) that will handle
* the events. I am currently test opening one of the fifos to
* ensure that the daemon is running and listening... I thought
* this would be less expensive than fork/exec'ing every time.
* Perhaps there is an even quicker/better way (no, checking the
* lock file is _not_ a better way).
*
* Returns: 1 on success, 0 otherwise
* Returns: 2 client path does not exists, dmeventd should be restarted
* 1 on success, 0 otherwise
*/
static int _start_daemon(char *dmeventd_path, struct dm_event_fifos *fifos)
static int _check_for_usable_fifos(char *dmeventd_path, struct dm_event_fifos *fifos)
{
int pid, ret = 0;
int status;
struct stat statbuf;
char default_dmeventd_path[] = DMEVENTD_PATH;
char *args[] = { dmeventd_path ? : default_dmeventd_path, NULL };
/*
* FIXME Explicitly verify the code's requirement that client_path is secure:
@@ -429,7 +420,7 @@ static int _start_daemon(char *dmeventd_path, struct dm_event_fifos *fifos)
if ((lstat(fifos->client_path, &statbuf) < 0)) {
if (errno == ENOENT)
/* Jump ahead if fifo does not already exist. */
goto start_server;
return 2;
else {
log_sys_error("stat", fifos->client_path);
return 0;
@@ -455,12 +446,14 @@ static int _start_daemon(char *dmeventd_path, struct dm_event_fifos *fifos)
log_error("%s is no longer a secure root-owned fifo with mode 0600.", fifos->client_path);
if (close(fifos->client))
log_sys_debug("close", fifos->client_path);
fifos->client = -1;
return 0;
}
/* server is running and listening */
if (close(fifos->client))
log_sys_debug("close", fifos->client_path);
fifos->client = -1;
return 1;
}
if (errno != ENXIO && errno != ENOENT) {
@@ -469,9 +462,36 @@ static int _start_daemon(char *dmeventd_path, struct dm_event_fifos *fifos)
return 0;
}
start_server:
/* server is not running */
return 2;
}
/*
* start_daemon
*
* This function forks off a process (dmeventd) that will handle
* the events. I am currently test opening one of the fifos to
* ensure that the daemon is running and listening... I thought
* this would be less expensive than fork/exec'ing every time.
* Perhaps there is an even quicker/better way (no, checking the
* lock file is _not_ a better way).
*
* Returns: 1 on success, 0 otherwise
*/
static int _start_daemon(char *dmeventd_path, struct dm_event_fifos *fifos)
{
struct stat statbuf;
char default_dmeventd_path[] = DMEVENTD_PATH;
char *args[] = { dmeventd_path ? : default_dmeventd_path, NULL };
int pid, ret = 0;
int status;
switch (_check_for_usable_fifos(dmeventd_path, fifos)) {
case 0: return_0;
case 1: return 1; /* Already running dmeventd */
}
/* server is not running */
if ((args[0][0] == '/') && stat(args[0], &statbuf)) {
log_sys_error("stat", args[0]);
return 0;
@@ -492,8 +512,17 @@ start_server:
strerror(errno));
else if (WEXITSTATUS(status))
log_error("Unable to start dmeventd.");
else
ret = 1;
else {
/* Loop here till forked dmeventd is serving fifos */
for (ret = 100; ret > 0; --ret)
switch (_check_for_usable_fifos(dmeventd_path, fifos)) {
case 0: return_0;
case 1: return 1;
case 2: usleep(1000); break;
}
/* ret == 0 */
log_error("Dmeventd is not serving fifos.");
}
}
return ret;
@@ -725,7 +754,7 @@ static char *_fetch_string(char **src, const int delimiter)
/* Parse a device message from the daemon. */
static int _parse_message(struct dm_event_daemon_message *msg, char **dso_name,
char **uuid, enum dm_event_mask *evmask)
char **uuid, unsigned *evmask)
{
char *id;
char *p = msg->data;
@@ -750,7 +779,7 @@ int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next)
int ret = 0;
const char *uuid = NULL;
char *reply_dso = NULL, *reply_uuid = NULL;
enum dm_event_mask reply_mask = 0;
unsigned reply_mask = 0;
struct dm_task *dmt = NULL;
struct dm_event_daemon_message msg = { 0 };
struct dm_info info;
@@ -800,7 +829,7 @@ int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next)
}
dm_event_handler_set_dso(dmevh, reply_dso);
dm_event_handler_set_event_mask(dmevh, reply_mask);
dm_event_handler_set_event_mask(dmevh, (enum dm_event_mask) reply_mask);
free(reply_dso);
reply_dso = NULL;
@@ -959,7 +988,7 @@ void dm_event_log(const char *subsys, int level, const char *file,
fprintf(stream, "%28s:%4d %s", file, line, indent);
vfprintf(stream, _(format), ap);
fputc('\n', stream);
fflush(stream);
(void) fflush(stream);
}
pthread_mutex_unlock(&_log_mutex);
@@ -978,7 +1007,7 @@ void dm_event_log(const char *subsys, int level, const char *file,
static char *_skip_string(char *src, const int delimiter)
{
src = srtchr(src, delimiter);
src = strchr(src, delimiter);
if (src && *(src + 1))
return src + 1;
return NULL;

View File

@@ -29,19 +29,22 @@
*/
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_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_SYNC_STATUS = 0x010000, /* Mirror synchronization completed/failed. */
DM_EVENT_TIMEOUT = 0x020000, /* Timeout has occured */
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);
@@ -109,7 +112,7 @@ int dm_event_unregister_handler(const struct dm_event_handler *dmevh);
/* Set debug level for logging, and whether to log on stdout/stderr or syslog */
void dm_event_log_set(int debug_log_level, int use_syslog);
/* Log messages acroding to current debug level */
/* Log messages according to current debug level */
__attribute__((format(printf, 6, 0)))
void dm_event_log(const char *subsys, int level, const char *file,
int line, int dm_errno_or_class,

View File

@@ -15,6 +15,7 @@
#include "lib/misc/lib.h"
#include "dmeventd_lvm.h"
#include "daemons/dmeventd/libdevmapper-event.h"
#include "lib/metadata/metadata-exported.h" /* MIRROR_SYNC_LAYER */
#include "tools/lvm2cmd.h"
#include <pthread.h>
@@ -87,7 +88,7 @@ int dmeventd_lvm2_init(void)
lvm2_disable_dmeventd_monitoring(_lvm_handle);
/* FIXME Temporary: move to dmeventd core */
lvm2_run(_lvm_handle, "_memlock_inc");
log_debug("lvm plugin initilized.");
log_debug("lvm plugin initialized.");
}
_register_count++;
@@ -103,7 +104,7 @@ void dmeventd_lvm2_exit(void)
pthread_mutex_lock(&_register_mutex);
if (!--_register_count) {
log_debug("lvm plugin shuting down.");
log_debug("lvm plugin shutting down.");
lvm2_run(_lvm_handle, "_memlock_dec");
dm_pool_destroy(_mem_pool);
_mem_pool = NULL;
@@ -143,7 +144,7 @@ int dmeventd_lvm2_command(struct dm_pool *mem, char *buffer, size_t size,
}
/* strip off the mirror component designations */
if ((layer = strstr(lv, "_mimagetmp")) ||
if ((layer = strstr(lv, MIRROR_SYNC_LAYER)) ||
(layer = strstr(lv, "_mlog")))
*layer = '\0';

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

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

@@ -17,7 +17,7 @@
#include "daemons/dmeventd/libdevmapper-event.h"
#include "lib/config/defaults.h"
/* Hold enough elements for the mximum number of RAID images */
/* Hold enough elements for the maximum number of RAID images */
#define RAID_DEVS_ELEMS ((DEFAULT_RAID_MAX_IMAGES + 63) / 64)
struct dso_state {
@@ -84,7 +84,7 @@ static int _process_raid_event(struct dso_state *state, char *params, const char
*/
if (!state->warned && status->insync_regions < status->total_regions) {
state->warned = 1;
log_warn("WARNING: waiting for resynchronization to finish "
log_warn("WARNING: Waiting for resynchronization to finish "
"before initiating repair on RAID device %s.", device);
/* Fall through to allow lvconvert to run. */
}
@@ -114,7 +114,7 @@ out:
}
void process_event(struct dm_task *dmt,
enum dm_event_mask event __attribute__((unused)),
enum dm_event_mask evmask __attribute__((unused)),
void **user)
{
struct dso_state *state = *user;

View File

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

View File

@@ -45,10 +45,10 @@
struct dso_state {
struct dm_pool *mem;
int metadata_percent_check;
int metadata_percent;
int data_percent_check;
int data_percent;
dm_percent_t metadata_percent_check;
dm_percent_t metadata_percent;
dm_percent_t data_percent_check;
dm_percent_t data_percent;
uint64_t known_metadata_size;
uint64_t known_data_size;
unsigned fails;
@@ -87,7 +87,7 @@ static int _run_command(struct dso_state *state)
log_verbose("Executing command: %s", state->cmd_str);
/* TODO:
* Support parallel run of 'task' and it's waitpid maintainence
* Support parallel run of 'task' and it's waitpid maintenance
* ATM we can't handle signaling of SIGALRM
* as signalling is not allowed while 'process_event()' is running
*/
@@ -155,7 +155,7 @@ static int _wait_for_pid(struct dso_state *state)
}
void process_event(struct dm_task *dmt,
enum dm_event_mask event __attribute__((unused)),
enum dm_event_mask evmask,
void **user)
{
const char *device = dm_task_get_name(dmt);
@@ -179,7 +179,7 @@ void process_event(struct dm_task *dmt,
return;
}
if (event & DM_EVENT_DEVICE_ERROR) {
if (evmask & DM_EVENT_DEVICE_ERROR) {
/* Error -> no need to check and do instant resize */
state->data_percent = state->metadata_percent = 0;
if (_use_policy(dmt, state))
@@ -223,10 +223,12 @@ void process_event(struct dm_task *dmt,
}
#if THIN_DEBUG
log_debug("Thin pool status " FMTu64 "/" FMTu64 " "
FMTu64 "/" FMTu64 ".",
log_debug("Thin pool status " FMTu64 "/" FMTu64 " (" FMTu64 ") "
FMTu64 "/" FMTu64 " (" FMTu64").",
tps->used_data_blocks, tps->total_data_blocks,
state->known_data_size,
tps->used_metadata_blocks, tps->total_metadata_blocks,
tps->used_data_blocks, tps->total_data_blocks);
state->known_metadata_size);
#endif
/* Thin pool size had changed. Clear the threshold. */
@@ -245,7 +247,7 @@ void process_event(struct dm_task *dmt,
/*
* Trigger action when threshold boundary is exceeded.
* Report 80% threshold warning when it's used above 80%.
* Only 100% is exception as it cannot be surpased so policy
* Only 100% is exception as it cannot be surpassed so policy
* action is called for: >50%, >55% ... >95%, 100%
*/
state->metadata_percent = dm_make_percent(tps->used_metadata_blocks, tps->total_metadata_blocks);
@@ -379,14 +381,13 @@ int register_device(const char *device,
state->argv[1] = str + 1; /* 1 argument - vg/lv */
_init_thread_signals(state);
} else /* Unuspported command format */
} else /* Unsupported command format */
goto inval;
state->max_fails = 1;
state->pid = -1;
*user = state;
log_info("Monitoring thin pool %s.", device);
return 1;
inval:
log_error("Invalid command for monitoring: %s.", cmd_str);
@@ -430,7 +431,6 @@ int unregister_device(const char *device,
_restore_thread_signals(state);
dmeventd_lvm2_exit_with_pool(state);
log_info("No longer monitoring thin pool %s.", device);
return 1;
}

View File

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

View File

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

@@ -67,7 +67,7 @@ def lvs_state_retrieve(selection, cache_refresh=True):
try:
# When building up the model, it's best to process LVs with the least
# dependencies to those that are dependant upon other LVs. Otherwise, when
# dependencies to those that are dependent upon other LVs. Otherwise, when
# we are trying to gather information we could be in a position where we
# don't have information available yet.
lvs = sorted(cfg.db.fetch_lvs(selection), key=get_key)
@@ -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

@@ -351,7 +351,7 @@ class DataStore(object):
else:
rc = []
for s in pv_name:
# Ths user could be using a symlink instead of the actual
# The user could be using a symlink instead of the actual
# block device, make sure we are using actual block device file
# if the pv name isn't in the lookup
if s not in self.pv_path_to_uuid:

View File

@@ -133,7 +133,7 @@ def process_args():
def running_under_systemd():
""""
Checks to see if we are running under systemd, by checking damon fd 0, 1
Checks to see if we are running under systemd, by checking daemon fd 0, 1
systemd sets stdin to /dev/null and 1 & 2 are a socket
"""
base = "/proc/self/fd"
@@ -214,7 +214,7 @@ def main():
cfg.loop = GLib.MainLoop()
for thread in thread_list:
thread.damon = True
thread.daemon = True
thread.start()
# In all cases we are going to monitor for udev until we get an

View File

@@ -160,7 +160,7 @@ class ObjectManager(AutomatedProperties):
# (path, dbus_object.lvm_id))
# We want fast access to the object by a number of different ways,
# so we use multiple hashs with different keys
# so we use multiple hashes with different keys
self._lookup_add(dbus_object, path, dbus_object.lvm_id,
dbus_object.Uuid)
@@ -272,7 +272,7 @@ class ObjectManager(AutomatedProperties):
For a given lvm asset return the dbus object path registered for it.
This method first looks up by uuid and then by lvm_id. You
can search by just one by setting uuid == lvm_id (uuid or lvm_id).
If the object is not found and path_create is a not None, the
If the object is not found and path_create is not None, the
path_create function will be called to create a new object path and
register it with the object manager for the specified uuid & lvm_id.
Note: If path create is not None, uuid and lvm_id cannot be equal
@@ -295,7 +295,7 @@ class ObjectManager(AutomatedProperties):
if uuid == lvm_id:
path = self._id_lookup(lvm_id)
else:
# We have an uuid and a lvm_id we can do sanity checks to ensure
# We have a uuid and an lvm_id we can do sanity checks to ensure
# that they are consistent
# If a PV is missing its device path is '[unknown]' or some

View File

@@ -778,6 +778,7 @@ class LockFile(object):
def __enter__(self):
try:
os.makedirs(os.path.dirname(self.lock_file), exist_ok=True)
self.fd = os.open(self.lock_file, os.O_CREAT | os.O_RDWR, stat.S_IRUSR | stat.S_IWUSR)
# Get and set the close on exec and lock the file

View File

@@ -50,8 +50,8 @@ 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)))
CFLAGS += $(LIBSYSTEMD_CFLAGS) -DUSE_SD_NOTIFY
ifeq ("@SD_NOTIFY_SUPPORT@", "yes")
CFLAGS += $(LIBSYSTEMD_CFLAGS)
LIBS += $(LIBSYSTEMD_LIBS)
endif

View File

@@ -38,7 +38,7 @@ static int stop_lockspaces = 0;
static char *arg_vg_name = NULL;
#define DUMP_SOCKET_NAME "lvmlockd-dump.sock"
#define DUMP_BUF_SIZE (1024 * 1024)
#define DUMP_BUF_SIZE (4 * 1024 * 1024)
static char dump_buf[DUMP_BUF_SIZE+1];
static int dump_len;
static struct sockaddr_un dump_addr;
@@ -67,6 +67,160 @@ do { \
syslog(LOG_WARNING, fmt, ##args); \
} while (0)
/*
* Like sscanf, but requires buffer size to be specified
* for storing scanned strings, e.g.
*
* szscanf("%s", sizeof(buf), buf);
*
* Up to size-1 input bytes will be copied into buf.
* A null byte will be written to buf following the
* last copied byte. When nothing is copied to buf,
* no terminating null byte is written.
*
* If an input string matching %s is too long for the
* specified buffer size, the characters that would have
* been copied are ignored.
*
* Only recognizes: %d, %u, %s.
*/
static int szscanf(const char *input, const char *format, ...)
{
va_list args;
const char *fm;
const char *in;
int matched = 0;
int n;
va_start(args, format);
fm = format;
in = input;
while (*fm != '\0') {
/*
* format is a string containing:
* 1. %d matching int from input
* %u matching unsigned int from input
* %s matching non-whitespace characters from input
* 2. whitespace chars matching zero or more whitespace
* characters from input
* 3. non-whitespace chars matching the same input chars
*/
if (*fm == '%') {
/*
* case 1: %u, %d, or %s
*/
/* advance past '%' character, to look for 'u', 'd' or 's' */
fm++;
if (*fm == 'd') {
/*
* read an int (%d)
*/
int *dest = va_arg(args, int *);
if (sscanf(in, "%d%n", dest, &n) == 1) {
in += n;
matched++;
} else {
/* matching failure: no input int */
break;
}
} else if (*fm == 'u') {
/*
* read an unsigned int (%u)
*/
unsigned int *dest = va_arg(args, unsigned int *);
if (sscanf(in, "%u%n", dest, &n) == 1) {
in += n;
matched++;
} else {
/* matching failure: no input unsigned int */
break;
}
} else if (*fm == 's') {
/*
* read a string (%s) into dest buffer with dest_size
* copy up to dest_size-1 characters into dest buffer
* write null byte into dest buffer following the last
* character copied. When dest_size-1 bytes are copied,
* the null byte is written into the final byte of the
* dest buffer. input bytes that would have been copied
* but did not fit in the dest buffer are skipped.
*/
size_t dest_size = va_arg(args, size_t);
char *dest = va_arg(args, char *);
char *out = dest;
/* don't copy leading input whitespace to dest */
while (isspace((unsigned char)*in))
in++;
/* copy non-whitespace characters from input to dest */
n = 0;
while (*in != '\0' && !isspace((unsigned char)*in) && (n < (int)dest_size-1)) {
*out = *in;
out++;
in++;
n++;
}
if (n) {
dest[n] = '\0';
matched++;
} else {
/* matching failure: no input string chars */
break;
}
/* ignore input bytes that would have been copied but didn't fit */
while (*in != '\0' && !isspace((unsigned char)*in))
in++;
} else {
/* unsupported format specifier */
matched = -1;
break;
}
/* advance past 'd', 'u', or 's' character */
fm++;
} else if (isspace((unsigned char)*fm)) {
/*
* case 2: format whitespace skips zero or more input
* whitespace characters
*/
while (isspace((unsigned char)*in))
in++;
/* advance past whitespace character */
fm++;
} else if (*fm == *in) {
/*
* case 3: literal character match between format and input
*/
fm++;
in++;
} else {
/*
* matching failure: format and input don't match
*/
break;
}
}
va_end(args);
return matched;
}
#define MAX_LINE 512
/* copied from lvmlockd-internal.h */
@@ -97,8 +251,11 @@ static void save_client_info(char *line)
uint32_t client_id = 0;
char name[MAX_NAME+1] = { 0 };
(void) sscanf(line, "info=client pid=%u fd=%d pi=%d id=%u name=%s",
&pid, &fd, &pi, &client_id, name);
/* info=client pid=%u fd=%d pi=%d id=%u name=%s */
if (szscanf(line, "info=client pid=%u fd=%d pi=%d id=%u name=%s",
&pid, &fd, &pi, &client_id, sizeof(name), name) < 0)
return;
clients[num_clients].client_id = client_id;
clients[num_clients].pid = pid;
@@ -126,20 +283,26 @@ static void format_info_ls(char *line)
char ls_name[MAX_NAME+1] = { 0 };
char vg_name[MAX_NAME+1] = { 0 };
char vg_uuid[MAX_NAME+1] = { 0 };
char vg_sysid[MAX_NAME+1] = { 0 };
char lock_args[MAX_ARGS+1] = { 0 };
char lock_type[MAX_NAME+1] = { 0 };
char vg_args[MAX_ARGS+1] = { 0 };
char lm_type[MAX_NAME+1] = { 0 };
(void) sscanf(line, "info=ls ls_name=%s vg_name=%s vg_uuid=%s vg_sysid=%s vg_args=%s lm_type=%s",
ls_name, vg_name, vg_uuid, vg_sysid, lock_args, lock_type);
/* info=ls ls_name=%s vg_name=%s vg_uuid=%s vg_args=%s lm_type=%s */
if (szscanf(line, "info=ls ls_name=%s vg_name=%s vg_uuid=%s vg_args=%s lm_type=%s",
sizeof(ls_name), ls_name,
sizeof(vg_name), vg_name,
sizeof(vg_uuid), vg_uuid,
sizeof(vg_args), vg_args,
sizeof(lm_type), lm_type) < 0)
return;
if (!first_ls)
printf("\n");
first_ls = 0;
printf("VG %s lock_type=%s %s\n", vg_name, lock_type, vg_uuid);
printf("VG %s lock_type=%s %s\n", vg_name, lm_type, vg_uuid);
printf("LS %s %s\n", lock_type, ls_name);
printf("LS %s %s\n", lm_type, ls_name);
}
static void format_info_ls_action(char *line)
@@ -151,8 +314,14 @@ static void format_info_ls_action(char *line)
uint32_t pid = 0;
char cl_name[MAX_NAME+1] = { 0 };
(void) sscanf(line, "info=ls_action client_id=%u %s %s op=%s",
&client_id, flags, version, op);
/* info=ls_action client_id=%u flags=%s version=%u op=%s rt=%s mode=%s lm_type=%s result=%d lm_rv=%d */
if (szscanf(line, "info=ls_action client_id=%u flags=%s version=%s op=%s",
&client_id,
sizeof(flags), flags,
sizeof(version), version,
sizeof(op), op) < 0)
return;
find_client_info(client_id, &pid, cl_name);
@@ -164,11 +333,18 @@ static void format_info_r(char *line, char *r_name_out, char *r_type_out)
char r_name[MAX_NAME+1] = { 0 };
char r_type[4] = { 0 };
char mode[4] = { 0 };
char sh_count[MAX_NAME+1] = { 0 };
uint32_t ver = 0;
int sh_count = 0;
unsigned int ver = 0;
(void) sscanf(line, "info=r name=%s type=%s mode=%s %s version=%u",
r_name, r_type, mode, sh_count, &ver);
/* info=r name=%s type=%s mode=%s sh_count=%d version=%s */
if (szscanf(line, "info=r name=%s type=%s mode=%s sh_count=%d version=%u",
sizeof(r_name), r_name,
sizeof(r_type), r_type,
sizeof(mode), mode,
&sh_count,
&ver) < 0)
return;
strcpy(r_name_out, r_name);
strcpy(r_type_out, r_type);
@@ -193,8 +369,8 @@ static void format_info_r(char *line, char *r_name_out, char *r_type_out)
static void format_info_lk(char *line, char *r_name, char *r_type)
{
char mode[4] = { 0 };
uint32_t ver = 0;
char flags[MAX_NAME+1] = { 0 };
uint32_t ver = 0;
uint32_t client_id = 0;
uint32_t pid = 0;
char cl_name[MAX_NAME+1] = { 0 };
@@ -205,8 +381,14 @@ static void format_info_lk(char *line, char *r_name, char *r_type)
return;
}
(void) sscanf(line, "info=lk mode=%s version=%u %s client_id=%u",
mode, &ver, flags, &client_id);
/* info=lk mode=%s version=%s flags=%s client_id=%u */
if (szscanf(line, "info=lk mode=%s version=%u flags=%s client_id=%u",
sizeof(mode), mode,
&ver,
sizeof(flags), flags,
&client_id) < 0)
return;
find_client_info(client_id, &pid, cl_name);
@@ -229,9 +411,9 @@ static void format_info_r_action(char *line, char *r_name, char *r_type)
char op[MAX_NAME+1] = { 0 };
char rt[4] = { 0 };
char mode[4] = { 0 };
char lm[MAX_NAME+1] = { 0 };
char result[MAX_NAME+1] = { 0 };
char lm_rv[MAX_NAME+1] = { 0 };
char lm_type[MAX_NAME+1] = { 0 };
int result = 0;
int lm_rv = 0;
uint32_t pid = 0;
char cl_name[MAX_NAME+1] = { 0 };
@@ -241,8 +423,19 @@ static void format_info_r_action(char *line, char *r_name, char *r_type)
return;
}
(void) sscanf(line, "info=r_action client_id=%u %s %s op=%s rt=%s mode=%s %s %s %s",
&client_id, flags, version, op, rt, mode, lm, result, lm_rv);
/* info=r_action client_id=%u flags=%s version=%s op=%s rt=%s mode=%s lm_type=%s result=%d lm_rv=%d */
if (szscanf(line, "info=r_action client_id=%u flags=%s version=%s op=%s rt=%s mode=%s lm_type=%s result=%d lm_rv=%d",
&client_id,
sizeof(flags), flags,
sizeof(version), version,
sizeof(op), op,
sizeof(rt), rt,
sizeof(mode), mode,
sizeof(lm_type), lm_type,
&result,
&lm_rv) < 0)
return;
find_client_info(client_id, &pid, cl_name);
@@ -264,19 +457,19 @@ static void format_info_r_action(char *line, char *r_name, char *r_type)
static void format_info_line(char *line, char *r_name, char *r_type)
{
if (!strncmp(line, "info=structs ", strlen("info=structs "))) {
if (!strncmp(line, "info=structs ", sizeof("info=structs ") - 1)) {
/* only print this in the raw info dump */
} else if (!strncmp(line, "info=client ", strlen("info=client "))) {
} else if (!strncmp(line, "info=client ", sizeof("info=client ") - 1)) {
save_client_info(line);
} else if (!strncmp(line, "info=ls ", strlen("info=ls "))) {
} else if (!strncmp(line, "info=ls ", sizeof("info=ls ") - 1)) {
format_info_ls(line);
} else if (!strncmp(line, "info=ls_action ", strlen("info=ls_action "))) {
} else if (!strncmp(line, "info=ls_action ", sizeof("info=ls_action ") - 1)) {
format_info_ls_action(line);
} else if (!strncmp(line, "info=r ", strlen("info=r "))) {
} else if (!strncmp(line, "info=r ", sizeof("info=r ") - 1)) {
/*
* r_name/r_type are reset when a new resource is found.
* They are reused for the lock and action lines that
@@ -286,11 +479,11 @@ static void format_info_line(char *line, char *r_name, char *r_type)
memset(r_type, 0, MAX_NAME+1);
format_info_r(line, r_name, r_type);
} else if (!strncmp(line, "info=lk ", strlen("info=lk "))) {
} else if (!strncmp(line, "info=lk ", sizeof("info=lk ") - 1)) {
/* will use info from previous r */
format_info_lk(line, r_name, r_type);
} else if (!strncmp(line, "info=r_action ", strlen("info=r_action "))) {
} else if (!strncmp(line, "info=r_action ", sizeof("info=r_action ") - 1)) {
/* will use info from previous r */
format_info_r_action(line, r_name, r_type);
} else {
@@ -940,7 +1133,7 @@ static int read_options(int argc, char *argv[])
int option_index = 0;
int c;
static struct option long_options[] = {
static const struct option _long_options[] = {
{"help", no_argument, 0, 'h' },
{"quit", no_argument, 0, 'q' },
{"info", no_argument, 0, 'i' },
@@ -962,7 +1155,7 @@ static int read_options(int argc, char *argv[])
}
while (1) {
c = getopt_long(argc, argv, "hqidE:D:w:k:r:Se", long_options, &option_index);
c = getopt_long(argc, argv, "hqidE:D:w:k:r:Se", _long_options, &option_index);
if (c == -1)
break;

View File

@@ -16,6 +16,8 @@
#define LVMLOCKD_SOCKET DEFAULT_RUN_DIR "/lvmlockd.socket"
#define LVMLOCKD_ADOPT_FILE DEFAULT_RUN_DIR "/lvmlockd.adopt"
#define LVMLOCKD_USE_SANLOCK_LVB 0
/* Wrappers to open/close connection */
static inline __attribute__((always_inline))
@@ -52,5 +54,10 @@ static inline void lvmlockd_close(daemon_handle h)
#define EREMOVED 219
#define EDEVOPEN 220 /* sanlock failed to open lvmlock LV */
#define ELMERR 221
#define EORPHAN 222
#define EADOPT_NONE 223
#define EADOPT_RETRY 224
#define EIOTIMEOUT 225
#define ELOCKREPAIR 226
#endif /* _LVM_LVMLOCKD_CLIENT_H */

File diff suppressed because it is too large Load Diff

View File

@@ -13,7 +13,7 @@
#include "tools/tool.h"
#include "daemon-server.h"
#include "libdaemon/server/daemon-server.h"
#include "lib/mm/xlate.h"
#include "lvmlockd-internal.h"
@@ -31,7 +31,6 @@
#include <errno.h>
#include <endian.h>
#include <fcntl.h>
#include <byteswap.h>
#include <syslog.h>
#include <dirent.h>
@@ -96,7 +95,6 @@ static int check_args_version(char *vg_args)
static int read_cluster_name(char *clustername)
{
static const char close_error_msg[] = "read_cluster_name: close_error %d";
char *n;
int fd;
int rv;
@@ -115,18 +113,19 @@ static int read_cluster_name(char *clustername)
rv = read(fd, clustername, MAX_ARGS);
if (rv < 0) {
log_error("read_cluster_name: cluster name read error %d, check dlm_controld", fd);
if (close(fd))
log_error(close_error_msg, fd);
return rv;
goto out;
}
clustername[rv] = 0;
n = strstr(clustername, "\n");
if (n)
*n = '\0';
rv = 0;
out:
if (close(fd))
log_error(close_error_msg, fd);
return 0;
log_error("read_cluster_name: close_error %d", fd);
return rv;
}
#define MAX_VERSION 16
@@ -169,8 +168,10 @@ int lm_prepare_lockspace_dlm(struct lockspace *ls)
struct lm_dlm *lmd;
int rv;
if (daemon_test)
if (daemon_test) {
log_debug("lm_prepare_lockspace_dlm test");
goto skip_args;
}
memset(sys_clustername, 0, sizeof(sys_clustername));
memset(arg_clustername, 0, sizeof(arg_clustername));
@@ -305,20 +306,27 @@ fail:
return rv;
}
int lm_add_lockspace_dlm(struct lockspace *ls, int adopt)
int lm_add_lockspace_dlm(struct lockspace *ls, int adopt_only, int adopt_ok)
{
struct lm_dlm *lmd = (struct lm_dlm *)ls->lm_data;
if (daemon_test)
return 0;
if (adopt)
if (adopt_only || adopt_ok) {
lmd->dh = dlm_open_lockspace(ls->name);
else
if (!lmd->dh && adopt_ok)
lmd->dh = dlm_new_lockspace(ls->name, 0600, DLM_LSFL_NEWEXCL);
if (!lmd->dh)
log_error("add_lockspace_dlm adopt_only %d adopt_ok %d %s error",
adopt_only, adopt_ok, ls->name);
} else {
lmd->dh = dlm_new_lockspace(ls->name, 0600, DLM_LSFL_NEWEXCL);
if (!lmd->dh)
log_error("add_lockspace_dlm %s error", ls->name);
}
if (!lmd->dh) {
log_error("add_lockspace_dlm %s adopt %d error", ls->name, adopt);
free(lmd);
ls->lm_data = NULL;
return -1;
@@ -354,7 +362,7 @@ int lm_rem_lockspace_dlm(struct lockspace *ls, int free_vg)
return 0;
}
static int lm_add_resource_dlm(struct lockspace *ls, struct resource *r, int with_lock_nl)
int lm_add_resource_dlm(struct lockspace *ls, struct resource *r, int with_lock_nl)
{
struct lm_dlm *lmd = (struct lm_dlm *)ls->lm_data;
struct rd_dlm *rdd = (struct rd_dlm *)r->lm_data;
@@ -386,7 +394,7 @@ static int lm_add_resource_dlm(struct lockspace *ls, struct resource *r, int wit
r->name, strlen(r->name),
0, NULL, NULL, NULL);
if (rv < 0) {
log_error("S %s R %s add_resource_dlm lock error %d", ls->name, r->name, rv);
log_error("%s:%s add_resource_dlm lock error %d", ls->name, r->name, rv);
return rv;
}
out:
@@ -410,7 +418,7 @@ int lm_rem_resource_dlm(struct lockspace *ls, struct resource *r)
rv = dlm_ls_unlock_wait(lmd->dh, lksb->sb_lkid, 0, lksb);
if (rv < 0) {
log_error("S %s R %s rem_resource_dlm unlock error %d", ls->name, r->name, rv);
log_error("%s:%s rem_resource_dlm unlock error %d", ls->name, r->name, rv);
}
out:
free(rdd->vb);
@@ -465,7 +473,7 @@ static int lm_adopt_dlm(struct lockspace *ls, struct resource *r, int ld_mode,
goto fail;
}
log_debug("S %s R %s adopt_dlm", ls->name, r->name);
log_debug("%s:%s adopt_dlm", ls->name, r->name);
if (daemon_test)
return 0;
@@ -474,29 +482,29 @@ static int lm_adopt_dlm(struct lockspace *ls, struct resource *r, int ld_mode,
* dlm returns 0 for success, -EAGAIN if an orphan is
* found with another mode, and -ENOENT if no orphan.
*
* cast/bast/param are (void *)1 because the kernel
* cast/bast/param are (void (*)(void*))1 because the kernel
* returns errors if some are null.
*/
rv = dlm_ls_lockx(lmd->dh, mode, lksb, flags,
r->name, strlen(r->name), 0,
(void *)1, (void *)1, (void *)1,
(void (*)(void*))1, (void (*)(void*))1, (void (*)(void*))1,
NULL, NULL);
if (rv == -1 && (errno == EAGAIN)) {
log_debug("S %s R %s adopt_dlm adopt mode %d try other mode",
log_debug("%s:%s adopt_dlm adopt mode %d try other mode",
ls->name, r->name, ld_mode);
rv = -EUCLEAN;
rv = -EADOPT_RETRY;
goto fail;
}
if (rv == -1 && (errno == ENOENT)) {
log_debug("S %s R %s adopt_dlm adopt mode %d no lock",
log_debug("%s:%s adopt_dlm adopt mode %d no lock",
ls->name, r->name, ld_mode);
rv = -ENOENT;
rv = -EADOPT_NONE;
goto fail;
}
if (rv < 0) {
log_debug("S %s R %s adopt_dlm mode %d flags %x error %d errno %d",
log_debug("%s:%s adopt_dlm mode %d flags %x error %d errno %d",
ls->name, r->name, mode, flags, rv, errno);
goto fail;
}
@@ -526,7 +534,7 @@ static int lm_adopt_dlm(struct lockspace *ls, struct resource *r, int ld_mode,
*/
int lm_lock_dlm(struct lockspace *ls, struct resource *r, int ld_mode,
struct val_blk *vb_out, int adopt)
struct val_blk *vb_out, int adopt_only, int adopt_ok)
{
struct lm_dlm *lmd = (struct lm_dlm *)ls->lm_data;
struct rd_dlm *rdd = (struct rd_dlm *)r->lm_data;
@@ -536,7 +544,13 @@ int lm_lock_dlm(struct lockspace *ls, struct resource *r, int ld_mode,
int mode;
int rv;
if (adopt) {
if (adopt_ok) {
log_debug("%s:%s lock_dlm adopt_ok not supported", ls->name, r->name);
return -1;
}
if (adopt_only) {
log_debug("%s:%s lock_dlm adopt_only", ls->name, r->name);
/* When adopting, we don't follow the normal method
of acquiring a NL lock then converting it to the
desired mode. */
@@ -565,13 +579,13 @@ int lm_lock_dlm(struct lockspace *ls, struct resource *r, int ld_mode,
return -EINVAL;
}
log_debug("S %s R %s lock_dlm", ls->name, r->name);
log_debug("%s:%s lock_dlm", ls->name, r->name);
if (daemon_test) {
if (rdd->vb) {
vb_out->version = le16_to_cpu(rdd->vb->version);
vb_out->flags = le16_to_cpu(rdd->vb->flags);
vb_out->r_version = le32_to_cpu(rdd->vb->r_version);
vb_out->version = le16toh(rdd->vb->version);
vb_out->flags = le16toh(rdd->vb->flags);
vb_out->r_version = le32toh(rdd->vb->r_version);
}
return 0;
}
@@ -585,7 +599,7 @@ int lm_lock_dlm(struct lockspace *ls, struct resource *r, int ld_mode,
r->name, strlen(r->name),
0, NULL, NULL, NULL);
if (rv == -1) {
log_debug("S %s R %s lock_dlm acquire mode PR for %d rv %d",
log_debug("%s:%s lock_dlm acquire mode PR for %d rv %d",
ls->name, r->name, mode, rv);
goto lockrv;
}
@@ -598,17 +612,17 @@ int lm_lock_dlm(struct lockspace *ls, struct resource *r, int ld_mode,
0, NULL, NULL, NULL);
lockrv:
if (rv == -1 && errno == EAGAIN) {
log_debug("S %s R %s lock_dlm acquire mode %d rv EAGAIN", ls->name, r->name, mode);
log_debug("%s:%s lock_dlm acquire mode %d rv EAGAIN", ls->name, r->name, mode);
return -EAGAIN;
}
if (rv < 0) {
log_error("S %s R %s lock_dlm acquire error %d errno %d", ls->name, r->name, rv, errno);
log_error("%s:%s lock_dlm acquire error %d errno %d", ls->name, r->name, rv, errno);
return -ELMERR;
}
if (rdd->vb) {
if (lksb->sb_flags & DLM_SBF_VALNOTVALID) {
log_debug("S %s R %s lock_dlm VALNOTVALID", ls->name, r->name);
log_debug("%s:%s lock_dlm VALNOTVALID", ls->name, r->name);
memset(rdd->vb, 0, sizeof(struct val_blk));
memset(vb_out, 0, sizeof(struct val_blk));
goto out;
@@ -623,9 +637,9 @@ lockrv:
memcpy(&vb, lksb->sb_lvbptr, sizeof(struct val_blk));
memcpy(rdd->vb, &vb, sizeof(vb));
vb_out->version = le16_to_cpu(vb.version);
vb_out->flags = le16_to_cpu(vb.flags);
vb_out->r_version = le32_to_cpu(vb.r_version);
vb_out->version = le16toh(vb.version);
vb_out->flags = le16toh(vb.flags);
vb_out->r_version = le32toh(vb.r_version);
}
out:
return 0;
@@ -641,7 +655,7 @@ int lm_convert_dlm(struct lockspace *ls, struct resource *r,
uint32_t flags = 0;
int rv;
log_debug("S %s R %s convert_dlm", ls->name, r->name);
log_debug("%s:%s convert_dlm", ls->name, r->name);
flags |= LKF_CONVERT;
flags |= LKF_NOQUEUE;
@@ -650,12 +664,12 @@ int lm_convert_dlm(struct lockspace *ls, struct resource *r,
if (rdd->vb && r_version && (r->mode == LD_LK_EX)) {
if (!rdd->vb->version) {
/* first time vb has been written */
rdd->vb->version = cpu_to_le16(VAL_BLK_VERSION);
rdd->vb->version = htole16(VAL_BLK_VERSION);
}
rdd->vb->r_version = cpu_to_le32(r_version);
rdd->vb->r_version = htole32(r_version);
memcpy(lksb->sb_lvbptr, rdd->vb, sizeof(struct val_blk));
log_debug("S %s R %s convert_dlm set r_version %u",
log_debug("%s:%s convert_dlm set r_version %u",
ls->name, r->name, r_version);
flags |= LKF_VALBLK;
@@ -673,11 +687,11 @@ int lm_convert_dlm(struct lockspace *ls, struct resource *r,
0, NULL, NULL, NULL);
if (rv == -1 && errno == EAGAIN) {
/* FIXME: When does this happen? Should something different be done? */
log_error("S %s R %s convert_dlm mode %d rv EAGAIN", ls->name, r->name, mode);
log_error("%s:%s convert_dlm mode %d rv EAGAIN", ls->name, r->name, mode);
return -EAGAIN;
}
if (rv < 0) {
log_error("S %s R %s convert_dlm error %d", ls->name, r->name, rv);
log_error("%s:%s convert_dlm error %d", ls->name, r->name, rv);
rv = -ELMERR;
}
return rv;
@@ -709,17 +723,17 @@ int lm_unlock_dlm(struct lockspace *ls, struct resource *r,
memcpy(&vb_next, rdd->vb, sizeof(struct val_blk));
if (!vb_prev.version) {
vb_next.version = cpu_to_le16(VAL_BLK_VERSION);
vb_next.version = htole16(VAL_BLK_VERSION);
new_vb = 1;
}
if ((lmu_flags & LMUF_FREE_VG) && (r->type == LD_RT_VG)) {
vb_next.flags = cpu_to_le16(VBF_REMOVED);
vb_next.flags = htole16(VBF_REMOVED);
new_vb = 1;
}
if (r_version) {
vb_next.r_version = cpu_to_le32(r_version);
vb_next.r_version = htole32(r_version);
new_vb = 1;
}
@@ -727,21 +741,21 @@ int lm_unlock_dlm(struct lockspace *ls, struct resource *r,
memcpy(rdd->vb, &vb_next, sizeof(struct val_blk));
memcpy(lksb->sb_lvbptr, &vb_next, sizeof(struct val_blk));
log_debug("S %s R %s unlock_dlm vb old %x %x %u new %x %x %u",
log_debug("%s:%s unlock_dlm vb old %x %x %u new %x %x %u",
ls->name, r->name,
le16_to_cpu(vb_prev.version),
le16_to_cpu(vb_prev.flags),
le32_to_cpu(vb_prev.r_version),
le16_to_cpu(vb_next.version),
le16_to_cpu(vb_next.flags),
le32_to_cpu(vb_next.r_version));
le16toh(vb_prev.version),
le16toh(vb_prev.flags),
le32toh(vb_prev.r_version),
le16toh(vb_next.version),
le16toh(vb_next.flags),
le32toh(vb_next.r_version));
} else {
log_debug("S %s R %s unlock_dlm vb unchanged", ls->name, r->name);
log_debug("%s:%s unlock_dlm vb unchanged", ls->name, r->name);
}
flags |= LKF_VALBLK;
} else {
log_debug("S %s R %s unlock_dlm", ls->name, r->name);
log_debug("%s:%s unlock_dlm", ls->name, r->name);
}
if (daemon_test)
@@ -751,7 +765,7 @@ int lm_unlock_dlm(struct lockspace *ls, struct resource *r,
r->name, strlen(r->name),
0, NULL, NULL, NULL);
if (rv < 0) {
log_error("S %s R %s unlock_dlm error %d", ls->name, r->name, rv);
log_error("%s:%s unlock_dlm error %d", ls->name, r->name, rv);
rv = -ELMERR;
}
@@ -784,9 +798,16 @@ int lm_unlock_dlm(struct lockspace *ls, struct resource *r,
* the stale lockspaces on the others eventually.)
*/
/*
* On error, returns < 0
*
* On success:
* If other hosts are found, returns the number.
* If no other hosts are found (only ourself), returns 0.
*/
int lm_hosts_dlm(struct lockspace *ls, int notify)
{
static const char closedir_err_msg[] = "lm_hosts_dlm: closedir failed";
char ls_nodes_path[PATH_MAX];
struct dirent *de;
DIR *ls_dir;
@@ -809,7 +830,7 @@ int lm_hosts_dlm(struct lockspace *ls, int notify)
}
if (closedir(ls_dir))
log_error(closedir_err_msg);
log_error("lm_hosts_dlm: closedir failed");
if (!count) {
log_error("lm_hosts_dlm found no nodes in %s", ls_nodes_path);
@@ -826,10 +847,10 @@ int lm_hosts_dlm(struct lockspace *ls, int notify)
int lm_get_lockspaces_dlm(struct list_head *ls_rejoin)
{
static const char closedir_err_msg[] = "lm_get_lockspace_dlm: closedir failed";
struct lockspace *ls;
struct dirent *de;
DIR *ls_dir;
int ret = 0;
if (!(ls_dir = opendir(DLM_LOCKSPACES_PATH)))
return -ECONNREFUSED;
@@ -842,9 +863,8 @@ int lm_get_lockspaces_dlm(struct list_head *ls_rejoin)
continue;
if (!(ls = alloc_lockspace())) {
if (closedir(ls_dir))
log_error(closedir_err_msg);
return -ENOMEM;
ret = -ENOMEM;
goto out;
}
ls->lm_type = LD_LM_DLM;
@@ -852,10 +872,11 @@ int lm_get_lockspaces_dlm(struct list_head *ls_rejoin)
dm_strncpy(ls->vg_name, ls->name + strlen(LVM_LS_PREFIX), sizeof(ls->vg_name));
list_add_tail(&ls->list, ls_rejoin);
}
out:
if (closedir(ls_dir))
log_error(closedir_err_msg);
return 0;
log_error("lm_get_lockspace_dlm: closedir failed");
return ret;
}
int lm_is_running_dlm(void)

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

View File

@@ -13,6 +13,9 @@
#include "base/memory/container_of.h"
#include <stdint.h>
#include <pthread.h>
#define MAX_NAME 64
#define MAX_ARGS 64
@@ -59,6 +62,7 @@ enum {
LD_OP_BUSY,
LD_OP_QUERY_LOCK,
LD_OP_REFRESH_LV,
LD_OP_VG_STATUS,
};
/* resource types */
@@ -107,11 +111,14 @@ struct client {
#define LD_AF_SEARCH_LS 0x00000200
#define LD_AF_WAIT_STARTING 0x00001000
#define LD_AF_DUP_GL_LS 0x00002000
#define LD_AF_ADOPT 0x00010000
#define LD_AF_ADOPT 0x00010000 /* adopt ok but not required */
#define LD_AF_WARN_GL_REMOVED 0x00020000
#define LD_AF_LV_LOCK 0x00040000
#define LD_AF_LV_UNLOCK 0x00080000
#define LD_AF_SH_EXISTS 0x00100000
#define LD_AF_ADOPT_ONLY 0x00200000 /* adopt orphan or fail */
#define LD_AF_NODELAY 0x00400000
#define LD_AF_REPAIR 0x00800000
/*
* Number of times to repeat a lock request after
@@ -125,12 +132,24 @@ struct pvs {
int num;
};
#define OWNER_NAME_SIZE 64
#define OWNER_STATE_SIZE 32
struct owner {
uint32_t host_id;
uint32_t generation;
uint32_t timestamp;
char state[OWNER_STATE_SIZE];
char name[OWNER_NAME_SIZE];
};
struct action {
struct list_head list;
uint32_t client_id;
uint32_t flags; /* LD_AF_ */
uint32_t version;
uint64_t host_id;
uint32_t host_id;
uint64_t lv_size_bytes;
int8_t op; /* operation type LD_OP_ */
int8_t rt; /* resource type LD_RT_ */
int8_t mode; /* lock mode LD_LK_ */
@@ -139,6 +158,7 @@ struct action {
int max_retries;
int result;
int lm_rv; /* return value from lm_ function */
int align_mb;
char *path;
char vg_uuid[64];
char vg_name[MAX_NAME+1];
@@ -146,7 +166,8 @@ struct action {
char lv_uuid[MAX_NAME+1];
char vg_args[MAX_ARGS+1];
char lv_args[MAX_ARGS+1];
char vg_sysid[MAX_NAME+1];
char prev_lv_args[MAX_ARGS+1];
struct owner owner;
struct pvs pvs; /* PV list for idm */
};
@@ -159,6 +180,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;
@@ -185,13 +207,11 @@ struct lockspace {
char vg_name[MAX_NAME+1];
char vg_uuid[64];
char vg_args[MAX_ARGS+1]; /* lock manager specific args */
char vg_sysid[MAX_NAME+1];
int8_t lm_type; /* lock manager: LM_DLM, LM_SANLOCK */
void *lm_data;
uint64_t host_id;
uint32_t host_id;
uint64_t generation;
uint64_t free_lock_offset; /* for sanlock, start search for free lock here */
int free_lock_sector_size; /* for sanlock */
int free_lock_align_size; /* for sanlock */
struct pvs pvs; /* for idm: PV list */
uint32_t start_client_id; /* client_id that started the lockspace */
@@ -211,6 +231,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 */
@@ -277,15 +298,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 */
@@ -393,11 +414,12 @@ static inline const char *mode_str(int x)
int lm_init_vg_dlm(char *ls_name, char *vg_name, uint32_t flags, char *vg_args);
int lm_prepare_lockspace_dlm(struct lockspace *ls);
int lm_add_lockspace_dlm(struct lockspace *ls, int adopt);
int lm_add_lockspace_dlm(struct lockspace *ls, int adopt_only, int adopt_ok);
int lm_purge_locks_dlm(struct lockspace *ls);
int lm_rem_lockspace_dlm(struct lockspace *ls, int free_vg);
int lm_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);
struct val_blk *vb_out, int adopt_only, int adopt_ok);
int lm_convert_dlm(struct lockspace *ls, struct resource *r,
int ld_mode, uint32_t r_version);
int lm_unlock_dlm(struct lockspace *ls, struct resource *r,
@@ -419,69 +441,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)
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)
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;
}
@@ -504,15 +559,17 @@ static inline int lm_refresh_lv_check_dlm(struct action *act)
#ifdef LOCKDSANLOCK_SUPPORT
int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_args);
int lm_init_lv_sanlock(char *ls_name, char *vg_name, char *lv_name, char *vg_args, char *lv_args, int sector_size, int align_size, uint64_t free_offset);
int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_args, int opt_align_mb);
int lm_init_lv_sanlock(struct lockspace *ls, char *ls_name, char *vg_name, char *lv_name, char *vg_args, char *lv_args, char *prev_args);
int lm_free_lv_sanlock(struct lockspace *ls, struct resource *r);
int lm_rename_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_args);
int lm_prepare_lockspace_sanlock(struct lockspace *ls);
int lm_add_lockspace_sanlock(struct lockspace *ls, int adopt);
int lm_prepare_lockspace_sanlock(struct lockspace *ls, uint64_t *prev_generation, int repair);
int lm_add_lockspace_sanlock(struct lockspace *ls, int adopt_only, int adopt_ok, int nodelay);
int lm_rem_lockspace_sanlock(struct lockspace *ls, int free_vg);
int lm_add_resource_sanlock(struct lockspace *ls, struct resource *r);
int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode,
struct val_blk *vb_out, int *retry, int adopt);
struct val_blk *vb_out, int *retry, struct owner *owner,
int adopt_only, int adopt_ok, int repair);
int lm_convert_sanlock(struct lockspace *ls, struct resource *r,
int ld_mode, uint32_t r_version);
int lm_unlock_sanlock(struct lockspace *ls, struct resource *r,
@@ -525,7 +582,8 @@ int lm_gl_is_enabled(struct lockspace *ls);
int lm_get_lockspaces_sanlock(struct list_head *ls_rejoin);
int lm_data_size_sanlock(void);
int lm_is_running_sanlock(void);
int lm_find_free_lock_sanlock(struct lockspace *ls, uint64_t *free_offset, int *sector_size, int *align_size);
int lm_find_free_lock_sanlock(struct lockspace *ls, uint64_t lv_size_bytes);
int lm_vg_status_sanlock(struct lockspace *ls, struct action *act);
static inline int lm_support_sanlock(void)
{
@@ -534,12 +592,12 @@ static inline int lm_support_sanlock(void)
#else
static inline int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_args)
static inline int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_args, int opt_align_mb)
{
return -1;
}
static inline int lm_init_lv_sanlock(char *ls_name, char *vg_name, char *lv_name, char *vg_args, char *lv_args, int sector_size, int align_size, uint64_t free_offset)
static inline int lm_init_lv_sanlock(struct lockspace *ls, char *ls_name, char *vg_name, char *lv_name, char *vg_args, char *lv_args, char *prev_args)
{
return -1;
}
@@ -554,12 +612,12 @@ static inline int lm_rename_vg_sanlock(char *ls_name, char *vg_name, uint32_t fl
return -1;
}
static inline int lm_prepare_lockspace_sanlock(struct lockspace *ls)
static inline int lm_prepare_lockspace_sanlock(struct lockspace *ls, uint64_t *prev_generation, int repair)
{
return -1;
}
static inline int lm_add_lockspace_sanlock(struct lockspace *ls, int adopt)
static inline int lm_add_lockspace_sanlock(struct lockspace *ls, int adopt_only, int adopt_ok, int nodelay)
{
return -1;
}
@@ -569,8 +627,14 @@ static inline int lm_rem_lockspace_sanlock(struct lockspace *ls, int free_vg)
return -1;
}
static inline int lm_add_resource_sanlock(struct lockspace *ls, struct resource *r)
{
return -1;
}
static inline int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode,
struct val_blk *vb_out, int *retry, int adopt)
struct val_blk *vb_out, int *retry, struct owner *owner,
int adopt_only, int adopt_ok, int repair)
{
return -1;
}
@@ -627,7 +691,12 @@ static inline int lm_is_running_sanlock(void)
return 0;
}
static inline int lm_find_free_lock_sanlock(struct lockspace *ls, uint64_t *free_offset, int *sector_size, int *align_size)
static inline int lm_find_free_lock_sanlock(struct lockspace *ls, uint64_t lv_size_bytes)
{
return -1;
}
static inline int lm_vg_status_sanlock(struct lockspace *ls, struct action *act)
{
return -1;
}
@@ -644,11 +713,12 @@ static inline int lm_support_sanlock(void)
int lm_data_size_idm(void);
int lm_init_vg_idm(char *ls_name, char *vg_name, uint32_t flags, char *vg_args);
int lm_prepare_lockspace_idm(struct lockspace *ls);
int lm_add_lockspace_idm(struct lockspace *ls, int adopt);
int lm_add_lockspace_idm(struct lockspace *ls, int adopt_only, int adopt_ok);
int lm_rem_lockspace_idm(struct lockspace *ls, int free_vg);
int lm_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);
int adopt_only, int adopt_ok);
int lm_convert_idm(struct lockspace *ls, struct resource *r,
int ld_mode, uint32_t r_version);
int lm_unlock_idm(struct lockspace *ls, struct resource *r,
@@ -681,7 +751,7 @@ static inline int lm_prepare_lockspace_idm(struct lockspace *ls)
return -1;
}
static inline int lm_add_lockspace_idm(struct lockspace *ls, int adopt)
static inline int lm_add_lockspace_idm(struct lockspace *ls, int adopt_only, int adopt_ok)
{
return -1;
}
@@ -691,9 +761,14 @@ 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)
int adopt_only, int adopt_ok)
{
return -1;
}

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

@@ -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;
@@ -68,7 +71,7 @@ struct lvmpolld_lv {
struct lvmpolld_cmd_stat cmd_state;
unsigned init_rq_count; /* for debugging purposes only */
unsigned polling_finished:1; /* no more updates */
unsigned error:1; /* unrecoverable error occured in lvmpolld */
unsigned error:1; /* unrecoverable error occurred in lvmpolld */
};
typedef void (*lvmpolld_parse_output_fn_t) (struct lvmpolld_lv *pdlv, const char *line);
@@ -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

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

View File

@@ -25,6 +25,7 @@ DEVICE_MAPPER_SOURCE=\
device_mapper/libdm-targets.c \
device_mapper/libdm-timestamp.c \
device_mapper/mm/pool.c \
device_mapper/raid/raid_parser.c \
device_mapper/regex/matcher.c \
device_mapper/regex/parse_rx.c \
device_mapper/regex/ttree.c \
@@ -48,6 +49,6 @@ $(DEVICE_MAPPER_TARGET): $(DEVICE_MAPPER_OBJECTS)
$(Q) $(RM) $@
$(Q) $(AR) rsv $@ $(DEVICE_MAPPER_OBJECTS) > /dev/null
ifeq ("$(DEPENDS)","yes")
ifeq ("$(USE_TRACKING)","yes")
-include $(DEVICE_MAPPER_DEPENDS)
endif

View File

@@ -19,6 +19,7 @@
#include "base/data-struct/list.h"
#include "base/data-struct/hash.h"
#include "raid/target.h"
#include "vdo/target.h"
#include <inttypes.h>
@@ -175,12 +176,11 @@ struct dm_names {
struct dm_active_device {
struct dm_list list;
int major;
int minor;
char *name; /* device name */
dev_t devno;
const char *name; /* device name */
uint32_t event_nr; /* valid when DM_DEVICE_LIST_HAS_EVENT_NR is set */
char *uuid; /* valid uuid when DM_DEVICE_LIST_HAS_UUID is set */
const char *uuid; /* valid uuid when DM_DEVICE_LIST_HAS_UUID is set */
};
struct dm_versions {
@@ -192,7 +192,7 @@ struct dm_versions {
int dm_get_library_version(char *version, size_t size);
int dm_task_get_driver_version(struct dm_task *dmt, char *version, size_t size);
int dm_task_get_info(struct dm_task *dmt, struct dm_info *dmi);
int dm_task_get_info(struct dm_task *dmt, struct dm_info *info);
/*
* This function returns dm device's UUID based on the value
@@ -230,13 +230,6 @@ struct dm_names *dm_task_get_names(struct dm_task *dmt);
#define DM_DEVICE_LIST_HAS_UUID 2
int dm_task_get_device_list(struct dm_task *dmt, struct dm_list **devs_list,
unsigned *devs_features);
/*
* -1: no idea about uuid (not provided by DM_DEVICE_LIST ioctl)
* 0: uuid not present
* 1: listed and dm_active_device will be set for not NULL pointer
*/
int dm_device_list_find_by_uuid(struct dm_list *devs_list, const char *uuid,
const struct dm_active_device **dev);
/* Release all associated memory with list of active DM devices */
void dm_device_list_destroy(struct dm_list **devs_list);
@@ -312,15 +305,15 @@ int dm_task_add_target(struct dm_task *dmt,
#define DM_FORMAT_DEV_BUFSIZE 13 /* Minimum bufsize to handle worst case. */
int dm_format_dev(char *buf, int bufsize, uint32_t dev_major, uint32_t dev_minor);
/* Use this to retrive target information returned from a STATUS call */
/* Use this to retrieve target information returned from a STATUS call */
void *dm_get_next_target(struct dm_task *dmt,
void *next, uint64_t *start, uint64_t *length,
char **target_type, char **params);
/*
* Following dm_get_status_* functions will allocate approriate status structure
* Following dm_get_status_* functions will allocate appropriate status structure
* from passed mempool together with the necessary character arrays.
* Destroying the mempool will release all asociated allocation.
* Destroying the mempool will release all associated allocation.
*/
/* Parse params from STATUS call for mirror target */
@@ -549,7 +542,7 @@ const char *dm_sysfs_dir(void);
/*
* Configure default UUID prefix string.
* Conventionally this is a short capitalised prefix indicating the subsystem
* Conventionally this is a short capitalized prefix indicating the subsystem
* that is managing the devices, e.g. "LVM-" or "MPATH-".
* To support stacks of devices from different subsystems, recursive functions
* stop recursing if they reach a device with a different prefix.
@@ -592,7 +585,7 @@ int dm_device_has_mounted_fs(uint32_t major, uint32_t minor);
/*
* Callback is invoked for individal mountinfo lines,
* Callback is invoked for individual mountinfo lines,
* minor, major and mount target are parsed and unmangled.
*/
typedef int (*dm_mountinfo_line_callback_fn) (char *line, unsigned maj, unsigned min,
@@ -706,7 +699,7 @@ void *dm_tree_node_get_context(const struct dm_tree_node *node);
/*
* Returns 0 when node size and its children is unchanged.
* Returns 1 when node or any of its children has increased size.
* Rerurns -1 when node or any of its children has reduced size.
* Returns -1 when node or any of its children has reduced size.
*/
int dm_tree_node_size_changed(const struct dm_tree_node *dnode);
@@ -893,7 +886,7 @@ struct dm_tree_node_raid_params {
};
/*
* Version 2 of above node raid params struct to keeep API compatibility.
* Version 2 of above node raid params struct to keep API compatibility.
*
* Extended for more than 64 legs (max 253 in the MD kernel runtime!),
* delta_disks for disk add/remove reshaping,
@@ -916,7 +909,7 @@ struct dm_tree_node_raid_params_v2 {
* 'rebuilds' and 'writemostly' are bitfields that signify
* which devices in the array are to be rebuilt or marked
* writemostly. The kernel supports up to 253 legs.
* We limit ourselvs by choosing a lower value
* We limit ourselves by choosing a lower value
* for DEFAULT_RAID_MAX_IMAGES.
*/
uint64_t rebuilds[RAID_BITMAP_SIZE];
@@ -953,7 +946,7 @@ struct dm_config_node;
*
* policy_settings {
* migration_threshold=2048
* sequention_threashold=100
* sequential_threshold=100
* ...
* }
*
@@ -1031,6 +1024,7 @@ struct integrity_settings {
uint32_t commit_time;
uint32_t bitmap_flush_interval;
uint64_t sectors_per_bit;
uint32_t allow_discards;
unsigned journal_sectors_set:1;
unsigned interleave_sectors_set:1;
@@ -1039,6 +1033,7 @@ struct integrity_settings {
unsigned commit_time_set:1;
unsigned bitmap_flush_interval_set:1;
unsigned sectors_per_bit_set:1;
unsigned allow_discards_set:1;
};
int dm_tree_node_add_integrity_target(struct dm_tree_node *node,
@@ -1057,7 +1052,7 @@ int dm_tree_node_add_vdo_target(struct dm_tree_node *node,
const char *vdo_pool_name,
const char *data_uuid,
uint64_t data_size,
const struct dm_vdo_target_params *param);
const struct dm_vdo_target_params *vtp);
/*
* FIXME Add individual cache policy pairs <key> = value, like:
@@ -1100,7 +1095,7 @@ int dm_tree_node_add_replicator_dev_target(struct dm_tree_node *node,
/* End of Replicator API */
/*
* FIXME: Defines bellow are based on kernel's dm-thin.c defines
* FIXME: Defines below are based on kernel's dm-thin.c defines
* DATA_DEV_BLOCK_SIZE_MIN_SECTORS (64 * 1024 >> SECTOR_SHIFT)
* DATA_DEV_BLOCK_SIZE_MAX_SECTORS (1024 * 1024 * 1024 >> SECTOR_SHIFT)
*/
@@ -1166,7 +1161,7 @@ int dm_tree_node_set_thin_pool_error_if_no_space(struct dm_tree_node *node,
int dm_tree_node_set_thin_pool_read_only(struct dm_tree_node *node,
unsigned read_only);
/*
* FIXME: Defines bellow are based on kernel's dm-thin.c defines
* FIXME: Defines below are based on kernel's dm-thin.c defines
* MAX_DEV_ID ((1 << 24) - 1)
*/
#define DM_THIN_MAX_DEVICE_ID (UINT32_C((1 << 24) - 1))
@@ -1184,9 +1179,9 @@ void dm_tree_node_set_presuspend_node(struct dm_tree_node *node,
struct dm_tree_node *presuspend_node);
int dm_tree_node_add_target_area(struct dm_tree_node *node,
const char *dev_name,
const char *dlid,
uint64_t offset);
const char *dev_name,
const char *uuid,
uint64_t offset);
/*
* Only for temporarily-missing raid devices where changes are tracked.
@@ -1596,9 +1591,9 @@ int dm_fclose(FILE *stream);
* Pointer to the buffer is stored in *buf.
* Returns -1 on failure leaving buf undefined.
*/
int dm_asprintf(char **buf, const char *format, ...)
int dm_asprintf(char **result, const char *format, ...)
__attribute__ ((format(printf, 2, 3)));
int dm_vasprintf(char **buf, const char *format, va_list ap)
int dm_vasprintf(char **result, const char *format, va_list aq)
__attribute__ ((format(printf, 2, 0)));
/*
@@ -1947,7 +1942,7 @@ void dm_report_free(struct dm_report *rh);
* Prefix added to each field name with DM_REPORT_OUTPUT_FIELD_NAME_PREFIX
*/
int dm_report_set_output_field_name_prefix(struct dm_report *rh,
const char *report_prefix);
const char *output_field_name_prefix);
int dm_report_set_selection(struct dm_report *rh, const char *selection);
@@ -2040,6 +2035,7 @@ struct dm_config_tree *dm_config_create(void);
struct dm_config_tree *dm_config_from_string(const char *config_settings);
int dm_config_parse(struct dm_config_tree *cft, const char *start, const char *end);
int dm_config_parse_without_dup_node_check(struct dm_config_tree *cft, const char *start, const char *end);
int dm_config_parse_only_section(struct dm_config_tree *cft, const char *start, const char *end, const char *section);
void *dm_config_get_custom(struct dm_config_tree *cft);
void dm_config_set_custom(struct dm_config_tree *cft, void *custom);
@@ -2064,7 +2060,7 @@ void dm_config_destroy(struct dm_config_tree *cft);
/* Simple output line by line. */
typedef int (*dm_putline_fn)(const char *line, void *baton);
/* More advaced output with config node reference. */
/* More advanced output with config node reference. */
typedef int (*dm_config_node_out_fn)(const struct dm_config_node *cn, const char *line, void *baton);
/*
@@ -2086,7 +2082,7 @@ int dm_config_write_one_node_out(const struct dm_config_node *cn, const struct d
struct dm_config_node *dm_config_find_node(const struct dm_config_node *cn, const char *path);
int dm_config_has_node(const struct dm_config_node *cn, const char *path);
int dm_config_remove_node(struct dm_config_node *parent, struct dm_config_node *remove);
int dm_config_remove_node(struct dm_config_node *parent, struct dm_config_node *rem_node);
const char *dm_config_find_str(const struct dm_config_node *cn, const char *path, const char *fail);
const char *dm_config_find_str_allow_empty(const struct dm_config_node *cn, const char *path, const char *fail);
int dm_config_find_int(const struct dm_config_node *cn, const char *path, int fail);
@@ -2118,7 +2114,7 @@ unsigned dm_config_maybe_section(const char *str, unsigned len);
const char *dm_config_parent_name(const struct dm_config_node *n);
struct dm_config_node *dm_config_clone_node_with_mem(struct dm_pool *mem, const struct dm_config_node *node, int siblings);
struct dm_config_node *dm_config_clone_node_with_mem(struct dm_pool *mem, const struct dm_config_node *cn, int siblings);
struct dm_config_node *dm_config_create_node(struct dm_config_tree *cft, const char *key);
struct dm_config_value *dm_config_create_value(struct dm_config_tree *cft);
struct dm_config_node *dm_config_clone_node(struct dm_config_tree *cft, const struct dm_config_node *cn, int siblings);
@@ -2127,7 +2123,7 @@ struct dm_config_node *dm_config_clone_node(struct dm_config_tree *cft, const st
* Common formatting flags applicable to all config node types (lower 16 bits).
*/
#define DM_CONFIG_VALUE_FMT_COMMON_ARRAY 0x00000001 /* value is array */
#define DM_CONFIG_VALUE_FMT_COMMON_EXTRA_SPACES 0x00000002 /* add spaces in "key = value" pairs in constrast to "key=value" for better readability */
#define DM_CONFIG_VALUE_FMT_COMMON_EXTRA_SPACES 0x00000002 /* add spaces in "key = value" pairs in contrast to "key=value" for better readability */
/*
* Type-related config node formatting flags (higher 16 bits).
@@ -2173,7 +2169,7 @@ struct dm_pool *dm_config_memory(struct dm_config_tree *cft);
*/
#define DM_UDEV_DISABLE_DM_RULES_FLAG 0x0001
/*
* DM_UDEV_DISABLE_SUBSYTEM_RULES_FLAG is set in case we need to disable
* DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG is set in case we need to disable
* subsystem udev rules, but still we need the general DM udev rules to
* be applied (to create the nodes and symlinks under /dev and /dev/disk).
*/

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
@@ -87,10 +88,8 @@ static int _version_checked = 0;
static int _version_ok = 1;
static unsigned _ioctl_buffer_double_factor = 0;
const int _dm_compat = 0;
/* *INDENT-OFF* */
static struct cmd_data _cmd_data_v4[] = {
static const struct cmd_data _cmd_data_v4[] = {
{"create", DM_DEV_CREATE, {4, 0, 0}},
{"reload", DM_TABLE_LOAD, {4, 0, 0}},
{"remove", DM_DEV_REMOVE, {4, 0, 0}},
@@ -200,6 +199,7 @@ static int _get_proc_number(const char *file, const char *name,
char *line = NULL;
size_t len;
uint32_t num;
unsigned blocksection = (strcmp(file, PROC_DEVICES) == 0) ? 0 : 1;
if (!(fl = fopen(file, "r"))) {
log_sys_error("fopen", file);
@@ -207,7 +207,9 @@ static int _get_proc_number(const char *file, const char *name,
}
while (getline(&line, &len, fl) != -1) {
if (sscanf(line, "%u %255s\n", &num, &nm[0]) == 2) {
if (!blocksection && (line[0] == 'B'))
blocksection = 1;
else if (sscanf(line, "%u %255s\n", &num, &nm[0]) == 2) {
if (!strcmp(name, nm)) {
if (number) {
*number = num;
@@ -247,6 +249,16 @@ static int _control_device_number(uint32_t *major, uint32_t *minor)
return 1;
}
static int _control_unlink(const char *control)
{
if (unlink(control) && (errno != ENOENT)) {
log_sys_error("unlink", control);
return -1;
}
return 0;
}
/*
* Returns 1 if it exists on returning; 0 if it doesn't; -1 if it's wrong.
*/
@@ -262,10 +274,7 @@ static int _control_exists(const char *control, uint32_t major, uint32_t minor)
if (!S_ISCHR(buf.st_mode)) {
log_verbose("%s: Wrong inode type", control);
if (!unlink(control))
return 0;
log_sys_error("unlink", control);
return -1;
return _control_unlink(control);
}
if (major && buf.st_rdev != MKDEV(major, minor)) {
@@ -273,10 +282,7 @@ static int _control_exists(const char *control, uint32_t major, uint32_t minor)
"(%u, %u)", control,
MAJOR(buf.st_mode), MINOR(buf.st_mode),
major, minor);
if (!unlink(control))
return 0;
log_sys_error("unlink", control);
return -1;
return _control_unlink(control);
}
return 1;
@@ -480,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);
}
}
@@ -489,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);
}
}
@@ -593,23 +599,9 @@ int dm_check_version(void)
_version_checked = 1;
if (_check_version(dmversion, sizeof(dmversion), _dm_compat))
if (_check_version(dmversion, sizeof(dmversion), 0))
return 1;
if (!_dm_compat)
goto_bad;
log_verbose("device-mapper ioctl protocol version %u failed. "
"Trying protocol version 1.", _dm_version);
_dm_version = 1;
if (_check_version(dmversion, sizeof(dmversion), 0)) {
log_verbose("Using device-mapper ioctl protocol version 1");
return 1;
}
compat = "(compat)";
bad:
dm_get_library_version(libversion, sizeof(libversion));
log_error("Incompatible libdevmapper %s%s and kernel driver %s.",
@@ -668,7 +660,7 @@ void *dm_get_next_target(struct dm_task *dmt, void *next,
return t->next;
}
/* Unmarshall the target info returned from a status call */
/* Unmarshal the target info returned from a status call */
static int _unmarshal_status(struct dm_task *dmt, struct dm_ioctl *dmi)
{
char *outbuf = (char *) dmi + dmi->data_start;
@@ -778,7 +770,7 @@ static size_t _align_val(size_t val)
}
static void *_align_ptr(void *ptr)
{
return (void *)_align_val((size_t)ptr);
return (void *)(uintptr_t)_align_val((size_t)ptr);
}
static int _check_has_event_nr(void) {
@@ -791,19 +783,12 @@ static int _check_has_event_nr(void) {
return _has_event_nr;
}
struct dm_device_list {
struct dm_list list;
unsigned count;
unsigned features;
struct dm_hash_table *uuids;
};
int dm_task_get_device_list(struct dm_task *dmt, struct dm_list **devs_list,
unsigned *devs_features)
{
struct dm_names *names, *names1;
struct dm_active_device *dm_dev, *dm_new_dev;
struct dm_device_list *devs;
struct dm_list *devs;
unsigned next = 0;
uint32_t *event_nr;
char *uuid_ptr;
@@ -824,12 +809,12 @@ int dm_task_get_device_list(struct dm_task *dmt, struct dm_list **devs_list,
} while (next);
}
if (!(devs = malloc(sizeof(*devs) + (cnt ? cnt * sizeof(*dm_dev) + (char*)names1 - (char*)names + 256 : 0))))
/* buffer for devs + sorted ptrs + dm_devs + aligned strings */
if (!(devs = malloc(sizeof(*devs) + cnt * (2 * sizeof(void*) + sizeof(*dm_dev)) +
(cnt ? (char*)names1 - (char*)names + 256 : 0))))
return_0;
dm_list_init(&devs->list);
devs->count = cnt;
devs->uuids = NULL;
dm_list_init(devs);
if (!cnt) {
/* nothing in the list -> mark all features present */
@@ -837,27 +822,22 @@ int dm_task_get_device_list(struct dm_task *dmt, struct dm_list **devs_list,
goto out; /* nothing else to do */
}
dm_dev = (struct dm_active_device *) (devs + 1);
/* Shift position where to store individual dm_devs */
dm_dev = (struct dm_active_device *) ((long*) (devs + 1) + cnt);
do {
names = (struct dm_names *)((char *) names + next);
dm_dev->major = MAJOR(names->dev);
dm_dev->minor = MINOR(names->dev);
dm_dev->name = (char*)(dm_dev + 1);
dm_dev->devno = (dev_t) names->dev;
dm_dev->name = (const char *)(dm_dev + 1);
dm_dev->event_nr = 0;
dm_dev->uuid = NULL;
dm_dev->uuid = "";
len = strlen(names->name) + 1;
memcpy(dm_dev->name, names->name, len);
memcpy((char*)dm_dev->name, names->name, len);
dm_new_dev = _align_ptr((char*)(dm_dev + 1) + len);
if (_check_has_event_nr()) {
/* Hash for UUIDs with some more bits to reduce colision count */
if (!devs->uuids && !(devs->uuids = dm_hash_create(cnt * 8))) {
free(devs);
return_0;
}
*devs_features |= DM_DEVICE_LIST_HAS_EVENT_NR;
event_nr = _align_ptr(names->name + len);
@@ -866,55 +846,29 @@ int dm_task_get_device_list(struct dm_task *dmt, struct dm_list **devs_list,
if ((event_nr[1] & DM_NAME_LIST_FLAG_HAS_UUID)) {
*devs_features |= DM_DEVICE_LIST_HAS_UUID;
uuid_ptr = _align_ptr(event_nr + 2);
dm_dev->uuid = (char*) dm_new_dev;
len = strlen(uuid_ptr) + 1;
memcpy(dm_new_dev, uuid_ptr, len);
dm_dev->uuid = (const char *) dm_new_dev;
dm_new_dev = _align_ptr((char*)dm_new_dev + len);
memcpy(dm_dev->uuid, uuid_ptr, len);
if (!dm_hash_insert(devs->uuids, dm_dev->uuid, dm_dev))
return_0; // FIXME
#if 0
log_debug("Active %s (%s) %d:%d event:%u",
dm_dev->name, dm_dev->uuid,
dm_dev->major, dm_dev->minor, dm_dev->event_nr);
#endif
}
}
dm_list_add(&devs->list, &dm_dev->list);
dm_list_add(devs, &dm_dev->list);
dm_dev = dm_new_dev;
next = names->next;
} while (next);
out:
*devs_list = (struct dm_list *)devs;
*devs_list = devs;
return 1;
}
int dm_device_list_find_by_uuid(struct dm_list *devs_list, const char *uuid,
const struct dm_active_device **dev)
{
struct dm_device_list *devs = (struct dm_device_list *) devs_list;
struct dm_active_device *dm_dev;
if (devs->uuids &&
(dm_dev = dm_hash_lookup(devs->uuids, uuid))) {
if (dev)
*dev = dm_dev;
return 1;
}
return 0;
}
void dm_device_list_destroy(struct dm_list **devs_list)
{
struct dm_device_list *devs = (struct dm_device_list *) *devs_list;
if (devs) {
if (devs->uuids)
dm_hash_destroy(devs->uuids);
free(devs);
*devs_list = NULL;
}
@@ -1459,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>
@@ -79,7 +81,7 @@ struct dm_task {
};
struct cmd_data {
const char *name;
const char name[16];
const unsigned cmd;
const int version[3];
};

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;
@@ -537,7 +537,8 @@ int unmangle_string(const char *str, const char *str_name, size_t len,
}
if (str[i] == '\\' && str[i+1] == 'x') {
if (!sscanf(&str[i+2], "%2x%s", &code, str_rest)) {
if (!sscanf(&str[i+2], "%2x%" DM_TO_STRING(DM_NAME_LEN) "s",
&code, str_rest)) {
log_debug_activation("Hex encoding mismatch detected in %s \"%s\" "
"while trying to unmangle it.", str_name, str);
goto out;
@@ -1060,9 +1061,8 @@ static int _add_dev_node(const char *dev_name, uint32_t major, uint32_t minor,
if (info.st_rdev == dev)
return 1;
if (unlink(path) < 0) {
log_error("Unable to unlink device node for '%s'",
dev_name);
if (unlink(path) && (errno != ENOENT)) {
log_sys_error("unlink", path);
return 0;
}
} else if (_warn_if_op_needed(warn_if_udev_failed))
@@ -1106,8 +1106,8 @@ static int _rm_dev_node(const char *dev_name, int warn_if_udev_failed)
"Falling back to direct node removal.", path);
/* udev may already have deleted the node. Ignore ENOENT. */
if (unlink(path) < 0 && errno != ENOENT) {
log_error("Unable to unlink device node for '%s'", dev_name);
if (unlink(path) && (errno != ENOENT)) {
log_sys_error("unlink", path);
return 0;
}
@@ -1451,9 +1451,10 @@ struct node_op_parms {
static void _store_str(char **pos, char **ptr, const char *str)
{
strcpy(*pos, str);
size_t len = strlen(str) + 1;
memcpy(*pos, str, len);
*ptr = *pos;
*pos += strlen(*ptr) + 1;
*pos += len;
}
static void _del_node_op(struct node_op_parms *nop)
@@ -1703,15 +1704,17 @@ const char *dm_sysfs_dir(void)
*/
int dm_set_uuid_prefix(const char *uuid_prefix)
{
size_t len;
if (!uuid_prefix)
return_0;
if (strlen(uuid_prefix) > DM_MAX_UUID_PREFIX_LEN) {
if ((len = strlen(uuid_prefix)) > DM_MAX_UUID_PREFIX_LEN) {
log_error("New uuid prefix %s too long.", uuid_prefix);
return 0;
}
strcpy(_default_uuid_prefix, uuid_prefix);
memcpy(_default_uuid_prefix, uuid_prefix, len + 1);
return 1;
}
@@ -1740,6 +1743,9 @@ static void _unmangle_mountinfo_string(const char *src, char *buf)
*buf = '\0';
}
/* coverity[+tainted_string_sanitize_content:arg-0] */
static int _sanitize_line(const char *line) { return 1; }
/* Parse one line of mountinfo and unmangled target line */
static int _mountinfo_parse_line(const char *line, unsigned *maj, unsigned *min, char *buf)
{
@@ -1790,7 +1796,7 @@ static int _mountinfo_parse_line(const char *line, unsigned *maj, unsigned *min,
}
/*
* Function to operate on individal mountinfo line,
* Function to operate on individual mountinfo line,
* minor, major and mount target are parsed and unmangled
*/
int dm_mountinfo_read(dm_mountinfo_line_callback_fn read_fn, void *cb_data)
@@ -1810,7 +1816,8 @@ int dm_mountinfo_read(dm_mountinfo_line_callback_fn read_fn, void *cb_data)
}
while (!feof(minfo) && fgets(buffer, sizeof(buffer), minfo))
if (!_mountinfo_parse_line(buffer, &maj, &min, target) ||
if (!_sanitize_line(buffer) ||
!_mountinfo_parse_line(buffer, &maj, &min, target) ||
!read_fn(buffer, maj, min, target, cb_data)) {
stack;
r = 0;
@@ -1825,32 +1832,27 @@ int dm_mountinfo_read(dm_mountinfo_line_callback_fn read_fn, void *cb_data)
static int _sysfs_get_dm_name(uint32_t major, uint32_t minor, char *buf, size_t buf_size)
{
char *sysfs_path, *temp_buf = NULL;
char sysfs_path[PATH_MAX], temp_buf[2 * DM_NAME_LEN];
FILE *fp = NULL;
int r = 0;
size_t len;
if (!(sysfs_path = malloc(PATH_MAX)) ||
!(temp_buf = malloc(PATH_MAX))) {
log_error("_sysfs_get_dm_name: failed to allocate temporary buffers");
goto bad;
}
if (dm_snprintf(sysfs_path, PATH_MAX, "%sdev/block/%" PRIu32 ":%" PRIu32
if (dm_snprintf(sysfs_path, sizeof(sysfs_path),
"%sdev/block/%" PRIu32 ":%" PRIu32
"/dm/name", _sysfs_dir, major, minor) < 0) {
log_error("_sysfs_get_dm_name: dm_snprintf failed");
log_error("_sysfs_get_dm_name: dm_snprintf failed.");
goto bad;
}
if (!(fp = fopen(sysfs_path, "r"))) {
if (errno != ENOENT)
log_sys_error("fopen", sysfs_path);
else
if (errno == ENOENT)
log_sys_debug("fopen", sysfs_path);
else
log_sys_error("fopen", sysfs_path);
goto bad;
}
if (!fgets(temp_buf, PATH_MAX, fp)) {
if (!fgets(temp_buf, sizeof(temp_buf), fp)) {
log_sys_error("fgets", sysfs_path);
goto bad;
}
@@ -1858,20 +1860,21 @@ static int _sysfs_get_dm_name(uint32_t major, uint32_t minor, char *buf, size_t
len = strlen(temp_buf);
if (len > buf_size) {
log_error("_sysfs_get_dm_name: supplied buffer too small");
log_error("_sysfs_get_dm_name: supplied buffer too small.");
goto bad;
}
temp_buf[len ? len - 1 : 0] = '\0'; /* \n */
strcpy(buf, temp_buf);
if (len)
--len; /* strip \n */
memcpy(buf, temp_buf, len);
buf[len] = '\0';
r = 1;
bad:
if (fp && fclose(fp))
log_sys_error("fclose", sysfs_path);
free(temp_buf);
free(sysfs_path);
return r;
}
@@ -1954,7 +1957,7 @@ static int _sysfs_find_kernel_name(uint32_t major, uint32_t minor, char *buf, si
!strcmp(name_dev, "holders") ||
!strcmp(name_dev, "integrity") ||
!strcmp(name_dev, "loop") ||
!strcmp(name_dev, "queueu") ||
!strcmp(name_dev, "queue") ||
!strcmp(name_dev, "md") ||
!strcmp(name_dev, "mq") ||
!strcmp(name_dev, "power") ||
@@ -2409,7 +2412,7 @@ static int _get_cookie_sem(uint32_t cookie, int *semid)
break;
case EACCES:
log_error("No permission to access "
"notificaton semaphore identified "
"notification semaphore identified "
"by cookie value %" PRIu32 " (0x%x)",
cookie, cookie);
break;
@@ -2430,20 +2433,20 @@ static int _udev_notify_sem_inc(uint32_t cookie, int semid)
int val;
if (semop(semid, &sb, 1) < 0) {
log_error("semid %d: semop failed for cookie 0x%" PRIx32 ": %s",
log_error("cookie inc: semid %d: semop failed for cookie 0x%" PRIx32 ": %s",
semid, cookie, strerror(errno));
return 0;
}
if ((val = semctl(semid, 0, GETVAL)) < 0) {
log_error("semid %d: sem_ctl GETVAL failed for "
log_warn("cookie inc: semid %d: sem_ctl GETVAL failed for "
"cookie 0x%" PRIx32 ": %s",
semid, cookie, strerror(errno));
return 0;
}
log_debug_activation("Udev cookie 0x%" PRIx32 " (semid %d) incremented to %d",
cookie, semid, val);
log_debug_activation("Udev cookie 0x%" PRIx32 " (semid %d) incremented.",
cookie, semid);
} else
log_debug_activation("Udev cookie 0x%" PRIx32 " (semid %d) incremented to %d",
cookie, semid, val);
return 1;
}
@@ -2453,23 +2456,21 @@ static int _udev_notify_sem_dec(uint32_t cookie, int semid)
struct sembuf sb = {0, -1, IPC_NOWAIT};
int val;
if ((val = semctl(semid, 0, GETVAL)) < 0) {
log_error("semid %d: sem_ctl GETVAL failed for "
"cookie 0x%" PRIx32 ": %s",
semid, cookie, strerror(errno));
return 0;
}
if ((val = semctl(semid, 0, GETVAL)) < 0)
log_warn("cookie dec: semid %d: sem_ctl GETVAL failed for "
"cookie 0x%" PRIx32 ": %s",
semid, cookie, strerror(errno));
if (semop(semid, &sb, 1) < 0) {
switch (errno) {
case EAGAIN:
log_error("semid %d: semop failed for cookie "
log_error("cookie dec: semid %d: semop failed for cookie "
"0x%" PRIx32 ": "
"incorrect semaphore state",
semid, cookie);
break;
default:
log_error("semid %d: semop failed for cookie "
log_error("cookie dec: semid %d: semop failed for cookie "
"0x%" PRIx32 ": %s",
semid, cookie, strerror(errno));
break;
@@ -2477,9 +2478,12 @@ static int _udev_notify_sem_dec(uint32_t cookie, int semid)
return 0;
}
log_debug_activation("Udev cookie 0x%" PRIx32 " (semid %d) decremented to %d",
cookie, semid, val - 1);
if (val < 0)
log_debug_activation("Udev cookie 0x%" PRIx32 " (semid %d) decremented.",
cookie, semid);
else
log_debug_activation("Udev cookie 0x%" PRIx32 " (semid %d) decremented to %d",
cookie, semid, val - 1);
return 1;
}
@@ -2556,7 +2560,7 @@ static int _udev_notify_sem_create(uint32_t *cookie, int *semid)
sem_arg.val = 1;
if (semctl(gen_semid, 0, SETVAL, sem_arg) < 0) {
log_error("semid %d: semctl failed: %s", gen_semid, strerror(errno));
log_error("cookie create: semid %d: semctl failed: %s", gen_semid, strerror(errno));
/* We have to destroy just created semaphore
* so it won't stay in the system. */
(void) _udev_notify_sem_destroy(gen_cookie, gen_semid);
@@ -2564,9 +2568,10 @@ static int _udev_notify_sem_create(uint32_t *cookie, int *semid)
}
if ((val = semctl(gen_semid, 0, GETVAL)) < 0) {
log_error("semid %d: sem_ctl GETVAL failed for "
log_error("cookie create: semid %d: sem_ctl GETVAL failed for "
"cookie 0x%" PRIx32 ": %s",
gen_semid, gen_cookie, strerror(errno));
(void) _udev_notify_sem_destroy(gen_cookie, gen_semid);
goto bad;
}

View File

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

View File

@@ -53,6 +53,8 @@ struct parser {
int no_dup_node_check; /* whether to disable dup node checking */
const char *key; /* last obtained key */
unsigned ignored_creation_time;
unsigned section_indent;
const char *stop_after_section;
};
struct config_output {
@@ -70,12 +72,11 @@ static struct dm_config_value *_value(struct parser *p);
static struct dm_config_value *_type(struct parser *p);
static int _match_aux(struct parser *p, int t);
static struct dm_config_value *_create_value(struct dm_pool *mem);
static struct dm_config_node *_create_node(struct dm_pool *mem);
static struct dm_config_value *_create_str_value(struct dm_pool *mem, const char *str, size_t str_len);
static struct dm_config_node *_create_node(struct dm_pool *mem, const char *key, size_t key_len);
static char *_dup_tok(struct parser *p);
static char *_dup_token(struct dm_pool *mem, const char *b, const char *e);
static const int _sep = '/';
#define MAX_INDENT 32
#define match(t) do {\
@@ -86,20 +87,24 @@ static const int _sep = '/';
} \
} while(0)
/* match token */
static int _tok_match(const char *str, const char *b, const char *e)
{
while (*str && (b != e)) {
if (*str++ != *b++)
while (b < e) {
if (!*str ||
(*str != *b))
return 0;
++str;
++b;
}
return !(*str || (b != e));
return !*str; /* token is matching for \0 end */
}
struct dm_config_tree *dm_config_create(void)
{
struct dm_config_tree *cft;
struct dm_pool *mem = dm_pool_create("config", 10 * 1024);
struct dm_pool *mem = dm_pool_create("config", 63 * 1024);
if (!mem) {
log_error("Failed to allocate config pool.");
@@ -173,23 +178,24 @@ static struct dm_config_node *_config_reverse(struct dm_config_node *head)
return middle;
}
static int _do_dm_config_parse(struct dm_config_tree *cft, const char *start, const char *end, int no_dup_node_check)
static int _do_dm_config_parse(struct dm_config_tree *cft, const char *start, const char *end,
int no_dup_node_check, const char *section)
{
/* TODO? if (start == end) return 1; */
struct parser *p;
if (!(p = dm_pool_zalloc(cft->mem, sizeof(*p))))
return_0;
struct parser p = {
.mem = cft->mem,
.tb = start,
.te = start,
.fb = start,
.fe = end,
.line = 1,
.stop_after_section = section,
.no_dup_node_check = no_dup_node_check
};
p->mem = cft->mem;
p->fb = start;
p->fe = end;
p->tb = p->te = p->fb;
p->line = 1;
p->no_dup_node_check = no_dup_node_check;
_get_token(p, TOK_SECTION_E);
if (!(cft->root = _file(p)))
_get_token(&p, TOK_SECTION_E);
if (!(cft->root = _file(&p)))
return_0;
cft->root = _config_reverse(cft->root);
@@ -199,12 +205,23 @@ static int _do_dm_config_parse(struct dm_config_tree *cft, const char *start, co
int dm_config_parse(struct dm_config_tree *cft, const char *start, const char *end)
{
return _do_dm_config_parse(cft, start, end, 0);
return _do_dm_config_parse(cft, start, end, 0, NULL);
}
int dm_config_parse_without_dup_node_check(struct dm_config_tree *cft, const char *start, const char *end)
{
return _do_dm_config_parse(cft, start, end, 1);
return _do_dm_config_parse(cft, start, end, 1, NULL);
}
/*
* Stop parsing more sections after given section is parsed.
* Only non-section config nodes are then still parsed.
* It can be useful, when parsing i.e. lvm2 metadata and only physical_volumes config node is needed.
* This function is automatically running without_dup_node_check.
*/
int dm_config_parse_only_section(struct dm_config_tree *cft, const char *start, const char *end, const char *section)
{
return _do_dm_config_parse(cft, start, end, 1, section);
}
struct dm_config_tree *dm_config_from_string(const char *config_settings)
@@ -470,23 +487,33 @@ int dm_config_write_node_out(const struct dm_config_node *cn,
/*
* parser
*/
static char *_dup_string_tok(struct parser *p)
static const char *_string_tok(struct parser *p, size_t *len)
{
char *str;
ptrdiff_t d = p->te - p->tb;
p->tb++, p->te--; /* strip "'s */
if (p->te < p->tb) {
if (d < 2) {
log_error("Parse error at byte %" PRIptrdiff_t " (line %d): "
"expected a string token.",
p->tb - p->fb + 1, p->line);
return NULL;
}
if (!(str = _dup_tok(p)))
*len = (size_t)(d - 2); /* strip "'s */
return p->tb + 1;
}
static char *_dup_string_tok(struct parser *p)
{
const char *tok;
size_t len;
char *str;
if (!(tok = _string_tok(p, &len)))
return_NULL;
p->te++;
if (!(str = _dup_token(p->mem, tok, tok + len)))
return_NULL;
return str;
}
@@ -508,10 +535,9 @@ static struct dm_config_node *_make_node(struct dm_pool *mem,
{
struct dm_config_node *n;
if (!(n = _create_node(mem)))
if (!(n = _create_node(mem, key_b, key_e - key_b)))
return_NULL;
n->key = _dup_token(mem, key_b, key_e);
if (parent) {
n->parent = parent;
n->sib = parent->child;
@@ -526,17 +552,18 @@ static struct dm_config_node *_find_or_make_node(struct dm_pool *mem,
const char *path,
int no_dup_node_check)
{
const int sep = '/';
const char *e;
struct dm_config_node *cn = parent ? parent->child : NULL;
struct dm_config_node *cn_found = NULL;
while (cn || mem) {
/* trim any leading slashes */
while (*path && (*path == _sep))
while (*path && (*path == sep))
path++;
/* find the end of this segment */
for (e = path; *e && (*e != _sep); e++) ;
for (e = path; *e && (*e != sep); e++) ;
/* hunt for the node */
cn_found = NULL;
@@ -580,6 +607,8 @@ static struct dm_config_node *_section(struct parser *p, struct dm_config_node *
struct dm_config_node *root;
struct dm_config_value *value;
char *str;
size_t len;
char buf[8192];
if (p->t == TOK_STRING_ESCAPED) {
if (!(str = _dup_string_tok(p)))
@@ -593,9 +622,16 @@ static struct dm_config_node *_section(struct parser *p, struct dm_config_node *
match(TOK_STRING);
} else {
if (!(str = _dup_tok(p)))
return_NULL;
len = p->te - p->tb;
if (len < (sizeof(buf) - 1)) {
/* Use stack for smaller string */
str = buf;
memcpy(str, p->tb, len);
str[len] = '\0';
} else {
if (!(str = _dup_tok(p)))
return_NULL;
}
match(TOK_IDENTIFIER);
}
@@ -609,12 +645,28 @@ static struct dm_config_node *_section(struct parser *p, struct dm_config_node *
return_NULL;
if (p->t == TOK_SECTION_B) {
if (p->stop_after_section)
++p->section_indent;
match(TOK_SECTION_B);
while (p->t != TOK_SECTION_E) {
if (!(_section(p, root)))
return_NULL;
}
match(TOK_SECTION_E);
if (p->stop_after_section && (--p->section_indent == 1)) {
if (!strcmp(str, p->stop_after_section)) {
/* Found stopping section name -> parsing is finished.
* Now try to find the sequence "\n}\n" from end of b
* parsed buffer to continue filling remaining nodes */
for (p->te = p->fe - 1; p->te > p->tb; --p->te)
if ((p->te[-2] == '\n') &&
(p->te[-1] == '}') &&
(p->te[ 0] == '\n')) {
p->t = TOK_SECTION_E;
break;
}
}
}
} else {
match(TOK_EQ);
p->key = root->key;
@@ -671,16 +723,14 @@ static struct dm_config_value *_value(struct parser *p)
static struct dm_config_value *_type(struct parser *p)
{
/* [+-]{0,1}[0-9]+ | [0-9]*\.[0-9]* | ".*" */
struct dm_config_value *v = _create_value(p->mem);
char *str;
if (!v) {
log_error("Failed to allocate type value");
return NULL;
}
struct dm_config_value *v;
const char *str;
size_t len;
switch (p->t) {
case TOK_INT:
if (!(v = _create_value(p->mem)))
break;
v->type = DM_CFG_INT;
errno = 0;
v->v.i = strtoll(p->tb, NULL, 0); /* FIXME: check error */
@@ -701,6 +751,8 @@ static struct dm_config_value *_type(struct parser *p)
break;
case TOK_FLOAT:
if (!(v = _create_value(p->mem)))
break;
v->type = DM_CFG_FLOAT;
errno = 0;
v->v.f = strtod(p->tb, NULL); /* FIXME: check error */
@@ -712,31 +764,31 @@ static struct dm_config_value *_type(struct parser *p)
break;
case TOK_STRING:
v->type = DM_CFG_STRING;
if (!(v->v.str = _dup_string_tok(p)))
if (!(str = _string_tok(p, &len)))
return_NULL;
match(TOK_STRING);
if ((v = _create_str_value(p->mem, str, len))) {
v->type = DM_CFG_STRING;
match(TOK_STRING);
}
break;
case TOK_STRING_BARE:
v->type = DM_CFG_STRING;
if (!(v->v.str = _dup_tok(p)))
return_NULL;
match(TOK_STRING_BARE);
if ((v = _create_str_value(p->mem, p->tb, p->te - p->tb))) {
v->type = DM_CFG_STRING;
match(TOK_STRING_BARE);
}
break;
case TOK_STRING_ESCAPED:
v->type = DM_CFG_STRING;
if (!(str = _dup_string_tok(p)))
if (!(str = _string_tok(p, &len)))
return_NULL;
dm_unescape_double_quotes(str);
v->v.str = str;
match(TOK_STRING_ESCAPED);
if ((v = _create_str_value(p->mem, str, len))) {
v->type = DM_CFG_STRING;
dm_unescape_double_quotes((char*)v->v.str);
match(TOK_STRING_ESCAPED);
}
break;
default:
@@ -744,6 +796,12 @@ static struct dm_config_value *_type(struct parser *p)
p->tb - p->fb + 1, p->line);
return NULL;
}
if (!v) {
log_error("Failed to allocate type value.");
return NULL;
}
return v;
}
@@ -761,60 +819,52 @@ static int _match_aux(struct parser *p, int t)
*/
static void _get_token(struct parser *p, int tok_prev)
{
int values_allowed = 0;
/* Should next token be interpreted as value instead of identifier? */
const int values_allowed = (tok_prev == TOK_EQ ||
tok_prev == TOK_ARRAY_B ||
tok_prev == TOK_COMMA);
const char *te;
char c;
p->tb = p->te;
_eat_space(p);
if (p->tb == p->fe || !*p->tb) {
if (p->tb == p->fe ||
!((c = *p->tb))) {
p->t = TOK_EOF;
return;
}
/* Should next token be interpreted as value instead of identifier? */
if (tok_prev == TOK_EQ || tok_prev == TOK_ARRAY_B ||
tok_prev == TOK_COMMA)
values_allowed = 1;
p->t = TOK_INT; /* fudge so the fall through for
floats works */
te = p->te + 1; /* next character */
te = p->te;
switch (*te) {
switch (c) {
case SECTION_B_CHAR:
p->t = TOK_SECTION_B;
te++;
break;
case SECTION_E_CHAR:
p->t = TOK_SECTION_E;
te++;
break;
case '[':
p->t = TOK_ARRAY_B;
te++;
break;
case ']':
p->t = TOK_ARRAY_E;
te++;
break;
case ',':
p->t = TOK_COMMA;
te++;
break;
case '=':
p->t = TOK_EQ;
te++;
break;
case '"':
p->t = TOK_STRING_ESCAPED;
te++;
while ((te != p->fe) && (*te) && (*te != '"')) {
if ((*te == '\\') && (te + 1 != p->fe) &&
*(te + 1))
@@ -828,7 +878,6 @@ static void _get_token(struct parser *p, int tok_prev)
case '\'':
p->t = TOK_STRING;
te++;
while ((te != p->fe) && (*te) && (*te != '\''))
te++;
@@ -852,7 +901,7 @@ static void _get_token(struct parser *p, int tok_prev)
case '+':
case '-':
if (values_allowed) {
while (++te != p->fe) {
for (; te != p->fe; ++te) {
if (!isdigit((int) *te)) {
if (*te == '.') {
if (p->t != TOK_FLOAT) {
@@ -869,10 +918,10 @@ static void _get_token(struct parser *p, int tok_prev)
default:
p->t = TOK_IDENTIFIER;
while ((te != p->fe) && (*te) && !isspace(*te) &&
(*te != '#') && (*te != '=') &&
(*te != SECTION_B_CHAR) &&
(*te != SECTION_E_CHAR))
while ((te != p->fe) && ((c = *te)) && !isspace(c) &&
(c != '#') && (c != '=') &&
(c != SECTION_B_CHAR) &&
(c != SECTION_E_CHAR))
te++;
if (values_allowed)
p->t = TOK_STRING_BARE;
@@ -885,16 +934,19 @@ static void _get_token(struct parser *p, int tok_prev)
static void _eat_space(struct parser *p)
{
while (p->tb != p->fe) {
if (*p->te == '#')
if (!isspace(*p->te)) {
if (*p->te != '#')
break;
while ((p->te != p->fe) && (*p->te != '\n') && (*p->te))
++p->te;
}
else if (!isspace(*p->te))
break;
while ((p->te != p->fe) && isspace(*p->te)) {
while (p->te != p->fe) {
if (*p->te == '\n')
++p->line;
else if (!isspace(*p->te))
break;
++p->te;
}
@@ -910,9 +962,44 @@ static struct dm_config_value *_create_value(struct dm_pool *mem)
return dm_pool_zalloc(mem, sizeof(struct dm_config_value));
}
static struct dm_config_node *_create_node(struct dm_pool *mem)
static struct dm_config_value *_create_str_value(struct dm_pool *mem, const char *str, size_t str_len)
{
return dm_pool_zalloc(mem, sizeof(struct dm_config_node));
struct dm_config_value *cv;
char *str_buf;
if (!(cv = dm_pool_alloc(mem, sizeof(struct dm_config_value) + str_len + 1)))
return_NULL;
memset(cv, 0, sizeof(*cv));
if (str) {
str_buf = (char *)(cv + 1);
memcpy(str_buf, str, str_len);
str_buf[str_len] = '\0';
cv->v.str = str_buf;
}
return cv;
}
static struct dm_config_node *_create_node(struct dm_pool *mem, const char *key, size_t key_len)
{
struct dm_config_node *cn;
char *key_buf;
if (!(cn = dm_pool_alloc(mem, sizeof(struct dm_config_node) + key_len + 1)))
return_NULL;
memset(cn, 0, sizeof(*cn));
if (key) {
key_buf = (char *)(cn + 1);
memcpy(key_buf, key, key_len);
key_buf[key_len] = '\0';
cn->key = key_buf;
}
return cn;
}
static char *_dup_token(struct dm_pool *mem, const char *b, const char *e)
@@ -1329,19 +1416,20 @@ static struct dm_config_value *_clone_config_value(struct dm_pool *mem,
{
struct dm_config_value *new_cv;
if (!(new_cv = _create_value(mem))) {
log_error("Failed to clone config value.");
return NULL;
if (v->type == DM_CFG_STRING) {
if (!(new_cv = _create_str_value(mem, v->v.str, strlen(v->v.str)))) {
log_error("Failed to clone string config value.");
return NULL;
}
} else {
if (!(new_cv = _create_value(mem))) {
log_error("Failed to clone config value.");
return NULL;
}
new_cv->v = v->v;
}
new_cv->type = v->type;
if (v->type == DM_CFG_STRING) {
if (!(new_cv->v.str = dm_pool_strdup(mem, v->v.str))) {
log_error("Failed to clone config string value.");
return NULL;
}
} else
new_cv->v = v->v;
if (v->next && !(new_cv->next = _clone_config_value(mem, v->next)))
return_NULL;
@@ -1358,16 +1446,11 @@ struct dm_config_node *dm_config_clone_node_with_mem(struct dm_pool *mem, const
return NULL;
}
if (!(new_cn = _create_node(mem))) {
if (!(new_cn = _create_node(mem, cn->key, cn->key ? strlen(cn->key) : 0))) {
log_error("Failed to clone config node.");
return NULL;
}
if ((cn->key && !(new_cn->key = dm_pool_strdup(mem, cn->key)))) {
log_error("Failed to clone config node key.");
return NULL;
}
new_cn->id = cn->id;
if ((cn->v && !(new_cn->v = _clone_config_value(mem, cn->v))) ||
@@ -1378,23 +1461,20 @@ 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)
{
struct dm_config_node *cn;
if (!(cn = _create_node(cft->mem))) {
if (!(cn = _create_node(cft->mem, key, strlen(key)))) {
log_error("Failed to create config node.");
return NULL;
}
if (!(cn->key = dm_pool_strdup(cft->mem, key))) {
log_error("Failed to create config node's key.");
return NULL;
}
cn->parent = NULL;
cn->v = NULL;

View File

@@ -19,7 +19,6 @@
#include "misc/dm-ioctl.h"
#include "vdo/target.h"
#include <stdarg.h>
#include <string.h>
#include <sys/utsname.h>
@@ -152,15 +151,17 @@ struct thin_message {
struct load_segment {
struct dm_list list;
unsigned type;
uint64_t size;
unsigned type;
unsigned area_count; /* Linear + Striped + Mirrored + Crypt */
struct dm_list areas; /* Linear + Striped + Mirrored + Crypt */
uint32_t stripe_size; /* Striped + raid */
uint32_t region_size; /* Mirror + raid */
int persistent; /* Snapshot */
uint32_t chunk_size; /* Snapshot */
struct dm_tree_node *cow; /* Snapshot */
@@ -168,7 +169,6 @@ struct load_segment {
struct dm_tree_node *merge; /* Snapshot */
struct dm_tree_node *log; /* Mirror */
uint32_t region_size; /* Mirror + raid */
unsigned clustered; /* Mirror */
unsigned mirror_area_count; /* Mirror */
uint64_t flags; /* Mirror + Raid + Cache */
@@ -265,7 +265,7 @@ struct load_properties {
/*
* Preload tree normally only loads and not resume, but there is
* automatic resume when target is extended, as it's believed
* there can be no i/o flying to this 'new' extedend space
* there can be no i/o flying to this 'new' extended space
* from any device above. Reason is that preloaded target above
* may actually need to see its bigger subdevice before it
* gets suspended. As long as devices are simple linears
@@ -277,7 +277,7 @@ struct load_properties {
/*
* When comparing table lines to decide if a reload is
* needed, ignore any differences betwen the lvm device
* needed, ignore any differences between the lvm device
* params and the kernel-reported device params.
* dm-integrity reports many internal parameters on the
* table line when lvm does not explicitly set them,
@@ -288,8 +288,8 @@ struct load_properties {
/*
* Call node_send_messages(), set to 2 if there are messages
* When != 0, it validates matching transaction id, thus thin-pools
* where transation_id is passed as 0 are never validated, this
* allows external managment of thin-pool TID.
* where transaction_id is passed as 0 are never validated, this
* allows external management of thin-pool TID.
*/
unsigned send_messages;
/* Skip suspending node's children, used when sending messages to thin-pool */
@@ -348,7 +348,7 @@ struct dm_tree {
int retry_remove; /* 1 retries remove if not successful */
uint32_t cookie;
char buf[DM_NAME_LEN + 32]; /* print buffer for device_name (major:minor) */
const char **optional_uuid_suffixes; /* uuid suffixes ignored when matching */
const char * const *optional_uuid_suffixes; /* uuid suffixes ignored when matching */
};
/*
@@ -540,7 +540,8 @@ static struct dm_tree_node *_create_dm_tree_node(struct dm_tree *dtree,
struct dm_tree_node *node;
dev_t dev;
if (!(node = dm_pool_zalloc(dtree->mem, sizeof(*node))) ||
if (!dtree || !dtree->mem ||
!(node = dm_pool_zalloc(dtree->mem, sizeof(*node))) ||
!(node->name = dm_pool_strdup(dtree->mem, name)) ||
!(node->uuid = dm_pool_strdup(dtree->mem, uuid))) {
log_error("_create_dm_tree_node alloc failed.");
@@ -600,7 +601,7 @@ static struct dm_tree_node *_find_dm_tree_node_by_uuid(struct dm_tree *dtree,
const char *suffix, *suffix_position;
char uuid_without_suffix[DM_UUID_LEN + 1];
unsigned i = 0;
const char **suffix_list = dtree->optional_uuid_suffixes;
const char * const *suffix_list = dtree->optional_uuid_suffixes;
if ((node = dm_hash_lookup(dtree->uuids, uuid))) {
log_debug_activation("Matched uuid %s %s in deptree.", uuid, _node_name(node));
@@ -968,7 +969,7 @@ static int _check_device_not_in_use(const char *name, struct dm_info *info)
} else if (dm_device_has_holders(info->major, info->minor))
reason = "is used by another device";
else if (dm_device_has_mounted_fs(info->major, info->minor))
reason = "constains a filesystem in use";
reason = "contains a filesystem in use";
else
return 1;
@@ -1816,7 +1817,7 @@ static int _dm_tree_deactivate_children(struct dm_tree_node *dnode,
if (info.open_count) {
/* Skip internal non-toplevel opened nodes */
/* On some old udev systems without corrrect udev rules
/* On some old udev systems without correct udev rules
* this hack avoids 'leaking' active _mimageX legs after
* deactivation of mirror LV. Other suffixes are not added
* since it's expected newer systems with wider range of
@@ -2182,7 +2183,7 @@ int dm_tree_activate_children(struct dm_tree_node *dnode,
/*
* FIXME: Implement delayed error reporting
* activation should be stopped only in the case,
* the submission of transation_id message fails,
* the submission of transaction_id message fails,
* resume should continue further, just whole command
* has to report failure.
*/
@@ -2274,7 +2275,7 @@ static int _build_dev_string(char *devbuf, size_t bufsize, struct dm_tree_node *
return 1;
}
/* simplify string emiting code */
/* simplify string emitting code */
#define EMIT_PARAMS(p, str...)\
do {\
int w;\
@@ -2868,6 +2869,8 @@ static int _integrity_emit_segment_line(struct dm_task *dmt,
count++;
if (set->sectors_per_bit_set)
count++;
if (set->allow_discards_set && set->allow_discards)
count++;
EMIT_PARAMS(pos, "%s 0 %u %s %d fix_padding block_size:%u internal_hash:%s",
origin_dev,
@@ -2887,7 +2890,7 @@ static int _integrity_emit_segment_line(struct dm_task *dmt,
EMIT_PARAMS(pos, " journal_sectors:%u", set->journal_sectors);
if (set->interleave_sectors_set)
EMIT_PARAMS(pos, " ineterleave_sectors:%u", set->interleave_sectors);
EMIT_PARAMS(pos, " interleave_sectors:%u", set->interleave_sectors);
if (set->buffer_sectors_set)
EMIT_PARAMS(pos, " buffer_sectors:%u", set->buffer_sectors);
@@ -2904,6 +2907,9 @@ static int _integrity_emit_segment_line(struct dm_task *dmt,
if (set->sectors_per_bit_set)
EMIT_PARAMS(pos, " sectors_per_bit:%llu", (unsigned long long)set->sectors_per_bit);
if (set->allow_discards_set && set->allow_discards)
EMIT_PARAMS(pos, " allow_discards");
if (!dm_task_secure_data(dmt))
stack;
@@ -2965,7 +2971,7 @@ static int _vdo_emit_segment_line(struct dm_task *dmt, uint32_t major, uint32_t
* If there is already running VDO target, read 'existing' virtual size out of table line
* and avoid reading it them from VDO metadata device
*
* NOTE: ATM VDO virtual size can be ONLY extended thus it's simple to recongnize 'right' size.
* NOTE: ATM VDO virtual size can be ONLY extended thus it's simple to recognize 'right' size.
* However if there would be supported also reduction, this check would need to check range.
*/
if ((vdo_dmt = dm_task_create(DM_DEVICE_TABLE))) {
@@ -3356,9 +3362,26 @@ int dm_tree_preload_children(struct dm_tree_node *dnode,
/* Preload children first */
while ((child = dm_tree_next_child(&handle, dnode, 0))) {
/* Propagate delay of resume from parent node */
if (dnode->props.delay_resume_if_new > 1)
child->props.delay_resume_if_new = dnode->props.delay_resume_if_new;
/* When a parent node (other than root) is inactive, we cannot delay
* the resume of a new device.
* For example, preloading a RAID table with a pvmoved leg requires the
* leg LV to be active before loading the RAID LV, so the pvmove device must
* be resumed immediately.
* This scenario only occurs when neither the RAID nor pvmove device has
* been instantiated yet. In this case, starting the pvmove device does
* not leak access to the PV device without going through the mirror target.
* However, if the RAID is already active and running, we can only preload
* the new pvmove device, and a full suspend must occur before resuming
* the new table with the running pvmove. So until the resume point
* any IO is going through the existing table line and not via pvmove target.
*/
if ((child->props.delay_resume_if_new > 1) &&
!dnode->info.exists &&
(dnode != &dnode->dtree->root)) { /* Ignore when parent is root node */
log_debug("%s with inactive parent cancels delay_resume_if_new.",
_node_name(child));
child->props.delay_resume_if_new = 0;
}
/* Skip existing non-device-mapper devices */
if (!child->info.exists && child->info.major)
@@ -3377,7 +3400,7 @@ int dm_tree_preload_children(struct dm_tree_node *dnode,
if (!child->info.exists && !(node_created = _create_node(child, dnode)))
return_0;
/* Propagate delayed resume from exteded child node */
/* Propagate delayed resume from extended child node */
if (child->props.delay_resume_if_extended)
dnode->props.delay_resume_if_extended = 1;
@@ -3813,7 +3836,7 @@ int dm_tree_node_add_raid_target(struct dm_tree_node *node,
* - maximum 253 legs in a raid set (MD kernel limitation)
* - delta_disks for disk add/remove reshaping
* - data_offset for out-of-place reshaping
* - data_copies to cope witth odd numbers of raid10 disks
* - data_copies to cope with odd numbers of raid10 disks
*/
int dm_tree_node_add_raid_target_with_params_v2(struct dm_tree_node *node,
uint64_t size,
@@ -3864,7 +3887,7 @@ int dm_tree_node_add_cache_target(struct dm_tree_node *node,
{
struct dm_config_node *cn;
struct load_segment *seg;
static const uint64_t _modemask =
const uint64_t modemask =
DM_CACHE_FEATURE_PASSTHROUGH |
DM_CACHE_FEATURE_WRITETHROUGH |
DM_CACHE_FEATURE_WRITEBACK;
@@ -3876,12 +3899,12 @@ int dm_tree_node_add_cache_target(struct dm_tree_node *node,
return 0;
}
switch (feature_flags & _modemask) {
switch (feature_flags & modemask) {
case DM_CACHE_FEATURE_PASSTHROUGH:
case DM_CACHE_FEATURE_WRITEBACK:
if (strcmp(policy_name, "cleaner") == 0) {
/* Enforce writethrough mode for cleaner policy */
feature_flags = ~_modemask;
feature_flags = ~modemask;
feature_flags |= DM_CACHE_FEATURE_WRITETHROUGH;
}
/* Fall through */
@@ -4077,7 +4100,7 @@ int dm_tree_node_add_replicator_dev_target(struct dm_tree_node *node,
uint32_t slog_flags,
uint32_t slog_region_size)
{
log_error("Replicator targer is unsupported.");
log_error("Replicator target is unsupported.");
return 0;
}

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -120,7 +120,7 @@ int dm_get_status_raid(struct dm_pool *mem, const char *params,
if (!(pp = _skip_fields(p, 1)))
goto_bad;
/* Raid target can actually report more then real number of legs in a case
/* Raid target can actually report more than real number of legs in a case
* raid legs have been removed during initial raid array resynchronization */
if (i > (pp - p - 1))
i = pp - p - 1;
@@ -335,11 +335,19 @@ int dm_get_status_cache(struct dm_pool *mem, const char *params,
/* Read in policy args */
pp = p;
if (!(p = _skip_fields(p, 1)) ||
!(s->policy_name = dm_pool_zalloc(mem, (p - pp))))
goto bad;
if (sscanf(pp, "%s %d", s->policy_name, &s->policy_argc) != 2)
if (!(p = _skip_fields(p, 1)))
goto_bad;
i = p - pp;
if ((i < 1) ||
!(s->policy_name = dm_pool_zalloc(mem, i)))
goto_bad;
dm_strncpy(s->policy_name, pp, i);
if (sscanf(p, "%d", &s->policy_argc) != 1)
goto bad;
if (s->policy_argc &&
(!(s->policy_argv = dm_pool_zalloc(mem, sizeof(char *) * s->policy_argc)) ||
!(p = _skip_fields(p, 1)) ||
@@ -401,12 +409,12 @@ int dm_get_status_integrity(struct dm_pool *mem, const char *params,
struct dm_status_integrity **status)
{
struct dm_status_integrity *s;
char recalc_str[16] = "\0";
char recalc_str[16] = { 0 };
if (!(s = dm_pool_zalloc(mem, sizeof(*s))))
return_0;
if (sscanf(params, "%llu %llu %s",
if (sscanf(params, "%llu %llu %15s",
(unsigned long long *)&s->number_of_mismatches,
(unsigned long long *)&s->provided_data_sectors,
recalc_str) != 3) {
@@ -528,6 +536,21 @@ int dm_get_status_thin(struct dm_pool *mem, const char *params,
return 1;
}
static dm_status_mirror_health_t _get_health(char c)
{
switch (c) {
case 'A': return DM_STATUS_MIRROR_ALIVE;
case 'F': return DM_STATUS_MIRROR_FLUSH_FAILED;
case 'D': return DM_STATUS_MIRROR_WRITE_FAILED;
case 'S': return DM_STATUS_MIRROR_SYNC_FAILED;
case 'R': return DM_STATUS_MIRROR_READ_FAILED;
default:
log_warn("WARNING: Unknown mirror health status char: %c", c);
/* fall through */
case 'U': return DM_STATUS_MIRROR_UNCLASSIFIED;
}
}
/*
* dm core parms: 0 409600 mirror
* Mirror core parms: 2 253:4 253:5 400/400
@@ -556,7 +579,7 @@ int dm_get_status_mirror(struct dm_pool *mem, const char *params,
pos += used;
if (num_devs > DM_MIRROR_MAX_IMAGES) {
log_error(INTERNAL_ERROR "More then " DM_TO_STRING(DM_MIRROR_MAX_IMAGES)
log_error(INTERNAL_ERROR "More than " DM_TO_STRING(DM_MIRROR_MAX_IMAGES)
" reported in mirror status.");
goto out;
}
@@ -581,7 +604,7 @@ int dm_get_status_mirror(struct dm_pool *mem, const char *params,
pos += used;
for (i = 0; i < num_devs ; ++i)
s->devs[i].health = pos[i];
s->devs[i].health = _get_health(pos[i]);
if (!(pos = _skip_fields(pos, argc)))
goto_out;
@@ -626,7 +649,7 @@ int dm_get_status_mirror(struct dm_pool *mem, const char *params,
goto_out;
for (i = 0; i < s->log_count; ++i)
s->logs[i].health = pos[i];
s->logs[i].health = _get_health(pos[i]);
}
}

View File

@@ -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
@@ -209,7 +211,7 @@ struct dm_name_list {
};
#define DM_NAME_LIST_FLAG_HAS_UUID 1
#define DM_NAME_LIST_FLAG_DOESNT_HAVE_UUID 2
#define DM_NAME_LIST_FLAG_DOES_NOT_HAVE_UUID 2
/*
* Used to retrieve the target versions

View File

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

View File

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

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

View File

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

View File

@@ -0,0 +1,23 @@
/*
* Copyright (C) 2024 Red Hat, Inc. All rights reserved.
*
* This file is part of the device-mapper userspace tools.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef DEVICE_MAPPER_RAID_TARGET_H
#define DEVICE_MAPPER_RAID_TARGET_H
#include <stdint.h>
int dm_raid_count_failed_devices(const char *dev_path, uint32_t *nr_failed);
int dm_raid_clear_failed_devices(const char *dev_path, uint32_t *nr_failed);
#endif

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -28,11 +28,6 @@
#include "target.h"
#include "lib/mm/xlate.h"
//#include "linux/byteorder/big_endian.h"
//#include "linux/byteorder/little_endian.h"
//#define le32_to_cpu __le32_to_cpu
//#define le64_to_cpu __le64_to_cpu
#include <errno.h>
#include <fcntl.h>
@@ -72,7 +67,7 @@ enum {
struct vdo_header {
uint32_t id; /* The component this is a header for */
struct vdo_version_number version; /* The version of the data format */
size_t size; /* The size of the data following this header */
uint64_t size; /* The size of the data following this header */
} __packed;
struct vdo_geometry_block {
@@ -136,40 +131,40 @@ struct vdo_volume_geometry_4 {
struct vdo_index_config index_config;
} __packed;
/* Decoding mostly only some used stucture members */
/* Decoding mostly only some used structure members */
static void _vdo_decode_version(struct vdo_version_number *v)
{
v->major_version = le32_to_cpu(v->major_version);
v->minor_version = le32_to_cpu(v->minor_version);
v->major_version = le32toh(v->major_version);
v->minor_version = le32toh(v->minor_version);
}
static void _vdo_decode_header(struct vdo_header *h)
{
h->id = le32_to_cpu(h->id);
h->id = le32toh(h->id);
_vdo_decode_version(&h->version);
h->size = le64_to_cpu(h->size);
h->size = le64toh(h->size);
}
static void _vdo_decode_geometry_region(struct vdo_volume_region *vr)
{
vr->id = le32_to_cpu(vr->id);
vr->start_block = le64_to_cpu(vr->start_block);
vr->id = (enum vdo_volume_region_id) le32toh(vr->id);
vr->start_block = le64toh(vr->start_block);
}
static void _vdo_decode_volume_geometry(struct vdo_volume_geometry *vg)
{
vg->release_version = le32_to_cpu(vg->release_version);
vg->nonce = le64_to_cpu(vg->nonce);
vg->bio_offset = le64_to_cpu(vg->bio_offset);
vg->release_version = le32toh(vg->release_version);
vg->nonce = le64toh(vg->nonce);
vg->bio_offset = le64toh(vg->bio_offset);
_vdo_decode_geometry_region(&vg->regions[VDO_DATA_REGION]);
}
static void _vdo_decode_volume_geometry_4(struct vdo_volume_geometry *vg,
struct vdo_volume_geometry_4 *vg_4)
{
vg->release_version = le32_to_cpu(vg_4->release_version);
vg->nonce = le64_to_cpu(vg_4->nonce);
vg->release_version = le32toh(vg_4->release_version);
vg->nonce = le64toh(vg_4->nonce);
vg->bio_offset = 0;
vg->regions[VDO_DATA_REGION] = vg_4->regions[VDO_DATA_REGION];
_vdo_decode_geometry_region(&vg->regions[VDO_DATA_REGION]);
@@ -177,17 +172,17 @@ static void _vdo_decode_volume_geometry_4(struct vdo_volume_geometry *vg,
static void _vdo_decode_config(struct vdo_config *vc)
{
vc->logical_blocks = le64_to_cpu(vc->logical_blocks);
vc->physical_blocks = le64_to_cpu(vc->physical_blocks);
vc->slab_size = le64_to_cpu(vc->slab_size);
vc->recovery_journal_size = le64_to_cpu(vc->recovery_journal_size);
vc->slab_journal_blocks = le64_to_cpu(vc->slab_journal_blocks);
vc->logical_blocks = le64toh(vc->logical_blocks);
vc->physical_blocks = le64toh(vc->physical_blocks);
vc->slab_size = le64toh(vc->slab_size);
vc->recovery_journal_size = le64toh(vc->recovery_journal_size);
vc->slab_journal_blocks = le64toh(vc->slab_journal_blocks);
}
static void _vdo_decode_pvc(struct vdo_component_41_0 *pvc)
{
_vdo_decode_config(&pvc->config);
pvc->nonce = le64_to_cpu(pvc->nonce);
pvc->nonce = le64toh(pvc->nonce);
}
bool dm_vdo_parse_logical_size(const char *vdo_path, uint64_t *logical_blocks)
@@ -226,7 +221,7 @@ bool dm_vdo_parse_logical_size(const char *vdo_path, uint64_t *logical_blocks)
size = st.st_size;
}
if (read(fh, buffer, sizeof(buffer)) < 0) {
if (read(fh, buffer, sizeof(buffer)) < (int)(MAGIC_NUMBER_SIZE + sizeof(h))) {
log_sys_debug("read", vdo_path);
goto err;
}
@@ -270,7 +265,7 @@ bool dm_vdo_parse_logical_size(const char *vdo_path, uint64_t *logical_blocks)
goto err;
}
if (read(fh, buffer, sizeof(buffer)) < 0) {
if (read(fh, buffer, sizeof(buffer)) < (int)(sizeof(struct vdo_geometry_block) + sizeof(vn))) {
log_sys_debug("read", vdo_path);
goto err;
}

View File

@@ -28,7 +28,7 @@ bool dm_vdo_validate_target_params(const struct dm_vdo_target_params *vtp,
if ((vtp->minimum_io_size != (512 >> SECTOR_SHIFT)) &&
(vtp->minimum_io_size != (4096 >> SECTOR_SHIFT))) {
log_error("VDO minimum io size %u is unsupported [512, 4096].",
vtp->minimum_io_size);
(vtp->minimum_io_size << SECTOR_SHIFT));
valid = false;
}

24
doc/Problems.mdwn Normal file
View File

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

34
doc/README.mdwn Normal file
View File

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

160
doc/index.mdwn Normal file
View File

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

View File

@@ -13,7 +13,7 @@ different targets were rolling their own data structures, for example:
Maintaining these data structures takes a lot of work, so if possible
we'd like to reduce the number.
The persistent-data library is an attempt to provide a re-usable
The persistent-data library is an attempt to provide a reusable
framework for people who want to store metadata in device-mapper
targets. It's currently used by the thin-provisioning target and an
upcoming hierarchical storage target.

View File

@@ -41,7 +41,7 @@ metadata.
The zones of the device are separated into 2 types:
1) Metadata zones: these are conventional zones used to store metadata.
Metadata zones are not reported as useable capacity to the user.
Metadata zones are not reported as usable capacity to the user.
2) Data zones: all remaining zones, the vast majority of which will be
sequential zones used exclusively to store user data. The conventional

4
doc/local.css Normal file
View File

@@ -0,0 +1,4 @@
.page {
max-width: 1280px;
margin: auto;
}

View File

@@ -86,7 +86,7 @@ are as follows:
the policies outlined in the LVM configuration file - usually,
/etc/lvm/lvm.conf. Once this operation is complete, the logical volumes
will be consistent. However, the volume group will still be inconsistent -
due to the refernced-but-missing device/PV - and operations will still be
due to the referenced-but-missing device/PV - and operations will still be
restricted to the aforementioned actions until either the device is
restored or 'vgreduce --removemissing' is run.

View File

@@ -1,208 +0,0 @@
The design of LVMetaD
=====================
Invocation and setup
--------------------
The daemon should be started automatically by the first LVM command issued on
the system, when needed. The usage of the daemon should be configurable in
lvm.conf, probably with its own section. Say
lvmetad {
enabled = 1 # default
autostart = 1 # default
socket = "/path/to/socket" # defaults to /var/run/lvmetad or such
}
Library integration
-------------------
When a command needs to access metadata, it currently needs to perform a scan
of the physical devices available in the system. This is a possibly quite
expensive operation, especially if many devices are attached to the system. In
most cases, LVM needs a complete image of the system's PVs to operate
correctly, so all devices need to be read, to at least determine presence (and
content) of a PV label. Additional IO is done to obtain or write metadata
areas, but this is only marginally related and addressed by Dave's
metadata-balancing work.
In the existing scanning code, a cache layer exists, under
lib/cache/lvmcache.[hc]. This layer is keeping a textual copy of the metadata
for a given volume group, in a format_text form, as a character string. We can
plug the lvmetad interface at this level: in lvmcache_get_vg, which is
responsible for looking up metadata in a local cache, we can, if the metadata
is not available in the local cache, query lvmetad. Under normal circumstances,
when a VG is not cached yet, this operation fails and prompts the caller to
perform a scan. Under the lvmetad enabled scenario, this would never happen and
the fall-through would only be activated when lvmetad is disabled, which would
lead to local cache being populated as usual through a locally executed scan.
Therefore, existing stand-alone (i.e. no lvmetad) functionality of the tools
would be not compromised by adding lvmetad. With lvmetad enabled, however,
significant portions of the code would be short-circuited.
Scanning
--------
Initially (at least), the lvmetad will be not allowed to read disks: it will
rely on an external program to provide the metadata. In the ideal case, this
will be triggered by udev. The role of lvmetad is then to collect and maintain
an accurate (up to the data it has received) image of the VGs available in the
system. I imagine we could extend the pvscan command (or add a new one, say
lvmetad_client, if pvscan is found to be inappropriate):
$ pvscan --cache /dev/foo
$ pvscan --cache --remove /dev/foo
These commands would simply read the label and the MDA (if applicable) from the
given PV and feed that data to the running lvmetad, using
lvmetad_{add,remove}_pv (see lvmetad_client.h).
We however need to ensure a couple of things here:
1) only LVM commands ever touch PV labels and VG metadata
2) when a device is added or removed, udev fires a rule to notify lvmetad
While the latter is straightforward, there are issues with the first. We
*might* want to invoke the dreaded "watch" udev rule in this case, however it
ends up being implemented. Of course, we can also rely on the sysadmin to be
reasonable and not write over existing LVM metadata without first telling LVM
to let go of the respective device(s).
Even if we simply ignore the problem, metadata write should fail in these
cases, so the admin should be unable to do substantial damage to the system. If
there were active LVs on top of the vanished PV, they are in trouble no matter
what happens there.
Incremental scan
----------------
There are some new issues arising with the "udev" scan mode. Namely, the
devices of a volume group will be appearing one by one. The behaviour in this
case will be very similar to the current behaviour when devices are missing:
the volume group, until *all* its physical volumes have been discovered and
announced by udev, will be in a state with some of its devices flagged as
MISSING_PV. This means that the volume group will be, for most purposes,
read-only until it is complete and LVs residing on yet-unknown PVs won't
activate without --partial. Under usual circumstances, this is not a problem
and the current code for dealing with MISSING_PVs should be adequate.
However, the code for reading volume groups from disks will need to be adapted,
since it currently does not work incrementally. Such support will need to track
metadata-less PVs that have been encountered so far and to provide a way to
update an existing volume group. When the first PV with metadata of a given VG
is encountered, the VG is created in lvmetad (probably in the form of "struct
volume_group") and it is assigned any previously cached metadata-less PVs it is
referencing. Any PVs that were not yet encountered will be marked as MISSING_PV
in the "struct volume_group". Upon scanning a new PV, if it belongs to any
already-known volume group, this PV is checked for consistency with the already
cached metadata (in a case of mismatch, the VG needs to be recovered or
declared conflicted), and is subsequently unmarked MISSING_PV. Care need be
taken not to unmark MISSING_PV on PVs that have this flag in their persistent
metadata, though.
The most problematic aspect of the whole design may be orphan PVs. At any given
point, a metadata-less PV may appear orphaned, if a PV of its VG with metadata
has not been scanned yet. Eventually, we will have to decide that this PV is
really an orphan and enable its usage for creating or extending VGs. In
practice, the decision might be governed by a timeout or assumed immediately --
the former case is a little safer, the latter is probably more transparent. I
am not very keen on using timeouts and we can probably assume that the admin
won't blindly try to re-use devices in a way that would trip up LVM in this
respect. I would be in favour of just assuming that metadata-less VGs with no
known referencing VGs are orphans -- after all, this is the same approach as we
use today. The metadata balancing support may stress this a bit more than the
usual contemporary setups do, though.
Automatic activation
--------------------
It may also be prudent to provide a command that will block until a volume
group is complete, so that scripts can reliably activate/mount LVs and such. Of
course, some PVs may never appear, so a timeout is necessary. Again, this is
something not handled by current tools, but may become more important in
future. It probably does not need to be implemented right away though.
The other aspect of the progressive VG assembly is automatic activation. The
currently only problem with that is that we would like to avoid having
activation code in lvmetad, so we would prefer to fire up an event of some sort
and let someone else handle the activation and whatnot.
Cluster support
---------------
When working in a cluster, clvmd integration will be necessary: clvmd will need
to instruct lvmetad to re-read metadata as appropriate due to writes on remote
hosts. Overall, this is not hard, but the devil is in the details. I would
possibly disable lvmetad for clustered volume groups in the first phase and
only proceed when the local mode is robust and well tested.
With lvmlockd, lvmetad state is kept up to date by flagging either an
individual VG as "invalid", or the global state as "invalid". When either
the VG or the global state are read, this invalid flag is returned along
with the data. The client command can check for this invalid state and
decide to read the information from disk rather than use the stale cached
data. After the latest data is read from disk, the command may choose to
send it to lvmetad to update the cache. lvmlockd uses version numbers
embedded in its VG and global locks to detect when cached data becomes
invalid, and it then tells lvmetad to set the related invalid flag.
dct, 2015-06-23
Protocol & co.
--------------
I expect a simple text-based protocol executed on top of an Unix Domain Socket
to be the communication interface for lvmetad. Ideally, the requests and
replies will be well-formed "config file" style strings, so we can re-use
existing parsing infrastructure.
Since we already have two daemons, I would probably look into factoring some
common code for daemon-y things, like sockets, communication (including thread
management) and maybe logging and re-using it in all the daemons (clvmd,
dmeventd and lvmetad). This shared infrastructure should live under
daemons/common, and the existing daemons shall be gradually migrated to the
shared code.
Future extensions
-----------------
The above should basically cover the use of lvmetad as a cache-only
daemon. Writes could still be executed locally, and the new metadata version
can be provided to lvmetad through the socket the usual way. This is fairly
natural and in my opinion reasonable. The lvmetad acts like a cache that will
hold metadata, no more no less.
Above this, there is a couple of things that could be worked on later, when the
above basic design is finished and implemented.
_Metadata writing_: We may want to support writing new metadata through
lvmetad. This may or may not be a better design, but the write itself should be
more or less orthogonal to the rest of the story outlined above.
_Locking_: Other than directing metadata writes through lvmetad, one could
conceivably also track VG/LV locking through the same.
_Clustering_: A deeper integration of lvmetad with clvmd might be possible and
maybe desirable. Since clvmd communicates over the network with other clvmd
instances, this could be extended to metadata exchange between lvmetad's,
further cutting down scanning costs. This would combine well with the
write-through-lvmetad approach.
Testing
-------
Since (at least bare-bones) lvmetad has no disk interaction and is fed metadata
externally, it should be very amenable to automated testing. We need to provide
a client that can feed arbitrary, synthetic metadata to the daemon and request
the data back, providing reasonable (nearly unit-level) testing infrastructure.
Battle plan & code layout
=========================
- config_tree from lib/config needs to move to libdm/
- daemon/common *client* code can go to libdm/ as well (say
libdm/libdm-daemon.{h,c} or such)
- daemon/common *server* code stays, is built in daemon/ toplevel as a static
library, say libdaemon-common.a
- daemon/lvmetad *client* code goes to lib/lvmetad
- daemon/lvmetad *server* code stays (links in daemon/libdaemon_common.a)

View File

@@ -56,7 +56,7 @@ Device mapper
-------------
As well as the low level dm-ioctl driving code we need to have all our dm 'best
practise' stuff in here. For instance this is the code that decides to use the
practice' stuff in here. For instance this is the code that decides to use the
mirror target to move some data around; that knows to suspend a thin volume
before taking a snapshot of it. This module is going to have a lot more code
in it than the current libdevmapper.
@@ -150,7 +150,7 @@ interface to get round.
'lib' is where the bulk of our code currently is. Dependency-wise the code is
a bit like a ball of string. So splitting it up is going to take time. We can
probably pull code pretty quickly into the 'metadata model' dir. But factoring
out the dm best practises stuff is going to require splitting at least
out the dm best practices stuff is going to require splitting at least
files, and probably functions. Certainly not something that can be done in one
go. System should just be a question of cherry picking functions.

View File

@@ -51,3 +51,5 @@ In future optional target flags will be given in two situations:
This decision could well be contentious, so could distro maintainers feel
free to comment.
[[!tag legacy]]

View File

@@ -0,0 +1,76 @@
<!-- Page title -->
[[!meta title="Version 2.03.24 - Feature and Bug Fix Release"]]
Version 2.03.24
===============
* **Changes in udev rules, new version of systemd is recommended (256).**
* **When using LVs as PVs these are no longer auto activated!**
* Allow creating VDO device for thin data when creating thin pool.
* More devices can be used as external origin for thin snapshot.
* And [[!toggle text="more"]]
[[!toggleable text="""
Features
-----------------------
* Swap properties like hostname, date and time when swapping LVs.
* Allow thin snapshot taken of thin volume from another pool as external origin.
* Allow chaining of external origins.
### Changes to device handling
* **IMPORTANT:** When `devices/scan_lvs` is enabled found LVs are no longer auto
activated, must enable `LVM_PVSCAN_ON_LVS` in udev rules (*69-dm-lvm.rules*.)
* NOTE: It is not recommended to use LVs for PVs. If you have an use case for
this talk to us, please.
* Changes to devices file are now backed up in */etc/lvm/devices/backup/*.
Controlled by `devices/devicesfile_backup_limit` configuration option.
* When `devices/use_devicesfile` is set to `0` existing file is renamed to
*system.devices-unused.YYYYMMDD.HHMMSS* to prevent outdated file to be used
on reenabling.
### Use VDO device for thin pool's data
New option `--pooldatavdo` during lvcreate or lvconvert allows using VDO as backing device.
More options (`--compression {y|n}`, `--deduplication {y|n}`,
`--vdosettings STRING`) to control the options are supported by these commands.
Example of converting a *lvol1* to a thin pool with enabled compression and deduplication:
lvconvert --type thin-pool --pooldatavdo y vg/lvol1
Changes in command line
-----------------------
* Add *--wipesignature* option controlling signature wiping when converting volume to thin-pool.
* Allow *lvcreate --snapshot* without *{-T|--thin}* option when creating snapshot of a thin volume.
* Allow *--raidintegrity{,mode,blocksize}* options with implicit RAID1 (i.e. when *-m1* is used on command line)
./configure options
-------------------
These changes are for packagers:
* Add `--with-default-event-activation` option controlling default for
`global/event_activation`. Default value is unchanged. Useful when creating
builds for testing.
* Add `--with-modulesdir` option.
Changes in udev rules
---------------------
**IMPORTANT:** Rework of udev rules in cooperation with systemd is included in this release.
* `DM_SUSPENDED` and `DM_NOSCAN` are now entirely internal for DM and cannot be used outside of DM rules.
* Upper level rules should consume `DM_UDEV_DISABLE_OTHER_RULES_FLAG` rather than `DM_NOSCAN` and `DM_SUSPENDED`.
Also few more minor improvements:
* Better handling of `DISK_RO` events and suspended devices
"""]]
[[!tag]]
[[!meta date="Thu May 16 12:12:06 2024 +0200"]]

View File

@@ -0,0 +1,19 @@
<!-- Page title -->
[[!meta title="Version 2.03.25 - Feature and Bug Fix Release"]]
Version 2.03.25
===============
* Add `vgimportdevices --rootvg [--auto]` adding devices from root VG to devices file.
* Add `lvm-devices-import.{path,service}` service using the above to initialize devices file.
* Handle pruning ids from devices file when lvremove is called and a PV is on top of the LV.
* Change device cache data structures and caching to speed up operations with many LVs.
* Fix infinite loop in lvm shell completion causing out of memory issue (2.03.24).
* Allow forced change of locktype from none.
* Handle OPTIONS defined in /etc/sysconfig/lvmlockd.
* And as usually some clean up, static analysis fixes, etc.
<!-- remove the pending tag on release, remove draft tag once editing is complete -->
[[!tag]]
[[!meta date="Fri Jul 12 12:49:07 2024 +0200"]]

View File

@@ -0,0 +1,18 @@
<!-- Page title -->
[[!meta title="Version 2.03.26 - Feature and Bug Fix Release"]]
Version 2.03.26
===============
* Add `--integritysettings` option to manipulate dm-integrity settings.
* Add `--refresh` with `vgscan --mknodes`.
* Improve documentation for `--refresh` option.
* Use `log/report_command_log=1` config setting by default for JSON output format.
* Fix `vgmknodes --refresh` to wait for udev before checking `/dev` content.
* Fix internal error reported by pvmove on a VG with single PV.
* Fix unreleased memory pools on RAID lvextend.
* And as usually some clean up, static analysis fixes, etc.
<!-- remove the pending tag on release, remove draft tag once editing is complete -->
[[!tag]]
[[!meta date="Fri Aug 23 16:02:00 2024 +0200"]]

View File

@@ -0,0 +1,26 @@
<!-- Page title -->
[[!meta title="Version 2.03.27 - Bug Fix Release"]]
Version 2.03.27
===============
* Deprecate vdo settings `vdo_write_policy` and `vdo_write_policy`.
* Do not accept duplicate device names for pvcreate.
* Fix swap device size detection using blkid for lvresize/lvreduce/lvextend.
* Detect GPT partition table and pass partition filter if no partitions defined.
* Add `global/sanlock_align_size` option to configure sanlock lease size.
* Disable mem locking when `activation/reserved_stack` or `reserved_memory` is `0`.
* Fix locking issues in lvmlockd leaving thin pool inactive but locked.
* Corrected integrity parameter `interleave_sectors` for DM table line.
* Ignore `-i|--stripes`, `-I|--stripesize` for lvextend on raid0 LV, like on raid10.
* Fix lot of typos across lvm2 code base (codespell).
* Cleanup udev sync semaphore if `dm_{udev_create,task_set}_cookie` fails.
* Improve error messages on failed udev cookie create/inc/dec operation.
<!-- remove the pending tag on release, remove draft tag once editing is complete -->
[[!tag]]
<!--
For old releases add Release Timestamp like this, date from git show $COMMIT is fine.
[[!meta date="Wed Oct 2 14:19:23 2024 +0200"]]
-->

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