1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-09-30 17:44:21 +03:00

Compare commits

...

936 Commits

Author SHA1 Message Date
Marian Csontos
bb384f8488 pre-release 2018-07-19 18:35:42 +02:00
Marian Csontos
82feb5f111 WHATS_NEW 2018-07-19 18:33:59 +02:00
Zdenek Kabelac
66990bc7c8 allocation: add check for passing log allocation
Updates previous commit.
2018-07-09 00:58:30 +02:00
Zdenek Kabelac
6fcb2ba440 WHATS_NEW: update 2018-07-09 00:36:11 +02:00
Zdenek Kabelac
b8a7f6ba3d dev_io: no discard in testmode
When lvm2 command is executed in test mode, discard ioctl is skipped.
This may cause even data-loose in case, issuing discard for released
areas was enabled and user 'tested'  lvreduce.
2018-07-09 00:35:34 +02:00
Zdenek Kabelac
0851ee5301 allocator: fix thin-pool allocation
When allocating thin-pool with more then 1 device - try to
allocate 'metadataLV' with reuse of log-type allocation for mirror LV.
It should be naturally place on other device then 'dataLV'.

However due to somewhat hard to follow allocation logic code,
it's been rejected allocation in cases where there was not
enough space for data or metadata on single PV, thus to successed,
usage of segments was mandatory.

While user may use:

allocation/thin_pool_metadata_require_separate_pvs=1

to enforce separe meta and data LV - on default settings, this is not
enable thus segment allocation is meant to work.

NOTE:

As already said - the original intention of this whole  'if()' is unclear,
so try to split this test into multiple more simple tests that are more readable.

TODO: more validation.
2018-07-09 00:35:34 +02:00
Zdenek Kabelac
df8eef7096 memlock: extend exception list
Amound of linked libraries grows.
Most of them we don't need to lock in, since we are not using
them in locked section, so skip locking them in memory.
2018-07-04 13:41:08 +02:00
Zdenek Kabelac
c1dbb22ba4 tests: update with --yes
vgcfgrestore needs to confirm restore while LVs from VG are present.
2018-07-04 13:41:00 +02:00
Zdenek Kabelac
99cddd67a9 vcfgrestore: add prompt with active volumes
Add check for active device with names matching restored VG.
When such devices are present in dm table, prompt user, if he
wish to continue.
2018-07-04 13:40:50 +02:00
David Teigland
814dd84e07 Revert "man: fix lvreduce example"
-l -3 is correct, meaning reduce by 3.

This reverts commit d5bcc56eef.
2018-06-27 09:19:01 -05:00
David Teigland
d5bcc56eef man: fix lvreduce example 2018-06-27 08:58:22 -05:00
David Teigland
f7ffba204e devs: use bcache fd for read ahead ioctl
to avoid an unnecessary open of the device in
most cases.
2018-06-26 12:15:43 -05:00
David Teigland
90e419c645 scan: reopen RDWR during rescan
Commit a30e622279:
  "scan: work around udev problems by avoiding open RDWR"

had us reopen a device RDWR in the write function.  Since
we know earlier that the command intends to write to devices
in the VG, we can reopen the VG's devices RDWR during the
rescan instead of waiting until the writes to happen.
2018-06-26 12:15:43 -05:00
David Teigland
49147cbaa7 bcache.c add missing { 2018-06-26 12:15:43 -05:00
Marian Csontos
69907e0780 bcache: Fix null pointer dereferencing
(cherry picked from commit a14f21bf1d)

Conflicts:
	lib/device/bcache.c
2018-06-26 17:09:58 +02:00
Heinz Mauelshagen
b90d4b38e5 WHATS_NEW
(cherry picked from commit 11384637fb)

Conflicts:
	WHATS_NEW
2018-06-26 12:18:39 +02:00
Heinz Mauelshagen
befdfc245b test: add convcenience conversion tests linear <-> striped
Add tests for linear <-> striped|raid* conversions.

Add region_size config to reshape tests to avoid test
failures in case of it being defined unexpectedly in lvm.conf.

Related: rhbz1439925
Related: rhbz1447809
(cherry picked from commit 3810fd8d0d)
2018-06-26 12:15:56 +02:00
Heinz Mauelshagen
0d78e4c1e9 lvconvert: support linear <-> striped convenience conversions
"lvconvert --type {linear|striped|raid*} ..." on a striped/linear
LV provides convenience interim type to convert to the requested
final layout similar to the given raid* <-> raid* conveninece types.

Whilst on it, add missing raid5_n convenince type from raid5* to raid10.

Resolves: rhbz1439925
Resolves: rhbz1447809
Resolves: rhbz1573255
(cherry picked from commit bd7cdd0b09)
2018-06-26 12:15:50 +02:00
Heinz Mauelshagen
763c65314e segtype: add linear
Add linear segtype addressing FIXME in preparation
for linear <-> striped convenience conversion support

(cherry picked from commit de66704253)
2018-06-26 12:15:44 +02:00
Marian Csontos
24aee732a5 filter: make pointers distinguishable
This ammends commit: 4afb5971b9 with suggestions to improve debugging
from Nir Soffer.
2018-06-22 15:13:24 +02:00
Zdenek Kabelac
ba6ed5c90c snapshot: improve checking of merging snapshot
Add runtime detection for 'lvs -o+seg_monitor' and 'vgchange --monitor'.
This fix should avoid unnecessary timeout on systemd shutdown.
2018-06-22 15:05:22 +02:00
Zdenek Kabelac
e0c94d883a fsadm: missing -l description 2018-06-22 15:00:52 +02:00
Zdenek Kabelac
39e3b5d8ac cache: cleaner policy also uses fmt2
Format 2 is also with cleaner policy.
2018-06-22 15:00:10 +02:00
Zdenek Kabelac
39fc98d731 pvmove: improve lvs
When pvmoving LV - the target for LV is a mirror so the validation
that checked the type is matching was incorrect.

While we need a more generic enhancment of LVS output for pvmoved LVs,
for now at least stop showing internal errors and  'X' symbols in attrs.
2018-06-22 12:37:59 +02:00
Zdenek Kabelac
5503699c37 pvresize: add missing return
Log error path missed return 0.
Also fix some unneded bactraces (since log_error already shows
position).
2018-06-22 12:37:09 +02:00
Zdenek Kabelac
e0bfc946cb pvresize: update message
There is always at least PV header update even if the size
of PV remains same (so it's not really resized).
Try to make it a slightly less confusing.
2018-06-22 12:34:24 +02:00
Zdenek Kabelac
9546edeef9 systemd: add conficting sockets
Since we are using "DefaultDependencies=no" we do not get automatic STOP
job on socket connection - so automatically refuse connection on
shutdown by adding this Conflict definition to socket Unit.
2018-06-22 12:32:31 +02:00
Zdenek Kabelac
716199334c pvscan: code reshape 2018-06-22 12:31:32 +02:00
Zdenek Kabelac
4479228d32 vgchange: fix error code in error path
This rather hard to hit error path used wrong return value to signal
real error.
2018-06-22 12:29:42 +02:00
David Teigland
4afb5971b9 filter: use pointers to real addresses
instead of casting values 1 and 2 to pointers
which gcc optimization can have problems with.
2018-06-21 10:52:35 -05:00
David Teigland
dd075e93c1 coverity warnings about null info in lvmcache.c 2018-06-21 09:22:05 -05:00
David Teigland
d4fd39f64c lvmlockd: fix another missing lock_type null check
Same as 347c807f8.
2018-06-21 09:00:23 -05:00
Marian Csontos
acb784e2a8 bcache: fix memory leaks 2018-06-21 10:22:35 +02:00
Marian Csontos
8a0af1bec8 libdm: fix buffer overflow 2018-06-21 10:22:24 +02:00
David Teigland
8bd9a89c14 WHATS_NEW: recent changes 2018-06-20 14:32:29 -05:00
David Teigland
a30e622279 scan: work around udev problems by avoiding open RDWR
udev creates a train wreck of events if we open devices
with RDWR.  Until we can fix/disable/scrap udev, work around
this by opening RDONLY and then closing/reopening RDWR when
a write is needed.  This invalidates the bcache blocks for
the device before writing so it can trigger unnecessary
rereading.
2018-06-20 12:05:04 -05:00
David Teigland
76075ff55d clvmd: fix leak of saved_vg struct
Commit c016b573ee "clvmd: separate saved_vg from vginfo"
created a separate hash table for the saved_vg structs.
The vg's referenced by the saved_vg struct were all being
freed properly, but the svg wrapper struct itself was not
being freed.
2018-06-18 14:14:38 -05:00
David Teigland
bfb904af1c bcache: remove extraneous error message
an error from io_submit is already recognized by
the caller like errors during completion.
2018-06-18 11:59:57 -05:00
Marian Csontos
d88376ca78 post-release 2018-06-18 07:30:09 +02:00
Marian Csontos
6283f5ea3f pre-release 2018-06-18 07:21:51 +02:00
David Teigland
43ce357ebc man: update lvmsystemid wording
to refer to "shared VG" instead of "lockd VG".
2018-06-14 13:34:35 -05:00
David Teigland
d136790bab man: updates to lvmlockd
The terminology has migrated toward using "shared VG"
rather than "lockd VG".

Also improve the wording in a number of places.
2018-06-14 12:53:50 -05:00
David Teigland
214de62b5d lvmlockd: update method for changing clustered VG
The previous method for forcibly changing a clustered VG to
a local VG involved using -cn and --config locking_type=0.
Add an alternative that is consistent with other forced
lock type changes:
vgchange --locktype none --lockopt force.
2018-06-13 15:58:57 -05:00
David Teigland
e9c0a64fb5 WHATS_NEW for recent changes 2018-06-13 15:42:15 -05:00
Marian Csontos
7ac8e21f3c Merge branch 'dev-mcsontos-release' into stable 2018-06-13 19:13:52 +02:00
Marian Csontos
fdb362b998 post-release 2018-06-13 19:09:07 +02:00
Marian Csontos
06accf1395 pre-release 2018-06-13 14:13:35 +02:00
David Teigland
d3dcca639c lvmlockd: skip repair lock upgrade for non shared vgs
Only attempt lvmlockd lock upgrade for shared VGs.
2018-06-12 09:25:51 -05:00
David Teigland
98eb9e5754 man lvmlockd: remove unnecessary reference to lvmetad
it's optional to use it with lvmlockd
2018-06-07 13:42:11 -05:00
David Teigland
347c807f86 lvmlockd: fix missing lock_type null check
Missed checking if vg->lock_type is NULL in commit db8d3bdfa:
  lvmlockd: enable mirror split and merge with dlm lock_type
2018-06-06 13:56:02 -05:00
David Teigland
1e5f6887b1 devices: clean up io error messages
Remove the io error message from bcache.c since it is not
very useful without the device path.

Make the io error messages from dev_read_bytes/dev_write_bytes
more user friendly.
2018-06-06 10:05:08 -05:00
David Teigland
81f07c3cca man lvmlockd: update list of limitations 2018-05-31 16:38:39 -05:00
David Teigland
885eb2024f tests: enable non-working tests with lvmlockd
Those that are failing for reasons other than lvmlockd
restrictions.
2018-05-31 16:18:53 -05:00
David Teigland
00f6a8466e tests: enable more working tests with lvmlockd 2018-05-31 16:13:58 -05:00
David Teigland
06b2e5c176 lvmlockd: improve error message for existing lockspace
When a VG/lockspace already exists with the same name
don't just print the error number.
2018-05-31 15:52:23 -05:00
David Teigland
caa600a409 tests: enable lvcreate-pvtags with lvmlockd 2018-05-31 15:37:25 -05:00
David Teigland
b9c1cef817 lvmlockd: fix reverting new lv in error path
The wrong name was being used to free the LV lock
in lvmlockd in the error exit path.
2018-05-31 15:35:48 -05:00
David Teigland
4a01e4f389 tests: enable metadata-balance with lvmlockd 2018-05-31 15:12:34 -05:00
David Teigland
08771bbbbf tests: enable lvmlockd with tests using lvcreate -H -L LV 2018-05-31 14:49:16 -05:00
David Teigland
8d9d32b315 lvmlockd: enable lvcreate -H -L LV
Allow this command in a shared VG which had previously been
disallowed.
2018-05-31 14:20:11 -05:00
David Teigland
fdaa7e2e87 vgs: add report field for shared
equivalent to a non-empty -o locktype.
2018-05-31 10:23:03 -05:00
David Teigland
2beb3009bd tests: change lvcreate syntax to allow lvmlockd
Using the less ambiguous lvcreate syntax for creating a
cache LV allows more tests to run with lvmlockd.
2018-05-30 16:40:03 -05:00
David Teigland
214235367b tests: enable lvcreate cache tests with lvmlockd
Tests that want to use lvcreate to create a new
origin LV and then combine it with an existing
cache pool to create a cache LV.
2018-05-30 15:56:08 -05:00
David Teigland
c516321325 lvmlockd: enable lvcreate of new LV plus existing cache pool
In this command, lvcreate creates a new LV and then combines
it with an existing cache pool, producing a cache LV.  This
command was previously not allowed in in a shared VG.
2018-05-30 15:24:24 -05:00
David Teigland
27495a3555 tests: enable pvmove-restart with lvmlockd 2018-05-30 13:56:06 -05:00
David Teigland
05ee83579b tests: enable vg repair tests with lvmlockd 2018-05-30 12:57:46 -05:00
David Teigland
6cd0523337 lvmlockd: enable repairing shared VG while reading it
When the lvmlockd lock is shared, upgrade it to ex
when repair (writing) is needed during vg_read.

Pass the lockd state through additional read-related
functions so the instances of repair scattered through
vg_read can be handled.

(Temporary solution until the ad hoc repairs can be
pulled out of vg_read into a top level, centralized
repair function.)
2018-05-30 12:56:46 -05:00
David Teigland
063d065388 tests: add missing file 2018-05-30 09:25:45 -05:00
David Teigland
abba06fb3b tests: process-each-duplicate-pvs update for lvmlockd 2018-05-30 09:25:45 -05:00
David Teigland
3759a1f62b pvremove: skip lvmlockd locks for forced clearing
pvremove -ff to force clear a PV shouldn't care if
lvmlockd locks fail.
2018-05-30 09:25:45 -05:00
David Teigland
5c5e449dc5 lvmlockd: fix vgimportclone of a shared VG
The new VG from the duplicate PV is imported
as a local VG.
2018-05-30 09:25:45 -05:00
David Teigland
a40d447a02 tests: vgchange-usage update for lvmlockd 2018-05-30 09:25:45 -05:00
David Teigland
95cf127134 tests: vgcreate-usage update for lvmlockd 2018-05-30 09:25:45 -05:00
David Teigland
595196bc29 tests: enable lvmlockd for passing tests 2018-05-30 09:25:45 -05:00
David Teigland
403c87c1aa lvmlockd: enable creation of cache pool with lvcreate
Previously, cache pools needed to be created with lvconvert.
2018-05-30 09:25:45 -05:00
David Teigland
948f2d9979 lvmlockd: enable lvcreate of thin pool and thin lv in one command
Previously, thin pools and thin lvs need needed to be
created with separate commands, now the combined command
is permitted.
2018-05-30 09:25:45 -05:00
David Teigland
db8d3bdfa9 lvmlockd: enable mirror split and merge with dlm lock_type 2018-05-30 09:25:45 -05:00
David Teigland
3a4fe54ca1 config: revert to normal locking when no cluster
and suggest lvmlockd
2018-05-30 09:25:45 -05:00
David Teigland
7f7ec769d9 lvmlockd: do not use an LV lock for some lvchange options
Some lvchange options can be used even if the LV is active.
2018-05-30 09:25:45 -05:00
David Teigland
cd369d8a7f tests: separate lvmlockd tests with or without lvmetad 2018-05-30 09:25:45 -05:00
David Teigland
0c1d3db8db lvmlockd: accept repeated global lock requests
It's not an error if a command requests the global lock
when it has already acquired it.  It shouldn't happen,
but there could be cases we've not found.
2018-05-30 09:25:45 -05:00
David Teigland
6a44dceb48 tests: some missed skip with lvmlockd 2018-05-30 09:25:45 -05:00
David Teigland
5ac9f8d631 tests: fix skipping logic for lvmpolld and lvmlockd 2018-05-30 09:25:45 -05:00
David Teigland
6d14d5d16b scan: removed failed paths for devices
Drop a device path when the scan fails to open it.
2018-05-30 09:05:18 -05:00
Joe Thornber
06c789eda1 radix-tree: fix some bugs in remove_prefix and iterate
These weren't working if the prefix key was part of a prefix_chain.
2018-05-30 14:21:27 +01:00
Joe Thornber
1924426ad1 radix-tree: radix_tree_iterate() 2018-05-29 17:58:58 +01:00
Joe Thornber
c2a8bbed3b radix-tree: radix_tree_remove_prefix() 2018-05-29 13:25:59 +01:00
Joe Thornber
9b41efae82 radix-tree: call the value dtr when removing an entry. 2018-05-29 11:23:36 +01:00
Joe Thornber
0181c77e3f Merge branch '2018-05-29-radix-tree-iterate' into 2018-05-23-radix-tree-remove 2018-05-29 11:04:32 +01:00
Joe Thornber
033df741e2 data-struct/radix-tree: pass the value dtr into create.
Rather than having to pass it into every method that removes items.
2018-05-29 11:03:10 +01:00
David Teigland
28c8e95d19 scan: refresh paths and retry open
If scanning fails to open any devices, refresh the
device paths in dev cache, and retry the opens.
2018-05-25 13:09:07 -05:00
Alasdair G Kergon
9a730233c9 format_text: Use versionsort to sort archive files
Ensure that vg_100000-* follows vg_99999-* so that the expiry logic
doesn't stop too early.

   https://bugzilla.redhat.com/1481085
2018-05-24 17:51:03 +02:00
Marian Csontos
0ecf232194 Merge remote-tracking branch 'origin/master' 2018-05-24 17:32:42 +02:00
Zdenek Kabelac
3702f39ef3 tests: improve usability on older systems 2018-05-24 16:02:31 +02:00
Zdenek Kabelac
d6f2445996 man: another missed typo for thin plugin 2018-05-24 16:02:31 +02:00
Marian Csontos
264077907e post-release 2018-05-24 15:23:08 +02:00
Marian Csontos
adae8ee1c2 pre-release 2018-05-24 15:13:10 +02:00
Joe Thornber
7e85361c34 release note: typos 2018-05-24 12:32:16 +01:00
Joe Thornber
fab063cfcb release note: typo 2018-05-24 12:26:34 +01:00
Joe Thornber
9337ff48bc release note: 2.02.178 2018-05-24 12:22:11 +01:00
Zdenek Kabelac
a90de76fd8 tests: checking scanning correctness 2018-05-24 11:22:32 +02:00
Zdenek Kabelac
f865e1bf87 tests: passthrough args with extend_filter_LVMTEST
Don't rebuild config twice.
2018-05-24 11:22:59 +02:00
Zdenek Kabelac
89f34eaf0c tests: correcting symlink manipulation
Fix symlink and add 'verbose' pvs for a while for checking
scanning correctness.
2018-05-24 11:22:32 +02:00
Zdenek Kabelac
76a45424a7 tests: aux improve for mdadm support
Correcting some symlink handling.
2018-05-24 11:03:47 +02:00
Zdenek Kabelac
c46dbfb14e man: make generate 2018-05-23 19:46:47 +02:00
Zdenek Kabelac
4be1ec3da4 man: fix cut and paste bug
Fixing missing 'META' in DMEVENTD_THIN_POOL_METADATA.
2018-05-23 19:45:53 +02:00
Zdenek Kabelac
c35d3242a8 gitignore 2018-05-23 16:53:18 +02:00
Joe Thornber
6cd798f556 radix_tree_t: knock out some debug 2018-05-23 12:54:02 +01:00
Joe Thornber
b7fd8ac8eb radix_tree: add remove method 2018-05-23 12:48:06 +01:00
Joe Thornber
87291a2832 Merge branch 'master' of git+ssh://sourceware.org/git/lvm2 2018-05-23 09:14:29 +01:00
David Teigland
61583281e5 filters: clarify some parts of md filter
Rename some functions to be consistent with the return values,
and add some comments about how it works.
2018-05-22 14:07:13 -05:00
Joe Thornber
a60416a13f WHATS_NEW: typo 2018-05-22 09:46:59 +01:00
David Teigland
3c9ed33f83 scan: move warnings about duplicate devices
We have been warning about duplicate devices (and disabling lvmetad)
immediately when the dup was detected (during label_scan).  Move the
warnings (and the disabling) to happen later, after label_scan is
finished.

This lets us avoid an unwanted warning message about duplicates
in the special case were md components are eliminated during the
duplicate device resolution.
2018-05-21 16:48:02 -05:00
David Teigland
73ae68e1c4 man vgexport: expand description 2018-05-21 16:26:49 -05:00
Zdenek Kabelac
6029d6d8d8 tests: disable symlink test
It's quite unclear what the test is meant to do - disable it just like
within python test.
2018-05-21 11:59:39 +02:00
Zdenek Kabelac
25a66737e3 tests: use 4K extent size
To work with for 4k backend devices.
2018-05-21 11:58:10 +02:00
David Teigland
a9f2c1e1f5 lvmlockd: suppress error messages related to lvmetad
Log lvmetad related messages as debug, not as errors,
when using lvmlockd without lvmetad.
2018-05-18 16:00:54 -05:00
David Teigland
bc275bcddf fullreport: fix with lvmetad and only orphan PVs are visible
The report uses process_each_vg() which populates lvmcache
based on a VG list from lvmetad.  If there are no VGs,
but only orphan PVs, the orphans are not shown.  Add an
explicit call to populate lvmcache with PV info from lvmetad.
2018-05-18 14:31:52 -05:00
David Teigland
0253f5a21d fix id_write_format on non-uuid string
orphan vgs using the vgname "#orphans" as the vgid,
and valgrind complains about calling id_write_format
on that invalid uuid.
2018-05-18 13:41:20 -05:00
Zdenek Kabelac
b2574c2f3a python: use // for integer division 2018-05-18 16:25:44 +02:00
Zdenek Kabelac
3bbdde808a tests: pick either python2 or python3 .so
Use matching PYTHON library implementation.
2018-05-18 16:25:44 +02:00
Zdenek Kabelac
fbf64fe730 tests; make sure python_lvm_unit.py is executable 2018-05-18 16:25:44 +02:00
Zdenek Kabelac
43fb32e761 python: use python3 paths directly
Do not use /usr/bin/env for path of python3 as this is seen
as 'unwanted' and should be avoided.
2018-05-18 16:25:44 +02:00
Zdenek Kabelac
5b86b0e3dc build: set clean vars earlier
For better cleaning of test dirs.
2018-05-18 16:25:44 +02:00
David Teigland
f7435cd8c7 liblvm2app: add a couple tests
trivial sanity-check programs using liblvm2app
2018-05-17 15:55:44 -05:00
David Teigland
286c9c78b4 liblvm2app: fix valgrind memory warning 2018-05-17 15:18:11 -05:00
Heinz Mauelshagen
a39eaea27d tests: fix kernal_at_least argument in aux.sh 2018-05-17 14:41:47 +02:00
Joe Thornber
5052970da3 bcache: Don't call sysconf for every io 2018-05-17 10:05:10 +01:00
Joe Thornber
7ee0a6e44d Merge branch 'master' of git://sourceware.org/git/lvm2 2018-05-17 09:52:57 +01:00
Joe Thornber
3417d6229d scripts/code-stats.rb: count files better, handle bad utf8 2018-05-17 09:52:13 +01:00
Alex Bennée
c6ca81a38d bcache: don't use PAGE_SIZE compile const
PAGE_SIZE is not a compile time constant. Use sysconf instead like
elsewhere in the code.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
2018-05-17 10:38:16 +02:00
Rick Elrod
8c453e2e5e cleanup: fix grammar in output - less then -> less than
This minor patch fixes grammar in a few messages which get
printed to users. It also fixes the same grammar mistake in
several comments.

Signed-off-by: Rick Elrod <relrod@redhat.com>
--
2018-05-17 10:37:45 +02:00
David Teigland
28d35e5c59 scan: fix missing close in lib
lib was using dev_test_excl which wasn't closing the device.
Switch code to new io layer with excl open.
Also use exclusive open in some other places.
2018-05-16 14:48:30 -05:00
Joe Thornber
64dd656ef7 scripts: add a little scripts to show git history for the last 2 weeks. 2018-05-16 15:27:52 +01:00
Joe Thornber
7c852c75c3 unit-tests: remove a couple of debug printfs 2018-05-16 10:25:30 +01:00
Joe Thornber
e296f784c9 Merge branch 'master' of git://sourceware.org/git/lvm2 2018-05-16 10:11:58 +01:00
Joe Thornber
df2acbbb97 bcache: nr_ios_pending wasn't being incremented
... but it was being decremented on completion.  Which meant
it wrapped, and no prefetches were ever issued after the
first completion.
2018-05-16 10:09:17 +01:00
David Teigland
ed799404f8 doc: add some performance info 2018-05-15 15:17:36 -05:00
David Teigland
3bbc17a670 scan: use up to 1024 max bcache blocks
Create bcache with one block per device that
will be scanned up to 1024 max blocks.
2018-05-15 15:17:31 -05:00
Zdenek Kabelac
fb0aca86f8 lvmapp: do not unlock not locked VGs
After recent changes this seems to give some help, explore more...
2018-05-15 22:02:41 +02:00
Zdenek Kabelac
99cd7108d3 tests: better check for python libpath
Find also python3 lvm.so name.

And ATM just run a single test, otherwise we get too many cores.
2018-05-15 22:02:41 +02:00
Zdenek Kabelac
f8745dc23e python: specify libdm path for linking 2018-05-15 22:02:41 +02:00
Zdenek Kabelac
550380c1a4 tests: aux fixes
Properly check for kernel version.
Also detect sysfs throttling support.
2018-05-15 22:02:41 +02:00
Zdenek Kabelac
3b3ee66b1f tests: time limit waiting on lvmetad kill 2018-05-15 22:02:41 +02:00
Zdenek Kabelac
b5da4fdfce tests: drop junk 2018-05-15 22:02:41 +02:00
Zdenek Kabelac
be154e30e8 tests: move into generated file
Since python path is evaluated and we cannot use anymore /usr/bin/env
switch to generated file.
2018-05-15 22:02:41 +02:00
Zdenek Kabelac
ad756bb708 build: configure detect libaio
No point to start building lvm without this header file.

Although there could be 'some point' in supporting standalone build
of 'just' libdm  where the libaio might be avoided.

TODO: think about configure option for building libdm only.
2018-05-15 22:02:41 +02:00
David Teigland
c1abcee142 WHATS_NEW: updates 2018-05-15 10:49:06 -05:00
Zdenek Kabelac
889558fedb conf: update conf
Matching patch 2eba7c7755
2018-05-15 16:58:28 +02:00
Zdenek Kabelac
d25c135806 tests: fix size of COW
Needs to be changed to match 4K extent_size.
2018-05-15 16:49:53 +02:00
Zdenek Kabelac
0217c53b24 tests: dont try to use DAX based brd device
Unfortunatelly on kernels <4.16 lvm2 can't user brd ramdisks
for backend device as number of test is failing with this kernel
message:

device-mapper: ioctl: can't change device type after initial table load.

caused by DAX request-based handling, and lvm2 tries to replace device
with backend 'error' bio-based device and such table reload is being
rejected.

So ATM keep ramdisk only on most recent kernel to experiment a bit,
for older machines just stay safe and keep old slower loop backend.
2018-05-15 16:07:13 +02:00
Jonathan Brassow
2eba7c7755 clean-up: example.conf.in typo 2018-05-14 16:17:01 -05:00
David Teigland
11ceb77867 lvmcache: fix loop freeing infos
valgrind was concerned about loop through vginfo->infos,
so grab info from dev.
2018-05-14 13:45:55 -05:00
David Teigland
517d6cc418 scan: add some missing frees
some objects had been moved out of mem pools.
2018-05-14 13:38:16 -05:00
Zdenek Kabelac
0e56fa6892 tests: old systems do not have even throttling
When even throttling is not available, skip or use  should
with particular test piece.
2018-05-12 23:37:30 +02:00
Zdenek Kabelac
0a5edc1f12 tests: swith to mkstemp
As mkostemp is only on newer systems, switch to more old version
which effectively does exactly the same thing for given list of
open flags.
2018-05-12 23:23:54 +02:00
Zdenek Kabelac
9640320aea tests: start to use 4k mkfs
While newer system can detect need for 4K mkfs, on older test machines
running test suite over 4k is reporting problems.
Some more generic solution is needed thought.
2018-05-12 23:22:20 +02:00
Zdenek Kabelac
ca87674ea4 tests: fix check sysfs
Commit 810f856c24 missed to move
assign of P after setting maj & min.
2018-05-12 23:01:52 +02:00
Zdenek Kabelac
edede1d20f tests: do not try to create 1K extents 2018-05-12 22:52:41 +02:00
Zdenek Kabelac
093428b067 tests: restore functionality
Forgotten revert of tracing patch. Restoring previous functinality.
2018-05-12 22:51:43 +02:00
Zdenek Kabelac
7b8b13c62b tests: aux detecs supported segments
Replace previous compilation detection of present supported segtypes
with runtime check.
2018-05-12 22:50:36 +02:00
Zdenek Kabelac
35ffc3f8eb build: lcov reporting for unit tests
List also lcov for processed unit tests.
2018-05-12 18:18:23 +02:00
Zdenek Kabelac
67c02877a1 build: install unit-test 2018-05-12 18:18:23 +02:00
Zdenek Kabelac
4c7565b65d tests: add unit-test
Allow unit-test to be run as part of standard 'make check'.
2018-05-12 18:18:23 +02:00
Zdenek Kabelac
fa8d0b5766 tests: detect running bcache test on tmpfs
When test happens to run in tmpfs, it cannot use O_DIRECT (unsupported
with tmpfs).

CHECKME: unsure if detection of tmpfs is 'valid' but kind of works and
is very simple.
2018-05-12 18:18:23 +02:00
Zdenek Kabelac
79b2961399 build: rename device-mapper to device_mapper
As Makefiles already do use target with name 'device-mapper'
rename this new device-mapper dir to non-conflicting name.
We also seem to already use '_' in other dir names.

Also rename device_mapper/Makefile to source for generating Makefile.in
so we can use it for build in other source dirs properly.
2018-05-12 18:18:23 +02:00
Zdenek Kabelac
e2c766d37e build: fix build rules for srcdir
It's very hard to use some 'non-recurive' Makefiles with
rest of system running 'recursively'.

So ATM drop inclusion of subdir makefile and add support
for 2 new top-level targets:

unit-test  (builds test/unit dir)
run-unit-test (build & run test/unit/unit-test run)
2018-05-12 18:18:23 +02:00
Zdenek Kabelac
ac768a9d2b bcache: do not use libdm header files
Logging for libdm differs from lvm logging - keep using consisten
logging function calls.
2018-05-12 18:18:23 +02:00
Zdenek Kabelac
83e362cd32 build: make generate 2018-05-12 18:18:23 +02:00
Zdenek Kabelac
0b465d1543 tests: drop cache checking
Just like 52656c89fd
when now cache is compiled in 'unditionally'.

This patch is actually enforce by changes in
commit: 2bc896f2a3
where CACHE value is not set anymore.
2018-05-12 18:18:23 +02:00
Zdenek Kabelac
d38a2d64f0 tests: add support to run unit test 2018-05-12 18:18:23 +02:00
Zdenek Kabelac
7616a7f46e build: properly track source file for lmvlockctl
Ensure the source file is tracked by various cleanup functions.
2018-05-12 18:05:50 +02:00
Zdenek Kabelac
cbe81a0b05 tests: inittest may run without root
If the test does not need root, it can use 'SKIP_ROOT_DM_CHECK'.

For such test no actions needed root to initilize DM devices and
nodes will be take and test can check i.e. functional unit tests.
2018-05-12 18:05:50 +02:00
Zdenek Kabelac
0221ebfd64 tests: inittest compare string
Avoid logging warning when compared string is empty with -eq.
2018-05-12 18:05:50 +02:00
Zdenek Kabelac
a7a23e7dd2 tests: aux extra protection for rm -rf 2018-05-12 18:05:50 +02:00
Zdenek Kabelac
38b4354494 tests: again disable this raid test
Still kills testing machines even with 4.17-rc4 kernels
on reshaping.
2018-05-12 18:05:50 +02:00
Zdenek Kabelac
ec0f5c2bf6 tests: drop delaying
Here seem delaying dev has no use.
2018-05-12 18:05:50 +02:00
Zdenek Kabelac
86c8f0f01f tests: using throttling 2018-05-12 17:48:31 +02:00
Zdenek Kabelac
7362ed68be tests: move device discard 2018-05-12 17:48:31 +02:00
Zdenek Kabelac
f5da325d70 tests: use throttle_dm_mirror
In this case it's better to use throttling of mirror sync,
that delay everything with dm_delay.
2018-05-12 17:48:31 +02:00
Zdenek Kabelac
172d8fb355 tests: aux support throttling of dm mirror
Usage of dm_delay looks to be slowing not just 'delayed' portion
of device, but due to the fact it's also slows down ANY flush
operation on such device it's overal speed impact is huge.

In some case we can however user other methods to slowdown disk writes,
in case of old dm 'mirror'  target we can throttle  I/O of mirror
synchronisation giving the next commands enough time to test couple
race conditions.

Usage:

throttle_dm_mirror [percentage]

Thtrottle down sync speed (lowest is '1' which is also default when
unspecified)

restore_dm_mirror

Restores the value of throttling before call of  'throttle_dm_mirror'
Usually it should '100'
2018-05-12 17:48:31 +02:00
Zdenek Kabelac
0cadfdd69d tests: try running tests over ramdisk
Currently usage of loop device over backend file in ramdisk (tmpfs)
is actually causing unnecassary memory consution, since just
reading such loop device is causing RAM provisioning.

This patch add another possible way how to use ramdisk directly
through 'brd' device when possible (and allowed).

This however has it's limitation as well -  brd does not support
TRIM, so the only way how to erase is to remove brd module ??

Alse there is 4K sector size limitation imposed by ramdisk.

Anyway - for some mirror test that were using large amount of
disk space (tens of MB) this brings noticable speed boost.
(But could be worth to solve the slowness of loop in kernel?)

To prevent using 'brd' for testing set LVM_TEST_PREFER_BRD=0
like this:

make check_local LVM_TEST_PREFER_BRD=0
2018-05-12 17:48:31 +02:00
Zdenek Kabelac
842b3074b7 tests: crypt test cannot run on ramdisk
This test can't use brd (ramdisk) as backend since for some
weird reason  lsblk is not listing these device.

TODO: test could be probably rewritten to avoid using lsblk somehow??
2018-05-12 17:48:31 +02:00
Zdenek Kabelac
6f48741062 tests: happy using of 4K backend devices
When the backend device supports only 4K blocks (like ramdisk)
we cannot use for testing any smaller blocksize.

So recalc test for 4K extent size.

We may possibly introduce one list extra test that
can be executed on devices with 512b sectors to
check lvm2 support those min extent sizes...
2018-05-12 17:48:31 +02:00
Zdenek Kabelac
e2be14e2d5 tests: raise min size for XFS
Seems XFS now requires at least 1605 blocks.
2018-05-12 17:48:31 +02:00
Zdenek Kabelac
6740c78e83 poll: add stdout fflush after poll query
ATM it's a bit ugly to enforce flushing of 'stdio' here, but works as quick
hot-fix.

log_print*() is using buffered I/O.

But for pooling with typical 1s interval this may take a while before
buffer about continues progress gets flushed.
So ATM fflush().

TODO: either add  log_print*_with_flush() or maybe directly use just
line buffering with log_print() and only log_debug() keep using buffered
I/O mode.
2018-05-12 11:30:05 +02:00
David Teigland
09fcc8eaa8 scan: ignore duplicates that are md component devs
md devices using an older superblock version have
superblocks at the end of the md device.  For commands
that skip reading the end of devices during filtering,
the md component devs will be scanned, and will appear
as duplicate PVs to the original md device.  Remove
these md components from the list of unused duplicate
devices, so they are treated as if they had been
ignored during filtering.  This avoids the restrictions
that are placed on using PVs with duplicates.
2018-05-11 15:52:22 -05:00
David Teigland
73578e36fa dev_cache: remove the lvmcache check when closing fd
This is no longer used since devices are not held
open in dev_cache.
2018-05-11 14:30:10 -05:00
David Teigland
3e3cb22f2a dev_cache: fix close in utility functions
All these functions are now used as utilities,
e.g. for ioctl (not for io), and need to
open/close the device each time they are called.
(Many of the opens can probably be eliminated by
just using the bcache fd for the ioctl.)
2018-05-11 14:25:08 -05:00
David Teigland
5c9dcd99fd scan: remove unused args from label_read 2018-05-11 14:16:49 -05:00
David Teigland
b5d9914628 devs: recognize md devices in subsystem check
If md components appear as duplicate PVs, let the
existing subsystem check recognize the md device.
2018-05-11 14:00:19 -05:00
David Teigland
ccab54677c dev_cache: fix close in dev_get_block_size 2018-05-11 13:53:19 -05:00
David Teigland
bbb8040456 dev_cache: drop open_list
devices are now held open only in bcache,
so drop the dev_cache list of open devices
which is unused.
2018-05-11 12:47:56 -05:00
David Teigland
4362013872 bcache: disable fallback to old io
All io has been converted to bcache.
2018-05-11 11:35:56 -05:00
David Teigland
228ed56455 pvck: allow checking at user specified offsets
with the --labelsector option.  We probably don't
need all this code to support any value for this
option; it's unclear how, when, why it would be
used.
2018-05-11 11:23:51 -05:00
Joe Thornber
413488edc6 radix-tree: fix a function decl 2018-05-11 11:40:47 +01:00
Joe Thornber
30a4c7988e radix-tree: remove some unneccessary includes 2018-05-11 09:46:34 +01:00
Joe Thornber
0a31fb4aa3 doc: add a little document describing new directory structure. 2018-05-11 06:46:25 +01:00
Joe Thornber
576dd1fc41 radix-tree: First drop of radix tree.
An implementation of an adaptive radix tree.  Has the following nice
properties:

  - At least as fast as the hash table
  - Uses less memory
  - You don't need to give an expected size when you create
  - It scales nicely (ie. no large reallocations like the hash table).
  - You can iterate the keys in lexicographical order.

Only insert and lookup are implemented so far.  Plus there's a lot
more performance to come.
2018-05-11 06:10:01 +01:00
Joe Thornber
3b02b35c3e Merge branch 'master' of git+ssh://sourceware.org/git/lvm2 2018-05-11 05:39:27 +01:00
Joe Thornber
5f780813f2 bcache/sync io engine: handle short ios 2018-05-11 05:37:47 +01:00
David Teigland
9ad42e5f06 io: write log header with bcache 2018-05-10 16:25:33 -05:00
David Teigland
d974644db7 pvscan: remove unused var warning 2018-05-10 16:18:36 -05:00
David Teigland
57bb46c5e7 filter: use bcache for filter reads
Filters are still applied before any device reading or
the label scan, but any filter checks that want to read
the device are skipped and the device is flagged.

After bcache is populated, but before lvm looks for
devices (i.e. before label scan), the filters are
reapplied to the devices that were flagged above.
The filters will then find the data they need in
bcache.
2018-05-10 16:03:19 -05:00
Joe Thornber
39ce38eb88 label/lv_manip: squash some warnings 2018-05-10 15:14:39 +01:00
Joe Thornber
3c0f5bdd08 functional-tests/vdo: fix mem leak in test 2018-05-10 14:31:16 +01:00
Joe Thornber
ae50374811 bcache: Add sync io engine
Something to fall back to when testing.
2018-05-10 14:29:26 +01:00
Joe Thornber
67b80e2d9d bcache: knock out err param.
Dave used this for debugging.  Not needed in general.
2018-05-10 13:26:08 +01:00
Joe Thornber
2b96bb403c Merge branch 'master' of git+ssh://sourceware.org/git/lvm2 2018-05-10 13:02:27 +01:00
Joe Thornber
2ae4a04710 vdo status: Unit tests + fix bugs 2018-05-10 13:01:26 +01:00
Joe Thornber
e649f71022 Merge branch 'master' into 2018-04-30-vdo-support 2018-05-10 12:34:04 +01:00
David Teigland
38f33251b1 doc: add filter info to scanning 2018-05-09 12:54:38 -05:00
David Teigland
9a5bd01b0c io: replace dev_set with bcache equivalents 2018-05-09 11:29:52 -05:00
Joe Thornber
3600caa71d Merge branch 'master' of git+ssh://sourceware.org/git/lvm2 2018-05-09 11:07:24 +01:00
Joe Thornber
1c5c99afce bcache-utils: bcache_set_bytes() 2018-05-09 11:05:29 +01:00
Joe Thornber
2e1869b923 unit-test/bcache-utils: Tweak zero tests 2018-05-09 10:50:31 +01:00
David Teigland
a2310e2de0 doc: lvm disk reading 2018-05-04 10:54:29 -05:00
Heinz Mauelshagen
c9729022bf tests: bump raid target version in reshape tests
Adjust to target version allowing tests to succeed.
2018-05-04 16:58:11 +02:00
Heinz Mauelshagen
8bf92875f7 tests: don't rely on cache target in component-raid.sh
Lead to unnecessary skips of the test.
2018-05-04 16:54:01 +02:00
Joe Thornber
d2840b0ec1 Merge branch 'master' into 2018-04-30-vdo-support 2018-05-04 13:32:07 +01:00
Joe Thornber
bc50dc6e70 Merge branch 'master' of git+ssh://sourceware.org/git/lvm2 2018-05-04 09:49:55 +01:00
Joe Thornber
ed837e6971 Revert "build: Calculate dependencies at same time as compiling."
This reverts commit 0931067dc5.

The dep files should be in the build dir, which is not necc. the src dir.

Easy to fix, but reverting for now until I have time to revisit.
2018-05-04 09:48:40 +01:00
David Teigland
f4a60fe004 clvmd: saved_vg code and comment formatting 2018-05-03 14:54:48 -05:00
David Teigland
822a8b62be clvmd: don't save cft and buf for saved_vg 2018-05-03 14:54:48 -05:00
David Teigland
c016b573ee clvmd: separate saved_vg from vginfo
The clvmd saved_vg data is independent from the normal lvm
lvmcache vginfo data, so separate saved_vg from vginfo.
Normal lvm doesn't need to use save_vg at all, and in clvmd,
lvmcache changes on vginfo can be made without worrying
about unwanted effects on saved_vg.
2018-05-03 14:54:48 -05:00
David Teigland
a5e13f2eef clvmd: defer freeing saved vgs
To avoid the chance of freeing a saved vg while another
code path is using it, defer freeing saved vgs until
all the lvmcache content is dropped for the vg.
2018-05-03 14:54:48 -05:00
Heinz Mauelshagen
88fe07ad0a raid: use new internal APIs
Use APIs introduced with commit 4ebfd8e8eb
where appropriate to minimize redundant code.
2018-05-03 21:36:50 +02:00
Joe Thornber
49db9b5e0b Merge branch '2018-05-03-improve-bcache-utils' 2018-05-03 20:15:13 +01:00
Joe Thornber
ac18164a52 unit-test: a bunch of tests for bcache-utils 2018-05-03 20:13:13 +01:00
Heinz Mauelshagen
4ebfd8e8eb lvconvert: don't return success on degraded -m raid1 conversion
In case "lvconvert -mN RaidLV" was used on a degraded
raid1 LV, success was returned instead of an error.

Provide message to inform about the need to repair first
before changing number of mirrors and exit with error.

Add new lvconvert-m-raid1-degraded.sh test.

Resolves: rhbz1573960
2018-05-03 18:48:00 +02:00
Joe Thornber
b393fbec00 configure.ac: bad configure generated due to stray ;; 2018-05-03 15:38:05 +01:00
Joe Thornber
2bb02e24bf Merge branch 'master' of git+ssh://sourceware.org/git/lvm2 2018-05-03 14:23:12 +01:00
Joe Thornber
52656c89fd functional tests: Update have_raid function
No need to check if it's built in.
2018-05-03 14:22:24 +01:00
Joe Thornber
9cab005797 configure.ac: Remove some more remnants of optional RAID
(It's now always 'internal')
2018-05-03 14:21:21 +01:00
Joe Thornber
dfc320f5b8 bcache-utils: rewrite
They take care to avoid redundant reads now.
2018-05-03 11:36:29 +01:00
Joe Thornber
2688aafefb bcache: rename bcache_write_zeroes() -> bcache_zero_bytes()
Now matches the other util functions:

bcache_{prefetch,read,write,zero}_bytes()
2018-05-03 10:21:14 +01:00
Joe Thornber
8b755f1e04 bcache: rewrite bcache_write_zeros()
It now uses GF_ZERO to avoid reading blocks that are going to be
completely zeroed.
2018-05-03 10:14:56 +01:00
Joe Thornber
dc30d4b2f2 bcache: switch off_t -> uint64_t
We always want it to be 64bit
2018-05-03 09:37:43 +01:00
Joe Thornber
efad84ebc2 bcache: Move the utils to a separate file.
This makes it clearer that they don't access the cache internals.
2018-05-03 09:34:41 +01:00
Joe Thornber
b3c41bce3d bcache: add bcache_block_sectors() query fn 2018-05-03 09:33:55 +01:00
Joe Thornber
65912ce44d bcache: add a comment 2018-05-03 09:21:10 +01:00
David Teigland
977d0a3613 filters: increase MAX_FILTERS for new filter
The new signature filter was added without increasing this.
2018-05-02 14:10:30 -05:00
Joe Thornber
90d0ff6636 bcache: reorder includes in .c file too 2018-05-02 19:45:06 +01:00
Joe Thornber
8fd300f7df device/bcache: reorder includes 2018-05-02 18:59:43 +01:00
Joe Thornber
972b535220 build: add -D_FILE_OFFSET_BITS=64
I don't like having this in a common header because it means you end
up including too much and causing unneccessary dependencies.  eg,
lib/misc/lib.h includes libdevmapper.h, internationalisation, and
logging stuff.
2018-05-02 18:40:38 +01:00
Joe Thornber
9fe0be871c unit-test/matcher_t: Fixup Kabi's test
The matcher matches the regexes in reverse order.
2018-05-02 13:53:43 +01:00
Joe Thornber
506ab29bfd unit-test/matcher_t: add another (failing!) test for Kabi 2018-05-02 13:31:57 +01:00
Joe Thornber
6abc3f10ae vdo: get status parser compiling 2018-05-02 11:15:35 +01:00
Joe Thornber
11d9b0cae7 Merge branch 'master' into 2018-04-30-vdo-support 2018-05-02 10:09:20 +01:00
David Teigland
11436b00e0 tests: add gfs-pool test
Put back a test like the old one that was removed
in d709d8445f.

It verifies that lvm will ignore and not use a
gfs-pool device.
2018-05-01 15:24:42 -05:00
David Teigland
24e7745d7a devices: ignore lvm1 and pool devices 2018-05-01 15:18:47 -05:00
Joe Thornber
db0560c1b0 Merge branch 'master' of git+ssh://sourceware.org/git/lvm2 2018-05-01 20:04:30 +01:00
Joe Thornber
1553993ea1 Revert "build: Stop creating the symlinks in include/ on the fly."
This reverts commit cdcea0bf55.
2018-05-01 20:03:51 +01:00
David Teigland
39f05855c0 tests: remove use of lvm1 metadatatype 2018-05-01 13:29:57 -05:00
David Teigland
d709d8445f tests: remove gfs pool test 2018-05-01 13:25:40 -05:00
David Teigland
9687ee2a74 tests: update lvmetad-disabled to not use lvm1 2018-05-01 11:33:39 -05:00
David Teigland
8dcc973bbb bcache_write_bytes needs to be followed by flush
The improved bcache_write_bytes is not flushing, so
the caller needs to do that.
2018-05-01 09:33:55 -05:00
David Teigland
a418f88b76 lvmcache: fix typo in lvmcache_get_saved_vg 2018-05-01 09:06:57 -05:00
Joe Thornber
3ea862bdfc unit-test/bcache_t: test was using too large a block size 2018-05-01 14:17:12 +01:00
Joe Thornber
bfc61a9543 bcache: squash some warnings on rhel6 2018-05-01 13:21:53 +01:00
Joe Thornber
de042fa13d unit-test/bcache_t: Use a stripped down fixture for some tests 2018-05-01 12:54:57 +01:00
Joe Thornber
61153d90e5 build: update ./configure and configure.h.in
Fallout from Dave's removal of format1 and pool.
2018-05-01 12:12:07 +01:00
Joe Thornber
f564e78d98 bcache: rewrite bcache_{write,zero}_bytes
These are utility functions so should only use the public interface.

Also write_bytes was flushing, which will kill performance.
2018-05-01 12:07:33 +01:00
Joe Thornber
c863c9581d Merge branch 'master' of git+ssh://sourceware.org/git/lvm2 2018-05-01 10:48:42 +01:00
Joe Thornber
7aba7fe68b unit-test/io_engine_t: add a little test for bcache_{read,write}_bytes 2018-05-01 10:47:40 +01:00
Joe Thornber
f6459757af unit-test/bcache_t: fixup a test.
Problem found with valgrind.
2018-05-01 09:17:55 +01:00
David Teigland
c1cd18f21e Remove lvm1 and pool disk formats
There are likely more bits of code that can be removed,
e.g. lvm1/pool-specific bits of code that were identified
using FMT flags.

The vgconvert command can likely be reduced further.

The lvm1-specific config settings should probably have
some other fields set for proper deprecation.
2018-04-30 16:55:02 -05:00
David Teigland
029a76b4f8 clvmd: don't repair vg from vg_read in clvmd
The mixed up vg repair code in vg_read was trying
to repair a vg when vg_read was called by clvmd.
The clvmd daemon isn't supposed to be repairing
or writing a vg.

(This is a temporary workaround; vg repair will soon
be pulled out of vg_read so it can be called in a
controlled way and consolidated instead of spread
around.)
2018-04-30 15:56:51 -05:00
David Teigland
c365d7de4f tests: fix THIN built-in check 2018-04-30 13:12:17 -05:00
David Teigland
89935ace29 clvmd: keep old saved_vg if it matches new
There is no need to release the old saved_vg
if it matches the new version.
2018-04-30 13:03:15 -05:00
Joe Thornber
39f24a169c unit-test/io_engine_t: Improve the read test.
Now verifies what it reads.
2018-04-30 17:09:24 +01:00
Joe Thornber
ef79d639fe unit-test/io_engine_t: use posix_memalign() rather than aligned_alloc()
Not present on older systems.
2018-04-30 16:55:19 +01:00
Joe Thornber
cca815d240 Merge branch 'master' of git+ssh://sourceware.org/git/lvm2 2018-04-30 16:33:57 +01:00
Joe Thornber
1b08797419 configure: Remove --enable-testing 2018-04-30 16:31:33 +01:00
Joe Thornber
52ebad31ba vdo: Code drop for status parsing.
Doesn't even compile yet.  Squash this patch.
2018-04-30 16:16:58 +01:00
Joe Thornber
1ddbbb67e0 build: fix typo in dmeventd/plugins/Makefile.in 2018-04-30 15:31:57 +01:00
David Teigland
bdf7479449 toollib: fix wrong dev reference in process_each_label 2018-04-30 09:08:40 -05:00
Joe Thornber
9384b2b5c5 build: Remove unused Makefiles from configure.ac
Should have been in earlier patch.
2018-04-30 14:58:45 +01:00
Joe Thornber
2bc896f2a3 build: remove --with-{snapshots,mirrors,raid,thin,cache} options from ./configure
It now behaves as if the were all set as 'internal'
2018-04-30 10:11:23 +01:00
Joe Thornber
545ca59468 Merge branch 'master' of git+ssh://sourceware.org/git/lvm2 2018-04-30 09:56:04 +01:00
Joe Thornber
0a2b5d5748 [scripts] remove scripts/vg_convert
- it doesn't do anything other than tell you to run vgconvert
- it used to convert from lvm1 format, which is obsolete
2018-04-30 09:46:05 +01:00
Joe Thornber
65d6118e47 [metadata-liblvm.c] comment out some dead code and add a FIXME 2018-04-30 09:45:39 +01:00
Joe Thornber
513e9e3264 [lvmetad.h] Use static inline functions to stub out functions.
The macros were causing warnings because the arguments were percieved as
unused.
2018-04-30 09:45:13 +01:00
Joe Thornber
475626fb6c [build] uncomment 'serial 3' in an m4 file.
Squashes another autoreconf warning
2018-04-30 09:44:27 +01:00
Joe Thornber
865a9c5873 build: rename configure.in -> configure.ac
Squashes a warning from autotools
2018-04-30 09:42:11 +01:00
Zdenek Kabelac
b904d6653d tests: add also snapshot monitoring 2018-04-30 10:41:51 +02:00
Zdenek Kabelac
fade45b1d1 mirror: improve table update
Shift refresh of mirror table right into monitor_dev_for_events().
Use  !vg_write_lock_held() to recognize use of lvchange/vgchange.
(this shall change if this would no longer work, but requires
futher some API changes).

With this patch  dm mirror table is only refreshed when necassary.

Also update WARNING message about mirror usage without monitoring
and display LV name.
2018-04-30 10:41:51 +02:00
Zdenek Kabelac
dd7ac793a0 aux: enhance teardown to better handle weird names
When 'dmsetup' reports result with --nameprefixes it currently
incorrectly 'escapes' problematic characters.

Letting pass such string though shell 'eval' function is hard task.
So instead cut away substring.

Once dmsetup will start to properly escape backslash and apostrophe
this function may need further tuning.
2018-04-30 10:41:51 +02:00
Joe Thornber
877c2f2ffb Merge branch 'master' of git+ssh://sourceware.org/git/lvm2 into merge 2018-04-30 09:34:12 +01:00
Joe Thornber
0931067dc5 build: Calculate dependencies at same time as compiling.
Speeds up the build slightly.
2018-04-30 09:32:14 +01:00
David Teigland
138225a3a8 test: remove pv-duplicate
This wasn't testing duplicate PVs, which are tested by
process-each-duplicate-pvs.sh.
2018-04-27 16:25:41 -05:00
Joe Thornber
ab63923d19 unit-tests: Move to test/unit 2018-04-27 16:55:07 +01:00
Joe Thornber
cdcea0bf55 build: Stop creating the symlinks in include/ on the fly.
Git handles symlinks, tar handles symlinks.  So I've just put the
links themselves into git.

This simplifies dependencies a little, and stop some build loops I was
hitting.

External build dir now works too.
2018-04-27 16:06:59 +01:00
Joe Thornber
5c878167a2 Revert "build: Stop creating the symlinks in include/ on the fly."
This reverts commit f8f6219513.

It wasn't taking builds outside the src dir into account.
2018-04-27 15:30:08 +01:00
Joe Thornber
f8f6219513 build: Stop creating the symlinks in include/ on the fly.
Git handles symlinks, tar handles symlinks.  So I've just put the
links themselves into git.

This simplifies dependencies a little, and stop some build loops I was
hitting.
2018-04-27 15:12:15 +01:00
Joe Thornber
54856b2965 bcache: write some sanity checks for the asyn io engine
Mainly checks aio is installed properly.
2018-04-27 14:24:05 +01:00
Joe Thornber
e890c37704 [bcache] Some work on bcache_invalidate()
bcache_invalidate() now returns a bool to indicate success.  If fails
if the block is currently held, or the block is dirty and writeback
fails.

Added a bunch of unit tests for the invalidate functions.

Fixed some bugs to do with invalidating errored blocks.
2018-04-27 10:56:13 +01:00
Joe Thornber
8a14b8a733 [bcache] Add some unit tests for invalidate block.
Trying to identify dct's lockup.
2018-04-27 09:12:57 +01:00
David Teigland
5b6e62dc1f clvmd: drop old saved_vg when returning new saved_vg
In some pvmove tests, clvmd uses the new (precommitted)
saved_vg, but then requests the old saved_vg, and
expects that the new saved_vg be returned instead of
the old.  So, when returning the new saved_vg, forget
the old one so we don't return it again.
2018-04-26 14:57:45 -05:00
David Teigland
cdb8400de2 scan: refresh filters before scan
The filters save information about devices that should
be ignored, so if we need to repeat a scan  (unusual,
but happens in clvmd), we need to update the filters.
2018-04-26 14:48:13 -05:00
Joe Thornber
1c97fda425 [bcache] get all unit tests passing again 2018-04-26 13:13:27 +01:00
Joe Thornber
ea34dad66f [unit-test] Push the new unit test framwork.
See doc/unit-test.txt for details.

Some bcache tests failing.  Probably due to dct changing semantics, will
fix in follow up patch.
2018-04-26 11:59:39 +01:00
David Teigland
c7fdacbc50 pvmove: in fork mode destroy bcache in child
When pvmove was run in background mode and forks
instead of using lvmpolld, the child pvmove process
was not clearing the bcache from the parent, so all
the aio ops in the child were failing.
2018-04-25 16:40:36 -05:00
David Teigland
0fe4f65f65 scan: don't use cmd mem pool in scan
Make it consistent with all the other allocations
in scanning.
2018-04-25 16:40:08 -05:00
David Teigland
4670e9f698 skip some clvmd-specific code in common cases
This, or something like it, can probably be done
in many other places.
2018-04-25 16:40:08 -05:00
David Teigland
47bfac21ca clvmd: skip dev rescan after full scan
When clvmd does a full label scan just prior to
calling _vg_read(), pass a new flag into _vg_read
to indicate that the normal rescan of VG devs is
not needed.
2018-04-25 16:39:43 -05:00
David Teigland
1fec86571f clvmd: reuse a vg struct for sequential LV operations
After reading a VG, stash it in lvmcache as "saved_vg".
Before reading the VG again, try to use the saved_vg.
The saved_vg is dropped on VG lock operations.
2018-04-25 16:39:43 -05:00
David Teigland
f8616ac2d8 lvmcache: rename suspended_vg to saved_vg
The copy of the VG which clvmd stashes in lvmcache should
not only be used between suspend and resume, but between
sequential LV operations in clvmd, so that clvmd does not
need to reread the VG for each one.  Prepare for that by
renaming the stashed VG as "saved_vg".
2018-04-25 16:39:43 -05:00
Joe Thornber
28a9fcd94b Merge remote-tracking branch 'sourceware/master' into upstream 2018-04-25 09:18:42 +01:00
Zdenek Kabelac
dcb5434a7f tests: more zero usage
Another case where usage of zero backend for mirror legs is more
effective then using delayed_dev.
2018-04-23 22:42:18 +02:00
Zdenek Kabelac
fc3ed8856f tests: update testing to not use delay dev
Instead of using delayer device user 'zero' device and let mirror
do some real work which takes some time.

In case the test machine is too fast - mirror might need to be made bigger
to meet needed criteria.

Also move all test needed this 'zero' PV trick to the end of test
so  $dev2  and $dev4 are covered with 'zero' and can take any amount of
write without consuming any real space.
2018-04-23 22:42:18 +02:00
Zdenek Kabelac
c492fbb51c debug: more explanatory error message 2018-04-23 22:42:18 +02:00
Zdenek Kabelac
66f4f8c27f lvconvert: preserve regionsize from existing mirror
When adding leg to existing mirror - preserve its regionsize.
2018-04-23 22:42:18 +02:00
Zdenek Kabelac
ae27461777 lvchange: update mirror table when changing monitoring
Since for non-monitored mirrors we let mirror running without
error handling - when monitoring changes for mirror, updated
table (refresh) is needed.
2018-04-23 22:42:18 +02:00
Zdenek Kabelac
fcdac700f9 gcc: remove duplicate typedef 2018-04-23 22:42:18 +02:00
Joe Thornber
f2504257e4 [git] Update .gitignore 2018-04-23 09:49:37 +01:00
David Teigland
1409c4a1c2 clvm: rescan when VG or PV not found
Rescan devices to update lvmcache content when
clvmd vg_read doesn't find a VG or PV.
2018-04-20 16:09:49 -05:00
David Teigland
c42a18d372 liblvm2app: missed the addition of lvmcache_label_scan 2018-04-20 12:00:49 -05:00
David Teigland
aee27dc7ba scan: skip device rescan in vg_read
For reporting commands (pvs,vgs,lvs,pvdisplay,vgdisplay,lvdisplay)
we do not need to repeat the label scan of devices in vg_read if
they all had matching metadata in the initial label scan.  The
data read by label scan can just be reused for the vg_read.
This cuts the amount of device i/o in half, from two reads of
each device to one.  We have to be careful to avoid repairing
the VG if we've skipped rescanning.  (The VG repair code is very
poor, and will be redone soon.)
2018-04-20 11:23:14 -05:00
David Teigland
7b0a8f47be lvmpolld: update to use new scanning correctly 2018-04-20 11:22:48 -05:00
David Teigland
aa833bdd8a bcache: intercept test mode before write
Don't allow writes in test mode.  test mode should be
more sophisticated than just faking writes, and this
should be a last defense for cases where test mode is
not being checked correctly.
2018-04-20 11:22:48 -05:00
David Teigland
9b6a62f944 lvmcache: simplify
Recent changes allow some major simplification of the way
lvmcache works and is used.  lvmcache_label_scan is now
called in a controlled fashion at the start of commands,
and not via various unpredictable side effects.  Remove
various calls to it from other places.  lvmcache_label_scan
should not be called from anywhere during a command, because
it produces an incorrect representation of PVs with no MDAs,
and misclassifies them as orphans.  This has been a long
standing problem.  The invalid flag and rescanning based on
that is no longer used and removed.  The 'force' variation is
no longer needed and removed.
2018-04-20 11:22:48 -05:00
David Teigland
c0973e70a5 dev_cache: clean up scan
Pull out all of the twisted logic and simply call dev_cache_scan
at the start of the command prior to label scan.
2018-04-20 11:22:48 -05:00
David Teigland
89c65d4f71 remove unnecessary REQUIRES_FULL_LABEL_SCAN
we always scan all devices
2018-04-20 11:22:48 -05:00
David Teigland
45e5e702c1 scan: improve io error checking and reporting 2018-04-20 11:22:48 -05:00
David Teigland
6d05859862 bcache: let caller see an error 2018-04-20 11:22:48 -05:00
David Teigland
ae21305ee7 scan: drop bcache between lvm shell commands
A running lvm shell keeps all lvm devices open
unless the bcache is dropped.
2018-04-20 11:22:48 -05:00
David Teigland
a01a8d7172 tests: vgck now exits with error for bad vg 2018-04-20 11:22:48 -05:00
David Teigland
a9b0aa5c17 lvmetad: more fixes related to bcache
Need to open devs prior to bcache io.
2018-04-20 11:22:48 -05:00
David Teigland
e351f8bc66 lvmetad: need to set up bcache in another place
We need to find one common place to set up bcache
for the lvmetad case, instead of adding calls in
various places.
2018-04-20 11:22:48 -05:00
David Teigland
7e33bd1335 lvmetad: fix process_each_label
Was missing the call to populate lvmcache info from lvmetad
at the start of process_each_label.
2018-04-20 11:22:48 -05:00
David Teigland
ddb5de7a98 clvm: fix bcache scan handling
We can't let clvmd keep all scanned devs open,
which prevents them from being removed.  So
drop the bcache data (and close fds) affter
doing a label scan.

Also set up bcache before the clvm-specific
vg_read (which needs to rescan the vg's devs
using bcache) and destroy the bcache after.
2018-04-20 11:22:48 -05:00
David Teigland
196579af1f scan: check for errors in text layer
The scanning code in the format_text layer
has previously ignored errors.  Start checking
for and returning them.
2018-04-20 11:22:47 -05:00
David Teigland
44726ed9cb scan: remove lvmcache info for failed devs
When scanning a device fails, drop an lvmcache
info struct for it.
2018-04-20 11:22:47 -05:00
David Teigland
1717d4cb17 lvmcache: add shorter way to delete dev info
Don't make the caller look up the info first.
2018-04-20 11:22:47 -05:00
David Teigland
570c6239ee bcache: fix error handling
The error handling code wasn't working, but it
appears that just removing it is what we need.
The doesn't really need any different behavior
related to bcache blocks on an io error, it just
wants to know if there was an error.
2018-04-20 11:22:47 -05:00
David Teigland
217f3f8741 scan: add function to drop bcache blocks
which can be a little more efficient that destroy.
2018-04-20 11:22:47 -05:00
David Teigland
da2b155a9d scan: invalidate bcache for dev after errors
If there are errors reading or writing dev,
invalidate bcache for it.
2018-04-20 11:22:47 -05:00
David Teigland
4331182964 bcache: add some error messages for debugging 2018-04-20 11:22:47 -05:00
David Teigland
21057676a1 scan: create bcache with minimum number of blocks
In some odd cases (e.g. tests) there are very few devices
which results in creating too few blocks in bcache, so
create bcache with a minimum number of blocks.
2018-04-20 11:22:47 -05:00
David Teigland
e49b114f7e bcache: use wrappers for bcache read write in lvm
Using a wrapper makes it easier to disable bcache if needed.
2018-04-20 11:22:47 -05:00
David Teigland
8065492046 bcache: do all writes through bcache 2018-04-20 11:22:47 -05:00
David Teigland
8b26a007b1 misc bcache fixes from ejt 2018-04-20 11:22:47 -05:00
David Teigland
0da296003d vgchange: invalidate bcache for stacked LVs when deactivating
An LV with a stacked PV will be open in bcache and needs to be
invalidated to close the fd before attempting to deactivate.
2018-04-20 11:22:47 -05:00
David Teigland
34fd818caf scan: drop bcache and close fd for LV with stacked PV
When a PV is stacked on an LV, the LV will be kept in
bcache, and the open fd on the LV may interfere with
processing the LV.  So, drop/close a bcache fd for
an LV before processing the LV.
2018-04-20 11:22:47 -05:00
David Teigland
c2b10daf69 scan: put dev back on caller's list
Commit 6e442875613915e506440e59a290b56756df2521 missed
adding devs back to caller's list.
2018-04-20 11:22:47 -05:00
David Teigland
e7670d3338 pvck: use bcache 2018-04-20 11:22:47 -05:00
David Teigland
b504bb809e scan: use 128K bcache block size 2018-04-20 11:22:46 -05:00
David Teigland
ae093df3f1 test: vgsplit-usage if LVM1 tests 2018-04-20 11:22:46 -05:00
David Teigland
d75aa55784 disable LVM1 tests 2018-04-20 11:22:46 -05:00
David Teigland
96a61337b0 lvmdiskscan: use the new label_scan
instead of doing it's own.
2018-04-20 11:22:46 -05:00
David Teigland
28255e3eee scan: always setup bcache for commands using lvmetad
Do this at the start of the command so that it doesn't
need to be checked and set up in every function that
could need it.
2018-04-20 11:22:46 -05:00
David Teigland
f328532f05 scan: leave the caller's dev list unchanged
When scanning the list of devs from the caller
they are moved to another temporary list, but
were never returned to the original list.
2018-04-20 11:22:46 -05:00
David Teigland
7bce66c5e8 scan: setup bcache for commands using lvmetad
Commands using lvmetad will not begin with a proper
label_scan which initializes bcache, but may later
decide they need to scan a set of devs, in which case
they'll need bcache set up at that point.
2018-04-20 11:22:46 -05:00
David Teigland
6e580465b5 vgremove: fix force remove on devs with damaged metadata
The improved detection of bad metadata when scanning
(where errors were ignored before) means we now have to
override some errors when forcibly erasing damaged metadata.
2018-04-20 11:22:46 -05:00
David Teigland
37471bb477 scan: skip extra scan in vg_read
Drop an extra label scan in the recovery part
of vg_read.  This is a temporary improvement
until the pending replacement for the broken
recovery code burried in vg_read.
2018-04-20 11:22:46 -05:00
David Teigland
e4f478d86d scan: handle request to scan missing dev 2018-04-20 11:22:46 -05:00
David Teigland
89f54a5094 remove debugging print 2018-04-20 11:22:46 -05:00
David Teigland
c29899b910 remove unused variable in _pvremove_check_single 2018-04-20 11:22:46 -05:00
David Teigland
a1e3398ffc scan: handle no devices
Still create bcache.
2018-04-20 11:22:46 -05:00
David Teigland
9d2add1361 scan: add a dev to bcache before each read to handle write path
This is a temporary hacky workaround to the problem of
reads going through bcache and writes not using bcache.
The write path wants to read parts of data that it is
incrementally writing to disk, but the reads (using
bcache) don't work because the writes are not in the
bcache.  For now, add a dev to bcache before each attempt
to read it in case it's being used on the write path.
2018-04-20 11:22:46 -05:00
David Teigland
6c67c7557c scan: use separate fd for bcache
Create a new dev->bcache_fd that the scanning code owns
and is in charge of opening/closing.  This prevents other
parts of lvm code (which do various open/close) from
interfering with the bcache fd.  A number of dev_open
and dev_close are removed from the reading path since
the read path now uses the bcache.

With that in place, open(O_EXCL) for pvcreate/pvremove
can then be fixed.  That wouldn't work previously because
of other open fds.
2018-04-20 11:22:46 -05:00
David Teigland
4343280ebc process_each_label: use lvmcache
In the same way as the other process_each functions.
In the common case all the info that's needed can be
used from lvmcache after a label scan.  But this means
that unchosen devs for duplicate PVs need to be handled
explicitly.
2018-04-20 11:22:46 -05:00
David Teigland
f17c2cf7c6 pvremove: device check doesn't require label_read
It just needs to check if the device was found during
the scan, which means checking if it exists in lvmcache.
2018-04-20 11:22:45 -05:00
David Teigland
29c6c17121 format-text.c log message fixes 2018-04-20 11:22:45 -05:00
David Teigland
d9a77e8bb4 lvmcache: simplify metadata cache
The copy of VG metadata stored in lvmcache was not being used
in general.  It pretended to be a generic VG metadata cache,
but was not being used except for clvmd activation.  There
it was used to avoid reading from disk while devices were
suspended, i.e. in resume.

This removes the code that attempted to make this look
like a generic metadata cache, and replaces with with
something narrowly targetted to what it's actually used for.

This is a way of passing the VG from suspend to resume in
clvmd.  Since in the case of clvmd one caller can't simply
pass the same VG to both suspend and resume, suspend needs
to stash the VG somewhere that resume can grab it from.
(resume doesn't want to read it from disk since devices
are suspended.)  The lvmcache vginfo struct is used as a
convenient place to stash the VG to pass it from suspend
to resume, even though it isn't related to the lvmcache
or vginfo.  These suspended_vg* vginfo fields should
not be used or touched anywhere else, they are only to
be used for passing the VG data from suspend to resume
in clvmd.  The VG data being passed between suspend and
resume is never modified, and will only exist in the
brief period between suspend and resume in clvmd.

suspend has both old (current) and new (precommitted)
copies of the VG metadata.  It stashes both of these in
the vginfo prior to suspending devices.  When vg_commit
is successful, it sets a flag in vginfo as before,
signaling the transition from old to new metadata.

resume grabs the VG stashed by suspend.  If the vg_commit
happened, it grabs the new VG, and if the vg_commit didn't
happen it grabs the old VG.  The VG is then used to resume
LVs.

This isolates clvmd-specific code and usage from the
normal lvm vg_read code, making the code simpler and
the behavior easier to verify.

Sequence of operations:

- lv_suspend() has both vg_old and vg_new
  and stashes a copy of each onto the vginfo:
  lvmcache_save_suspended_vg(vg_old);
  lvmcache_save_suspended_vg(vg_new);

- vg_commit() happens, which causes all clvmd
  instances to call lvmcache_commit_metadata(vg).
  A flag is set in the vginfo indicating the
  transition from the old to new VG:
  vginfo->suspended_vg_committed = 1;

- lv_resume() needs either vg_old or vg_new
  to use in resuming LVs.  It doesn't want to
  read the VG from disk since devices are
  suspended, so it gets the VG stashed by
  lv_suspend:
  vg = lvmcache_get_suspended_vg(vgid);

If the vg_commit did not happen, suspended_vg_committed
will not be set, and in this case, lvmcache_get_suspended_vg()
will return the old VG instead of the new VG, and it will
resume LVs based on the old metadata.
2018-04-20 11:22:45 -05:00
David Teigland
79c4971210 label_scan: remove extra label scan and read for orphan PVs
When process_each_pv() calls vg_read() on the orphan VG, the
internal implementation was doing an unnecessary
lvmcache_label_scan() and two unnecessary label_read() calls
on each orphan.  Some of those unnecessary label scans/reads
would sometimes be skipped due to caching, but the code was
always doing at least one unnecessary read on each orphan.

The common format_text case was also unecessarily calling into
the format-specific pv_read() function which actually did nothing.

By analyzing each case in which vg_read() was being called on
the orphan VG, we can say that all of the label scans/reads
in vg_read_orphans are unnecessary:

1. reporting commands: the information saved in lvmcache by
the original label scan can be reported.  There is no advantage
to repeating the label scan on the orphans a second time before
reporting it.

2. pvcreate/vgcreate/vgextend: these all share a common
implementation in pvcreate_each_device().  That function
already rescans labels after acquiring the orphan VG lock,
which ensures that the command is using valid lvmcache
information.
2018-04-20 11:22:45 -05:00
David Teigland
5f138f3604 vgcreate: improve the use of label_scan
The old code was doing unnecessary label scans when
checking to see if the new VG name exists.  A single
label_scan is sufficient if it is done after the
new VG lock is held.
2018-04-20 11:22:45 -05:00
David Teigland
e3e5beec74 lvmetad: use new label_scan for update from pvscan
Take advantage of the common implementation with aio
and reduced disk reads.
2018-04-20 11:22:43 -05:00
David Teigland
9c71fa0214 lvmetad: use new label_scan for update from lvmlockd
When lvmlockd indicates that the lvmetad cache is out of
date because of changes by another node, lvmetad_pvscan_vg()
rescans the devices in the VG to update lvmetad.  Use the
new label_scan in this function to use the common code and
take advantage of the new aio and reduced reads.
2018-04-20 11:21:41 -05:00
David Teigland
098c843c50 independent metadata areas: fix bogus code
Fix mixing bitwise & and logical && which was
always 1 in any case.
2018-04-20 11:21:41 -05:00
David Teigland
d9ef9eb330 label_scan: fix independent metadata areas
This fixes the use of lvmcache_label_rescan_vg() in the previous
commit for the special case of independent metadata areas.

label scan is about discovering VG name to device associations
using information from disks, but devices in VGs with
independent metadata areas have no information on disk, so
the label scan does nothing for these VGs/devices.
With independent metadata areas, only the VG metadata found
in files is used.  This metadata is found and read in
vg_read in the processing phase.

lvmcache_label_rescan_vg() drops lvmcache info for the VG devices
before repeating the label scan on them.  In the case of
independent metadata areas, there is no metadata on devices, so the
label scan of the devices will find nothing, so will not recreate
the necessary vginfo/info data in lvmcache for the VG.  Fix this
by setting a flag in the lvmcache vginfo struct indicating that
the VG uses independent metadata areas, and label rescanning should
be skipped.

In the case of independent metadata areas, it is the metadata
processing in the vg_read phase that sets up the lvmcache
vginfo/info information, and label scan has no role.
2018-04-20 11:21:41 -05:00
David Teigland
748f29b42a scan: do scanning at the start of a command
Move the location of scans to make it clearer and avoid
unnecessary repeated scanning.  There should be one scan
at the start of a command which is then used through the
rest of command processing.

Previously, the initial label scan was called as a side effect
from various utility functions.  This would lead to it being called
unnecessarily.  It is an expensive operation, and should only be
called when necessary.  Also, this is a primary step in the
function of the command, and as such it should be called prominently
at the top level of command processing, not as a hidden side effect
of a utility function.  lvm knows exactly where and when the
label scan needs to be done.  Because of this, move the label scan
calls from the internal functions to the top level of processing.

Other specific instances of lvmcache_label_scan() are still called
unnecessarily or unclearly by specific commands that do not use
the common process_each functions.  These will be improved in
future commits.

During the processing phase, rescanning labels for devices in a VG
needs to be done after the VG lock is acquired in case things have
changed since the initial label scan.  This was being done by way
of rescanning devices that had the INVALID flag set in lvmcache.
This usually approximated the right set of devices, but it was not
exact, and obfuscated the real requirement.  Correct this by using
a new function that rescans the devices in the VG:
lvmcache_label_rescan_vg().

Apart from being inexact, the rescanning was extremely well hidden.
_vg_read() would call ->create_instance(), _text_create_text_instance(),
_create_vg_text_instance() which would call lvmcache_label_scan()
which would call _scan_invalid() which repeats the label scan on
devices flagged INVALID.  lvmcache_label_rescan_vg() is now called
prominently by _vg_read() directly.
2018-04-20 11:21:38 -05:00
David Teigland
4507ba3596 scan: use new label_scan for lvmcache_label_scan
To do label scanning, lvm code calls lvmcache_label_scan().
Change lvmcache_label_scan() to use the new label_scan()
based on bcache.

Also add lvmcache_label_rescan_vg() which calls the new
label_scan_devs() which does label scanning on only the
specified devices.  This is for a subsequent commit and
is not yet used.
2018-04-20 11:19:32 -05:00
David Teigland
a7cb76ae94 scan: use bcache for label scan and vg read
New label_scan function populates bcache for each device
on the system.

The two read paths are updated to get data from bcache.

The bcache is not yet used for writing.  bcache blocks
for a device are invalidated when the device is written.
2018-04-20 11:19:24 -05:00
David Teigland
697fa7aa1d [makefile] add -laio to makefiles 2018-04-20 11:13:17 -05:00
David Teigland
93fc937429 [device/bcache] bcache_read_bytes should put blocks 2018-04-20 11:12:50 -05:00
David Teigland
7be54bd687 [device/bcache] fix min() function 2018-04-20 11:12:50 -05:00
David Teigland
d9e6298edb [device/bcache] fix missing max_io fn in bcache async engine 2018-04-20 11:12:50 -05:00
Joe Thornber
dc8034f5eb [device/bcache] more work on bcache 2018-04-20 11:12:50 -05:00
Joe Thornber
1cde30eba0 [device/bcache] More fiddling with tests 2018-04-20 11:12:50 -05:00
Joe Thornber
6a57ed17a2 [device/bcache] add bcache_prefetch_bytes() and bcache_read_bytes()
Not tested yet.
2018-04-20 11:12:50 -05:00
Joe Thornber
467adfa082 [device/bcache] More tests and some bug fixes 2018-04-20 11:12:50 -05:00
Joe Thornber
8ae3b244fc [build] include test/unit/Makefile rather than recursive build
FIXME: unit tests are not currently run as part of make check.
2018-04-20 11:12:50 -05:00
Joe Thornber
b03e55a513 [device/bcache] rename a unit test 2018-04-20 11:12:50 -05:00
Joe Thornber
0d0fab3d2d [device/bcache] another unit test 2018-04-20 11:12:50 -05:00
Joe Thornber
19647d1cd4 [device/bcache] fix bug in _alloc_block 2018-04-20 11:12:50 -05:00
Joe Thornber
1563b93691 [device/bcache] Add bcache_max_prefetches()
Ignore prefetches if max io is in flight.
2018-04-20 11:12:50 -05:00
Joe Thornber
c4c4acfd42 [device/bcache] Add a couple of invalidate methods 2018-04-20 11:12:50 -05:00
Joe Thornber
0f0eb04edb [device/bcache] some more work on bcache 2018-04-20 11:12:50 -05:00
Joe Thornber
46867a45d2 [device/bcache] stub a unit test 2018-04-20 11:12:50 -05:00
Joe Thornber
cb2c4542a6 [git] Update .gitignore 2018-04-20 11:11:56 -05:00
Joe Thornber
38d77898ae [unit tests] remove old unit tests that weren't built or run. 2018-04-20 11:10:46 -05:00
Joe Thornber
7a475bef32 [build] Quieten the build down
It was hard to see warnings with the long command lines scrolling by so
quickly.

Use 'make V=1' if you need to see all the gritty details.
2018-04-20 11:10:45 -05:00
Joe Thornber
da7e13ef88 [lib/device/bcache] Tweaks after Kabi's review 2018-04-20 11:10:45 -05:00
Joe Thornber
acb42ec465 [device/bcache] Initial code drop.
Compiles.  Not written tests yet.
2018-04-20 11:10:45 -05:00
Joe Thornber
00f1b208a1 [io paths] Unpick agk's aio stuff 2018-04-20 11:03:58 -05:00
Zdenek Kabelac
d51429254f tests: improve mirror_images_redundant
Use only passed VG for lvs and avoid 1 extra uneeded use of lvs.
2018-04-20 12:17:01 +02:00
Zdenek Kabelac
ac18005de9 tests: update mirror test
Since lvconvert again is able to wait on mirror synchronization,
drop 'should'.

Also add FIXME about  'lvreduce' and too big region size.
2018-04-20 12:17:01 +02:00
Zdenek Kabelac
fa5ba7e42d coverity: ensure 0 end string
Use dm_strncpy() to enusure string ends with '\0'.
In case uuid does not fit, report error.
2018-04-20 12:17:01 +02:00
Zdenek Kabelac
037c234eaa cleanup: avoid compiler warn
When variable is unused...
2018-04-20 12:17:01 +02:00
Zdenek Kabelac
73cda0437f cleanup: correcting macro wrapping
Use proper do {} while(0) so ';' after macros are correctly
interpretted..
2018-04-20 12:17:01 +02:00
Zdenek Kabelac
9731d48691 cleanup: enhance debug message 2018-04-20 12:17:01 +02:00
Zdenek Kabelac
d437bd86ff cleanup: display_lvname update message
Add more display_lvname usage.
Update some error messages.
Indent.
2018-04-20 12:17:01 +02:00
Zdenek Kabelac
7323557379 cleanup: add _mb_ to regiosize option
Just like with others mentions default unit in function name.
2018-04-20 12:17:01 +02:00
Zdenek Kabelac
e878c3fc32 cleanup: correct casting 2018-04-20 12:17:01 +02:00
Zdenek Kabelac
27a1a0e5c0 cleanup: reorder condition
There is no point to wait for sync for non-locally active LV.
2018-04-20 12:17:01 +02:00
Zdenek Kabelac
1287edf626 cleanup: call uname once
Call uname() once and keep result for mirror use-case.
2018-04-20 12:16:58 +02:00
Zdenek Kabelac
d81e3f9b06 mirror: use vg mempool
Use vg mempool with mirror log metadata update.
2018-04-20 12:16:14 +02:00
Zdenek Kabelac
05f954ee9b mirror: checking for mirror segtype
Checking more correctly for mirror segtype here instead of
mirrored one which can be also 'raid'.
2018-04-20 12:16:14 +02:00
Zdenek Kabelac
79d214032b mirror: validate region_size for mirrors
Check for region size properties of mirror segments.
2018-04-20 12:16:13 +02:00
Zdenek Kabelac
1693fef529 mirror: properly reload table for log init
Since mirror can be stacked, we need to properly reload whole
table stack, otherwice we may mishandle devices in dm table.
2018-04-20 12:15:36 +02:00
Zdenek Kabelac
55d83f9f6e mirror: block_on_error only with monitoring
When user configured lvm2 to NOT user monitoring, activated mirror
actually hang upon error and it's quite unusable moment.

So instead Warn those 'brave' non-monitoring users about possible
problem and activation mirror without blocking error handling.

This also makes it a bit simpler for test suite to handle trouble
cases when test is running without  dmeventd.
2018-04-20 12:13:51 +02:00
Zdenek Kabelac
66400d003d mirror: fix region_size for clustered VG
When adjusting region size for clustered VG it always needs to fit
2 full bitset into 1MB due to old limits of CPG.

This is relatively big amount of bits, but we have still limitation
for region size to fit into 32bits (0x8000000).

So for too big mirrors this operation needs to fail - so whenever
function returns now 0, it means we can't find matching region_size.

Since return 0 is now 'error' we need to also pass proper region_size
when creating pvmove mirror.
2018-04-20 12:13:48 +02:00
Zdenek Kabelac
a19456b868 mirror: fix calcs for maximal region_size
Since extent_size is no longer power_of_2 this max region size
evalution was rather producing random bitsize as a combination
of lowest bit from number of extents and extent size itself.

Correct calculation to use whole LV size and pick biggest
possible power of 2 value smaller then UINT32_MAX.
2018-04-20 12:13:08 +02:00
Zdenek Kabelac
91965af9b1 mirror: improve mirror log size estimation
Drop mirrored mirror log limitation that applies only in very limited
use-case and actually mirrored mirror log is deprecated anyway.

So 'disk' mirror log is selecting the correct minimal size, and
bigger size is only enforced with real mirrored mirror log.

Also for mirrored mirror log we let use 'smalled' region size if needed
so if user uses  1G region size, we still keep small mirror log
with much smaller region size in this case when needed.

Also mirror log extent calculation is now properly detecting error
with too big mirrors where previosly trimmed uint32_t was applies
unintentionally.
2018-04-20 12:11:42 +02:00
Zdenek Kabelac
73189170f5 mirror: fix 32bit size calculation
On 32bit arch  size_t remains 4-byte wide - so size can't
get correct result for multiplication of 32bit numbers.
2018-04-20 12:08:57 +02:00
Zdenek Kabelac
ff3ffe30e4 activation: add generic rule for visibility change
Whenever we make visible LV out of previously invisible one,
reload it's table - the is mandator for proper udev rule
processing as well as ensure content of dm table is correct.

TODO: this new generic rule probably make extra raid rules unnecessary.
2018-04-20 12:07:36 +02:00
Zdenek Kabelac
9068de011d lvconvert: drop limitation for converting lv
Fixing regresion on argument acceptance where any lv can be passed
with paramaterless lvconvert which is meant to figure out needed
operation - i.e. wait for  mirror synchronization.

User has no other 'effective' method to wait for mirror getting in-sync.
2018-04-20 12:06:51 +02:00
Zdenek Kabelac
a7d077b89b thin: restore usability of thin for external origin
With command definition it's been lost support for thin LV being
an external origin for another thinLV.
2018-04-20 12:06:03 +02:00
Zdenek Kabelac
ace97c9f9c pvmove: support properly subLV locking
Since we support snapshot of mirrors, we do need to properly check
for stacked lock holder - fixes problem of pvmove in cluster
with mirrors under snapshot.

WHATS_NEW for this patch goes with 'Restore pvmove support...'
2018-04-20 12:03:16 +02:00
Martin Wilck
7a7b8a7778 udev: keep systemd vars on change event in 69-dm-lvm-metad.rules for systemd reload
The current logic that avoids setting SYSTEMD_ALIAS and SYSTEMD_WANTS
on "change" events is flawed in the default "systemd background job"
configuration. For systemd, it's important that device properties don't
change spuriously.

If an "add" event starts lvm2-pvscan@.service for a device, and a
"change" event follows, removing SYSTEMD_ALIAS and SYSTEMD_WANTS from the
udev db, information about unit dependencies between the device and the
pvscan service can be lost in systemd, in particular if the daemon
configuration is reloaded.

Steps to reproduce problem:

- create a device with an LVM PV
- remove device
- add device (generates "add" and "change" uevents for the device)
  (at this point SYSTEMD_ALIAS and SYSTEMD_WANTS are clear in udev db)
- systemctl daemon-reload
  (systemd reloads udev db)
- vgchange -a n
- remove device

=> the lvm2-pvscan@.service for the device is still active although the
device is gone.

- add device again

=> the PV is not detected, because systemd sees the lvm2-pvscan@.service
as active and thus doesn't restart it.

The original purpose of this logic was to avoid volumes being scanned
over and over again. With systemd background jobs, that isn't necessary,
because systemd will not restart the job as long as it's active.

Signed-off-by: Martin Wilck <mwilck@suse.com>
2018-04-17 11:38:12 +02:00
Martin Wilck
99bfbbf229 udev: explicit pvscan rule in 69-dm-lvm-metad.rules
Make the distinction between the cases with and without systemd
background jobs explicit in 69-dm-lvm-metad.rules rather than
substituting the rule from the Makefile. At this stage,
this improves only readibility, at the cost of one GOTO statement.

This patch introduces no functional change to the udev rules.

Signed-off-by: Martin Wilck <mwilck@suse.com>
2018-04-17 11:32:52 +02:00
Heinz Mauelshagen
bc286910ec test: add lvcreate-raid-volume_list
Test that no (Sub)LV remnants persist if the volume group is
not listed in configuration variable activation/volume_list,
hence not activatable thus causing initialization of rmeta
SubLVs to fail.

Related: rhbz1161347
2018-04-06 15:26:38 +02:00
Zdenek Kabelac
3a48fb47b7 tests: shellcheck misc
Few more minor complains from ShellCheck.
2018-03-23 17:25:00 +01:00
Zdenek Kabelac
1507956383 tests: shellcheck split assing
Keep possibly error unmasked by assign
2018-03-23 17:25:00 +01:00
Zdenek Kabelac
397b7891ff tests: shellcheck liter 2018-03-23 17:25:00 +01:00
Zdenek Kabelac
410c992744 tests: shellcheck use grep -E
Replace egrep with grep -E
2018-03-23 17:25:00 +01:00
Zdenek Kabelac
14abe1e87b tests: shellcheck prevention check
Always make sure variable is set to something else the /dev/*
2018-03-23 17:25:00 +01:00
Zdenek Kabelac
cafcc5813a fsadm: shellcheck prefer explicit escaping
Backslash is literal in "\t". Prefer explicit escaping: "\\t".
2018-03-23 17:25:00 +01:00
Zdenek Kabelac
fe69731d31 tests: handle setting better
When using 'make check...  LVM_TEST_AUX_TRACE=0'  make it behaving
like other supported VARS in use so it's like disabled.
2018-03-23 17:25:00 +01:00
Zdenek Kabelac
30975a3328 libdm: enhance mounted fs detection
btrfs is using fake major:minor device numbers.
try to be smarter and detect used node via DM device name.

This shortens delays, where i.e. lvm2 is asked to deactivate
volume with mounted btrfs as such operation is not retryed
and user is informed about device being in use.
2018-03-23 17:24:58 +01:00
Zdenek Kabelac
8c02cc9e8f tests: update no tool test
Correct testing with format 1 and mq policy.

Add testing of 'smq'

Fix testing with clvmd - where logged message is part of clvmd log
and we can only check command status.
2018-03-19 12:08:04 +01:00
Zdenek Kabelac
4e0c0417ce cleanup: typo fix 2018-03-19 12:05:57 +01:00
Zdenek Kabelac
8d7ece126b cache: disallow to combine format 2 with mq
Only policy 'smq' is meant to be used with format version 2.
Code used to let pass 'mq' policy also with format 2. But 'mq'
is obsoloted wth smq and kernel currently matches it. But this
is incompatible with older original mq logic - so disallow creation
of this rather useless combination.
2018-03-19 12:02:08 +01:00
Zdenek Kabelac
08487a3098 tests: use 4k extents
Use 4K chunks since some older kernels are not capable
to create striped volumes with smaller size.

TODO: lvm2 should detect this ahead and avoid kernel
reporting "Invalid chunk".
2018-03-18 00:30:43 +01:00
Zdenek Kabelac
e5b40e0488 tests: check activation of cache without cache_check 2018-03-17 23:33:58 +01:00
Zdenek Kabelac
9e7b00a3b9 tests: test striped COW LV 2018-03-17 23:33:58 +01:00
Zdenek Kabelac
c82ab92d04 cleanup: use zalloc
Replace malloc() + memset()   with zalloc().
2018-03-17 23:33:58 +01:00
Zdenek Kabelac
5c40e81a7e cleanup: use direct initializer 2018-03-17 23:33:58 +01:00
Zdenek Kabelac
f4383a70ba coverity: drop unused local static var 2018-03-17 23:33:58 +01:00
Zdenek Kabelac
aa75e181be coverity: drop unneeded header files 2018-03-17 23:33:58 +01:00
Zdenek Kabelac
b4c69320fc coverity: move declaration out of the loop
Move declaration of count counter outside the while loop.
2018-03-17 23:33:58 +01:00
Zdenek Kabelac
f2d0eefa77 coverity: make use of defined variable
Since we declare 'r', let's use the value for something.
2018-03-17 23:33:58 +01:00
Zdenek Kabelac
26c58027fb coverity: validate descriptor
Since this function is called with 'fd == -1', but Coverity can't see
this path can't be visited with this argument, add explicit check for
valid descriptor.
2018-03-17 23:33:58 +01:00
Zdenek Kabelac
f331eb1c0d coverity: ensure lock_type is not NULL 2018-03-17 23:33:58 +01:00
Zdenek Kabelac
fd6661dfcf coverity: add missing error check for str_list_add
Validate success.
2018-03-17 23:33:58 +01:00
Zdenek Kabelac
d727382275 lvconvert: accept striped LV as snapshot COW LV
Restore back acceptance of striped LV to be valid COW LV.
2018-03-17 23:33:58 +01:00
Zdenek Kabelac
67fbe980a7 raid: fix version check of target
Comparision missed to check patch level for matching minor version.
Howerver since all checked patchlevels were 0 - the fix doesn't change result.
2018-03-17 23:30:14 +01:00
Zdenek Kabelac
689af32313 pools: skip checks when tools are missing
If the tools for checking thin_pool or cache metadata are missing,
issue rather just a WARNING, but let the operation of activation
continue.

This has the advantage, the if user is missing those tools,
but he already started to use thinpool or cacheing, he can
access these volumes with a WARNING.

Also if the user is using too old tools i.e. for CacheV2 format
dmpd tool 0.7 is required - provide informative WARNING and
skip failure from older tool version which can't understand
new format V2.
2018-03-17 23:29:11 +01:00
Heinz Mauelshagen
d68d71013f lvcreate: remove RaidLV on creation failure
In case a newly created RaidLV is blacklisted using config
\"activation { volume list = [ ... ] }\" (i.e. its SubLVs stay inactive),
the metadata SubLVs can't get wiped thus failing the creation.

As a result, the RaidLV together with its SubLVs
is left behind in an inconsistent state.

Fix by removing the RaidLV and provide a hint about volume_list reasoning.

Resolves: rhbz1161347
2018-03-16 15:57:53 +01:00
Zdenek Kabelac
9553dc7761 activation: separate prioritized counter
While prioritized_section() based on raised priority works
nicely for standard lvm comman - separate counter is actually needed
when it's used in daemons like clvmd/dmeventd  where priority
stays raised all the time.
2018-03-15 12:30:45 +01:00
Zdenek Kabelac
f6f8f0c7fd tests: skip test when not enough space
Make the test skipped instead of failing when there was not
enough space.
2018-03-15 11:01:04 +01:00
Zdenek Kabelac
bed869a8a0 tests: use DM_DEBUG_WITH_LINE_NUMBERS
Use src:line also for debugging of tools like dmsetup.
2018-03-15 11:01:04 +01:00
Zdenek Kabelac
750fc2e876 tests: fix running tests on systems without udevd
Variable was unbound on systems without running udevd.
2018-03-15 11:01:04 +01:00
Zdenek Kabelac
285413b502 cleanup: missing dots and indent 2018-03-15 11:01:04 +01:00
Zdenek Kabelac
d794444715 activation: check for prioritized_section
Detect we are in prioritezed section instead of critical one,
since these operation were supposed to NOT be happining during
whole set of operation.

This patch fixes verification of udev operations.
2018-03-15 11:01:04 +01:00
Zdenek Kabelac
6365f011b0 locking: introduce prioritized_section
Introduce prioritized_section() as a closer match to previous logic
of critical_section() that has been held over longer sequence of
ioctl commands - essentially it's matching operation on a single
cookie.

While 'critical_section()' now corresponds to locked memory - we hold
this memory only between suspend/resume thus notion of 'cookie' was
lost.

This patch restores some logic unintentionaly lost with dropping
memory locking for just activation/deactivation calls.
2018-03-15 10:59:42 +01:00
Zdenek Kabelac
043f58452a libdm-stats: fix error messages
When function dm_stats_populate() returns 0 it's an error and needs
log_error() message -  function can't have 'success' returning 0 or
error without reasons.
2018-03-15 10:56:31 +01:00
Zdenek Kabelac
a082ce2613 dmstatus: check nr_regions ahead of find call
Prevent call of dm_stats_populate(), when there has been no
stats region detected for a DM device.
Such skip is evaluated as 'correct' visit of stats call and
not causing 'dmstats' command failure.
2018-03-15 10:54:19 +01:00
Zdenek Kabelac
4c925692f5 dmsetup: loop output table as verbose
Resulting loop table line was streamed to 'stderr' stream - assuming this
was not a feature when user used '-v' for more verbose output
and properly show it via  'log_verbose()' on 'stdout'.
2018-03-15 10:50:30 +01:00
Zdenek Kabelac
70ad633638 devcache: add reason and always log_error
With these read errors it's useful to know the reason.
Also avoid to log error just once so we know exactly
how many times we did failing read.

On the other hand reduce repeated log_error() on code 'backtrace'
path and change severity of message to just log_debug() so the
actual read error is printed once for one read.
2018-03-15 10:50:28 +01:00
Zdenek Kabelac
2b3b486a37 libdm: support for DM_DEBUG_WITH_LINE_NUMBERS
For any libdm tool using default debugging function allow
to show source filename and code line number when this
functionality is available.
2018-03-15 10:49:24 +01:00
Marian Csontos
eae54b67d8 test: Skip tests which require too much RAM
- Tests for RAID reshape under load require too much RAM
2018-03-13 13:42:45 +01:00
Zdenek Kabelac
90512910e5 tests: try unfreezeing raids
With problematic kernels raid devices can be occasionaly left with
'frozen' status - try to 'unfreeze' them with idle message on teardown.

Also replace couple greps with 'built-in' dmsetup --select feature.

Note: dmsetup --select  currently reports 'No devices found' on stdout
and return success - looks like a bug to fix.
2018-03-13 12:58:57 +01:00
Zdenek Kabelac
b1ace8ce19 dmsetup: indent 2018-03-13 12:58:57 +01:00
Zdenek Kabelac
e9cadbe105 cleanup: matching signess 2018-03-13 12:58:57 +01:00
Zdenek Kabelac
49a8c786d5 dmsetup: report close as debug
Since close() failures are not causing command errors,
issue error via debug log stream only.
2018-03-13 12:58:57 +01:00
Zdenek Kabelac
06c1f71897 dmsetup: use dm_snprintf 2018-03-13 12:58:57 +01:00
Zdenek Kabelac
3f351466f7 dmsetup: update _display_info
Handle error code.
2018-03-13 12:58:57 +01:00
Zdenek Kabelac
7ac7cc0ac8 dmsetup: update messages 2018-03-13 12:58:57 +01:00
Zdenek Kabelac
9476cf8cdc dmsetup: join large fprintf
Concatenate strings and make binary slightly smaller.
2018-03-13 12:58:57 +01:00
Zdenek Kabelac
5f5db7cf41 dmsetup: stderr to log_error 2018-03-13 12:58:57 +01:00
Zdenek Kabelac
f203d4e206 dmsetup: cleanup err usage
Macro err() add '\n'.
2018-03-13 12:58:57 +01:00
Zdenek Kabelac
3b7834af17 dmsetup: use stderr for error output
When dmsetup command returns error, the message goes to stderr.
2018-03-13 12:58:57 +01:00
Zdenek Kabelac
29b2cfba06 mirror: correct locking for mirror log initialization
The code was not acking proper lock holding LVs when trying to
initialize mirror log to predefined values.
2018-03-13 12:58:27 +01:00
Zdenek Kabelac
1bd57b4c1d scanning: skip more private devices
Just like lvm2 has internal devices like _tdata which is using UUID with
suffix, there is similar private type of device for crypto device where
they are using CRYPT-TEMP uuid prefix.

Also ignore stratis.
2018-03-13 12:57:33 +01:00
Zdenek Kabelac
e095586d9e cleanup: use path on stack 2018-03-13 12:57:08 +01:00
Zdenek Kabelac
0edd89fadc raid: skip frozen raid devices
Some kernel version suffer from bad state transition where a device
steps into 'frozen' mode. Any application that tries to read such
raid gets unfortunatelly bloked.

As some sort of protection try to skip such raid device from being
scanned to minimize chances to block lvm2 command on such scan.

When such device is found, warning gets printed.
2018-03-13 12:57:01 +01:00
Zdenek Kabelac
a8a579b154 cleanup: all tests needs target_type
Simplify code.
2018-03-13 12:53:59 +01:00
Heinz Mauelshagen
0646fd465e dev_manager: always activate RAID SubLVs readwrite
RaidLVs on read_only_volume_list have their SubLVs
activated readonly thus disabling metadata updates
or image resynchronization/recovery.  Bug also causes
automatic repairs to fail.

Fix by always activating the RAID SubLVs readwrite.

Resolves: rhbz1208269
2018-03-12 22:29:54 +01:00
Heinz Mauelshagen
dd88a0f05c raid: support raid5_n convenience type on conversion to raid10
Fix requesting a conversion on raid5_{ls,rs,la,ra} -> raid10
not offering offering interim convenience type raid5_n.

Resolves: rhbz1468600
2018-03-09 21:23:16 +01:00
Zdenek Kabelac
6cb2c35d16 cleanup: use log_warn
There message are not causing command failure thus turn them
into warnings.
2018-03-08 10:40:27 +01:00
Zdenek Kabelac
ee37838b11 cache: fix lock usage for cache conversion
Just like with lvcreate, this lvconvert case also need to properly
check which LV actually holds lock for cached origin - as it might
be i.e. thin-pool tdata subLV.
2018-03-08 10:39:47 +01:00
Zdenek Kabelac
7421252edc snapshot: skip invalid snapshost
When scanning DM device, skip automatically invalid snapshot devices.
They behave just like 'error' device.
2018-03-08 10:39:44 +01:00
Zdenek Kabelac
a6fdb9d9d7 snapshot: keep COW writable for read-only volumes
When snapshot is created in read-only mode with 'lvcreate -s -pr...',
lvm2 still needs to be able to write to layered -cow volume
to store metadata and exceptions blocks.

TODO: in some case we might be able to do full tree with read-only
volume but this probably needs futher validation:
1. checking snapshot header already exist
2. origin & snapshot are both in read-only mode.
2018-03-08 10:39:03 +01:00
Zdenek Kabelac
15b6793528 tests: skipping test waiting for fixed kernel
Once working kernel is released, reenable me...
2018-03-06 15:42:49 +01:00
Zdenek Kabelac
b05caca77e tests: component activation 2018-03-06 15:42:49 +01:00
Zdenek Kabelac
eb3597acb3 activation: support proper /dev names for component LVs
When LV is activated AS componet LV - ensure there will
be /dev/vgname/lvname  link present for such LV.
2018-03-06 15:42:49 +01:00
Zdenek Kabelac
112846ce0b activation: support activation of component LVs
Occasionaly users may need to peek into 'component devices.
Normally lvm2 does not let users activation component.

This patch adds special mode where user can activate
component LV in a 'read-only' mode i.e.:

lvchange -ay vg/pool_tdata

All devices can be deactivated with:

lvchange -an vg  |  vgchange -an....
2018-03-06 15:42:46 +01:00
Zdenek Kabelac
6134a71a90 lvconvert: support for convertsion with active component devices
If componet devices could be activated alone, ensure they are not breaking
common commands.

TODO: mostly likely this is not a definite list of all needed checks
and more will come later.
2018-03-06 15:42:07 +01:00
Zdenek Kabelac
f92b6f9930 lvremove: ensure no subLV is active
Since component activation is going to be enabled, enusure,
no subLV is active when we deactivate LV.
2018-03-06 15:42:07 +01:00
Zdenek Kabelac
73e93ef5e5 lvremove: validate removed component LV is not active
This is the 'last' place where a LV is present in metadata.
Any removed device should not be left active in dm table.
So this check is an extra validation protection to capture any
forgotten deactivation (adding 1 extra ioctl into lvremove path)
2018-03-06 15:42:07 +01:00
Zdenek Kabelac
ca9cbd92c4 activation: add base lv component function
Introduce:

lv_is_component() check is LV is actually a component device.

lv_component_is_active() checking if any component device is active.

lv_holder_is_active() is any component holding device is active.
2018-03-06 15:42:05 +01:00
Zdenek Kabelac
6481471c9d debug: update comment 2018-03-06 15:40:34 +01:00
Zdenek Kabelac
b6e7a0b490 cleanup: more usage of dm_strncpy
Use existing wrapper function arournd  strncpy + buf[] = 0;
2018-03-06 15:40:34 +01:00
Zdenek Kabelac
f04abd1f8a lvremove: drop duplicate check for active LV
Since this code branch already tested LV is active,
avoid repeating same query.
2018-03-06 15:40:31 +01:00
Zdenek Kabelac
23de09aeb8 lvcreate: fix activation of cached LV
Since LV for caching can be already a stacked LV, proper activation
needs to use lock holding LV.
2018-03-06 15:39:27 +01:00
Zdenek Kabelac
b2f1254c14 raid: move VG update after archiving happened
Update of LV le_count needs to happen after archive().
2018-03-06 15:38:15 +01:00
Zdenek Kabelac
ce199db848 raid: fix error path for lv_raid_data_offset
Avoid using allocated status on error path.
2018-03-06 15:36:11 +01:00
Zdenek Kabelac
9be086fbee thin: pass environment to scripts
When dmeventd thin plugin forks a configurable script, switch to use
execvp to pass whole environment present to dmeventd - so all configured
paths present at dmeventd startup are visible to script.

This was likely not a problem for common user enviroment,
however in test suite case variable like LVM_SYSTEM_DIR were
not actually used from test itself but rather from
a system present lvm.conf and this may have cause strange
behavior of a testing script.
2018-03-06 15:35:04 +01:00
Zdenek Kabelac
406d6de651 cleanup: indent 2018-02-28 21:15:55 +01:00
Zdenek Kabelac
16c209c613 cleanup: use lv_is_used_cache_pool
Use lv_is_used_cache_pool() to simplify the code.
Function was introduced later and this code missed to use it.
2018-02-28 21:15:55 +01:00
Zdenek Kabelac
e643de6e61 cleanup: explicitely ignore result code
ATM too long prefix is silently ignored.
2018-02-28 21:15:55 +01:00
Zdenek Kabelac
805bf6ec74 cleanup: unused header file 2018-02-28 21:15:55 +01:00
Zdenek Kabelac
6ba94fdd81 debug: change message severity
Although it's internal issue - in this case command continue without
any reported error - thus hide this internal error into debug.
2018-02-28 21:15:55 +01:00
Zdenek Kabelac
cc4855acbe tests: check inactive extorig resize 2018-02-28 21:15:55 +01:00
Zdenek Kabelac
052f28746d lvresize: check external origin with new size
Instead of checking with existing size of external origin LV,
use correctly the new 'wanted' size of this LV whether it fits
the limitiation requirements for older thin-pool target.

Otherwise code started to the the resize, updates metadata and
just fails during 'resize' in case the LV was active. For
inactive LV operation could have actually passed.
2018-02-28 21:15:55 +01:00
Zdenek Kabelac
b09ea3b6f7 lvremove: drop unneded check
Checking here for cache_pool is not necessary and in effect
the check is not even right - since there are internal
states that do allow to active such LV.
2018-02-28 21:08:40 +01:00
Zdenek Kabelac
749372caf3 command: use bigger buffer
Instead of use 'silently' shortened passed string - always
make sure we take either a full copy or return error.
2018-02-28 21:08:40 +01:00
Zdenek Kabelac
bc1adc32cb lv_manip: enhance for_each_sub_lv
Fix missing 'externalLV' traversing for thins with external origins.

Replace extra for_each_sub_lv_except_pools() with better
internal logic allowing selectively to cut of processed subLV tree.

Extend error code for function 'fn()' when it returns -1 it will
stop futher tree scan for given LV.

Also a bit simplify code to have only one place that
is calling 'fn()' and use level counter to know
depth of traversing.

Update renaming travering to skip trees for pools
and external origins.
2018-02-28 21:08:38 +01:00
Zdenek Kabelac
6b48868cf0 io: keep 64b arithmetic
Widen to 64b arithmetic from start.
2018-02-28 21:05:18 +01:00
Zdenek Kabelac
261e6c3df6 raid: add free for error path
Recent patch forget to release now allocated 'dso' on error path.
2018-02-28 21:05:18 +01:00
Zdenek Kabelac
9bfc8881cb coverity: missing free on error path 2018-02-28 21:05:18 +01:00
Marian Csontos
32bcdd90ae tests: check vgsplit thin-data and ext.origin 2018-02-27 14:37:47 +01:00
Zdenek Kabelac
8e5305f630 tests: correct usage of pipe
This is somewhat tricky - for test suite we keep using
'set -e -o pipefail'  - the effect here is - we get error report
from any 'failing' command in whole pipeline - thus when something
like this:   'lvs | head -1'  is used - and  'head' finishes before
lead 'lvs' is done - it recieves SIGPIPE and exits with error,
and somewhat misleading gets occasionally reported depending
of speed of commands.

For this case we have to avoid using standard pipes and rather
switch to using streamed results with temporary output file.
This is all nicely handled with bash feature '< <()'.

For more info:
https://stackoverflow.com/questions/41516177/bash-zcat-head-causes-pipefail
2018-02-19 16:45:10 +01:00
Zdenek Kabelac
e7f1329cae debug: capture internal error for too long resource name
Should never happen, so just put in internal error instead of silently
passing some shortened resource name.
2018-02-19 16:45:10 +01:00
Zdenek Kabelac
c3bb2b29d4 locking: move cache dropping to primary locking code
While 'file-locking' code always dropped cached VG before
lock was taken - other locking types actually missed this.

So while the cache dropping has been implement for i.e. clvmd,
actually running command in cluster keept using cache even
when the lock has been i.e. dropped and taken again.

This rather 'hard-to-hit' error was noticable in some
tests running in cluster where content of PV has been
changed (metadata-balance.sh)

Fix the code by moving cache dropping directly lock_vol() function.

TODO: it's kind of strange we should ever need drop_cached_metadata()
used in several places - this all should happen automatically
this some futher thinking here is likely needed.
2018-02-19 16:45:05 +01:00
Zdenek Kabelac
e87fa7c9ce sanlock: set proper return value
In last patch one error path missed to assign correct return value.
Assing it directly to 'ret' as log_error was already reported.
2018-02-19 16:44:10 +01:00
Marian Csontos
1671b83585 doc: Fixing VDO document 2018-02-16 17:10:54 +01:00
Zdenek Kabelac
f5401fbd34 tests: update 2018-02-15 13:56:35 +01:00
Zdenek Kabelac
552e60b3a1 pvmove: enhance accepted states of active LVs
Improve pvmove to accept 'locally' active LVs together with
exclusive active LVs.

In the 1st. phase it now recognizes whether exclusive pvmove is needed.
For this case only 'exclusively' or 'locally-only without remote
activative state' LVs are acceptable and all others are skipped.

During build-up of pvmove 'activation' steps are taken, so if
there is any problem we can now 'skip' LVs from pvmove operation
rather then giving-up whole pvmove operation.

Also when pvmove is restarted, recognize need of exclusive pvmove,
and use it whenever there is LV, that require exclusive activation.
2018-02-15 13:55:38 +01:00
Zdenek Kabelac
a2d2fe3a8c locking: exclusive can be either remote or local
When LOCK is exclusive and LV is already locally active,
it cannot be active remotely.
2018-02-15 13:54:55 +01:00
Zdenek Kabelac
a1195aaa66 cleanup: add missing WARNING
ATM log_warn() is supposed to be used with WARNING: prefix.
2018-02-15 13:52:02 +01:00
Marian Csontos
d67f160200 mirror: Add deprecation warning for mirrored log 2018-02-14 13:32:04 +01:00
Marian Csontos
dd6fbcbb69 test: mirrored mirrorlog is not supposed to work in cluster 2018-02-14 13:10:52 +01:00
Zdenek Kabelac
c3642957c5 gcc: remove warns about free of const 2018-02-13 19:56:02 +01:00
Zdenek Kabelac
0eb9daf602 segtype: no libmem pool usage for name allocation
Allocate name with plain malloc & free.
2018-02-13 19:11:28 +01:00
Zdenek Kabelac
32febed8d5 segtype: replace mempool allocation
So this is a bit more complex and possibly worth futher checking.

ATM  clvmd drops  cmd->mem  mempool AFTER refresh of cmd.
So anything allocating from cmd->mem during toolcontext init
will likely die at some point in time.

As a quick fix - just use regular malloc/free for 'dso' alloction.

It's worth to note -  cmd->libmem seems to be often misused
causing hidden memleaking for clvmd.
2018-02-13 19:11:28 +01:00
Zdenek Kabelac
e40768ac32 debug: add stack tracking 2018-02-12 22:15:03 +01:00
Zdenek Kabelac
27399755fd segtype: better get_monitor_dso_path api
Instead of allocating always 4K for dso path, use only real needed size.
Also simplify API call and move common functionality into function
itself.
2018-02-12 22:15:03 +01:00
Zdenek Kabelac
e113df129e cleanup: decode dso path just once
Build dso plugin name during  segtype initialisation and just
use the string during command life-time.

Also slightlt update message verbosity and make it very_verbose
when operation is going to be made and 'verbose' when it's done.
2018-02-12 22:15:03 +01:00
Zdenek Kabelac
6dff5dc653 activation: cleanup error to warning
Since for the code it's not fatal to fail on monitoring,
issue correct warning message instead of error.
2018-02-12 22:15:03 +01:00
Zdenek Kabelac
d90a647802 activation: separate reporting of error and monitoring status
Avoid using same return code for reporting 2 different things
and stricly report error code by return value and add new
parameter for reporting monitoring status.

This makes easier to recognize which error we got from dm_event
and continue only with  ENOENT.
2018-02-12 22:14:59 +01:00
Zdenek Kabelac
12fba201be cleanup: detect dmeventd_executable just once
Avoid repeating debug messages about dmeventd executable
and just remember it once for whole cmd lifetime.
2018-02-12 22:14:25 +01:00
Zdenek Kabelac
4f278324c7 lvmlockd: improve dm path creation for sanlock LV
Use devmapper function to create matching dm name with mangling.
Drop extra '-1' from buffer passed to snprintf.
2018-02-12 22:14:25 +01:00
Zdenek Kabelac
7239a45b79 clean: drop unneeded -1 for snprintf
man gives:
snprintf() and vsnprintf() write at most size bytes
(including the terminating null byte ('\0')) to str.
2018-02-12 22:14:25 +01:00
Zdenek Kabelac
d94036f8ed vgimportclone: add some dm_snprintf checks
Check if the generated vg name still fits the buffer.
So too long strings are rejected.
Drop -1  from size passed to snprintf - as the \0 is already included.
2018-02-12 22:14:22 +01:00
Zdenek Kabelac
60b61f2db3 libdm-stats: correct checking of dm_snprintf error
Function dm_snprintf returns -1 on error, while 0 is still
considered valid result code so correcting error path testing.
2018-02-12 22:13:57 +01:00
Zdenek Kabelac
afdbb28f72 toolcontext: light context missed to set-up mem mempool
If cmd->mem was null, then systemd generator was failing on:

(gdb) bt
dm_pool_alloc_aligned (p=0x0, s=96, alignment=8) at mm/pool-fast.c:95
dm_pool_alloc (p=0x0, s=96) at mm/pool-fast.c:90
dm_pool_zalloc (p=0x0, s=96) at mm/pool.c:74
config_file_read_fd (mem=0x0, cft=0x55f4339dbad0, dev=0x55f4339dfac0, reason=DEV_IO_MDA_CONTENT, offset=0, size=82293, offset2=0, size2=0,
    checksum_fn=0x0, checksum=0, checksum_only=0, no_dup_node_check=0, ioflags=0, config_file_read_fd_callback=0x0, config_file_read_fd_context=0x0) at config/config.c:567
config_file_read (mem=0x0, cft=0x55f4339dbad0) at config/config.c:658
config_file_open_and_read (config_file=0x7f49aef14540 <config_file> "/var/tmp/lvm/etc/lvm/lvm.conf", source=CONFIG_FILE, cmd=0x55f4339d6260)
    at config/config.c:282
_load_config_file (cmd=0x55f4339d6260, tag=0x7f49aeca15da "", local=0) at commands/toolcontext.c:824
_init_lvm_conf (cmd=0x55f4339d6260) at commands/toolcontext.c:853
create_config_context () at commands/toolcontext.c:1814
lvm_config_find_bool (libh=0x0, config_path=0x55f431a884ad "global/use_lvmetad", fail=0) at lvm_base.c:144
main ()
2018-02-12 22:13:53 +01:00
Zdenek Kabelac
34a9e3d3cd python: add devmapper library to linking
On occasional gcc releases it's better to specify also -ldevmapper
to linking logic for python object.

It's in fact more correct since the liblvm.c code is using
libdevmapper functions - that were linked in only via
liblvm2app library.
2018-02-09 11:00:18 +01:00
Zdenek Kabelac
7cfe5ab9bc partial revert "command: Skip some memory zeroing."
This partially reverts commit da37cbd24f.
As the _cmdline structure use mempool for allocated ellement
that is being release on cmd_context close.

Before the better fix is made - restore previous logic and
reinitialize cmd structures again for new cmd_context.

Problem can be hit with e.g. this test run:

make check_local T=foreign LVM_VALGRIND_DMEVENTD=1

Invalid read of size 1
   at 0x4C31C83: strcmp (vg_replace_strmem.c:846)
   by 0x6BA0939: _find_command (lvmcmdline.c:1555)
   by 0x6BA4304: lvm_run_command (lvmcmdline.c:2810)
   by 0x6BD5E02: lvm2_run (lvmcmdlib.c:91)
   by 0x685607E: dmeventd_lvm2_run (dmeventd_lvm.c:118)
   by 0x6652684: _use_policy (dmeventd_thin.c:117)
   by 0x6652E56: process_event (dmeventd_thin.c:298)
   by 0x10CC5A: _do_process_event (dmeventd.c:945)
   by 0x10CF83: _monitor_thread (dmeventd.c:1033)
   by 0x54B35E0: start_thread (in /usr/lib64/libpthread-2.26.9000.so)
   by 0x57C30EE: clone (in /usr/lib64/libc-2.26.9000.so)
 Address 0x6266270 is 4,352 bytes inside a block of size 8,192 free'd
   at 0x4C2ED68: free (vg_replace_malloc.c:530)
   by 0x5289142: dm_free_wrapper (dbg_malloc.c:393)
   by 0x528998A: _free_chunk (pool-fast.c:318)
   by 0x52892A6: dm_pool_destroy (pool-fast.c:78)
   by 0x6A8E52C: destroy_toolcontext (toolcontext.c:2254)
   by 0x6BA5BD6: lvm_fin (lvmcmdline.c:3327)
   by 0x6BD5EA7: lvm2_exit (lvmcmdlib.c:123)
   by 0x6856013: dmeventd_lvm2_exit (dmeventd_lvm.c:103)
   by 0x66535B8: unregister_device (dmeventd_thin.c:432)
   by 0x10CBBC: _do_unregister_device (dmeventd.c:926)
   by 0x10CD74: _monitor_unregister (dmeventd.c:979)
   by 0x10D094: _monitor_thread (dmeventd.c:1066)
   by 0x54B35E0: start_thread (in /usr/lib64/libpthread-2.26.9000.so)
   by 0x57C30EE: clone (in /usr/lib64/libc-2.26.9000.so)
 Block was alloc'd at
   at 0x4C2DBBB: malloc (vg_replace_malloc.c:299)
   by 0x5288F46: dm_malloc_aux (dbg_malloc.c:287)
   by 0x52890AC: dm_malloc_wrapper (dbg_malloc.c:371)
   by 0x52898E6: _new_chunk (pool-fast.c:286)
   by 0x52893BA: dm_pool_alloc_aligned (pool-fast.c:106)
   by 0x5289310: dm_pool_alloc (pool-fast.c:90)
   by 0x6A8A21A: _load_config_file (toolcontext.c:808)
   by 0x6A8A3D9: _init_lvm_conf (toolcontext.c:842)
   by 0x6A8D3BD: create_toolcontext (toolcontext.c:1941)
   by 0x6BA5B24: init_lvm (lvmcmdline.c:3308)
   by 0x6BD5B7C: cmdlib_lvm2_init (lvmcmdlib.c:34)
   by 0x6BD5EB8: lvm2_init (lvm2cmd.c:20)
   by 0x6855EA7: dmeventd_lvm2_init (dmeventd_lvm.c:67)
   by 0x665305F: register_device (dmeventd_thin.c:352)
   by 0x10CB7A: _do_register_device (dmeventd.c:916)
   by 0x10CEE4: _monitor_thread (dmeventd.c:1006)
   by 0x54B35E0: start_thread (in /usr/lib64/libpthread-2.26.9000.so)
   by 0x57C30EE: clone (in /usr/lib64/libc-2.26.9000.so)
2018-02-09 10:59:07 +01:00
Zdenek Kabelac
83258e3385 toolcontext: do not change stream for pthreaded programs
With pthreaded daemons like 'dmeventd' using  liblvm via plugin,
lvm2 actually should not 'play' with streams at all - as there
could be parallel outputs running.

As a current quick workaround just disable change for pthreaded
program (gettid() != getpid()).

TODO: it's possible the change of buffering actually doesn't serve us
any measurable benefit and could be dropped as whole later...

Meanwhile this patch is fixing this occasional valgrind race report:

Invalid read of size 4
   at 0x571892C: vfprintf (in /usr/lib64/libc-2.26.9000.so)
   by 0x57216B3: fprintf (in /usr/lib64/libc-2.26.9000.so)
   by 0x5042886: dm_event_log (libdevmapper-event.c:925)
   by 0x10B015: _dmeventd_log (dmeventd.c:125)
   by 0x10D289: _unregister_for_event (dmeventd.c:1146)
   by 0x10E52E: _handle_request (dmeventd.c:1583)
   by 0x10E6D7: _do_process_request (dmeventd.c:1631)
   by 0x10E7C6: _process_request (dmeventd.c:1660)
   by 0x1101A4: main (dmeventd.c:2285)
 Address 0x6264d30 is 192 bytes inside a block of size 552 free'd
   at 0x4C2ED68: free (vg_replace_malloc.c:530)
   by 0x573907D: fclose@@GLIBC_2.2.5 (in /usr/lib64/libc-2.26.9000.so)
   by 0x6AC5C00: reopen_standard_stream (log.c:189)
   by 0x6A8E62C: destroy_toolcontext (toolcontext.c:2271)
   by 0x6BA5C22: lvm_fin (lvmcmdline.c:3339)
   by 0x6BD5EF3: lvm2_exit (lvmcmdlib.c:123)
   by 0x6856013: dmeventd_lvm2_exit (dmeventd_lvm.c:103)
   by 0x66535B8: unregister_device (dmeventd_thin.c:432)
   by 0x10CBBC: _do_unregister_device (dmeventd.c:926)
   by 0x10CD74: _monitor_unregister (dmeventd.c:979)
   by 0x10D094: _monitor_thread (dmeventd.c:1066)
   by 0x54B35E0: start_thread (in /usr/lib64/libpthread-2.26.9000.so)
   by 0x57C30EE: clone (in /usr/lib64/libc-2.26.9000.so)
 Block was alloc'd at
   at 0x4C2DBBB: malloc (vg_replace_malloc.c:299)
   by 0x573932B: fdopen@@GLIBC_2.2.5 (in /usr/lib64/libc-2.26.9000.so)
   by 0x6AC5DC2: reopen_standard_stream (log.c:200)
   by 0x6A8D11D: create_toolcontext (toolcontext.c:1898)
   by 0x6BA5B6B: init_lvm (lvmcmdline.c:3319)
   by 0x6BD5BC8: cmdlib_lvm2_init (lvmcmdlib.c:34)
   by 0x6BD5F04: lvm2_init (lvm2cmd.c:20)
   by 0x6855EA7: dmeventd_lvm2_init (dmeventd_lvm.c:67)
   by 0x665305F: register_device (dmeventd_thin.c:352)
   by 0x10CB7A: _do_register_device (dmeventd.c:916)
   by 0x10CEE4: _monitor_thread (dmeventd.c:1006)
   by 0x54B35E0: start_thread (in /usr/lib64/libpthread-2.26.9000.so)
   by 0x57C30EE: clone (in /usr/lib64/libc-2.26.9000.so)
....
Process terminating with default action of signal 6 (SIGABRT): dumping core
   at 0x570016B: raise (in /usr/lib64/libc-2.26.9000.so)
   by 0x5701520: abort (in /usr/lib64/libc-2.26.9000.so)
   by 0x57437D8: __libc_message (in /usr/lib64/libc-2.26.9000.so)
   by 0x5743831: __libc_fatal (in /usr/lib64/libc-2.26.9000.so)
   by 0x5744056: _IO_vtable_check (in /usr/lib64/libc-2.26.9000.so)
   by 0x574751C: __overflow (in /usr/lib64/libc-2.26.9000.so)
   by 0x574191A: fputc (in /usr/lib64/libc-2.26.9000.so)
   by 0x50428E3: dm_event_log (libdevmapper-event.c:934)
   by 0x10B015: _dmeventd_log (dmeventd.c:125)
   by 0x10D289: _unregister_for_event (dmeventd.c:1146)
   by 0x10E52E: _handle_request (dmeventd.c:1583)
   by 0x10E6D7: _do_process_request (dmeventd.c:1631)
   by 0x10E7C6: _process_request (dmeventd.c:1660)
   by 0x1101A4: main (dmeventd.c:2285)
2018-02-09 10:56:40 +01:00
Alasdair G Kergon
1b6d0346a3 format_text: Use versionsort to sort archive files
Ensure that vg_100000-* follows vg_99999-* so that the expiry logic
doesn't stop too early.

   https://bugzilla.redhat.com/1481085
2018-02-09 01:08:55 +00:00
Alasdair G Kergon
d6cabbbc53 device: Fix basic async I/O error handling 2018-02-08 20:19:21 +00:00
Alasdair G Kergon
3e29c80122 device: Queue any aio beyond defined limits. 2018-02-08 20:15:37 +00:00
Alasdair G Kergon
db41fe6c5d lvmcache: Use asynchronous I/O when scanning devices. 2018-02-08 20:15:29 +00:00
Alasdair G Kergon
8c7bbcfb0f device: Basic config and setup to support async I/O. 2018-02-08 20:15:14 +00:00
Alasdair G Kergon
7a9af3cd0e device: Add flag to indicate that a code path can support AIO
Until the whole source supports AIO, library code can check for
AIO_SUPPORTED_CODE_PATH to determine whether or not it is OK
to use AIO.
2018-02-06 01:11:00 +00:00
Alasdair G Kergon
e869a52cc4 callbacks: Miscellaneous fixes for recent changes 2018-02-06 01:09:39 +00:00
Zdenek Kabelac
e727da6cf1 configure: ensure path /usr/sbin is checked for some tools
Some tools are typically installed into /usr/sbin (or /sbin) dir.
And some systems do not add this path to user's $PATH var.

Ensure sbin paths are looked through...
2018-02-01 21:57:05 +01:00
Zdenek Kabelac
4d4d5bf323 libdm: accept mirror status with userspace word in the line
Just making sure the parser will not stop - although greater level of
support needs to be added (Describing doc seems to be missing however).
2018-02-01 21:56:07 +01:00
Zdenek Kabelac
083c221cbe pvmove: reinstantiate clustered pvmove
In fact  pvmove does support  'clustered-core' target for clustered
pvmove of LVs activated on multiple nodes.

This patch restores support for activation of pvmove on all nodes
for LVs that are also activate on all nodes.
2018-02-01 21:55:20 +01:00
Tim Foerster
34fb5202bd lvmdbusd: Remove duplicated DataPercent definition 2018-01-25 08:37:24 -06:00
Marian Csontos
edb209776f doc: Add VDO stacking document 2018-01-25 11:15:23 +01:00
Zdenek Kabelac
a1cfef9f26 dev_io: fix writes for unaligned buffers
Actually the removed code is necessary - since not all writes are
getting alligned buffer - older compilers seems to be not able
to create 4K aligned buffers on stack - this the aligning code still
need to be present for write path.
2018-01-23 13:36:12 +01:00
Zdenek Kabelac
102926ed9f tests: update set of devices
Previous change added slighly more complex mapping so missed to update
few pieces.
2018-01-23 11:45:18 +01:00
Zdenek Kabelac
6e9148e7ab debug: drop DEBUG_MEM path
Memory is not allocated so no DEBUG_MEM part is needed.
2018-01-23 11:45:18 +01:00
Zdenek Kabelac
2ee105089a python: some LVs do need exclusive activation 2018-01-23 11:45:18 +01:00
Alasdair G Kergon
9194610f42 device: Add ioflags parameter to transfer additional state.
Flags are set on the initial I/O and passed to any callbacks that
may in turn issue further I/O using the inherited flags.
2018-01-21 21:10:23 +00:00
Zdenek Kabelac
f3c75bb201 activation: move check later
Check for lv when it's known in all cases.
2018-01-17 15:15:43 +01:00
Zdenek Kabelac
e16d309d56 tests: check pvmove is merging segments
pvmove was imporoved to properly merge consqutive segments after pvmove
so check it's working.
2018-01-17 14:45:48 +01:00
Zdenek Kabelac
5baf2de898 tests: longer startup timeout for daemons with valgrind
It's getting noticable somewhat slower...
2018-01-17 14:45:48 +01:00
Zdenek Kabelac
8ebd45fde7 tests: check preserved exclusivness of snapshot merge
Detect if origin remains exclusively activated after merging.
2018-01-17 14:45:48 +01:00
Zdenek Kabelac
8c7ec44bf0 tests: properly test with clustered VG
Testing in cluster makes sense only with clustered VG.
2018-01-17 14:45:48 +01:00
Zdenek Kabelac
3aedaa7f2a cleanup: drop unused code 2018-01-17 14:45:48 +01:00
Zdenek Kabelac
38b81e6537 cleanup: enhance messages
Add extra info about failing local exlusive activation
(as in cluster the LV can be active on some other nodes).
2018-01-17 14:45:48 +01:00
Zdenek Kabelac
a8bcdef4fd activation: guard exclusive activation
Add protectional internall error whenever we spot activation
of 'exclusive' only segments in 'non-exclusive' mode.

TODO: possibly the activation locking could be enhanced to handle
this fully behind the scene - as for now this works purely for
lvchange/vgchange activation.
2018-01-17 14:45:47 +01:00
Zdenek Kabelac
f41935909f dmeventd: add check for result code
Check result from pthread_kill.
2018-01-17 14:44:33 +01:00
Zdenek Kabelac
02621cffb0 pvmove: drop misleading pvmove restriction for cluster
pvmove handles properly locked LVs in cluster and this extra check
actually cause misbehavior as some LVs were silently skipped from
operation scope.
2018-01-17 14:44:33 +01:00
Zdenek Kabelac
5a961d3411 pvmove: better check for exclusive LV 2018-01-17 14:44:33 +01:00
Zdenek Kabelac
7c6fb63041 pvmove: fix _remove_sibling_pvs_from_trim_list
Fix the function to really check it sibling raid image LV.
For LV_rmeta_0  check for   LV_rimage_0   instead of
LV_rmeta_0rimage_0.
2018-01-17 14:44:31 +01:00
Zdenek Kabelac
e86910b052 lvconvert: use excl activation for conversion
Use properly exclusive activation when reactivating origin after
snapshot merge (since origin must have been previously also exlusively
activated).

Same applies when converting volumes to thin-pool or cache.

Previously used 'only' local activation incorrectly allowed local
activation of some targets (i.e. raid) - thus 'leaking' chance to
activate same device on another node - which can be a problem
for device types like raid.
2018-01-17 14:43:34 +01:00
Alasdair G Kergon
c26458339e device: Move buffer allocation nearer to the I/O.
Don't allocate memory until it's needed - later we'll add
some of the I/O to an internal queue instead of issuing it
immediately.
2018-01-16 01:12:08 +00:00
Alasdair G Kergon
081902b4c1 device: Merge _dev_read and dev_read_callback. 2018-01-16 00:41:42 +00:00
Alasdair G Kergon
0a3c6bf8c6 format_text: Refactor mda counting in label processing. 2018-01-15 23:47:44 +00:00
Alasdair G Kergon
73b5ee64e7 format_text: Change update_mda_baton to use label not labeller 2018-01-15 20:13:53 +00:00
Alasdair G Kergon
b825987b2f device: Rearrange _aligned_io(). 2018-01-15 20:10:54 +00:00
Alasdair G Kergon
c90582344d device: Add reason to devbuf. 2018-01-15 19:38:18 +00:00
Alasdair G Kergon
1f01eaa612 device: Store offset to data instead of pointer.
We want to save the relative offset before we've allocated the
buffer's memory.
2018-01-15 19:32:59 +00:00
Alasdair G Kergon
61d3296f2a device: Reorder device.h before change. 2018-01-15 19:24:01 +00:00
Alasdair G Kergon
da37cbd24f command: Skip some memory zeroing.
commands[] is in bss, its content wouldn't change if reinitialised
and unregister has no memory to free so don't bother.
2018-01-13 03:44:15 +00:00
Alasdair G Kergon
e4e2abc8bc libdm: Fix a size_t in _dm_malloc_aligned_aux message. 2018-01-12 00:42:53 +00:00
Alasdair G Kergon
5bbe68cf15 man: regenerate 2018-01-12 00:30:52 +00:00
Alasdair G Kergon
35cdd9cf48 label: Clean up storing of device and label sector.
No longer use the external 'result' pointer internally to set up the
cached label.  The callback _set_label_read_result() is now given the
internal label pointer directly

Callers that don't need the result are no longer required to pass a
label pointer into label_read().
2018-01-11 02:54:00 +00:00
Alasdair G Kergon
f771d3f870 config: Move use_mmap to local variable. 2018-01-10 20:35:02 +00:00
Alasdair G Kergon
6210c1ec28 device: Mark read-only device buffers const. 2018-01-10 19:57:10 +00:00
Alasdair G Kergon
c350f96c09 device: Eliminate unnecessary buffer from dev_read. 2018-01-10 18:48:01 +00:00
Alasdair G Kergon
366493a1d1 device: Suppress repeated reads of the same data.
If the data being requested is present in last_[extra_]devbuf,
return that directly instead of reading it from disk again.

Typical LVM2 access patterns request data within two adjacent 4k blocks
so we eliminate some read() system calls by always reading at least 8k.
2018-01-10 15:52:03 +00:00
Alasdair G Kergon
dcb2a5a611 device: Remove some data copying between buffers.
Callers that read larger amounts of data now get a pointer to read-only
data directly without copying it through an intermediate buffer.  This
data is owned by the device layer so the callers no longer free it.
2018-01-10 15:48:03 +00:00
Alasdair G Kergon
4d568b709c device: Free cached device bufs when metadata invalid or dev closed. 2018-01-10 15:48:03 +00:00
Alasdair G Kergon
bd0967a4b1 device: Keep the last data buffer read off each device.
If there's a second metadata area on device, we record that separately.

Note that the memory requirements aren't restricted yet.
2018-01-10 15:48:03 +00:00
Alasdair G Kergon
bacc942333 allocation: Avoid exceeding array bounds in allocation tag code
If _limit_to_one_area_per_tag() changes nothing it writes beyond
the array.
2018-01-10 15:48:03 +00:00
Alasdair G Kergon
e2438b5b9f format_text: Use malloc aligned for export buffer 2018-01-10 15:48:03 +00:00
Alasdair G Kergon
b65246499b label: Rename a variable 2018-01-10 15:48:03 +00:00
Alasdair G Kergon
ea96381534 libdm: Introduce dm_malloc_aligned 2018-01-10 15:48:03 +00:00
David Teigland
943b217797 man lvmlockd: remove lv resizing comment 2018-01-10 09:17:57 -06:00
David Teigland
51340888aa lvmlockd: print warning when skipping locking 2018-01-09 11:46:00 -06:00
David Teigland
46cedb105b lvmlockd: add lockopt values for skipping selected locks
and add lockopt to common options.
2018-01-09 11:20:10 -06:00
Alasdair G Kergon
f4675af4cf format_text: Use vgsummary callbacks 2018-01-09 03:14:30 +00:00
Alasdair G Kergon
4b02d4e22e label: Add label_read callback. 2018-01-08 23:30:50 +00:00
Alasdair G Kergon
6d322e68f3 label: Add callback fns (partially) 2018-01-08 17:04:56 +00:00
Alasdair G Kergon
5e7d3ad749 device: Introduce dev_read_callback
If it obtains the data, it passes it into the supplied callback function
and returns 1.  Otherwise the callback receives failed = 1.

Updated config_file_read_fd to use this and similarly return the data
via a callback fn of its own.
2018-01-06 02:40:12 +00:00
Alasdair G Kergon
946f07af3e metadata: Use a consistent format for callback fn parameters 2018-01-05 14:24:56 +00:00
Alasdair G Kergon
a0ddfad94b metadata: Change the new data processing fns to void.
Move the existing fn return codes into the new structs.
2018-01-05 03:12:22 +00:00
Alasdair G Kergon
c70c9f6565 format_text: Split vgname_from_mda into three pieces. 2018-01-04 21:13:44 +00:00
Alasdair G Kergon
d61b1369d0 format_text: Split out raw_read_mda_header processing 2018-01-04 15:52:59 +00:00
Alasdair G Kergon
139209ef42 format_text: Split up _update_mda.
Dedicated functions are now used to process each piece of data obtained,
so the refactoring in this file gives us one for the vgsummary and one
for the metadata header.  This new type of function takes two parameters
(for now), the obtained data plus a single struct (that must not
reference any data on the stack) that wraps up the entire context needed
to process it.
2018-01-04 12:25:24 +00:00
Alasdair G Kergon
111a9fcff5 format_text: Allocate update_mda baton from mempool.
Also store return code.  Note that fatal and non-fatal errors while
handling the mda aren't currently distinguished.
2018-01-03 23:53:00 +00:00
Alasdair G Kergon
5a846e0929 format_text: Split the text import fns into two pieces. 2018-01-03 20:48:02 +00:00
Alasdair G Kergon
4b9806ab6f toolcontext: Add paired label_init to refresh_toolcontext.
label_init() and label_exit() should be paired.
2018-01-02 22:00:31 +00:00
Alasdair G Kergon
22b6c482ec config: Split config buffer processing into new fn.
Wrap its parameters into struct process_config_file_params allocated
from a mempool now passed into the config_file_read* fns.
2018-01-02 21:10:46 +00:00
David Teigland
96801ac085 man lvmlockd: update wording 2018-01-02 13:35:58 -06:00
Alasdair G Kergon
3db51e3f0e label: Wrap _find_labeller params into a struct.
Move the actual buffer reading up to _label_read() so _find_labeller()
just examines the buffer supplied.
2018-01-02 17:15:32 +00:00
Alasdair G Kergon
9b830791ea label: Move _set_label_read_result call into _find_labeller.
Move responsibility for setting the label_read() result parameter down
into _find_labeller().
2018-01-02 15:30:58 +00:00
Alasdair G Kergon
4f4ddb806d label: Move setting result of label_read into separate fn. 2018-01-02 14:19:20 +00:00
Alasdair G Kergon
e6b4b41881 label: Add mempool. 2018-01-02 13:37:12 +00:00
Zdenek Kabelac
0bf1cc2320 tests: sleep first
Sleep a bit before checking /sys/block dir so the kernel has a moment to
actually put scsi debug device in it...

Some quite old kernels are in troubles with this plain searching grep
without sleep (namely 2.6.32)

modprobe scsi_debug
 <sleep .1>
grep -H scsi_debug /sys/block/*/device/model
modprobe -r scsi_debug
2017-12-19 15:28:07 +01:00
Zdenek Kabelac
3a841515af lvm-string: add function to detect component LV suffix
Add is_component_lvname() function to recognize component LV name.
2017-12-19 15:28:07 +01:00
Alasdair G Kergon
17649d4ac8 device: Move dev_read memory allocation into device layer.
Rename dev_read() to dev_read_buf() - the function that reads data
into a supplied buffer.

Introduce a new dev_read() that allocates the buffer it returns and
switch the important users over to this.  No caller may change the
returned data.  (For now, callers are responsible for freeing it after
use, but later the device layer will take full ownership.)

dev_read_buf() should only be used for tiny buffers or unimportant code
(such as the old disk formats).
2017-12-19 01:31:50 +00:00
David Teigland
3f9ae846b8 lvmlockd: clear coverity complaint
from previous coverity fix, it's never happy.
2017-12-18 15:19:17 -06:00
Alasdair G Kergon
81be333e9f post-release 2017-12-18 20:43:09 +00:00
Alasdair G Kergon
a1f7a48325 pre-release 2017-12-18 20:36:10 +00:00
Alasdair G Kergon
5f45cb90a7 format_text: Transfer circular buf alloc to device layer.
Instead of the caller passing dev_read_circular() a buffer to fill with
data, the device layer itself now allocates it.
2017-12-15 22:34:26 +00:00
Alasdair G Kergon
beee9940a5 format_text: Separate out code paths for buffer wraparound
The creation of wrapped around metadata - where the start of metadata is
written up to the end of the buffer and the remainder follows back at
the start of the buffer - is now restricted to cases where writing the
metadata in one piece wouldn't fit.  This shouldn't happen in 'normal'
usage so let's begin treating the code for this as a special case that
can be ignored when optimising 'normal' cases.
2017-12-15 21:12:19 +00:00
Alasdair G Kergon
145ded10c2 format_text: Supply mempool directly to raw_read_mda_header. 2017-12-15 14:57:05 +00:00
Marian Csontos
83e1a0bad8 lvm2app: Suppress deprecation warnings for our builds 2017-12-14 16:45:53 +01:00
Marian Csontos
c957d46f1d lvmdbusd: Make lvmdbusd executable
- Add files built from *.in to builddir files.
- Add all files built from *.in to DISTCLEAN_TARGETS.
2017-12-14 16:45:53 +01:00
Marian Csontos
c48d22bd3c docs: Add TESTING file 2017-12-14 16:45:47 +01:00
Heinz Mauelshagen
584ff361df test: fix trap adding proper teardown to previous, new raid tests
Also remove superfluous variable.
2017-12-13 14:41:23 +01:00
Heinz Mauelshagen
86fa0333ff test: new raid tests
Add three new raid tests with io load and table
reloads during reshape for target 1.13.2.

Add a raid0 to raid10 conversion test.

Also add more signals to trap in lvconvert-raid-reshape-load.sh.
2017-12-13 13:30:53 +01:00
Alasdair G Kergon
3edc25dbdf format_text: Round size written up to multiple of 4096.
Zero-fill metadata up to the next 4096 boundary then write out a
multiple of 4096 bytes to avoid triggering a read-modify-write.
2017-12-12 22:52:22 +00:00
Alasdair G Kergon
78ffa44fc5 format_text: Change metadata alignment from 512 to 4096.
If there is sufficient space in the metadata area, align the next
metadata to a disk offset that is a multiple of 4096 bytes and
don't write it circularly.  If it doesn't all fit at the end
of the metadata area, go back to the start and write it all there
contiguously.

If there is insufficient space to use the new stricter rules, revert to
the original behaviour, aligning on 512-byte boundaries wrapping around
the circular buffer as required.
2017-12-12 20:57:36 +00:00
Alasdair G Kergon
643df602c7 format_text: More refactoring of metadata offset calcs 2017-12-12 18:51:32 +00:00
Alasdair G Kergon
4002f5e206 format_text: Refactor and document metadata offset calculation. 2017-12-12 18:36:54 +00:00
Alasdair G Kergon
e932c5da50 device: Fix an unpaired device close.
dev_open_flags contains an unpaired dev_close_immediate so increment
open_count before calling it.
2017-12-12 17:56:58 +00:00
Alasdair G Kergon
b96862ee11 metadata: Consistently skip metadata areas that failed.
Even after writing some metadata encountered problems, some commands
continue (rightly or wrongly) and attempt to make further changes.

Once an mda is marked MDA_FAILED, don't try to use it again.
This also applies when reverting, where one loop already skips
failed mdas but the other doesn't.

This fixes some device open_count warnings on relevant failure paths.
2017-12-12 17:52:45 +00:00
Marian Csontos
15ccea7111 test: Fix condition when detecting lvmdbusd 2017-12-12 14:19:22 +01:00
Alasdair G Kergon
c5ef76bf27 device: Internal error if writing 0 bytes to dev. 2017-12-12 12:57:25 +00:00
Marian Csontos
7272fd2210 lvmdbusd: All tools use detected python3
- lvmdb.py and lvm_shell_proxy.py can be used as standalone tools, so
  should use detected value.
- clean executable bit on *.in files.
2017-12-12 13:17:07 +01:00
Marian Csontos
2f4c2a43d4 test: lvmdbusd is used for process name
lvmdbusd was started, but the process was not recognized by pgrep.

- configure does not make the script executable - set the flag
  explicitly when running make check,
- process name changed to lvmdbusd. The previous python3 value
  originated from the use of /usr/bin/env.
2017-12-12 13:17:07 +01:00
Alasdair G Kergon
b76c6951aa format_text: Adjust metadata alignment calculation.
Use new ALIGN_ABSOLUTE macro when calculating the start location
of new metadata and adjust the end of buffer detection so that
there is no longer an imposed gap between old and new metadata.
2017-12-11 20:25:03 +00:00
Alasdair G Kergon
053d35de47 format_text: Use absolute alignment to calculate metadata usage
Currently both start and offset should always be divisible by alignment,
so this should have no effect, but a later patch will increase alignment
so these variables can no longer be optimised out.
2017-12-11 17:14:38 +00:00
Alasdair G Kergon
2db67a8ea0 format_text: Move metadata size checking into separate fn.
Move checks into _metadata_fits_into_buffer() and add macro for alignment.
2017-12-11 17:08:29 +00:00
Alasdair G Kergon
46393bfca0 format_text: Log additional circular buffer information. 2017-12-11 16:07:34 +00:00
Alasdair G Kergon
49d486319f format_text: Replace PRI with FMT. 2017-12-11 15:39:25 +00:00
Marian Csontos
75d4d8e9a4 configure: Fix deprecation warning for lvmapp
* and properly regenerate configure script
2017-12-11 15:20:48 +01:00
Marian Csontos
2aedc98242 lvmdbusd: Fix path to python3
lvmdbusd executable script must use python3 interpreter detected by
configure script, as site-packages directory used for library is only
used by that interpreter.
2017-12-11 12:36:54 +01:00
Marian Csontos
6a6c8d7b81 configure: applib is not required by dbusd 2017-12-11 12:12:42 +01:00
Zdenek Kabelac
a64c73a979 cleanup: debug message 2017-12-08 13:21:15 +01:00
Zdenek Kabelac
700e2a2d25 cleanup: switch to standard query
In /tools part we should mostly use standard functions
lv_is_active*  unless there is good reason to not use it.
2017-12-08 13:21:15 +01:00
Zdenek Kabelac
71485ebfc7 thin: regression fix for metadata checking
Fix regression from commit f173274fe4
and restore support for 'disabled' checking via lvm.conf.
2017-12-08 13:21:15 +01:00
Zdenek Kabelac
455b26b8db activation: keep priority till memlock_unlock
Although it doesn't look like it can be a measurable problem
and costs some time to flip priorities outside of activation window.

So just like with memory locking preserve priority until call
memlock_unlock() appears.

(addition to commit c086dfadc3).
2017-12-08 13:21:15 +01:00
Zdenek Kabelac
4e8af1d3aa vgchange: drop extra counting
As the loop for background polling _poll_lvs_in_vg checks for active LVs,
avoid doing unnecessary extra check before.
2017-12-08 13:21:14 +01:00
Alasdair G Kergon
14b1e5270d format_text: Use explicit alignment in wrapping calc.
Expand out the metadata wrapping calculations to prepare
to support a larger alignment.

The current alignment is 512 bytes so
(mdac_area_start + rlocn->offset) % alignment is zero.
2017-12-08 01:18:46 +00:00
Zdenek Kabelac
4c88c4626d debug: update debug msg
Use _node_name.
2017-12-07 21:00:39 +01:00
Zdenek Kabelac
717714b24f cleanup: use log_warn 2017-12-07 21:00:39 +01:00
Zdenek Kabelac
f173274fe4 cleanup: reorder calling of pool checking tools
Test for zero header before even starting to create argument list for
execution of thin/cache_check tool.
2017-12-07 21:00:39 +01:00
Zdenek Kabelac
820b1b98fc libdm: drop extra structure copy
When doing resume, directly pass location where new updated info
needs to be stored.

_resume_node() ensures the info is ONLY updated when the function
is successful and never changes it on error path.
2017-12-07 21:00:39 +01:00
Zdenek Kabelac
82ae02bc6a libdm: use delay_resume_if_extended
Update the logic towards more explicit logic.

Preload tree normally does not want to resume, only
in certain cases of extension or new loaded nodes can be
resumed. So introduce new internal variable delay_resume_if_extended
controlable by target.

Patch itself is not changing current existing behaviour,
and rather documents existing problem in more readable way.

lvm2 needs to introduce explicit mechanism how to support more
fain-grained (and safe) logic to i.e. resize thin-pool which
can be sitting on cached raid volume.
2017-12-07 21:00:39 +01:00
Zdenek Kabelac
297d5915c3 libdm: avoid checking status on activation
Variable props.send_messages has 3 states and was not used properly
here.  Activation in this moment does not need to verify thin-pool status
as that has been already checked on preload.
So only if there are some real messages (value 2) call function
for sending them.
2017-12-07 21:00:36 +01:00
Zdenek Kabelac
4a4ea47f70 libdm: add help func _get_last_load_segment
Share code for same functionality.
2017-12-07 20:59:37 +01:00
Zdenek Kabelac
c3e224ad0e thin: missing type is error 2017-12-07 20:59:37 +01:00
Zdenek Kabelac
2208ebfe16 thin: always clear memory before parsing status
Ensure there cannot be 'reused' any data from some previous call.
2017-12-07 20:59:28 +01:00
Alasdair G Kergon
2166d7be72 lvmetad: drop stray underscore 2017-12-07 16:24:14 +00:00
Alasdair G Kergon
d591d04103 device: Tag I/O for each mda on a device separately in log messages.
Mark the first metadata area on each text format PV as MDA_PRIMARY.
Pass this information down to the device layer so that when
there are two metadata areas on a block device, we can easily
distinguish two independent streams of I/O.
2017-12-07 03:48:11 +00:00
David Teigland
54154dc6f1 lvmlockd: clear coverity complaint 2017-12-06 10:49:31 -06:00
David Teigland
0f0f6978e7 lvmlock: return an error if lvb cannot be written
It doesn't make much difference, because if this happens,
it means there are other more significant problems.
2017-12-06 10:49:31 -06:00
Marian Csontos
9e4dc83241 Update WHATS_NEW 2017-12-06 10:41:14 +01:00
David Teigland
b910c34f09 lvmlockd: use pool lock for tmeta access
When a command is run on a named tmeta LV, use
the lock on the pool.
2017-12-05 14:31:03 -06:00
David Teigland
b9e4198500 lvmlockd: fix log print
from previous commit
2017-12-05 13:48:30 -06:00
David Teigland
5d5807b238 lvmlockd: improve error message for VG lock conflict
When there is significant VG lock contention which retries
have not been able to mask, print a better error message.
2017-12-05 11:53:03 -06:00
David Teigland
46d6f7a639 lvmlockd: recognize normal errors from sanlock_convert
Don't log an error message for error values returned
by sanlock_convert for expected conditions like lock
contention or io timeouts.
2017-12-05 11:53:03 -06:00
David Teigland
bd893348b4 lvmlockd: avoid blocking in sanlock_convert
Use the same flag as sanlock_acquire() for the
same purpose.  sanlock_convert can block like
acquire when doing a sh to ex conversion.
2017-12-05 11:53:03 -06:00
Heinz Mauelshagen
94632eb155 deactivate_lvs: deactivate any missing RaidLV legs
In case of failed legs, raid replaces those with
e.g. "vg-lv_rimage_0-missing_0_0" mapped to an error target.

Those errouneously remain on deactivation.

Fix by removing them on deactivation/removal of the RaidLV.
2017-12-05 18:48:06 +01:00
Alasdair G Kergon
7195df5aca device: Skip read-modify-write if replacing whole block. 2017-12-05 01:00:38 +00:00
Alasdair G Kergon
e4805e4883 device: categorise block i/o
Introduce enum dev_io_reason to categorise block device I/O
in debug messages so it's obvious what it is for.

DEV_IO_SIGNATURES   /* Scanning device signatures */
DEV_IO_LABEL        /* LVM PV disk label */
DEV_IO_MDA_HEADER   /* Text format metadata area header */
DEV_IO_MDA_CONTENT  /* Text format metadata area content */
DEV_IO_FMT1         /* Original LVM1 metadata format */
DEV_IO_POOL         /* Pool metadata format */
DEV_IO_LV           /* Content written to an LV */
DEV_IO_LOG          /* Logging messages */
2017-12-04 23:45:26 +00:00
Zdenek Kabelac
698483b5a1 activation: also lock memory for clustered locking
Commit  c086dfadc3 missed to lock memory
for clustering suspend part since it's using differnt locking reason.
2017-12-04 23:33:02 +01:00
Zdenek Kabelac
406b566cfc cleanup: drop unneeded check
Code already has dereferenced UUID before this point,
and its already given we require name & uuid when ading new node
(although uuid could be empty string).
2017-12-04 15:45:49 +01:00
Zdenek Kabelac
5abf6b7c21 cleanup: messsage cleanup 2017-12-04 15:38:50 +01:00
Zdenek Kabelac
76954884c7 cleanup: drop unused define 2017-12-04 15:38:50 +01:00
Zdenek Kabelac
110dac870c cleanup: use existing define with prefix 2017-12-04 15:38:50 +01:00
Zdenek Kabelac
1f73cadd2d cleanup: use log_warn
Fucntion is not failing execution -> log_warn.
2017-12-04 15:38:50 +01:00
Zdenek Kabelac
76322d3b3e clenaup: use log_warn
Avoid logging error when function is not failing.
Technically can't really happen ATM anyway.
2017-12-04 15:38:50 +01:00
Zdenek Kabelac
2a01e3d4ca cleanup: use _node_name
Use existing internal method for create 'name (major:minor)' string
for debug messages and reduce some messages.
2017-12-04 15:38:50 +01:00
Zdenek Kabelac
925fec6ecb cleanup: stack tracing 2017-12-04 15:38:50 +01:00
Zdenek Kabelac
e3366787b6 cleanup: mark success at the end
Simplify setting 'success' return value and use common use-pattern
for handling return code.
2017-12-04 15:38:50 +01:00
Zdenek Kabelac
10f37345eb cleanup: drop impossible test case
This test can never be true since info is embeded struct.
2017-12-04 15:38:50 +01:00
Zdenek Kabelac
1f6d79ab48 cleanup: simplier error message
Use single 'error' message just with different reason.
2017-12-04 15:38:50 +01:00
Zdenek Kabelac
7379a2624b cleanup: futher code reduction
Just like everywhere else - use single if() for major:minor setup
(it basically can't fail as of today anyway)

Always leave funtion with correctly set pointers even on error path.
2017-12-04 15:38:50 +01:00
Zdenek Kabelac
2a22576b2d cleanup: drop unused header
DM_UUID_LEN is no longer needed.
2017-12-04 15:38:50 +01:00
Zdenek Kabelac
e447d7ca5e libdm: support for replicator target is dropped
Replicator never really existed in upstream kernel and its support
got deprecated.

Also its support never got finished so no code is supposed to be
using it anyway.

Libdm symbols are remaining, just the implementation will always
return failure - so any user of:

dm_tree_node_add_replicator_dev_target()
dm_tree_node_add_replicator_target().

will now always recieve error message.
2017-12-04 15:38:50 +01:00
Zdenek Kabelac
63368a5064 libdm: watch for failing _info_by_dev
Separate handling of error code from _info_by_dev.
This error can only happeng when we are running out of memory.
In such case there is urgent need to stop any futher proceeding
of command and run to error ASAP.
2017-12-04 15:38:50 +01:00
Heinz Mauelshagen
b74e7f6a78 test: allow to succeed in the cluster
Avoiding "$(get first_extent_sector "$d")" in the loop
allows the test to succeed in the cluster.  Further cluster
analysis needed to get to the core reason.
2017-12-01 18:59:55 +01:00
Heinz Mauelshagen
053314f295 test: add large tests skip option
The lvm2 test suite aims at small test resource footprints
(few PVs, small PV sizes) to run on tmpfs backed loop device.

OTOH, lvconvert-reshape-raid.sh aims to test the maxima of
supported total stripes of 64.  This patch adds a prerequisite
conditional to skip tests using more than 14 stripes.

It requires the target version 1.13.1 to avoid deadlocks.
2017-12-01 18:50:55 +01:00
Heinz Mauelshagen
7aef59c6c3 test: reduce pv sizes, fix comment and stripe size 2017-12-01 18:42:37 +01:00
Heinz Mauelshagen
16fa9d9ed5 test: cleanup command 2017-12-01 18:39:38 +01:00
Heinz Mauelshagen
4daad1cf11 lv_manip: allow extension on --nosync raid lv
If the recovery of the repleced leg(s) of a RaidLV created without
initial resynchronization (i.e. "lvcreate --nosync ...") got
interrupted, it can't be extended because of the < 100% sync rate.
2017-12-01 18:38:18 +01:00
Heinz Mauelshagen
3688eeeea0 test: disable new reshape test until target version 1.13.1 2017-12-01 18:33:11 +01:00
Heinz Mauelshagen
9681d98cc4 test: new reshape test under io load 2017-12-01 18:31:12 +01:00
Heinz Mauelshagen
d3d18e637c raid: ignore --stripesize on raid4/5 conversion to 1 stripe
In case caller passes in changed stripe size when reshaping raid4/5
to 1 stripe aiming to convert to raid1 and optionally to linear,
ignore it to prevent data corruption.
2017-12-01 15:00:09 +01:00
Zdenek Kabelac
a42c3a0e90 cleanup: remove debug code 2017-12-01 12:19:09 +01:00
Zdenek Kabelac
0e177cc7c9 cleanup: simplify _deps code
Make _deps to always return name & uuid,
and postpone duplication of name and uuid into _create_dm_tree_node().
Saves some duplicated code.
2017-12-01 12:19:09 +01:00
Zdenek Kabelac
4dc8184803 suspend: optimize generated list
Avoid adding same LV multiple times into the list.
Just saves couple extra calls and ioctls and makes log shorter.
2017-12-01 12:19:09 +01:00
Zdenek Kabelac
7e794b7748 activation: avoid rechecking pvmove node
Use new 3rd. state of trace_pvmove_deps == 2.
In this state we know, we have already seen the node and can skip futher
testing.   Remainging value 1 signals we want to track, and value 0
is for ignoring tracking, but node is still checking in this case.

Reduces large amount of duplicate ioctl queries.
2017-12-01 12:19:09 +01:00
Zdenek Kabelac
e4db42e476 activation: extend resume validation
Check also all snapshosts when resume is requested,
the origin volume is already resume, but possibly
some subLV or snapshot LV could be suspended if
we are still in critical_section.
2017-12-01 12:19:09 +01:00
Zdenek Kabelac
c086dfadc3 activation: split priority from memory locking
When entering any critical section, lvm2 used to lock process memory
and raised task priority to avoid problem with page swapping and minimize
time of having non-resumed devices in table.

With this patch, memory locking which which is expensive is only used when
entering  'suspending' section as only in this section there is risk
lvm could be suspending a device which later can be needed for paging.

Raised priority is still kept for all section entrances as this is
low-cost operation and may accelerate table resumes - although the real
impact can be still considered later.
2017-12-01 12:19:09 +01:00
Zdenek Kabelac
c489dd2e17 pvmove: add missing segment merging
When pvmove is finished and metadata are updated, the code missed
to merge possible mergable segments - so add explicit merging
call after pvmoved volumes are unlocked.

This avoids weird results where i.e. lvs could have been reporting
non-matching segments as lvs upon metadata read is doing silent segment
merging while dm table left after pvmove was still preserving
non-merged segments.
2017-12-01 12:19:09 +01:00
Zdenek Kabelac
fbd8b456db pvmove: move code from tools to lib
Move code manipulating with locking flags into /lib part of lvm.
2017-12-01 12:18:32 +01:00
Marian Csontos
94d3878efb Update WHATS_NEW 2017-11-30 13:30:28 +01:00
Marian Csontos
b8caca4652 tests: Fix common_dev_ argument handling
from[:[len]] arguments with missing colon assigned from to len, instead
of till_the_end_of_device.
2017-11-28 12:03:35 +01:00
Alasdair G Kergon
a9812ec9d3 label: Remove unused verify functions.
label_verify has never been used so remove it.
2017-11-28 01:36:55 +00:00
Zdenek Kabelac
02e934c444 cleanup: reuse existing macro
Use existing macro to detect striped raid segment.
2017-11-27 10:34:30 +01:00
Zdenek Kabelac
efa17cae24 cmdline: avoid overrun on very large numbers.
When large size number (>2^31) is given on command line it could be
misdetected and in certain cases lead to wrongly casted number.

So make sure all cases always do set _MAX number in case the value would
not fit within the supported range instead of getting some random value
within the range.

In most cases this was not a problem to detect, but i.e. stripesize
parameter might have been fooled by certain large numbers.
2017-11-27 10:34:30 +01:00
Zdenek Kabelac
34eb082bbc toollib: improve stripes args reading
Rewrite validation of stripes and stripe_size args into more readable
sequential code.

Extend reading of stripes & stripes_size args so it better knows
defaults for types like striped raid.

TODO: this should really be a value obtained for segtype structure and
all the weird conditions and modification of stripes and stripe_size
around lvm2 code should be dropped.
2017-11-27 10:34:30 +01:00
Zdenek Kabelac
f70404addb pvmove: enhance delayed_resume logic
ATM we want to support delayed resume purely in pvmove case.
So have libdm logic internal to recognize difference beween
pvmove and other targets that do use delayed resume.

This fixes problem introduced with commit aa68b898ff
for mirror-on-mirror or snapshot-on-mirror problem.

TODO: likely added new API call and let libdm user select
delayed nodes explicitely.
2017-11-26 00:36:48 +01:00
Zdenek Kabelac
8c6fd0933f activation: enhance holders detection
Use code which detectes handlers in a way, which is more
backward-compatible friendly.

Replace read of 'sysfs' uuid entry with dm ioctl call.

Use /sys/block/dm-X/holders path instead of
new path  /sys/dev/block/major:minor/holders.

TODO:
There are few more occurencies of this logic around the code
so some abstract interface should be considered.
2017-11-26 00:31:26 +01:00
Zdenek Kabelac
ce83162d7c tests: more places where missing should not appear 2017-11-24 16:09:59 +01:00
Zdenek Kabelac
7eae2647c0 tests: typo 2017-11-24 16:09:59 +01:00
Zdenek Kabelac
7bffbe0e2f cleanup: update error messages
Correct printed lv names in error messages
and add missing trace for return.
2017-11-24 16:09:59 +01:00
Zdenek Kabelac
b0398f42ad cleanup: using max args consistently
Define and use MAX_PDATA_ARGS for thin_repair and cache_repair consistently.
2017-11-24 16:09:59 +01:00
Zdenek Kabelac
54741aeac5 cleanup: reduce couple debug lines 2017-11-24 16:09:59 +01:00
Zdenek Kabelac
5e88d3a89b cache: use conditional in warning message
In some cases the message could be slightly misleading so use
here rather conditional.

TODO:

In future we may possibly further tune the message in case we are
certain the level of redundancy protection has not been reduced.
2017-11-24 16:09:59 +01:00
Zdenek Kabelac
5b5c5cc618 toollib: avoid printing default stripe size
When user is not creating striped LV, do not print
rather confusing info about default stripe size.
2017-11-24 16:09:59 +01:00
Zdenek Kabelac
16ef133be2 pvmove: finish no longer needs explicit resumed
Activation code can see from holders needed LVs for resume.
2017-11-24 16:09:59 +01:00
Zdenek Kabelac
2a6981a697 activation: automaticaly discover pvmove holders
When pvmove is finished and does 'suspend/resume' on PVMOVE LV,
on resume path committed metadata are already showing 'standalone'
pvmove LV prepared just for removal.

However code should be able to 'resume' preloaded LV there were
participating in pvmove operation.

Previously this was all done in the 'tools' part of lvm2 code.
So the lvconvert upon pvmove finish had to explicitely call 'resume' on every such LV.
Now 'smarted' activation code is able to deduce and combine all information from
the active dm table and committed metadata so single  call resolves
it all in one go.

Internally holders are detected by reading sysfs directory to capture
all needed UUID which are then looked in lvm2 metadata and all such
LVs are automatically collected into dmtree.
2017-11-24 16:09:59 +01:00
Zdenek Kabelac
ddbe763eb8 mirror: use lv_update_and_reload_origin
Replace complex code with standard lv_update_and_reload_origin().
Extra suspend should not be necessary.
(If they would be - dependency tree would have bug for fixing).
2017-11-24 16:05:21 +01:00
Zdenek Kabelac
aa68b898ff libdm: preload propagates delayed resume
Propagate delayed resume at least for preload case in a simple way.
Currently  PVMOVE depends on internal logic where 'mirror' with
corelog is 'possible' PVMOVE. In such case resume of 'created'
node is 'delayed'.

This is mostly an ugly internal hack - but for the moment being when we
add propagation for preload - it does work reasonable.

TODO: provide standard API and avoid this internal 'guessing'.
2017-11-24 16:05:21 +01:00
Zdenek Kabelac
b5be7420d9 locking: pvmove is locking holding LV
As we do get lock for pvmove LV - it's lockholder ATM.
2017-11-24 16:05:21 +01:00
Zdenek Kabelac
8cf10948bd resume: secure critical section
Only  thin-pool with origin_only suspend is allowed to be not suspending anything.
In such case pairing resume will 'decrement' critical section counter.
2017-11-24 16:05:21 +01:00
Zdenek Kabelac
ae6beda12d suspend: handle start of pvmove
Just like suspend handles preload for pvmove finish,
in similar way handle suspend of starting pvmove.

In this case the  precommited metadata are checked for list of PVMOVEed
LVs and those are suspended in with committed metadata.
2017-11-24 16:05:21 +01:00
David Teigland
175d06a929 lvconvert: prevent combining split snapshots in shared vg
splitting snapshots was already prevented.
2017-11-21 11:45:49 -06:00
David Teigland
ea0463791d man: lvmlockd steps for changing lock type
were not quite correct
2017-11-21 10:37:00 -06:00
David Teigland
bbaaf4f1d3 lvmlockd: override unknown lock manager error numbers
When sanlock or dlm lock managers return an error number
that we don't recognize, replace it with a generic -ELMERR
which is defined in the set of special lvmlockd error
numbers.  Otherwise, an unknown lock manager error number
could be misinterpreted for something else if it happened
to overlap another set of error numbers (which they have
not thus far.)
2017-11-17 10:59:12 -06:00
David Teigland
e52d2e3bd8 lvmlockd: retry on other sanlock errors
These less common errors returned from sanlock should
also cause sanlock to retry the lock acquire:

- i/o timeout occurs during sanlock_acquire().
  other i/o on the same disk as the leases can cause
  sanlock i/o timeouts.

- low level disk paxos contention between hosts naturally
  causes one host to not acquire the lease.  There are a
  couple special error numbers associated with these cases
  that should just be recognized as a normal failure to
  acquire the lease.
2017-11-17 10:59:12 -06:00
Alasdair G Kergon
115e66e9be device: log debug when I/O bounce buffer used 2017-11-16 19:16:10 +00:00
Alasdair G Kergon
efb0e7ac6f lvmdiskscan: Remove unnecessary read.
dev_get_size will open the device itself.
2017-11-16 19:13:03 +00:00
Heinz Mauelshagen
93c02e2532 raid: add validation checks for reshape flags
Enhance vg_validate() raid checking functions to check for
flags  LV_RESHAPE and LV_RESHAPE_DELTA_DISKS_(MINUS|PLUS).
2017-11-15 21:24:44 +01:00
Zdenek Kabelac
b0618f9011 tests: pvmove supports more cases
pvmove handles cached LVs as well as snapshots now.
2017-11-15 21:00:29 +01:00
Zdenek Kabelac
0f0dc1a2a5 pvmove: remove unusued code
Support for snapshot and cache LVs should now work.
Remove protection rejecting pvmove for them.
2017-11-15 21:00:29 +01:00
Zdenek Kabelac
b978f505ff pvmove: activation changes
Do not use precommitted LV for suspend of pvmoving LVs.
2017-11-15 21:00:26 +01:00
Zdenek Kabelac
a25f9b2106 pvmove: change locking on finish 2017-11-15 14:07:00 +01:00
Zdenek Kabelac
9d04ecc7b3 cleanup: update log messages 2017-11-15 14:03:22 +01:00
Zdenek Kabelac
838592a171 activate_lvs: use exclusive activation
There is no need to differentiation between clustered VG and normal VG.
As the activation depends on locking type.

Use unconditionally locally exclusive activation for pvmove.
2017-11-15 14:03:22 +01:00
Zdenek Kabelac
8212e1047e pvmove: always flush when working with pvmove tree 2017-11-15 14:03:22 +01:00
Zdenek Kabelac
35b207946a activation: suspend pvmove using lv.
Whenever pvmove tree is going to be generated for suspend
and such LV has a user - use this 'using LV' to generate
correct dm tree  holding all components.
2017-11-15 14:03:22 +01:00
Zdenek Kabelac
9e2a68a981 activation: check subLV before skipping resume
LV is asked for resume, and its already resume and tool
is inside 'critical_section()' check if there is any suspended sub LV.
In that case 'resume' operation will not be skipped.
2017-11-15 14:03:22 +01:00
Zdenek Kabelac
c820b43fc0 activate_lvs: deactivate on uniterate
When activation of LVs fails prior pvmove start, try to deactivate
already activated LVs.

TODO: possibly remember which LVs where already activate and only those
take down - devices which are already in-use will stay active.
2017-11-15 12:11:33 +01:00
Zdenek Kabelac
eab9097b46 layers: collect only lock holding LVs 2017-11-15 12:11:33 +01:00
Zdenek Kabelac
cc854c0617 pvmove: return pvmove itself
When find_pvmove_lv_in_lv() get already a 'pvmoving' LV - return it.
2017-11-15 11:51:53 +01:00
Zdenek Kabelac
919744375e pvmove: snapshots need to go with origin device
Enable future support for pvmove for COW LVs.
2017-11-15 11:51:53 +01:00
Marian Csontos
7c5531b4ca Update WHATS_NEW 2017-11-15 10:01:50 +01:00
Alasdair G Kergon
fe63c09381 regenerate man and conf 2017-11-15 01:05:07 +00:00
Alasdair G Kergon
02e9876665 log: Add io debug class 2017-11-15 01:02:15 +00:00
Alasdair G Kergon
b5f62a143d metadata: Eliminate redundant nested VG metadata
Only lv_committed() now uses vg->vg_committed and it appears redundant
if its contents match the enclosing VG so don't waste cycles creating it
when that's known to be true when no write lock is held so the struct
won't get modified.
2017-11-14 15:38:55 +00:00
Heinz Mauelshagen
7a5728fb4c test: additional avoid have_raid overhead 2017-11-14 14:41:44 +00:00
Heinz Mauelshagen
97750cd12f test: avoid have_raid overhead 2017-11-14 14:41:15 +00:00
Heinz Mauelshagen
ebd0fed0ce raid: correct raid6_n_6 -> raid5 convenience type
Fix "lvconvert --type raid5 RaidLV" on a "raid6_n_6" LV offering
false "raid6_ls_6" instead of "raid5_n".
2017-11-14 14:41:06 +00:00
Alasdair G Kergon
00acae12a4 metadata: Remove unused vg.cft_precommitted
The precommitted metadata config_tree is now only referenced from a
single function so just use a local variable instead.
2017-11-14 01:22:09 +00:00
Alasdair G Kergon
6bf0f04ae2 log: Improve various device-related messages
- Use 'lvmcache' consistently instead of 'metadata cache'
- Always use 5 characters for source line number
- Remember to convert uuids into printable form
- Use <no name> rather than (null) when VG has no name.
2017-11-13 19:45:33 +00:00
Alasdair G Kergon
598fcccf45 persistent filter: Skip import before rescan
The persistent filter should not be imported by any command that doesn't
use it so take addtional note of REQUIRES_FULL_LABEL_SCAN (for vgrename)
and introduce IGNORE_PERSISTENT_FILTER for vgscan and pvscan.
2017-11-13 19:45:16 +00:00
Zdenek Kabelac
fe69a8d215 tests: use nonflusing status
Avoid being blocked when reporting status with flushing on some stacked
device tree.
2017-11-11 01:00:35 +01:00
Zdenek Kabelac
dd06a0a4a6 lv_lock_holder: unused cache-pool is not lock holder
Unused cache-pool is only a constainer for data and metadata,
and does not present localble entity.
2017-11-11 00:59:46 +01:00
Zdenek Kabelac
52cee9dd83 lvremove: for unused cache deactive sublv 2017-11-11 00:59:19 +01:00
Zdenek Kabelac
55b8204ca3 reload: do not take backup with suspended devices
If the suspend/resume sequence would leave some device in suspend
for possible later resume, backup cannot be takes (fs holding backups
could be still frozen in critical section())
2017-11-11 00:58:11 +01:00
Zdenek Kabelac
1ac7fde67b cleanup: remove stack tracing for ok path 2017-11-11 00:56:10 +01:00
Zdenek Kabelac
b9ac1c12d0 cleanup: constify lv parameter 2017-11-11 00:56:10 +01:00
Zdenek Kabelac
05f9acdc7f raid: protect raid4 activation
Move check for presence of raid4 into the right place
so there is no way how to hit activation of any LV
with raid4 on kernel which does not support it.
2017-11-11 00:56:10 +01:00
Ondrej Kozina
f0d1c8429b test: check dmsetup hides integrity encryption keys 2017-11-10 15:23:07 +01:00
Ondrej Kozina
32e747dd31 dmsetup: hide integrity encryption keys on table output 2017-11-10 15:23:00 +01:00
Marian Csontos
512b2adc77 test: D-Bus test_nesting requires filter 2017-11-09 11:57:59 +01:00
Marian Csontos
cd3b5e60a8 test: Rename test nothing methods
These two methods might be useful for debugging, but are not testing
anything.
2017-11-09 11:31:54 +01:00
Heinz Mauelshagen
9958c41927 raid: reject message for 2-legged raid4/5 -> striped
Commit 763db8aab0 rejects 2-legged
conversions to striped/raid0 but different messages are displayed
for raid0 or striped. This commit provides the same rejection messages.
2017-11-08 18:17:26 +01:00
Heinz Mauelshagen
763db8aab0 raid: reject conversion request to striped/raid0 on 2-legged raid4/5
raid4/5 LVs may only be converted to striped or raid0/raid0_meta
in case they have at least 3 legs. 2-legged raid4/5 are a result
of either converting a raid1 to raid4/5 (takeover) or converting
a raid4/5 with more than 2 legs to raid1 with 2 legs (reshape).

The raid4/5 personalities map those as raid1,
thus reject conversion to striped/raid0.

Resolves: rhbz1511047
2017-11-08 17:49:04 +01:00
Zdenek Kabelac
b78add3df5 tests: allow to proceed futher with test
So raid doesn't want to create raid arrays with bigger regionsize ATM,
so just use smaller regionsize.
2017-11-08 00:02:54 +01:00
Zdenek Kabelac
d6473b2018 tests: detect racy systemd version
Systemd 222 has a bug - where it's sometimes umount unpredictibly just
mounted device - skip testing when this happens.
2017-11-08 00:02:54 +01:00
Zdenek Kabelac
2172115379 tests: have some space for 2nd mda
pvcreate with 2MDAs needs some extra space.
2017-11-08 00:02:54 +01:00
Zdenek Kabelac
f7fc7bc44a lvconvert: update delaying message
Make more obvious the operation just got delayed
(using same wording as with thin snapshots)
2017-11-08 00:02:54 +01:00
Zdenek Kabelac
e822a9f38d tests: snasphot merging 2017-11-07 21:34:35 +01:00
Zdenek Kabelac
0c9e3e8df2 coverity: add some initilizers
Coverity cannot do a deeper analyzis so let's make just reports
go away and initialize them to 0.
2017-11-07 21:26:11 +01:00
Zdenek Kabelac
3076a839a5 cleanup: drop unneeded headerfiles
Coverity reported these are no longer in use.
2017-11-07 21:26:11 +01:00
Zdenek Kabelac
f7f2f77dca cleanup: update messages in lvconvert
Use display_lvname and update thin snapshot merge error message.
2017-11-07 21:26:11 +01:00
Zdenek Kabelac
e2fce429cf cleanup: gcc const warning 2017-11-07 21:26:11 +01:00
Zdenek Kabelac
d45a9c0f5b shellcheck: fsadm cleanup
Use some more "" for bash vars
2017-11-07 21:26:11 +01:00
Zdenek Kabelac
0f0baec1f3 blkdeactive: use /sbin for mdamd
Do not using lvm's  @SBINDIR@ for mdadm path.
Set this directly to  /sbin/mdadm like other tools.

Group them separately
2017-11-07 21:26:11 +01:00
Zdenek Kabelac
2354fb3fe4 coverity: avoid overflow_before_widen
TODO: it likely should be checked value is >0...
2017-11-07 21:26:11 +01:00
Zdenek Kabelac
56b527a6fb coverity: avoid memleak
When security_level was set, allocated filename was leaking.
2017-11-07 21:26:09 +01:00
Eric Ren
14d0b0bbdd clvmd: supress ENOENT error on testing connection
In HA cluster, we have "clvm" resource agent to manage clvmd daemon.
The agent invokes clvmd like: "clvmd -T90 -d0", which  always prints
a scaring error message:

"""
local socket: connect failed: No such file or directory
"""

When specifed with "-d" option, clvmd tries to check if an instance
of the clvmd daemon is already running through a testing connection.
The connect() will fail with this ENOENT error in such case, so supress
the error message in such case.

TODO: add missing error reaction code - since ofter log_error, program
is not supposed to continue running (log_error() is for reporting
stopping problems).

Signed-off-by: Eric Ren <zren@suse.com>
2017-11-07 21:24:39 +01:00
Zdenek Kabelac
014122256b snapshot: prevent repeated merging
Check and prevent starting another snapshot merge before
exiting merging is finished.

TODO: we can possibly implement smarter logic to drop existing
merging and start a new one.
2017-11-07 21:22:50 +01:00
Alasdair G Kergon
1b6dfd4802 post-release 2017-11-03 04:42:54 +00:00
Alasdair G Kergon
29300e72ee pre-release 2017-11-03 02:28:55 +00:00
Jonathan Brassow
4129cf5090 testsuite: Forgot to pull 'should's after fixing RAID4/5/6 mismatch test
Test will now fail rather than warn if conditions are not met.
2017-11-02 10:25:46 -05:00
Jonathan Brassow
9e8dec2f38 testsuite: Fix problem when checking RAID4/5/6 for mismatches.
The lvchange-raid[456].sh test checks that mismatches can be detected
properly.  It does this by writing garbage to the back half of one of
the legs directly.  When performing a "check" or "repair" of mismatches,
MD does a good job going directly to disk and bypassing any buffers that
may prevent it from seeing mismatches.  However, in the case of RAID4/5/6
we have the stripe cache to contend with and this is not bypassed.  Thus,
mismatches which have /just/ happened to an area that now populates the
stripe cache may be overlooked.  This isn't a serious issue, however,
because the stripe cache is short-lived and reasonably small.  So, while
there may be a small window of time between the disk changing underneath
the RAID array and when you run a "check"/"repair" - causing a mismatch
to be missed - that would be no worse than if a user had simply run a
"check" a few seconds before the disk changed.  IOW, it simply isn't worth
making a fuss over dropping the stripe cache before beginning a "check" or
"repair" (which we actually did attempt to do a while back).

So, to get the test running smoothly, we simply deactivate and reactivate
the LV to force the stripe cache to be dropped and then proceed.  We could
just as easily wait a few seconds for the stripe cache to empty also.
2017-11-02 09:49:35 -05:00
Jonathan Brassow
5013032845 testsuite: Add and document a 'should' for "idle" -> "recover" RAID test
When a "recover" is just starting for a RAID LV, it is possible to get
"idle" for the sync action if the status is issued quickly enough.  This
is fine, the MD thread just hasn't gotten things going yet.  However,
the /need/ for a "recover" should be marked in md->recovery and it would
be simple enough to fix the kernel so this doesn't happen.  May eventually
want a separate bug for this, but for now it fits with RHBZ 1507719.
2017-11-02 08:53:48 -05:00
Bastian Blank
58b763c99c systemd: remove Install sections from socket-activated services
We always preferred and recommended socket activation for our services
so remove the Install section in related .service units which are unused
in this case and keep only the Install section in associated .socket
units.

Signed-off-by: Bastian Blank <waldi@debian.org>
2017-11-01 15:37:19 +01:00
Zdenek Kabelac
7a394575fb cleanup: use segtype_is_raid_with_meta
Replace with common macro.
2017-11-01 00:59:22 +01:00
Zdenek Kabelac
7a28b243fa cleanup: pvmove messages
Just add some dots to messages and remove unneeded
stack trace from return after log_error.
2017-11-01 00:58:31 +01:00
Zdenek Kabelac
373372c8ab lv_manip: hide layered LV temporarily
Since vg_validate() now rejects LVs without segments and
insert_layer_for_segments_on_pv() gets just created
'layer_lv' without segment,  it needs to be hidden
from vg->lvs during processing of _align_segment_boundary_to_pe_range()
as this function calls  lv_validate() and now requires
vg to be consistent.  LV is then put back into vg->lvs.
2017-11-01 00:55:24 +01:00
Zdenek Kabelac
0ba3939542 pvmove: simplify name generation 2017-11-01 00:55:24 +01:00
Jonathan Brassow
bc29785d09 test: clean-up failing test case and document 'should' cases
There are two known bugs in the lvconvert-raid-status-validation.sh
test.  The first one I consider to be more of an annoyance (1507719).
The second one I consider to be more serious (1507729).

RHBZ 1507719 simply documents the fact that the three RAID status
fields may not always be coherent due to the way they are set and
unset when the MD thread is shutting down and starting up.  For
example, the sync ratio may be 100% but the sync action may not
yet have switched to "idle" and the health characters may not yet
all be 'A's (i.e. the devices set to InSync).

RHBZ 1507729 is more serious.  The sync ratio can be 100% for a
short period of time after upconverting linear -> RAID1.  It is
reset to 0 once the MD sync thread gets to work on it.  It does
this because, technically, the array /is/ in-sync if the new
devices are excluded - i.e. the data is 100% available and
consistent.  I'm not sure what to do about this problem, but we'd
much rather not have this state that looks exactly like the
end of the process when the sync ratio is 100% because the
"recover" process finished, but the sync action and health
characters haven't been updated yet.  Put simply, the problem
is that we can't tell if a sync is starting or finished based
on the status output.
2017-10-30 21:58:38 -05:00
Alasdair G Kergon
248144d066 liblvm: Fix segfault in lvm_pv_remove.
Since 4fa5add6b1 ("pvcreate: Wipe cached
bootloaderarea when wiping label.") label_remove is responsible
for the lvmcache_del.  (toollib and liblvm need fixing to share
the code.)
2017-10-30 22:03:35 +00:00
Zdenek Kabelac
7e3be7d1ba tests: revert commit change
Commit 0424410773 by mistake took also
this unwanted local modification of test - revert it.
2017-10-30 17:27:29 +01:00
Zdenek Kabelac
2b6391538c raid: setup LV size earlier
New validation code which does require to not store LV with no size
(no segments) revealed this size setup code needs to happen
earlier.
2017-10-30 17:23:56 +01:00
Zdenek Kabelac
3efd1f9c6e tests: load reiserfs
Preload reiserfs module for the case, fs is present/compiled for a
kernel but it's not present in memory.

Size reducition needs --yes confirmation to preceed for reiserfs.
2017-10-30 14:39:16 +01:00
Zdenek Kabelac
83d5db056b lvreduce: check LV has segment
Before accessing content make sure LV has segment.
This can be used in case code removes LV without segments
(i.e. on some error path)
2017-10-30 14:39:16 +01:00
Zdenek Kabelac
0424410773 validation: capture store of LV without segment 2017-10-30 14:39:16 +01:00
Zdenek Kabelac
e9206fb93d devcache: track more udev errors
Add a bit more details for failing udev function.
2017-10-30 13:16:50 +01:00
Zdenek Kabelac
af21263cb3 thin: fix merging messages
Correct reported message when thin snapshot has been already merged.
So lvm2 is no longer reporting "Mergins of snapshot X will occur..."
(even with swapped names).
2017-10-30 11:53:39 +01:00
Zdenek Kabelac
90ee7783b4 pool: drop create spare on error path
When thin/cache pool creation fails and command created _pmspare,
such volume is now removed on error path.
2017-10-30 11:53:39 +01:00
Alasdair G Kergon
52fd66210b metadata: Avoid accessing ignored metadata.
When an ignored metadata area gets flagged for use again, make sure the
code doesn't try to parse its old metadata.  Firstly by trying to detect
this situation and skipping the read (while still remembering the
position reached in the circular buffer), and secondly by clearing the
invalid live metadata location on disk as a precaution when subsequently
writing out the precommitted metadata.

Problems showed up when a metadata area in one VG got moved to
another VG in ignored state (still holding metadata for the original
VG) and then later got brought into use in the new VG - only the header
should be read in this case, not any of the metadata content.
2017-10-27 22:53:43 +01:00
Alasdair G Kergon
84aca4201e vgsplit: Fix detection of moved PVs.
vgsplit shares the vg_rename code so that must only set the PV_MOVED_VG
flag introduced in commit 486ed10848
("vgmerge: Fix intermediate metadata corruption") on PVs that moved.
2017-10-27 22:53:43 +01:00
Zdenek Kabelac
eb710cced1 tests: update checked messages 2017-10-27 17:07:42 +02:00
Zdenek Kabelac
63c50ced89 snapshot: relocate common code validation for snapshot origin
Since both lvcreate and lvconvert needs to check for same
type of allowed origin for snapshot - move the code into
a single function.

This way we also fix several inconsitencies where snapshot
has been allowed by mistake either through lvcreate or
lvconvert path.
2017-10-27 17:07:42 +02:00
Zdenek Kabelac
0c68c19c32 man: Makefiles with V=1 support
Generation of man pages is generating lot of barely readable output.
For normal build quietize this a bit.

For original verbose build start to use  'make V=1'
(just like i.e. linux kernel does)

TODO: apply at more places...
2017-10-27 17:05:15 +02:00
Alasdair G Kergon
4b0f6829f6 dmsetup: Add unknown device error to dmsetup status.
Treat status the same way as info if provided device name doesn't exist.
2017-10-26 17:47:13 +01:00
Heinz Mauelshagen
fdcc709ed0 WHATS_NEW: ignore stripes/stripesize on RAID takover 2017-10-26 18:18:24 +02:00
Heinz Mauelshagen
adb80816fb lvcreate: error message with dot. 2017-10-26 17:25:22 +02:00
Heinz Mauelshagen
4a3884245d raid: ignore --stripes/--stripesize on takeover
Converting from one raid level to another, no changes
of stripes or stripesize can be requested because those
are subject to reshaping.  I.e. the process requires to
takeover first and secondly request raid algorithm,
stripe or stripesize changes.

Ignore any related changes display warninngs
and proceed with the takeover.

Without this patch, a takeover requesting
stripesize change causes data corruption!
2017-10-26 17:16:23 +02:00
Zdenek Kabelac
b765288bf2 tests: better clustering support
Use exclusive activation for snapshot conversion since we can only
convert exclusively active volumes.
2017-10-26 14:04:58 +02:00
Zdenek Kabelac
1e80ec8926 tests: allow override of LVM_LOG_FILE_MAX_LINES
Just like with other vars support this:

make check_local T=xyz LVM_LOG_FILE_MAX_LINES=10000000

Allows easily to override existing line limit.
Also increase limiting size of logs per command since some of
our commands are becoming very verbose....
2017-10-26 14:04:58 +02:00
Zdenek Kabelac
04186616be Makefile: help shows hint about LVM_LOG_FILE_MAX_LINES 2017-10-26 14:04:58 +02:00
Zdenek Kabelac
837bfab75c log: better message when reached log limit
Add explaining message, when command was aborted due to the reach
of configure line number count (LVM_LOG_FILE_MAX_LINES)
for logging (used mainly with testing).
2017-10-26 14:04:58 +02:00
Zdenek Kabelac
1758614f96 WHATS_NEW: missed
Last patch missed to mention, we've improved/fixed generated paths
in units and init.d shell scripts when lvm2 was plainly configured
with just i.e. --prefix.

Note: some distros might have fully specified --sbindir and
--usrsbindir - thus those very not seeing problems in generated paths.
2017-10-26 14:04:58 +02:00
Zdenek Kabelac
44c4fe8e61 commands: drop secondary for lvconvert --type snapshot
Both form were marked and secondary thus none of the supported
syntax entered manpage.

This restores appearance of snapshot conversion in man page.
2017-10-25 22:02:54 +02:00
Zdenek Kabelac
35df4b10eb shellcheck: some apostrophe changes and cleanups 2017-10-25 22:02:54 +02:00
Zdenek Kabelac
34618c2d30 scripts: paths update
Correct usage of sbindir also for scripts so the path
no longer needs resolving more vars like exec_prefix & prefix.
2017-10-25 22:02:54 +02:00
Zdenek Kabelac
d809fbb541 systemd: use proper sbindir path
Replace lowercase  @sbindir@  with  @SBINDIR@ which contains
fully decoded path.

Same with  @usrsbindir@ which is also used with clvmd and cmirrord.

Also handle SYSCONFDIR for EnvironmentFile.

Patch fixes generated unit files with strings like:
ExecStart=${exec_prefix}/sbin/lvm
2017-10-25 22:02:54 +02:00
Zdenek Kabelac
3f59969c3f configure: improve support for sbindir path
Introduce few more AC_SUBST vars for usage in *.in generation.

In some case we want to replace i.e. $sbindir with full path
instead of current ${exec_prefix}/sbin.

This patch provides:

USRSBINDIR
SBINDIR
DEFAULT_SYS_LOCK_DIR
SYSCONFDIR

At the same time properly use sbindir & usrsbindir with
lvm, fsadm, clvmd from one primary definition.
2017-10-25 22:02:54 +02:00
Zdenek Kabelac
f32ef63b6c tests: snapshot conversions
Add missing tests for snapshost conversions.
2017-10-25 22:02:24 +02:00
Zdenek Kabelac
0a0cc696ca typo: fix invalid 2017-10-25 22:02:24 +02:00
Zdenek Kabelac
0e7edd1d24 snapshot: improve validation
Do not allow to take snapshot of mirror/raid leg or log or metadata LV.
This was actually never supported, but user was able to create it,
and this put device stack in hardly fixable state (needs manual work).

This prevents such creation to pass.

Also improve validation when recreating snapshot volume type
from origin and COW volume.
2017-10-25 21:58:01 +02:00
Jonathan Brassow
38f7fbac64 clean-up: Correct the comment to match the particular test case 2017-10-24 14:06:44 -05:00
Zdenek Kabelac
10c76ce35a tests:check lvconvert with /dev in vglvname 2017-10-24 16:16:08 +02:00
Zdenek Kabelac
ea63a38f5a lvconvert: fixing extraction of vgname
Correction to function for extracting vgname out of lvconvert
parameters.

Avoid repeating some checks.

Add code to handle generic options which may provide vgname in its argument
and compare them all so they match to a single vgname (otherwise it's a
error).

Extract default (envvar) vgname only when no position nor optional vgname is
found.

Fixing regression instroduce with patchset started with commit:
1e2420bca8   (2.02.169)
2017-10-24 16:16:08 +02:00
Ondrej Kozina
dcc8f90c58 fsadm: refactor resize_crypt function
split resize_crypt function in two.

a) Detect proper dm-crypt device type and count new --size
   value for cryptsetup resize command.

b) Perform the resize
2017-10-24 13:41:16 +02:00
Ondrej Kozina
9916d8fa9a fsadm: rename local variables to avoid confusion 2017-10-24 13:41:09 +02:00
Ondrej Kozina
213cea3aaa test: add regression test for fsadm bug
the bug in LUKS grow/shrink decision in fsadm was
masked due to fact that default LVM2 extent size
was larger than LUKS1 default data offset for dm-crypt
mapping. The new test address this bug.
2017-10-24 13:41:00 +02:00
Ondrej Kozina
af781897fa fsadm: fix bug in LUKS grow/shrink decision branch 2017-10-24 13:40:54 +02:00
Ondrej Kozina
6df7917581 fsadm: add luks specific error message for small devices 2017-10-24 13:40:50 +02:00
Zdenek Kabelac
888dd33148 tests: check stacked cache dataLV of thin-pool 2017-10-23 12:01:16 +02:00
Zdenek Kabelac
df3ff32fc0 lvcreate: skip checking for name restriction for caching
lvcreate supports a 'conversion' when caching LV.
This normally worked fine, however in case passed LV was
thin-pool's data LV with suffix _tdata we have failed to early.

As the easiest fix looks dropping validation of name when
caching type is select - such name check will happen later
once the VG is opened again and properly detect if the LV
with protected name already exists and can be converted,
or will be rejected as ambigiuous operation requiring user
to specify  --type cache | --type cache-pool.
2017-10-23 12:01:15 +02:00
Zdenek Kabelac
d6fcab900b lvextend: detect stacked cache lv used for thinpool
Ensure, that cacheLV is not tried to be resize until full support is
added.
2017-10-23 12:00:43 +02:00
Zdenek Kabelac
de58df390b lvconvert: preserve names of converted LV
When prompting and warning for conversion, remember initial LV names,
so after conversion is finished, correct original names are printed.
2017-10-23 11:58:27 +02:00
Heinz Mauelshagen
d6f4563103 test: remove 'should's from test to test target status race fix 2017-10-19 17:41:44 +02:00
Alasdair G Kergon
f3ae99dcc0 liblvm: Move lib code used exclusively into metadata-liblvm.c
Also remove some redundant function definitions from metadata.h.
2017-10-18 19:29:32 +01:00
Alasdair G Kergon
f1cc5b12fd tidy: Add missing underscores to statics. 2017-10-18 15:58:13 +01:00
Zdenek Kabelac
327d9d59be libdm: fix typo in libdevmapper.pc
Fixing name for RT libraries and using RT_LIBS.
2017-10-18 00:04:06 +02:00
David Teigland
1b319f39d6 lvmlockd: check error for sanlock access to lvmlock LV
When the sanlock daemon does not have permission to access
the lvmlock LV, make the error messages more helpful.
2017-10-17 13:45:53 -05:00
Alasdair G Kergon
146745ad88 device: Separate errors for dev not found and filtered.
Replaced the confusing device error message "not found (or ignored by
filtering)" by either "not found" or "excluded by a filter".
(Later we should be able to say which filter.)

Left the the liblvm code paths alone.
2017-10-17 02:12:41 +01:00
Zdenek Kabelac
1f359f7558 tests: check external origin is monitored 2017-10-16 15:47:46 +02:00
Zdenek Kabelac
186a3da998 thin: monitor also external origin
Add missing monitoring for external origin LVs and add -real suffix
for UUID used for monitoring of external origin.
2017-10-16 15:47:46 +02:00
Marian Csontos
12aff59183 configure: autoreconf 2017-10-16 07:48:23 +02:00
David Teigland
6ac1e04b3a replicator: remove the code
It has not been used in a long time and is not
expected to be used further.
2017-10-13 16:20:42 -05:00
Marian Csontos
e14c0cabd9 Update WHATS_NEW 2017-10-13 13:11:01 +02:00
Heinz Mauelshagen
cf13a30eaa lvcreate: allow 100%FREE creation of "--type mirror" to work
Fixes the following case with 3PVs and 3 legs "mirror" LV:

# lvcreate -l100%FREE --type mirror -m2 vg3
  Insufficient free space for log allocation for logical volume .
  Unable to allocate extents for mirror log.

Related: rhbz1269533
2017-10-12 17:43:24 +02:00
Marian Csontos
ae55b1b20a test: "Disable" lvconvert-raid-reshape
...when running from ramdisk. This causes test failure, so it is kept on
eyes.
2017-10-12 10:55:02 +02:00
Ondrej Kozina
71261ae374 test: update fsadm-crypt to pass with legacy cryptsetup 2017-10-11 14:39:33 +02:00
Ondrej Kozina
f5beb58561 fsadm: implement 'check' for a fs on top of LUKS 2017-10-11 14:39:22 +02:00
Ondrej Kozina
c795a3b37f fsadm: fail 'check' explicitly on unsupported fs type 2017-10-11 14:39:15 +02:00
Ondrej Kozina
74fd0dd6c4 fsadm: respect DM_DEV_DIR variable 2017-10-11 14:39:07 +02:00
Zdenek Kabelac
e02e5b0c5b activation: fix activation lock
Activation lock has a primary purpose to serialize locking of individual
LV in case there is no other protecting mechanism for parallel
execution.

However in the case an activated LV is composed from several other LVs,
noone should be able to manipulate with those LVs as well.

This patch add a very 'naive' global VG activation locking in this case.
In the future we may introduce smarter function detecting minimal closed
graph components if this will appear as bottleneck

Patch checks if the  VG Write lock is held - in this case we do not
need any more locking - command has exclusive access to VG.

In case we have clustered VG and we are activating an LV which does not
need other LVs - we also do not need any more locks.

In all other cases take respective lock - for single LV - use lvid,
for complex LVs  use vgname.
2017-10-11 14:24:28 +02:00
Zdenek Kabelac
9bd7615fef activation: fix locking resource name for activation lock
Avoid cutting away 1st. character for activation lock.
Unlike with VG name locks like #orphan we should not cut-off 1st.
characted from resource name.
2017-10-11 14:24:28 +02:00
Ondrej Kozina
e61313843f test: fsadm-crypt.sh fixes
use conservative 'luksOpen' command instead
fix reiserfs tests on plain crypt devices
2017-10-10 15:47:04 +02:00
Ondrej Kozina
59145715f1 fsadm: minor fixes for crypt support
drop useless asterisk expansion
enforce matching string prefix by adding ^
2017-10-10 15:21:35 +02:00
Ondrej Kozina
27ef503b35 test: add fsadm crypt test 2017-10-10 14:19:07 +02:00
Ondrej Kozina
30293baaa0 fsadm: add support for crypt devices 2017-10-10 14:18:57 +02:00
Alasdair G Kergon
22789563de thin: Improve overprovisioning and repair warnings. 2017-10-09 19:48:00 +01:00
Heinz Mauelshagen
3a639d8144 raid: cleanup raid4/5/6/10 validation check 2017-10-09 16:13:45 +02:00
Heinz Mauelshagen
44275c763c raid: fix validation check for raid0 segment data_offset member
Commit 2f754b73ff missed one.
2017-10-09 16:03:35 +02:00
Heinz Mauelshagen
5f13e33d54 lvcreate: fix region size on striped RaidLVs
Creating striped RaidLVs with lv size not divisible by region size
caused the region size to be adjusted:

# lvcreate   --type raid5 -n region_check.32.00m_3 -i 3 -L 1g --nosync -R 32.00m raid_sanity
  Using default stripesize 64.00 KiB.
  Rounding size 1.00 GiB (256 extents) up to stripe boundary size <1.01 GiB(258 extents).
  WARNING: New raid5 won't be synchronised. Don't read what you didn't write!
  Using reduced mirror region size of 8.00 MiB
  Logical volume region_check.32.00m_3 created.

Fix by not imposing "mirror" constraints on "raid".

Resolves: rhbz1404007
2017-10-09 14:35:06 +02:00
Heinz Mauelshagen
2f754b73ff raid: fix validation checks for segment data_offset member
Commit 222e1e3ace was not
valuing special case of data_ofset member equal to 1.
2017-10-09 14:01:23 +02:00
Heinz Mauelshagen
554a761db2 raid: return previous reshape space allocation properly
Fix returning previous allocation of reshape space.
2017-10-09 13:55:01 +02:00
Alasdair G Kergon
f005a6e792 man: regenerate 2017-10-06 23:10:02 +01:00
Alasdair G Kergon
a994fc5e50 post-release 2017-10-06 22:16:58 +01:00
Alasdair G Kergon
73b72b8331 pre-release 2017-10-06 22:10:48 +01:00
Alasdair G Kergon
486ed10848 vgmerge: Fix intermediate metadata corruption
vgmerge suffers from a similar problem to the one fixed in commit
8146548d25 ("vgsplit: Fix intermediate
metadata corruption.")

When merging, splitting or renaming VGs, use a new PV status flag
PV_MOVED_VG to mark the PVs that hold metadata with the old VG name and
use this to provide PV-level granularity instead of incorrectly assuming
all PVs in the VG are the same.
2017-10-06 02:20:45 +01:00
Thomas Lamprecht
a781b1c178 dmeventd: ensure systemd service gets stopped on shutdown
Add these for dmeventd systemd unit (dm-event.service):

  Before: shutdown.target
  Conflicts: shutdown.target

This will cause the dmeventd to be properly stopped at shutdown (after
all the dmeventd clients unregistered their devices from monitoring)
with dm-event.service's stop action (there's no direct action defined
for the "stop" so systemd sends SIGTERM instead).

Before, we let dmeventd to get killed only as part of the very last
SIGTERM/SIGKILL for all the remaining processes late in the shutdown
sequence so we may have missed some logs if dmeventd encountered an
error during its shutdown (logging facilities are already off at this
late time in shutdown sequence).

Ref: https://www.redhat.com/archives/lvm-devel/2017-October/msg00000.html
2017-10-05 13:01:55 +02:00
Zdenek Kabelac
3ae8adce92 fsadm: add --help
Newer version of blockdev tool needs --help as the tool is no longer
printing help without this option like it used to in past.
2017-10-05 10:23:20 +02:00
Zdenek Kabelac
9940c2f754 dmeventd: schedule exit on break
When dmeventd receives SIGTERM/INT/HUP/QUIT it validates if exit is possible.
If there was any device still monitored, such exit request used to
be ignored/refused. This 'usually' worked reasonably well, however if there
is very short time period between last device is unmonitored and signal
reception - there was possibility such EXIT was ignored, as dmeventd has
not yet got into idle state even commands like 'vgchange -an' has already
finished.

This patch changes logic towards scheduling EXIT to the nearest
point when there is no monitored device.

EXIT is never forgotten.

NOTE: if there is only a single monitored device and someone sends
SIGTERM and later someone uses i.e. 'lvchange --refresh' after
unmonitoring dmeventd will exit and new instance needs to be
started.
2017-10-05 10:19:21 +02:00
Heinz Mauelshagen
a95f656d0d raid: enhance conversion rejection message
Related: rhbz1439399
2017-10-04 17:05:59 +02:00
Tony Asleson
32c87d56b1 lvmdbusd: thread stacks dump support
If you send a SIGUSR1 (10) to the daemon it will dump all the
threads current stacks to stdout.  This will be useful when the
daemon is apparently hung and not processing requests.

eg.
$ sudo kill -10 <daemon pid>
2017-09-27 07:45:00 -05:00
Tony Asleson
60e3dbd6d5 lvmdbusd: Give threads names
This will allow easier debug.
2017-09-27 07:45:00 -05:00
Tony Asleson
2074094e77 lvmdbusd: Main thread exception logging
Make sure that any and all code that executes in the main thread is
wrapped with a try/except block to ensure that at the very least
we log when things are going wrong.
2017-09-27 07:45:00 -05:00
Marian Csontos
090db98828 pvmove: Change error message
Change error message to match previously used one used by tests.
2017-09-27 13:20:25 +02:00
Alasdair G Kergon
8146548d25 vgsplit: Fix intermediate metadata corruption.
Changing the VG of a PV uses the same on-disk mechanism as vgrename.
This relies on recognising both the old and new VG names.  Prior to this
patch the vgsplit code incorrectly provided the new VG name twice
instead of the old and new ones.  This lead the low-level mechanism not
to recognise the device as already belonging to a VG and so paying no
attention to the location of its existing metadata, sometimes partly
overwriting it and then later trying to read the corrupt metadata and
issuing a checksum error.
2017-09-22 18:34:34 +01:00
Peter Rajnoha
b0f4e0fcec blkdeactivate: cleanup
Use a different variable for translated name in dm/md_deactivate fn
Fix dmraidoption/dmraidoptions in man page.
2017-09-22 11:10:57 +02:00
Tony Asleson
bdccab07f9 lvmdbusd: Improve args comparison 2017-09-21 14:35:36 -05:00
Tony Asleson
7a6e438df8 lvmdbusd: Ensure vg_uuid is present
In some cases we are seeing where there are no VGs, but the data returned from
lvm shows that the PVs have the following for the VG:

"vg_name":"[unknown]", "vg_uuid":""

The code was only checking for the exitence of the VG name and we called into
the function get_object_path_by_uuid_lvm_id which requires both the VG name and
the LV name to exist (asserts this) which results in the following stack trace:

Traceback (most recent call last):
  File "/home/tasleson/lvm2/daemons/lvmdbusd/utils.py", line 563, in runner
    obj._run()
  File "/home/tasleson/lvm2/daemons/lvmdbusd/utils.py", line 584, in _run
    self.rc = self.f(*self.args)
  File "/home/tasleson/lvm2/daemons/lvmdbusd/fetch.py", line 26, in
		_main_thread_load
    cache_refresh=False)[1]
  File "/home/tasleson/lvm2/daemons/lvmdbusd/pv.py", line 48, in load_pvs
    emit_signal, cache_refresh)
  File "/home/tasleson/lvm2/daemons/lvmdbusd/loader.py", line 37, in common
    objects = retrieve(search_keys, cache_refresh=False)
  File "/home/tasleson/lvm2/daemons/lvmdbusd/pv.py", line 40, in
		pvs_state_retrieve
    p["pv_attr"], p["pv_tags"], p["vg_name"], p["vg_uuid"]))
  File "/home/tasleson/lvm2/daemons/lvmdbusd/pv.py", line 84, in __init__
    vg_uuid, vg_name, vg_obj_path_generate)
  File "/home/tasleson/lvm2/daemons/lvmdbusd/objectmanager.py", line 318,
		in get_object_path_by_uuid_lvm_id
    assert uuid
AssertionError
2017-09-21 14:35:36 -05:00
Tony Asleson
e3965d392c lvmdbusd: Fix hang in MThreadRunner
When executing in the main thread, if we encounter an exception we
will bypass the notify_all call on the condition and the calling thread
never wakes up.

@staticmethod
    def runner(obj):
        # noinspection PyProtectedMember
Exception thrown here
 ----> obj._run()
So the following code doesn't run, which causes calling thread to hang
	with obj.cond:
            obj.function_complete = True
            obj.cond.notify_all()

Additionally for some unknown reason the stderr is lost.
Best guess is it's something to do with scheduling a python function
into the GLib.idle_add.  That made finding issue quite difficult.
2017-09-21 14:35:36 -05:00
Peter Rajnoha
096fcb5a6e blkdeactivate: also try to unmount /boot on blkdeactivate -u if on top of supported device
There's nothing special about /boot other than it's used during boot.
But when blkdeactivate is called either on all devices or including a
device where the /boot is on top, we should also include this mount
point when doing unmount before deactivation of supported devices.
2017-09-21 17:15:48 +02:00
Peter Rajnoha
584b4ae38b blk-availability: use blkdeactivate -r wait in blk-availability systemd service/initscript 2017-09-21 17:10:15 +02:00
Peter Rajnoha
95087c8f96 blkdeactivate: add blkdeactivate -r wait option to wait for MD resync/recovery/reshape
The new blkdeactivate -r|mdraidoption wait causes blkdeactivate to wait
for any resync/recovery/reshape that is currently in progress before
deactivating the device.

If this option is used, blkdeactivate calls mdadm -W|--wait before
mdadm -S|--stop.
2017-09-21 17:10:15 +02:00
Peter Rajnoha
7fa0d52262 blkdeactivate: fix blkdeactivate regression with failing DM/MD devs deactivation
Revert dc50f2f4a0.

We're canonicalizing/escaping the names here and we're reusing the
variable name so the code doesn't need to use extra variables and
further assignments that may confuse us. Let's keep the code simple.

The

   local name=(...$name)

is not the same as

   local name
   name=(...$name)

(I know various code-checking tools fuss about this and recommend
the 2nd way, but let's ignore those tools' nitpicking here please.)
2017-09-21 17:10:15 +02:00
Peter Rajnoha
9f34125d5d blkdeactivate: fix --{dm,lvm,mpath}options option name recognition
There was a typo in blkdeactivate --dmoption/--lvmoption/mpathoption,
it had missing "s" at the end and it was not recognized properly, only
short names for the options (-d/-l/-m).
2017-09-21 17:08:44 +02:00
David Teigland
0ab9e4b6a7 improve error messages when command rules fail
When certain cmd def RULE's fail, the error messages can
sometimes be confusing.  This expands the error messages
to help clarify why the rule failed, especially in cases
where options are used incorrectly.
2017-09-20 11:10:35 -05:00
David Teigland
f2ee0e7aca pvmove: require LV name in a shared VG
In a shared VG, only allow pvmove with a named LV,
so that only PE's used by the LV will be moved.
The LV is then activated exclusively, ensuring that
the PE's being moved are not used from another host.

Previously, pvmove was mistakenly allowed on a full PV.
This won't work when LVs using that PV are active on
other hosts.
2017-09-20 09:56:51 -05:00
David Teigland
518a8e8cfb lvmlockd: activate mirror LVs in shared mode with cmirrord
Previously lvmlockd disallowed mirror LVs to be activated
in shared mode.
2017-09-20 09:55:34 -05:00
Zdenek Kabelac
d9f9ce1268 tests: use portable df output
For awk parsing more 'predictable' format of output line is needed.
2017-09-20 15:34:02 +02:00
Zdenek Kabelac
a15b796146 tests: repair of cachepool 2017-09-20 15:14:16 +02:00
Zdenek Kabelac
2fd2b197ab tests: check for free space in test dir
Avoid starting test, when test dir has less then 50M of free space.
Better to crash early before letting die machine on weird crash
in OOM cases...

Also show free disk space when test starts
2017-09-20 15:14:16 +02:00
Zdenek Kabelac
a02db1c45a libdm: fix parentheses in assignment + comparison
As reported, fix incorrect placement of parentheses.
TODO: add testing code.
2017-09-20 15:14:16 +02:00
Zdenek Kabelac
a65649b45d lvconvert: support repair of cache/cachepool
Extend repair for cache and cachepool target
and user 'lvconvert_repair' routine name.
2017-09-20 15:14:16 +02:00
Zdenek Kabelac
aeb4f2bf3d lvconvert: repair supports poometadatespare switch
Enable handling of  --poolmetadataspare so if user can prevent
creation of _pmspare volume during --repair operation (just
like during actual lvcreate or lvconvert) for pool volumes.
2017-09-20 15:14:16 +02:00
Marian Csontos
03bcd29481 configure: Add warning for D-Bus w/o notifications
Building D-Bus support without notifications is not recommended.
2017-09-20 13:07:06 +02:00
Marian Csontos
0c46f9cf0c configure: Update configure 2017-09-20 13:07:06 +02:00
Marian Csontos
8493df8edd liblvm: Add deprecation warning to configure 2017-09-20 13:07:06 +02:00
Marian Csontos
4cbacf6bac liblvm: Deprecate library and bindings
It is recommended to use D-Bus API instead of liblvm2app or python
bindings.
2017-09-20 13:07:06 +02:00
David Teigland
5407327bc6 toollib: fix parentheses in assignment + comparison 2017-09-19 09:19:24 -05:00
David Teigland
200793edc6 man pvscan: just write --activate in description
rather than -a|--activate, because web pages on
man7.org are not printing the | character.
2017-09-18 10:56:39 -05:00
Alasdair G Kergon
d73eddcdc0 dmsetup: Process -S to filter input device lists.
The following commands now pass the device list through a
--select|-S filter before processing:

suspend resume clear wipe_table remove deps status table
2017-09-14 23:41:17 +01:00
David Teigland
8e8755319c lvcreate: use cmd defs to deny unspported lockd cases
In a shared VG, lvconvert must be used to create thin pools
and cache pools, not the lvcreate variants of those commands.
Deny these cases early in lvcreate using the new command defs.
Denying these cases deeper in the code was missing some
cleanup of the partially completed command.
2017-09-14 12:28:48 -05:00
David Teigland
d93a2bb741 revert tidy: prefer not using else after return
Revert the lvmlockd.c changes from:
  commit 0bf836aa14
  "tidy: prefer not using else after return"

The commit introduced at least one regression, which broke
lvcreate of a thin pool in a shared VG.
2017-09-14 12:28:48 -05:00
Alasdair G Kergon
29834b6e91 kernel: Refresh dm-ioctl.h
Adds DM_DEV_ARM_POLL
2017-09-14 17:50:56 +01:00
Alasdair G Kergon
71dbe0fe26 post-release 2017-09-13 20:46:25 +01:00
Alasdair G Kergon
918f0a92da pre-release 2017-09-13 20:38:29 +01:00
Alasdair G Kergon
901c919d22 README: Include new github links
We've decided to mirror the upstream code onto github for the
convenience of people already using that platform.
2017-09-13 20:20:04 +01:00
Zdenek Kabelac
03efec2712 deamonize: restore detection of errors
Keep forked environment for daemon more strick and check even
for nearly impossible to happen errors.
2017-09-06 11:47:53 +02:00
David Teigland
3071837e21 lvmlockd: always disallow mirror splitting
lv_raid_split() was correctly prevented in a shared VG,
but lv_raid_split_and_track() was missing that check.
2017-09-05 10:28:33 -05:00
David Teigland
09c792c206 lvmlockd: fix check for no running lock manager
In some cases it was reporting there was no running
lock manager when there is.
2017-08-29 15:18:12 -05:00
David Teigland
f847fcd31a lvmlockd: print error about starting lock manager
In the case where lvmlockd is running, but no lock manager
is running, we should print a specific error message about
that situation.
2017-08-28 16:24:00 -05:00
Zdenek Kabelac
c8fdc5c087 cleanup: easier to read code
Split into lines for better reading.
2017-08-25 14:20:59 +02:00
Zdenek Kabelac
962874bfe2 dmsetup: validate strtol reading
Better validation for --mode option.
2017-08-25 14:20:59 +02:00
Zdenek Kabelac
47b7d4a733 dmsetup: add missing -- for option 2017-08-25 14:20:59 +02:00
Zdenek Kabelac
26d97f179f reporting: validate time parsing with strtol
Check for out-of-range numbers being result of strtol parsing.
2017-08-25 14:20:59 +02:00
Zdenek Kabelac
d79d919329 lvmlockd: log pthread_join errno code
Log possible errno with pthread_join (and one close() instance).
2017-08-25 14:20:59 +02:00
Zdenek Kabelac
da9a8fdedc lvmlockctl: fix check for failing close
On  close() failure it's -1.
2017-08-25 14:20:59 +02:00
Zdenek Kabelac
288e10cf8b lvmlockd: avoid double unlock of client_mutex
Avoid double unlocking of client_mutex and
and unlock client_mutex in 'else' branch
since it's already unlocked in 'if (cl->dead)' branch.
2017-08-25 14:20:59 +02:00
Zdenek Kabelac
b3b1e788e1 daemonize: more unified code
ATM we have several instances of daemonizing code.
Each has its 'special' logic so not completely easy
to unify them all into a single routine.

Start to unify them and use one strategy for rediricting
all input/outpus to /dev/null - use 'dup2' function for this
and open /dev/null before fork to make sure it's available.
2017-08-25 14:20:57 +02:00
Zdenek Kabelac
5de9444202 locking: avoid descriptor leak for nonblocking mode
When file-locking mode failed on locking, such description was leaked
(typically not an issue since command usually exists afterwards).
So shirt close() at the end of function and use it in all error paths.

Also make sure, when interrrupt is detected, it's really not holding
lock and returns 0.
2017-08-25 14:12:55 +02:00
David Teigland
043ff47b05 man lvmthin: change fsck references
to more generic terms like repair.
2017-08-24 10:25:01 -05:00
David Teigland
e71c3ff187 lvmlockd: fix mutex unlock
Remove an unwanted pthread_mutex_unlock which would
lead to a double unlock.
2017-08-23 11:30:55 -05:00
David Teigland
46ddd5520c lvmlockd: add comment about temp ls name 2017-08-23 11:25:18 -05:00
Zdenek Kabelac
539a48a328 debug: add stack trace point 2017-08-22 10:23:31 +02:00
Zdenek Kabelac
c1e3f96c97 lvmcache: check for lvmcache_foreach_mda return code
lvmcache_foreach_mda() can fail for numerous reasons
and failing error code cannot be ignored (out-of-memory...)

TODO: might need more error handling tunning.
2017-08-22 10:23:31 +02:00
Zdenek Kabelac
d4ce98de4d lvmlockd: shorter code
gcc warns here about storring 69 bytes in 64 byte array (losing
potentially 4 bytes from 'ls->name').

lvmlockd-core.c:2657:36: warning: ‘%s’ directive output may be truncated writing up to 64 bytes into a region of size 60 [-Wformat-truncation=]
  snprintf(tmp_name, MAX_NAME, "REM:%s", ls->name);
                                    ^~
lvmlockd-core.c:2657:2: note: ‘snprintf’ output between 5 and 69 bytes into a destination of size 64
  snprintf(tmp_name, MAX_NAME, "REM:%s", ls->name);
  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Replaced with slightly better code - but it still misses error path what
to do if the name would be truncated... - so added FIXME.

Also using all bytes for snprintf() buffer size
(as the size is with \0 included)
2017-08-22 10:23:31 +02:00
Zdenek Kabelac
0e42b31dc3 libdm: fix errpath for control node creation
When control node failure happens, umask was not restored.
Fix it by using common exit path.
2017-08-22 10:23:29 +02:00
698 changed files with 22925 additions and 19523 deletions

101
.gitignore vendored
View File

@@ -1,6 +1,7 @@
*.5
*.7
*.8
*.8_gen
*.a
*.d
*.o
@@ -30,3 +31,103 @@ make.tmpl
/cscope.out
/tags
/tmp/
tools/man-generator
tools/man-generator.c
test/lib/lvchange
test/lib/lvconvert
test/lib/lvcreate
test/lib/lvdisplay
test/lib/lvextend
test/lib/lvmconfig
test/lib/lvmdiskscan
test/lib/lvmsadc
test/lib/lvmsar
test/lib/lvreduce
test/lib/lvremove
test/lib/lvrename
test/lib/lvresize
test/lib/lvs
test/lib/lvscan
test/lib/pvchange
test/lib/pvck
test/lib/pvcreate
test/lib/pvdisplay
test/lib/pvmove
test/lib/pvremove
test/lib/pvresize
test/lib/pvs
test/lib/pvscan
test/lib/vgcfgbackup
test/lib/vgcfgrestore
test/lib/vgchange
test/lib/vgck
test/lib/vgconvert
test/lib/vgcreate
test/lib/vgdisplay
test/lib/vgexport
test/lib/vgextend
test/lib/vgimport
test/lib/vgimportclone
test/lib/vgmerge
test/lib/vgmknodes
test/lib/vgreduce
test/lib/vgremove
test/lib/vgrename
test/lib/vgs
test/lib/vgscan
test/lib/vgsplit
test/api/lvtest.t
test/api/pe_start.t
test/api/percent.t
test/api/python_lvm_unit.py
test/api/test
test/api/thin_percent.t
test/api/vglist.t
test/api/vgtest.t
test/lib/aux
test/lib/check
test/lib/clvmd
test/lib/dm-version-expected
test/lib/dmeventd
test/lib/dmsetup
test/lib/dmstats
test/lib/fail
test/lib/flavour-ndev-cluster
test/lib/flavour-ndev-cluster-lvmpolld
test/lib/flavour-ndev-lvmetad
test/lib/flavour-ndev-lvmetad-lvmpolld
test/lib/flavour-ndev-lvmpolld
test/lib/flavour-ndev-vanilla
test/lib/flavour-udev-cluster
test/lib/flavour-udev-cluster-lvmpolld
test/lib/flavour-udev-lvmetad
test/lib/flavour-udev-lvmetad-lvmpolld
test/lib/flavour-udev-lvmlockd-dlm
test/lib/flavour-udev-lvmlockd-sanlock
test/lib/flavour-udev-lvmlockd-test
test/lib/flavour-udev-lvmpolld
test/lib/flavour-udev-vanilla
test/lib/fsadm
test/lib/get
test/lib/inittest
test/lib/invalid
test/lib/lvm
test/lib/lvm-wrapper
test/lib/lvmchange
test/lib/lvmdbusd.profile
test/lib/lvmetad
test/lib/lvmpolld
test/lib/not
test/lib/paths
test/lib/paths-common
test/lib/runner
test/lib/should
test/lib/test
test/lib/thin-performance.profile
test/lib/utils
test/lib/version-expected
test/unit/dmraid_t.c
test/unit/unit-test

View File

@@ -1,6 +1,6 @@
#
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
# Copyright (C) 2004-2015 Red Hat, Inc. All rights reserved.
# Copyright (C) 2004-2018 Red Hat, Inc. All rights reserved.
#
# This file is part of LVM2.
#
@@ -18,7 +18,7 @@ top_builddir = @top_builddir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
SUBDIRS = conf daemons include lib libdaemon libdm man scripts tools
SUBDIRS = conf daemons include lib libdaemon libdm man scripts device_mapper tools
ifeq ("@UDEV_RULES@", "yes")
SUBDIRS += udev
@@ -43,8 +43,7 @@ endif
ifeq ($(MAKECMDGOALS),distclean)
SUBDIRS = conf include man test scripts \
libdaemon lib tools daemons libdm \
udev po liblvm python \
unit-tests/datastruct unit-tests/mm unit-tests/regex
udev po liblvm python device_mapper
tools.distclean: test.distclean
endif
DISTCLEAN_DIRS += lcov_reports*
@@ -62,6 +61,9 @@ po: tools daemons
man: tools
all_man: tools
scripts: liblvm libdm
test: tools daemons
unit-test: lib
run-unit-test: unit-test
lib.device-mapper: include.device-mapper
libdm.device-mapper: include.device-mapper
@@ -97,7 +99,7 @@ endif
DISTCLEAN_TARGETS += cscope.out
CLEAN_DIRS += autom4te.cache
check check_system check_cluster check_local check_lvmetad check_lvmpolld check_lvmlockd_test check_lvmlockd_dlm check_lvmlockd_sanlock unit: all
check check_system check_cluster check_local check_lvmetad check_lvmpolld check_lvmlockd_test check_lvmlockd_dlm check_lvmlockd_sanlock unit-test run-unit-test: test
$(MAKE) -C test $(@)
conf.generate man.generate: tools
@@ -146,7 +148,7 @@ install_system_dirs:
$(INSTALL_ROOT_DIR) $(DESTDIR)$(DEFAULT_RUN_DIR)
$(INSTALL_ROOT_DATA) /dev/null $(DESTDIR)$(DEFAULT_CACHE_DIR)/.cache
install_initscripts:
install_initscripts:
$(MAKE) -C scripts install_initscripts
install_systemd_generators:
@@ -169,6 +171,7 @@ install_tmpfiles_configuration:
LCOV_TRACES = libdm.info lib.info liblvm.info tools.info \
libdaemon/client.info libdaemon/server.info \
test/unit.info \
daemons/clvmd.info \
daemons/dmeventd.info \
daemons/lvmetad.info \
@@ -211,31 +214,6 @@ endif
endif
ifeq ("$(TESTING)", "yes")
# testing and report generation
RUBY=ruby1.9 -Ireport-generators/lib -Ireport-generators/test
.PHONY: unit-test ruby-test test-programs
# FIXME: put dependencies on libdm and liblvm
# FIXME: Should be handled by Makefiles in subdirs, not here at top level.
test-programs:
cd unit-tests/regex && $(MAKE)
cd unit-tests/datastruct && $(MAKE)
cd unit-tests/mm && $(MAKE)
unit-test: test-programs
$(RUBY) report-generators/unit_test.rb $(shell find . -name TESTS)
$(RUBY) report-generators/title_page.rb
memcheck: test-programs
$(RUBY) report-generators/memcheck.rb $(shell find . -name TESTS)
$(RUBY) report-generators/title_page.rb
ruby-test:
$(RUBY) report-generators/test/ts.rb
endif
ifneq ($(shell which ctags),)
.PHONY: tags
tags:

13
README
View File

@@ -8,10 +8,15 @@ There is no warranty - see COPYING and COPYING.LIB.
Tarballs are available from:
ftp://sourceware.org/pub/lvm2/
ftp://sources.redhat.com/pub/lvm2/
https://github.com/lvmteam/lvm2/releases
The source code is stored in git:
https://sourceware.org/git/?p=lvm2.git
git clone git://sourceware.org/git/lvm2.git
mirrored to:
https://github.com/lvmteam/lvm2
git clone https://github.com/lvmteam/lvm2.git
git clone git@github.com:lvmteam/lvm2.git
Mailing list for general discussion related to LVM2:
linux-lvm@redhat.com
@@ -29,6 +34,14 @@ and multipath-tools:
dm-devel@redhat.com
Subscribe from https://www.redhat.com/mailman/listinfo/dm-devel
Website:
https://sourceware.org/lvm2/
Report upstream bugs at:
https://bugzilla.redhat.com/enter_bug.cgi?product=LVM%20and%20device-mapper
or open issues at:
https://github.com/lvmteam/lvm2/issues
The source code repository used until 7th June 2012 is accessible here:
http://sources.redhat.com/cgi-bin/cvsweb.cgi/LVM2/?cvsroot=lvm2.

62
TESTING Normal file
View File

@@ -0,0 +1,62 @@
LVM2 Test Suite
===============
The codebase contains many tests in the test subdirectory.
Before running tests
--------------------
Keep in mind the testsuite MUST run under root user.
It is recommended not to use LVM on the test machine, especially when running
tests with udev (`make check_system`.)
You MUST disable (or mask) any LVM daemons:
- lvmetad
- dmeventd
- lvmpolld
- lvmdbusd
- lvmlockd
- clvmd
- cmirrord
For running cluster tests, we are using singlenode locking. Pass
`--with-clvmd=singlenode` to configure.
NOTE: This is useful only for testing, and should not be used in produciton
code.
To run D-Bus daemon tests, existing D-Bus session is required.
Running tests
-------------
As root run:
make check
To run only tests matching a string:
make check T=test
To skip tests matching a string:
make check S=test
There are other targets and many environment variables can be used to tweak the
testsuite - for full list and description run `make -C test help`.
Installing testsuite
--------------------
It is possible to install and run a testsuite against installed LVM. Run the
following:
make -C test install
Then lvm2-testsuite binary can be executed to test installed binaries.
See `lvm2-testsuite --help` for options. The same environment variables can be
used as with `make check`.

View File

@@ -1 +1 @@
2.02.174(2)-git (2017-07-20)
2.02.180(2) (2018-07-19)

View File

@@ -1 +1 @@
1.02.143-git (2017-07-20)
1.02.149 (2018-07-19)

193
WHATS_NEW
View File

@@ -1,5 +1,196 @@
Version 2.02.174 -
Version 2.02.180 - 19th July 2018
=================================
Never send any discard ioctl with test mode.
Fix thin-pool alloc which needs same PV for data and metadata.
Extend list of non-memlocked areas with newly linked libs.
Enhance vgcfgrestore to check for active LVs in restored VG.
lvconvert: provide possible layouts between linear and striped/raid
Fix unmonitoring of merging snapshots.
Add missing -l description in fsadm man page.
Cache can uses metadata format 2 with cleaner policy.
Avoid showing internal error in lvs output or pvmoved LVs.
Fix check if resized PV can also fit metadata area.
Reopen devices RDWR only before writing to avoid udev issues.
Change pvresize output confusing when no resize took place.
Fix lvmetad hanging on shutdown.
Fix mem leak in clvmd and more coverity issues.
Version 2.02.179 - 18th June 2018
=================================
Allow forced vgchange to lock type none on clustered VG.
Add the report field "shared".
Enable automatic metadata consistency repair on a shared VG.
Fix pvremove force on a PV with a shared VG.
Fixed vgimportclone of a PV with a shared VG.
Enable previously disallowed thin/cache commands in shared VGs.
Enable metadata-related changes on LVs active with shared lock.
Do not continue trying to use a device that cannot be opened.
Fix problems opening a device that fails and returns.
Use versionsort to fix archive file expiry beyond 100000 files.
Version 2.02.178 - 13th June 2018
=================================
Version 2.02.178-rc1 - 24th May 2018
====================================
Add libaio dependency for build.
Remove lvm1 and pool format handling and add filter to ignore them.
Move some filter checks to after disks are read.
Rework disk scanning and when it is used.
Add new io layer and shift code to using it.
Fix lvconvert's return code on degraded -m raid1 conversion.
--enable-testing switch for ./configure has been removed.
--with-snapshots switch for ./configure has been removed.
--with-mirrors switch for ./configure has been removed.
--with-raid switch for ./configure has been removed.
--with-thin switch for ./configure has been removed.
--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.
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.
Enhance mirror log size estimation and use smaller size when possible.
Fix incorrect mirror log size calculation on 32bit arch.
Enhance preloading tree creating.
Fix regression on acceptance of any LV on lvconvert.
Restore usability of thin LV to be again external origin for another thin.
Keep systemd vars on change event in 69-dm-lvm-metad.rules for systemd reload.
Write systemd and non-systemd rule in 69-dm-lvm-metad.rules, GOTO active one.
Add test for activation/volume_list (Sub)LV remnants.
Disallow usage of cache format 2 with mq cache policy.
Again accept striped LV as COW LV with lvconvert -s (2.02.169).
Fix raid target version testing for supported features.
Allow activation of pools when thin/cache_check tool is missing.
Remove RaidLV on creation failure when rmeta devices can't be activated.
Add prioritized_section() to restore cookie boundaries (2.02.177).
Enhance error messages when read error happens.
Enhance mirror log initialization for old mirror target.
Skip private crypto and stratis devices.
Skip frozen raid devices from scanning.
Activate RAID SubLVs on read_only_volume_list readwrite.
Offer convenience type raid5_n converting to raid10.
Automatically avoid reading invalid snapshots during device scan.
Ensure COW device is writable even for read-only thick snapshots.
Support activation of component LVs in read-only mode.
Extend internal library to recognize and work with component LV.
Skip duplicate check for active LV when prompting for its removal.
Activate correct lock holding LV when it is cached.
Do not modify archived metadata when removing striped raid.
Fix memleak on error path when obtaining lv_raid_data_offset.
Fix compatibility size test of extended external origin.
Add external_origin visiting in for_each_sub_lv().
Ensure cluster commands drop their device cache before locking VG.
Do not report LV as remotely active when it's locally exclusive in cluster.
Add deprecate messages for usage of mirrors with mirrorlog.
Separate reporting of monitoring status and error status.
Improve validation of created strings in vgimportclone.
Add missing initialisation of mem pool in systemd generator.
Do not reopen output streams for multithreaded users of liblvm.
Configure ensures /usr/bin dir is checked for dmpd tools.
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.
Avoid exceeding array bounds in allocation tag processing.
Add --lockopt to common options and add option to skip selected locks.
Version 2.02.177 - 18th December 2017
=====================================
When writing text metadata content, use complete 4096 byte blocks.
Change text format metadata alignment from 512 to 4096 bytes.
When writing metadata, consistently skip mdas marked as failed.
Refactor and adjust text format metadata alignment calculation.
Fix python3 path in lvmdbusd to use value detected by configure.
Reduce checks for active LVs in vgchange before background polling.
Ensure _node_send_message always uses clean status of thin pool.
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.
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.
Command will lock memory only when suspending volumes.
Merge segments when pvmove is finished.
Remove label_verify that has never been used.
Ensure very large numbers used as arguments are not casted to lower values.
Enhance reading and validation of options stripes and stripes_size.
Fix printing of default stripe size when user is not using stripes.
Activation code for pvmove automatically discovers holding LVs for resume.
Make a pvmove LV locking holder.
Do not change critical section counter on resume path without real resume.
Enhance activation code to automatically suspend pvmove participants.
Prevent conversion of thin volumes to snapshot origin when lvmlockd is used.
Correct the steps to change lock type in lvmlockd man page.
Retry lock acquisition on recognized sanlock errors.
Fix lock manager error codes in lvmlockd.
Remove unnecessary single read from lvmdiskscan.
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.
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.
Avoid importing persistent filter in vgscan/pvscan/vgrename.
Fix memleak of string buffer when vgcfgbackup runs in secure mode.
Do not print error when clvmd cannot find running clvmd.
Prevent start of new merge of snapshot if origin is already being merged.
Fix offered type for raid6_n_6 to raid5 conversion (raid5_n).
Deactivate sub LVs when removing unused cache-pool.
Do not take backup with suspended devices.
Avoid RAID4 activation on incompatible kernels under all circumstances.
Reject conversion request to striped/raid0 on 2-legged raid4/5.
Version 2.02.176 - 3rd November 2017
====================================
Keep Install section only in lvm2-{lvmetad,lvmpolld}.socket systemd unit.
Fix segfault in lvm_pv_remove in liblvm. (2.02.173)
Do not allow storing VG metadata with LV without any segment.
Fix printed message when thin snapshot was already merged.
Remove created spare LV when creation of thin-pool failed.
Avoid reading ignored metadata when mda gets used again.
Fix detection of moved PVs in vgsplit. (2.02.175)
Ignore --stripes/--stripesize on RAID takeover
Improve used paths for generated systemd units and init shells.
Disallow creation of snapshot of mirror/raid subLV (was never supported).
Fix regression in more advanced vgname extraction in lvconvert (2.02.169).
Allow lvcreate to be used for caching of _tdata LV.
Avoid internal error when resizing cache type _tdata LV (not yet supported).
Show original converted names when lvconverting LV to pool volume.
Move lib code used only by liblvm into metadata-liblvm.c.
Distinguish between device not found and excluded by filter.
Monitor external origin LVs.
Remove the replicator code, including configure --with-replicators.
Allow lvcreate --type mirror to work with 100%FREE.
Improve selection of resource name for complex volume activation lock.
Avoid cutting first character of resource name for activation lock.
Support for encrypted devices in fsadm.
Improve thin pool overprovisioning and repair warning messages.
Fix incorrect adjustment of region size on striped RaidLVs.
Version 2.02.175 - 6th October 2017
===================================
Use --help with blockdev when checking for --getsize64 support in fsadm.
Dump lvmdbusd debug information with SIGUSR1.
Fix metadata corruption in vgsplit and vgmerge intermediate states.
Add PV_MOVED_VG PV status flag to mark PVs moving between VGs.
Fix lvmdbus hang and recognise unknown VG correctly.
Improve error messages when command rules fail.
Require LV name with pvmove in a shared VG.
Allow shared active mirror LVs with lvmlockd, dlm, and cmirrord.
Support lvconvert --repair with cache and cachepool volumes.
lvconvert --repair respects --poolmetadataspare option.
Mark that we don't plan to develop liblvm2app and python bindings any further.
Fix thin pool creation in shared VG. (2.02.173)
Version 2.02.174 - 13th September 2017
======================================
Prevent raid1 split with trackchanges in a shared VG.
Avoid double unlocking of client & lockspace mutexes in lvmlockd.
Fix leaking of file descriptor for non-blocking filebased locking.
Fix check for 2nd mda at end of disk fits if using pvcreate --restorefile.
Use maximum metadataarea size that fits with pvcreate --restorefile.
Always clear cached bootloaderarea when wiping label e.g. in pvcreate.

View File

@@ -1,5 +1,52 @@
Version 1.02.143 -
Version 1.02.149 - 19th July 2018
=================================
Version 1.02.148 - 18th June 2018
=================================
Version 1.02.147 - 13th June 2018
=================================
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.
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.
Parsing mirror status accepts 'userspace' keyword in status.
Introduce dm_malloc_aligned for page alignment of buffers.
Version 1.02.146 - 18th December 2017
=====================================
Activation tree of thin pool skips duplicated check of pool status.
Remove code supporting replicator target.
Do not ignore failure of _info_by_dev().
Propagate delayed resume for pvmove subvolumes.
Suppress integrity encryption keys in 'table' output unless --showkeys supplied.
Version 1.02.145 - 3rd November 2017
====================================
Keep Install section only in dm-event.socket systemd unit.
Issue a specific error with dmsetup status if device is unknown.
Fix RT_LIBS reference in generated libdevmapper.pc for pkg-config
Version 1.02.144 - 6th October 2017
===================================
Schedule exit when received SIGTERM in dmeventd.
Also try to unmount /boot on blkdeactivate -u if on top of supported device.
Use blkdeactivate -r wait in blk-availability systemd service/initscript.
Add blkdeactivate -r wait option to wait for MD resync/recovery/reshape.
Fix blkdeactivate regression with failing DM/MD devs deactivation (1.02.142).
Fix typo in blkdeactivate's '--{dm,lvm,mpath}options' option name.
Correct return value testing when get reserved values for reporting.
Take -S with dmsetup suspend/resume/clear/wipe_table/remove/deps/status/table.
Version 1.02.143 - 13th September 2017
======================================
Restore umask when creation of node fails.
Add --concise to dmsetup create for many devices with tables in one command.
Accept minor number without major in library when it knows dm major number.
Introduce single-line concise table output format: dmsetup table --concise

View File

@@ -155,7 +155,7 @@ AC_DEFUN([AC_TRY_LDFLAGS],
# and this notice are preserved. This file is offered as-is, without any
# warranty.
#serial 3
serial 3
AC_DEFUN([AX_GCC_BUILTIN], [
AS_VAR_PUSHDEF([ac_var], [ax_cv_have_$1])

210
aclocal.m4 vendored
View File

@@ -69,32 +69,63 @@ AC_DEFUN([AX_PYTHON_MODULE],[
fi
])
# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
# serial 1 (pkg-config-0.24)
#
# Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
dnl pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
dnl serial 11 (pkg-config-0.29)
dnl
dnl Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
dnl Copyright © 2012-2015 Dan Nicholson <dbn.lists@gmail.com>
dnl
dnl This program is free software; you can redistribute it and/or modify
dnl it under the terms of the GNU General Public License as published by
dnl the Free Software Foundation; either version 2 of the License, or
dnl (at your option) any later version.
dnl
dnl This program is distributed in the hope that it will be useful, but
dnl WITHOUT ANY WARRANTY; without even the implied warranty of
dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
dnl General Public License for more details.
dnl
dnl You should have received a copy of the GNU General Public License
dnl along with this program; if not, write to the Free Software
dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
dnl 02111-1307, USA.
dnl
dnl As a special exception to the GNU General Public License, if you
dnl distribute this file as part of a program that contains a
dnl configuration script generated by Autoconf, you may include it under
dnl the same distribution terms that you use for the rest of that
dnl program.
# PKG_PROG_PKG_CONFIG([MIN-VERSION])
# ----------------------------------
dnl PKG_PREREQ(MIN-VERSION)
dnl -----------------------
dnl Since: 0.29
dnl
dnl Verify that the version of the pkg-config macros are at least
dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's
dnl installed version of pkg-config, this checks the developer's version
dnl of pkg.m4 when generating configure.
dnl
dnl To ensure that this macro is defined, also add:
dnl m4_ifndef([PKG_PREREQ],
dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])])
dnl
dnl See the "Since" comment for each macro you use to see what version
dnl of the macros you require.
m4_defun([PKG_PREREQ],
[m4_define([PKG_MACROS_VERSION], [0.29])
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 Since: 0.16
dnl
dnl Search for the pkg-config tool and set the PKG_CONFIG variable to
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.
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)))?$])
@@ -116,18 +147,19 @@ if test -n "$PKG_CONFIG"; then
PKG_CONFIG=""
fi
fi[]dnl
])# PKG_PROG_PKG_CONFIG
])dnl PKG_PROG_PKG_CONFIG
# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
#
# Check to see whether a particular set of modules exists. Similar
# to PKG_CHECK_MODULES(), but does not set variables or print errors.
#
# Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG])
# only at the first occurence in configure.ac, so if the first place
# it's called might be skipped (such as if it is within an "if", you
# have to call PKG_CHECK_EXISTS manually
# --------------------------------------------------------------
dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
dnl -------------------------------------------------------------------
dnl Since: 0.18
dnl
dnl Check to see whether a particular set of modules exists. Similar to
dnl PKG_CHECK_MODULES(), but does not set variables or print errors.
dnl
dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG])
dnl only at the first occurence in configure.ac, so if the first place
dnl it's called might be skipped (such as if it is within an "if", you
dnl have to call PKG_CHECK_EXISTS manually
AC_DEFUN([PKG_CHECK_EXISTS],
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
if test -n "$PKG_CONFIG" && \
@@ -137,8 +169,10 @@ m4_ifvaln([$3], [else
$3])dnl
fi])
# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
# ---------------------------------------------
dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
dnl ---------------------------------------------
dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting
dnl pkg_failed based on the result.
m4_define([_PKG_CONFIG],
[if test -n "$$1"; then
pkg_cv_[]$1="$$1"
@@ -150,10 +184,11 @@ m4_define([_PKG_CONFIG],
else
pkg_failed=untried
fi[]dnl
])# _PKG_CONFIG
])dnl _PKG_CONFIG
# _PKG_SHORT_ERRORS_SUPPORTED
# -----------------------------
dnl _PKG_SHORT_ERRORS_SUPPORTED
dnl ---------------------------
dnl Internal check to see if pkg-config supports short errors.
AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
@@ -161,19 +196,17 @@ if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
else
_pkg_short_errors_supported=no
fi[]dnl
])# _PKG_SHORT_ERRORS_SUPPORTED
])dnl _PKG_SHORT_ERRORS_SUPPORTED
# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
# [ACTION-IF-NOT-FOUND])
#
#
# Note that if there is a possibility the first call to
# PKG_CHECK_MODULES might not happen, you should be sure to include an
# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
#
#
# --------------------------------------------------------------
dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
dnl [ACTION-IF-NOT-FOUND])
dnl --------------------------------------------------------------
dnl Since: 0.4.0
dnl
dnl Note that if there is a possibility the first call to
dnl PKG_CHECK_MODULES might not happen, you should be sure to include an
dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
AC_DEFUN([PKG_CHECK_MODULES],
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
@@ -227,16 +260,40 @@ else
AC_MSG_RESULT([yes])
$3
fi[]dnl
])# PKG_CHECK_MODULES
])dnl PKG_CHECK_MODULES
# PKG_INSTALLDIR(DIRECTORY)
# -------------------------
# Substitutes the variable pkgconfigdir as the location where a module
# should install pkg-config .pc files. By default the directory is
# $libdir/pkgconfig, but the default can be changed by passing
# DIRECTORY. The user can override through the --with-pkgconfigdir
# parameter.
dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
dnl [ACTION-IF-NOT-FOUND])
dnl ---------------------------------------------------------------------
dnl Since: 0.29
dnl
dnl Checks for existence of MODULES and gathers its build flags with
dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags
dnl and VARIABLE-PREFIX_LIBS from --libs.
dnl
dnl Note that if there is a possibility the first call to
dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to
dnl include an explicit call to PKG_PROG_PKG_CONFIG in your
dnl configure.ac.
AC_DEFUN([PKG_CHECK_MODULES_STATIC],
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
_save_PKG_CONFIG=$PKG_CONFIG
PKG_CONFIG="$PKG_CONFIG --static"
PKG_CHECK_MODULES($@)
PKG_CONFIG=$_save_PKG_CONFIG[]dnl
])dnl PKG_CHECK_MODULES_STATIC
dnl PKG_INSTALLDIR([DIRECTORY])
dnl -------------------------
dnl Since: 0.27
dnl
dnl Substitutes the variable pkgconfigdir as the location where a module
dnl should install pkg-config .pc files. By default the directory is
dnl $libdir/pkgconfig, but the default can be changed by passing
dnl DIRECTORY. The user can override through the --with-pkgconfigdir
dnl parameter.
AC_DEFUN([PKG_INSTALLDIR],
[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])])
m4_pushdef([pkg_description],
@@ -247,16 +304,18 @@ AC_ARG_WITH([pkgconfigdir],
AC_SUBST([pkgconfigdir], [$with_pkgconfigdir])
m4_popdef([pkg_default])
m4_popdef([pkg_description])
]) dnl PKG_INSTALLDIR
])dnl PKG_INSTALLDIR
# PKG_NOARCH_INSTALLDIR(DIRECTORY)
# -------------------------
# Substitutes the variable noarch_pkgconfigdir as the location where a
# module should install arch-independent pkg-config .pc files. By
# default the directory is $datadir/pkgconfig, but the default can be
# changed by passing DIRECTORY. The user can override through the
# --with-noarch-pkgconfigdir parameter.
dnl PKG_NOARCH_INSTALLDIR([DIRECTORY])
dnl --------------------------------
dnl Since: 0.27
dnl
dnl Substitutes the variable noarch_pkgconfigdir as the location where a
dnl module should install arch-independent pkg-config .pc files. By
dnl default the directory is $datadir/pkgconfig, but the default can be
dnl changed by passing DIRECTORY. The user can override through the
dnl --with-noarch-pkgconfigdir parameter.
AC_DEFUN([PKG_NOARCH_INSTALLDIR],
[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])])
m4_pushdef([pkg_description],
@@ -267,13 +326,15 @@ AC_ARG_WITH([noarch-pkgconfigdir],
AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir])
m4_popdef([pkg_default])
m4_popdef([pkg_description])
]) dnl PKG_NOARCH_INSTALLDIR
])dnl PKG_NOARCH_INSTALLDIR
# PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE,
# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
# -------------------------------------------
# Retrieves the value of the pkg-config variable for the given module.
dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE,
dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
dnl -------------------------------------------
dnl Since: 0.28
dnl
dnl Retrieves the value of the pkg-config variable for the given module.
AC_DEFUN([PKG_CHECK_VAR],
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl
@@ -282,7 +343,7 @@ _PKG_CONFIG([$1], [variable="][$3]["], [$2])
AS_VAR_COPY([$1], [pkg_cv_][$1])
AS_VAR_IF([$1], [""], [$5], [$4])dnl
])# PKG_CHECK_VAR
])dnl PKG_CHECK_VAR
# Copyright (C) 1999-2014 Free Software Foundation, Inc.
#
@@ -536,5 +597,4 @@ AC_DEFUN([AM_RUN_LOG],
echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
(exit $ac_status); }])
m4_include([acinclude.m4])

View File

@@ -0,0 +1,862 @@
// 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,
// modify, copy, or redistribute it subject to the terms and conditions
// of the GNU Lesser General Public License v.2.1.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program; if not, write to the Free Software Foundation,
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#include "radix-tree.h"
#include "base/memory/container_of.h"
#include "base/memory/zalloc.h"
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
//----------------------------------------------------------------
enum node_type {
UNSET = 0,
VALUE,
VALUE_CHAIN,
PREFIX_CHAIN,
NODE4,
NODE16,
NODE48,
NODE256
};
struct value {
enum node_type type;
union radix_value value;
};
// This is used for entries that have a key which is a prefix of another key.
struct value_chain {
union radix_value value;
struct value child;
};
struct prefix_chain {
struct value child;
unsigned len;
uint8_t prefix[0];
};
struct node4 {
uint32_t nr_entries;
uint8_t keys[4];
struct value values[4];
};
struct node16 {
uint32_t nr_entries;
uint8_t keys[16];
struct value values[16];
};
struct node48 {
uint32_t nr_entries;
uint8_t keys[256];
struct value values[48];
};
struct node256 {
uint32_t nr_entries;
struct value values[256];
};
struct radix_tree {
unsigned nr_entries;
struct value root;
radix_value_dtr dtr;
void *dtr_context;
};
//----------------------------------------------------------------
struct radix_tree *radix_tree_create(radix_value_dtr dtr, void *dtr_context)
{
struct radix_tree *rt = malloc(sizeof(*rt));
if (rt) {
rt->nr_entries = 0;
rt->root.type = UNSET;
rt->dtr = dtr;
rt->dtr_context = dtr_context;
}
return rt;
}
static inline void _dtr(struct radix_tree *rt, union radix_value v)
{
if (rt->dtr)
rt->dtr(rt->dtr_context, v);
}
// Returns the number of values removed
static unsigned _free_node(struct radix_tree *rt, struct value v)
{
unsigned i, nr = 0;
struct value_chain *vc;
struct prefix_chain *pc;
struct node4 *n4;
struct node16 *n16;
struct node48 *n48;
struct node256 *n256;
switch (v.type) {
case UNSET:
break;
case VALUE:
_dtr(rt, v.value);
nr = 1;
break;
case VALUE_CHAIN:
vc = v.value.ptr;
_dtr(rt, vc->value);
nr = 1 + _free_node(rt, vc->child);
free(vc);
break;
case PREFIX_CHAIN:
pc = v.value.ptr;
nr = _free_node(rt, pc->child);
free(pc);
break;
case NODE4:
n4 = (struct node4 *) v.value.ptr;
for (i = 0; i < n4->nr_entries; i++)
nr += _free_node(rt, n4->values[i]);
free(n4);
break;
case NODE16:
n16 = (struct node16 *) v.value.ptr;
for (i = 0; i < n16->nr_entries; i++)
nr += _free_node(rt, n16->values[i]);
free(n16);
break;
case NODE48:
n48 = (struct node48 *) v.value.ptr;
for (i = 0; i < n48->nr_entries; i++)
nr += _free_node(rt, n48->values[i]);
free(n48);
break;
case NODE256:
n256 = (struct node256 *) v.value.ptr;
for (i = 0; i < 256; i++)
nr += _free_node(rt, n256->values[i]);
free(n256);
break;
}
return nr;
}
void radix_tree_destroy(struct radix_tree *rt)
{
_free_node(rt, rt->root);
free(rt);
}
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_unset(struct radix_tree *rt, struct value *v, uint8_t *kb, uint8_t *ke, union radix_value rv)
{
unsigned len = ke - kb;
if (!len) {
// value
v->type = VALUE;
v->value = rv;
rt->nr_entries++;
} else {
// prefix -> value
struct prefix_chain *pc = zalloc(sizeof(*pc) + len);
if (!pc)
return false;
pc->child.type = VALUE;
pc->child.value = rv;
pc->len = len;
memcpy(pc->prefix, kb, len);
v->type = PREFIX_CHAIN;
v->value.ptr = pc;
rt->nr_entries++;
}
return true;
}
static bool _insert_value(struct radix_tree *rt, struct value *v, uint8_t *kb, uint8_t *ke, union radix_value rv)
{
unsigned len = ke - kb;
if (!len)
// overwrite
v->value = rv;
else {
// value_chain -> value
struct value_chain *vc = zalloc(sizeof(*vc));
if (!vc)
return false;
vc->value = v->value;
if (!_insert(rt, &vc->child, kb, ke, rv)) {
free(vc);
return false;
}
v->type = VALUE_CHAIN;
v->value.ptr = vc;
}
return true;
}
static bool _insert_value_chain(struct radix_tree *rt, struct value *v, uint8_t *kb, uint8_t *ke, union radix_value rv)
{
struct value_chain *vc = v->value.ptr;
return _insert(rt, &vc->child, kb, ke, rv);
}
static unsigned min(unsigned lhs, unsigned rhs)
{
if (lhs <= rhs)
return lhs;
else
return rhs;
}
static bool _insert_prefix_chain(struct radix_tree *rt, struct value *v, uint8_t *kb, uint8_t *ke, union radix_value rv)
{
struct prefix_chain *pc = v->value.ptr;
if (*kb == pc->prefix[0]) {
// There's a common prefix let's split the chain into two and
// recurse.
struct prefix_chain *pc2;
unsigned i, len = min(pc->len, ke - kb);
for (i = 0; i < len; i++)
if (kb[i] != pc->prefix[i])
break;
pc2 = zalloc(sizeof(*pc2) + pc->len - i);
pc2->len = pc->len - i;
memmove(pc2->prefix, pc->prefix + i, pc2->len);
pc2->child = pc->child;
// FIXME: this trashes pc so we can't back out
pc->child.type = PREFIX_CHAIN;
pc->child.value.ptr = pc2;
pc->len = i;
if (!_insert(rt, &pc->child, kb + i, ke, rv)) {
free(pc2);
return false;
}
} else {
// Stick an n4 in front.
struct node4 *n4 = zalloc(sizeof(*n4));
if (!n4)
return false;
n4->keys[0] = *kb;
if (!_insert(rt, n4->values, kb + 1, ke, rv)) {
free(n4);
return false;
}
if (pc->len) {
n4->keys[1] = pc->prefix[0];
if (pc->len == 1) {
n4->values[1] = pc->child;
free(pc);
} else {
memmove(pc->prefix, pc->prefix + 1, pc->len - 1);
pc->len--;
n4->values[1] = *v;
}
n4->nr_entries = 2;
} else
n4->nr_entries = 1;
v->type = NODE4;
v->value.ptr = n4;
}
return true;
}
static bool _insert_node4(struct radix_tree *rt, struct value *v, uint8_t *kb, uint8_t *ke, union radix_value rv)
{
struct node4 *n4 = v->value.ptr;
if (n4->nr_entries == 4) {
struct node16 *n16 = zalloc(sizeof(*n16));
if (!n16)
return false;
n16->nr_entries = 5;
memcpy(n16->keys, n4->keys, sizeof(n4->keys));
memcpy(n16->values, n4->values, sizeof(n4->values));
n16->keys[4] = *kb;
if (!_insert(rt, n16->values + 4, kb + 1, ke, rv)) {
free(n16);
return false;
}
free(n4);
v->type = NODE16;
v->value.ptr = n16;
} else {
n4 = v->value.ptr;
if (!_insert(rt, n4->values + n4->nr_entries, kb + 1, ke, rv))
return false;
n4->keys[n4->nr_entries] = *kb;
n4->nr_entries++;
}
return true;
}
static bool _insert_node16(struct radix_tree *rt, struct value *v, uint8_t *kb, uint8_t *ke, union radix_value rv)
{
struct node16 *n16 = v->value.ptr;
if (n16->nr_entries == 16) {
unsigned i;
struct node48 *n48 = zalloc(sizeof(*n48));
if (!n48)
return false;
n48->nr_entries = 17;
memset(n48->keys, 48, sizeof(n48->keys));
for (i = 0; i < 16; i++) {
n48->keys[n16->keys[i]] = i;
n48->values[i] = n16->values[i];
}
n48->keys[*kb] = 16;
if (!_insert(rt, n48->values + 16, kb + 1, ke, rv)) {
free(n48);
return false;
}
free(n16);
v->type = NODE48;
v->value.ptr = n48;
} else {
if (!_insert(rt, n16->values + n16->nr_entries, kb + 1, ke, rv))
return false;
n16->keys[n16->nr_entries] = *kb;
n16->nr_entries++;
}
return true;
}
static bool _insert_node48(struct radix_tree *rt, struct value *v, uint8_t *kb, uint8_t *ke, union radix_value rv)
{
struct node48 *n48 = v->value.ptr;
if (n48->nr_entries == 48) {
unsigned i;
struct node256 *n256 = zalloc(sizeof(*n256));
if (!n256)
return false;
for (i = 0; i < 256; i++) {
if (n48->keys[i] >= 48)
continue;
n256->values[i] = n48->values[n48->keys[i]];
}
if (!_insert(rt, n256->values + *kb, kb + 1, ke, rv)) {
free(n256);
return false;
}
free(n48);
v->type = NODE256;
v->value.ptr = n256;
} else {
if (!_insert(rt, n48->values + n48->nr_entries, kb + 1, ke, rv))
return false;
n48->keys[*kb] = n48->nr_entries;
n48->nr_entries++;
}
return true;
}
static bool _insert_node256(struct radix_tree *rt, struct value *v, uint8_t *kb, uint8_t *ke, union radix_value rv)
{
struct node256 *n256 = v->value.ptr;
bool was_unset = n256->values[*kb].type == UNSET;
if (!_insert(rt, n256->values + *kb, kb + 1, ke, rv))
return false;
if (was_unset)
n256->nr_entries++;
return true;
}
// 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)
{
if (kb == ke) {
if (v->type == UNSET) {
v->type = VALUE;
v->value = rv;
rt->nr_entries++;
} else if (v->type == VALUE) {
v->value = rv;
} else {
struct value_chain *vc = zalloc(sizeof(*vc));
if (!vc)
return false;
vc->value = rv;
vc->child = *v;
v->type = VALUE_CHAIN;
v->value.ptr = vc;
rt->nr_entries++;
}
return true;
}
switch (v->type) {
case UNSET:
return _insert_unset(rt, v, kb, ke, rv);
case VALUE:
return _insert_value(rt, v, kb, ke, rv);
case VALUE_CHAIN:
return _insert_value_chain(rt, v, kb, ke, rv);
case PREFIX_CHAIN:
return _insert_prefix_chain(rt, v, kb, ke, rv);
case NODE4:
return _insert_node4(rt, v, kb, ke, rv);
case NODE16:
return _insert_node16(rt, v, kb, ke, rv);
case NODE48:
return _insert_node48(rt, v, kb, ke, rv);
case NODE256:
return _insert_node256(rt, v, kb, ke, rv);
}
// can't get here
return false;
}
struct lookup_result {
struct value *v;
uint8_t *kb;
};
static struct lookup_result _lookup_prefix(struct value *v, uint8_t *kb, uint8_t *ke)
{
unsigned i;
struct value_chain *vc;
struct prefix_chain *pc;
struct node4 *n4;
struct node16 *n16;
struct node48 *n48;
struct node256 *n256;
if (kb == ke)
return (struct lookup_result) {.v = v, .kb = kb};
switch (v->type) {
case UNSET:
case VALUE:
break;
case VALUE_CHAIN:
vc = v->value.ptr;
return _lookup_prefix(&vc->child, kb, ke);
case PREFIX_CHAIN:
pc = v->value.ptr;
if (ke - kb < pc->len)
return (struct lookup_result) {.v = v, .kb = kb};
for (i = 0; i < pc->len; i++)
if (kb[i] != pc->prefix[i])
return (struct lookup_result) {.v = v, .kb = kb};
return _lookup_prefix(&pc->child, kb + pc->len, ke);
case NODE4:
n4 = v->value.ptr;
for (i = 0; i < n4->nr_entries; i++)
if (n4->keys[i] == *kb)
return _lookup_prefix(n4->values + i, kb + 1, ke);
break;
case NODE16:
// FIXME: use binary search or simd?
n16 = v->value.ptr;
for (i = 0; i < n16->nr_entries; i++)
if (n16->keys[i] == *kb)
return _lookup_prefix(n16->values + i, kb + 1, ke);
break;
case NODE48:
n48 = v->value.ptr;
i = n48->keys[*kb];
if (i < 48)
return _lookup_prefix(n48->values + i, kb + 1, ke);
break;
case NODE256:
n256 = v->value.ptr;
return _lookup_prefix(n256->values + *kb, kb + 1, ke);
}
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)
{
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)
{
struct node4 *n4 = zalloc(sizeof(*n4));
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;
}
static void _degrade_to_n16(struct node48 *n48, struct value *result)
{
struct node4 *n16 = zalloc(sizeof(*n16));
n16->nr_entries = n48->nr_entries;
memcpy(n16->keys, n48->keys, n48->nr_entries * sizeof(*n16->keys));
memcpy(n16->values, n48->values, n48->nr_entries * sizeof(*n16->values));
free(n48);
result->type = NODE16;
result->value.ptr = n16;
}
static void _degrade_to_n48(struct node256 *n256, struct value *result)
{
unsigned i, count = 0;
struct node4 *n48 = zalloc(sizeof(*n48));
n48->nr_entries = n256->nr_entries;
for (i = 0; i < 256; i++) {
if (n256->values[i].type == UNSET)
continue;
n48->keys[count] = i;
n48->values[count] = n256->values[i];
count++;
}
free(n256);
result->type = NODE48;
result->value.ptr = n48;
}
static bool _remove(struct radix_tree *rt, struct value *root, uint8_t *kb, uint8_t *ke)
{
bool r;
unsigned i;
struct value_chain *vc;
struct prefix_chain *pc;
struct node4 *n4;
struct node16 *n16;
struct node48 *n48;
struct node256 *n256;
if (kb == ke) {
if (root->type == VALUE) {
root->type = UNSET;
_dtr(rt, root->value);
return true;
} else if (root->type == VALUE_CHAIN) {
vc = root->value.ptr;
_dtr(rt, vc->value);
memcpy(root, &vc->child, sizeof(*root));
free(vc);
return true;
} else
return false;
}
switch (root->type) {
case UNSET:
case VALUE:
// this is a value for a prefix of the key
return false;
case VALUE_CHAIN:
vc = root->value.ptr;
r = _remove(rt, &vc->child, kb, ke);
if (r && (vc->child.type == UNSET)) {
memcpy(root, &vc->child, sizeof(*root));
free(vc);
}
return r;
case PREFIX_CHAIN:
pc = root->value.ptr;
if (ke - kb < pc->len)
return false;
for (i = 0; i < pc->len; i++)
if (kb[i] != pc->prefix[i])
return false;
return _remove(rt, &pc->child, kb + pc->len, ke);
case NODE4:
n4 = root->value.ptr;
for (i = 0; i < n4->nr_entries; i++) {
if (n4->keys[i] == *kb) {
r = _remove(rt, n4->values + i, kb + 1, ke);
if (r && n4->values[i].type == UNSET) {
n4->nr_entries--;
if (i < n4->nr_entries)
// slide the entries down
memmove(n4->keys + i, n4->keys + i + 1,
sizeof(*n4->keys) * (n4->nr_entries - i));
if (!n4->nr_entries)
root->type = UNSET;
}
return r;
}
}
return false;
case NODE16:
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) {
n16->nr_entries--;
if (i < n16->nr_entries)
// slide the entries down
memmove(n16->keys + i, n16->keys + i + 1,
sizeof(*n16->keys) * (n16->nr_entries - i));
if (n16->nr_entries <= 4)
_degrade_to_n4(n16, root);
}
return r;
}
}
return false;
case NODE48:
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;
n48->nr_entries--;
if (n48->nr_entries <= 16)
_degrade_to_n16(n48, root);
}
return r;
}
return false;
case NODE256:
n256 = root->value.ptr;
r = _remove(rt, n256->values + (*kb), kb + 1, ke);
if (r && n256->values[*kb].type == UNSET) {
n256->nr_entries--;
if (n256->nr_entries <= 48)
_degrade_to_n48(n256, root);
}
return r;
}
return false;
}
bool radix_tree_remove(struct radix_tree *rt, uint8_t *key_begin, uint8_t *key_end)
{
if (_remove(rt, &rt->root, key_begin, key_end)) {
rt->nr_entries--;
return true;
}
return false;
}
static bool _prefix_chain_matches(struct lookup_result *lr, 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;
}
}
return false;
}
unsigned radix_tree_remove_prefix(struct radix_tree *rt, uint8_t *kb, uint8_t *ke)
{
unsigned count = 0;
struct lookup_result lr = _lookup_prefix(&rt->root, kb, ke);
if (lr.kb == ke || _prefix_chain_matches(&lr, ke)) {
count = _free_node(rt, *lr.v);
lr.v->type = UNSET;
}
rt->nr_entries -= count;
return count;
}
bool radix_tree_lookup(struct radix_tree *rt,
uint8_t *kb, uint8_t *ke, union radix_value *result)
{
struct value_chain *vc;
struct lookup_result lr = _lookup_prefix(&rt->root, kb, ke);
if (lr.kb == ke) {
switch (lr.v->type) {
case VALUE:
*result = lr.v->value;
return true;
case VALUE_CHAIN:
vc = lr.v->value.ptr;
*result = vc->value;
return true;
default:
return false;
}
}
return false;
}
// FIXME: build up the keys too
static bool _iterate(struct value *v, struct radix_tree_iterator *it)
{
unsigned i;
struct value_chain *vc;
struct prefix_chain *pc;
struct node4 *n4;
struct node16 *n16;
struct node48 *n48;
struct node256 *n256;
switch (v->type) {
case UNSET:
// can't happen
break;
case VALUE:
return it->visit(it, NULL, NULL, v->value);
case VALUE_CHAIN:
vc = v->value.ptr;
return it->visit(it, NULL, NULL, vc->value) && _iterate(&vc->child, it);
case PREFIX_CHAIN:
pc = v->value.ptr;
return _iterate(&pc->child, it);
case NODE4:
n4 = (struct node4 *) v->value.ptr;
for (i = 0; i < n4->nr_entries; i++)
if (!_iterate(n4->values + i, it))
return false;
return true;
case NODE16:
n16 = (struct node16 *) v->value.ptr;
for (i = 0; i < n16->nr_entries; i++)
if (!_iterate(n16->values + i, it))
return false;
return true;
case NODE48:
n48 = (struct node48 *) v->value.ptr;
for (i = 0; i < n48->nr_entries; i++)
if (!_iterate(n48->values + i, it))
return false;
return true;
case NODE256:
n256 = (struct node256 *) v->value.ptr;
for (i = 0; i < 256; i++)
if (n256->values[i].type != UNSET && !_iterate(n256->values + i, it))
return false;
return true;
}
// can't get here
return false;
}
void radix_tree_iterate(struct radix_tree *rt, uint8_t *kb, uint8_t *ke,
struct radix_tree_iterator *it)
{
struct lookup_result lr = _lookup_prefix(&rt->root, kb, ke);
if (lr.kb == ke || _prefix_chain_matches(&lr, ke))
_iterate(lr.v, it);
}
//----------------------------------------------------------------

View File

@@ -0,0 +1,58 @@
// 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,
// 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 BASE_DATA_STRUCT_RADIX_TREE_H
#define BASE_DATA_STRUCT_RADIX_TREE_H
#include <stdbool.h>
#include <stdint.h>
//----------------------------------------------------------------
struct radix_tree;
union radix_value {
void *ptr;
uint64_t n;
};
typedef void (*radix_value_dtr)(void *context, union radix_value v);
// dtr will be called on any deleted entries. dtr may be NULL.
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);
// Returns the number of values removed
unsigned radix_tree_remove_prefix(struct radix_tree *rt, uint8_t *prefix_b, uint8_t *prefix_e);
bool radix_tree_lookup(struct radix_tree *rt,
uint8_t *kb, uint8_t *ke, 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.
bool (*visit)(struct radix_tree_iterator *it,
uint8_t *kb, uint8_t *ke, union radix_value v);
};
void radix_tree_iterate(struct radix_tree *rt, uint8_t *kb, uint8_t *ke,
struct radix_tree_iterator *it);
//----------------------------------------------------------------
#endif

View File

@@ -0,0 +1,23 @@
// 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,
// 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 BASE_MEMORY_CONTAINER_OF_H
#define BASE_MEMORY_CONTAINER_OF_H
//----------------------------------------------------------------
#define container_of(v, t, head) \
((t *)((const char *)(v) - (const char *)&((t *) 0)->head))
//----------------------------------------------------------------
#endif

31
base/memory/zalloc.h Normal file
View File

@@ -0,0 +1,31 @@
// 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,
// 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 BASE_MEMORY_ZALLOC_H
#define BASE_MEMORY_ZALLOC_H
#include <stdlib.h>
#include <string.h>
//----------------------------------------------------------------
static inline void *zalloc(size_t len)
{
void *ptr = malloc(len);
if (ptr)
memset(ptr, 0, len);
return ptr;
}
//----------------------------------------------------------------
#endif

View File

@@ -611,9 +611,9 @@ log {
# Select log messages by class.
# Some debugging messages are assigned to a class and only appear in
# debug output if the class is listed here. Classes currently
# available: memory, devices, activation, allocation, lvmetad,
# available: memory, devices, io, activation, allocation, lvmetad,
# metadata, cache, locking, lvmpolld. Use "all" to see everything.
debug_classes = [ "memory", "devices", "activation", "allocation", "lvmetad", "metadata", "cache", "locking", "lvmpolld", "dbus" ]
debug_classes = [ "memory", "devices", "io", "activation", "allocation", "lvmetad", "metadata", "cache", "locking", "lvmpolld", "dbus" ]
}
# Configuration section backup.
@@ -702,29 +702,17 @@ global {
activation = 1
# Configuration option global/fallback_to_lvm1.
# Try running LVM1 tools if LVM cannot communicate with DM.
# This option only applies to 2.4 kernels and is provided to help
# switch between device-mapper kernels and LVM1 kernels. The LVM1
# tools need to be installed with .lvm1 suffices, e.g. vgscan.lvm1.
# They will stop working once the lvm2 on-disk metadata format is used.
# This setting is no longer used.
# This configuration option has an automatic default value.
# fallback_to_lvm1 = @DEFAULT_FALLBACK_TO_LVM1@
# fallback_to_lvm1 = 0
# Configuration option global/format.
# The default metadata format that commands should use.
# The -M 1|2 option overrides this setting.
#
# Accepted values:
# lvm1
# lvm2
#
# This setting is no longer used.
# This configuration option has an automatic default value.
# format = "lvm2"
# Configuration option global/format_libraries.
# Shared libraries that process different metadata formats.
# If support for LVM1 metadata was compiled as a shared library use
# format_libraries = "liblvm2format1.so"
# This setting is no longer used.
# This configuration option does not have a default value defined.
# Configuration option global/segment_libraries.
@@ -821,13 +809,6 @@ global {
# encountered the internal error. Please only enable for debugging.
abort_on_internal_errors = 0
# Configuration option global/detect_internal_vg_cache_corruption.
# Internal verification of VG structures.
# Check if CRC matches when a parsed VG is used multiple times. This
# is useful to catch unexpected changes to cached VG structures.
# Please only enable for debugging.
detect_internal_vg_cache_corruption = 0
# Configuration option global/metadata_read_only.
# No operations that change on-disk metadata are permitted.
# Additionally, read-only commands that encounter metadata in need of

384
configure vendored
View File

@@ -643,6 +643,7 @@ LVMETAD_PIDFILE
DMEVENTD_PIDFILE
WRITE_INSTALL
VALGRIND_POOL
USRSBINDIR
USE_TRACKING
UDEV_HAS_BUILTIN_BLKID
UDEV_RULE_EXEC_DETECTION
@@ -652,16 +653,16 @@ UDEV_RULES
UDEV_PC
THIN
TESTSUITE_DATA
TESTING
STATIC_LINK
STATICDIR
SNAPSHOTS
SYSCONFDIR
SELINUX_PC
SELINUX_LIBS
SBINDIR
REPLICATORS
READLINE_LIBS
RT_LIBS
RAID
PYTHON3DIR
PYTHON2DIR
PYTHON3_LIBDIRS
@@ -674,7 +675,6 @@ PYTHON_BINDINGS
PYTHON3
PTHREAD_LIBS
M_LIBS
POOL
PKGCONFIG
ODIRECT
OCFDIR
@@ -689,8 +689,6 @@ LVM_MINOR
LVM_MAJOR
LVM_LIBAPI
LVM_VERSION
LVM1_FALLBACK
LVM1
LIB_SUFFIX
LDDEPS
JOBS
@@ -710,6 +708,7 @@ DEFAULT_USE_LVMLOCKD
DEFAULT_USE_LVMPOLLD
DEFAULT_USE_LVMETAD
DEFAULT_USE_BLKID_WIPING
DEFAULT_SYS_LOCK_DIR
DEFAULT_SYS_DIR
DEFAULT_SPARSE_SEGTYPE
DEFAULT_RUN_DIR
@@ -717,7 +716,6 @@ DEFAULT_RAID10_SEGTYPE
DEFAULT_PROFILE_SUBDIR
DEFAULT_PID_DIR
DEFAULT_MIRROR_SEGTYPE
DEFAULT_FALLBACK_TO_LVM1
DEFAULT_LOCK_DIR
DEFAULT_DM_RUN_DIR
DEFAULT_DATA_ALIGNMENT
@@ -777,8 +775,6 @@ LOCKD_SANLOCK_LIBS
LOCKD_SANLOCK_CFLAGS
VALGRIND_LIBS
VALGRIND_CFLAGS
CUNIT_LIBS
CUNIT_CFLAGS
GENPNG
GENHTML
LCOV
@@ -880,6 +876,7 @@ infodir
docdir
oldincludedir
includedir
runstatedir
localstatedir
sharedstatedir
sysconfdir
@@ -911,16 +908,11 @@ with_device_gid
with_device_mode
with_device_nodes_on
with_default_name_mangling
enable_lvm1_fallback
with_lvm1
with_pool
with_cluster
with_snapshots
with_mirrors
with_raid
with_default_mirror_segtype
with_default_raid10_segtype
with_replicators
with_default_sparse_segtype
with_thin
with_thin_check
@@ -948,7 +940,6 @@ with_cmirrord_pidfile
enable_debug
with_optimisation
enable_profiling
enable_testing
enable_valgrind_pool
enable_devmapper
enable_lvmetad
@@ -1040,8 +1031,6 @@ DLM_CFLAGS
DLM_LIBS
SACKPT_CFLAGS
SACKPT_LIBS
CUNIT_CFLAGS
CUNIT_LIBS
VALGRIND_CFLAGS
VALGRIND_LIBS
LOCKD_SANLOCK_CFLAGS
@@ -1095,6 +1084,7 @@ datadir='${datarootdir}'
sysconfdir='${prefix}/etc'
sharedstatedir='${prefix}/com'
localstatedir='${prefix}/var'
runstatedir='${localstatedir}/run'
includedir='${prefix}/include'
oldincludedir='/usr/include'
docdir='${datarootdir}/doc/${PACKAGE}'
@@ -1347,6 +1337,15 @@ do
| -silent | --silent | --silen | --sile | --sil)
silent=yes ;;
-runstatedir | --runstatedir | --runstatedi | --runstated \
| --runstate | --runstat | --runsta | --runst | --runs \
| --run | --ru | --r)
ac_prev=runstatedir ;;
-runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
| --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
| --run=* | --ru=* | --r=*)
runstatedir=$ac_optarg ;;
-sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
ac_prev=sbindir ;;
-sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
@@ -1484,7 +1483,7 @@ fi
for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
datadir sysconfdir sharedstatedir localstatedir includedir \
oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
libdir localedir mandir
libdir localedir mandir runstatedir
do
eval ac_val=\$$ac_var
# Remove trailing slashes.
@@ -1637,6 +1636,7 @@ Fine tuning of the installation directories:
--sysconfdir=DIR read-only single-machine data [PREFIX/etc]
--sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
--localstatedir=DIR modifiable single-machine data [PREFIX/var]
--runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run]
--libdir=DIR object code libraries [EPREFIX/lib]
--includedir=DIR C header files [PREFIX/include]
--oldincludedir=DIR C header files for non-gcc [/usr/include]
@@ -1673,8 +1673,6 @@ Optional Features:
speeds up one-time build.
--enable-static_link use this to link the tools to their libraries
statically (default is dynamic linking
--enable-lvm1_fallback use this to fall back and use LVM1 binaries if
device-mapper is missing from the kernel
--disable-thin_check_needs_check
required if thin_check version is < 0.3.0
--disable-cache_check_needs_check
@@ -1686,7 +1684,6 @@ Optional Features:
--enable-cmirrord enable the cluster mirror log daemon
--enable-debug enable debugging
--enable-profiling gather gcov profiling data
--enable-testing enable testing targets in the makefile
--enable-valgrind-pool enable valgrind awareness of pools
--disable-devmapper disable LVM2 device-mapper interaction
--enable-lvmetad enable the LVM Metadata Daemon
@@ -1742,20 +1739,14 @@ Optional Packages:
create nodes on resume or create [ON=resume]
--with-default-name-mangling=MANGLING
default name mangling: auto/none/hex [auto]
--with-lvm1=TYPE LVM1 metadata support: internal/shared/none
[internal]
--with-pool=TYPE GFS pool read-only support: internal/shared/none
[internal]
--with-cluster=TYPE cluster LVM locking support: internal/shared/none
[internal]
--with-snapshots=TYPE snapshot support: internal/shared/none [internal]
--with-mirrors=TYPE mirror support: internal/shared/none [internal]
--with-raid=TYPE raid support: internal/shared/none [internal]
--with-default-mirror-segtype=TYPE
default mirror segtype: raid1/mirror [raid1]
--with-default-raid10-segtype=TYPE
default mirror segtype: raid10/mirror [raid10]
--with-replicators=TYPE replicator support: internal/shared/none [none]
--with-default-sparse-segtype=TYPE
default sparse segtype: thin/snapshot [thin]
--with-thin=TYPE thin provisioning support: internal/shared/none
@@ -1876,9 +1867,6 @@ Some influential environment variables:
SACKPT_CFLAGS
C compiler flags for SACKPT, overriding pkg-config
SACKPT_LIBS linker flags for SACKPT, overriding pkg-config
CUNIT_CFLAGS
C compiler flags for CUNIT, overriding pkg-config
CUNIT_LIBS linker flags for CUNIT, overriding pkg-config
VALGRIND_CFLAGS
C compiler flags for VALGRIND, overriding pkg-config
VALGRIND_LIBS
@@ -4367,6 +4355,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
CFLAGS=$save_CFLAGS
CXXFLAGS=$save_CXXFLAGS
PATH_SBIN="$PATH:/usr/sbin:/sbin"
ac_ext=c
@@ -6152,7 +6141,7 @@ fi
for ac_header in assert.h ctype.h dirent.h errno.h fcntl.h float.h \
getopt.h inttypes.h langinfo.h libgen.h limits.h locale.h paths.h \
getopt.h inttypes.h langinfo.h libaio.h libgen.h limits.h locale.h paths.h \
signal.h stdarg.h stddef.h stdio.h stdlib.h string.h sys/file.h \
sys/ioctl.h syslog.h sys/mman.h sys/param.h sys/resource.h sys/stat.h \
sys/time.h sys/types.h sys/utsname.h sys/wait.h time.h \
@@ -8240,9 +8229,14 @@ $as_echo "$ac_cv_flag_HAVE_FULL_RELRO" >&6; }
################################################################################
if test "$prefix" = NONE; then
datarootdir=${ac_default_prefix}/share
fi
################################################################################
test "$exec_prefix" = NONE -a "$prefix" = NONE && exec_prefix=""
test "x$prefix" = xNONE && prefix=$ac_default_prefix
# Let make expand exec_prefix.
test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
################################################################################
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking file owner" >&5
@@ -8377,78 +8371,6 @@ cat >>confdefs.h <<_ACEOF
_ACEOF
################################################################################
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable lvm1 fallback" >&5
$as_echo_n "checking whether to enable lvm1 fallback... " >&6; }
# Check whether --enable-lvm1_fallback was given.
if test "${enable_lvm1_fallback+set}" = set; then :
enableval=$enable_lvm1_fallback; LVM1_FALLBACK=$enableval
else
LVM1_FALLBACK=no
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $LVM1_FALLBACK" >&5
$as_echo "$LVM1_FALLBACK" >&6; }
if test "$LVM1_FALLBACK" = yes; then
DEFAULT_FALLBACK_TO_LVM1=1
$as_echo "#define LVM1_FALLBACK 1" >>confdefs.h
else
DEFAULT_FALLBACK_TO_LVM1=0
fi
cat >>confdefs.h <<_ACEOF
#define DEFAULT_FALLBACK_TO_LVM1 $DEFAULT_FALLBACK_TO_LVM1
_ACEOF
################################################################################
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to include support for lvm1 metadata" >&5
$as_echo_n "checking whether to include support for lvm1 metadata... " >&6; }
# Check whether --with-lvm1 was given.
if test "${with_lvm1+set}" = set; then :
withval=$with_lvm1; LVM1=$withval
else
LVM1=internal
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $LVM1" >&5
$as_echo "$LVM1" >&6; }
case "$LVM1" in
none|shared) ;;
internal)
$as_echo "#define LVM1_INTERNAL 1" >>confdefs.h
;;
*) as_fn_error $? "--with-lvm1 parameter invalid" "$LINENO" 5 ;;
esac
################################################################################
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to include support for GFS pool metadata" >&5
$as_echo_n "checking whether to include support for GFS pool metadata... " >&6; }
# Check whether --with-pool was given.
if test "${with_pool+set}" = set; then :
withval=$with_pool; POOL=$withval
else
POOL=internal
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $POOL" >&5
$as_echo "$POOL" >&6; }
case "$POOL" in
none|shared) ;;
internal)
$as_echo "#define POOL_INTERNAL 1" >>confdefs.h
;;
*) as_fn_error $? "--with-pool parameter invalid" "$LINENO" 5
esac
################################################################################
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to include support for cluster locking" >&5
$as_echo_n "checking whether to include support for cluster locking... " >&6; }
@@ -8514,19 +8436,6 @@ $as_echo "#define MIRRORED_INTERNAL 1" >>confdefs.h
esac
################################################################################
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to include raid" >&5
$as_echo_n "checking whether to include raid... " >&6; }
# Check whether --with-raid was given.
if test "${with_raid+set}" = set; then :
withval=$with_raid; RAID=$withval
else
RAID=internal
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $RAID" >&5
$as_echo "$RAID" >&6; }
# Check whether --with-default-mirror-segtype was given.
if test "${with_default_mirror_segtype+set}" = set; then :
@@ -8543,15 +8452,10 @@ else
DEFAULT_RAID10_SEGTYPE="raid10"
fi
case "$RAID" in
none) test "$DEFAULT_MIRROR_SEGTYPE" = "raid1" && DEFAULT_MIRROR_SEGTYPE="mirror"
test "$DEFAULT_RAID10_SEGTYPE" = "raid10" && DEFAULT_RAID10_SEGTYPE="mirror" ;;
shared) ;;
internal)
$as_echo "#define RAID_INTERNAL 1" >>confdefs.h
;;
*) as_fn_error $? "--with-raid parameter invalid" "$LINENO" 5 ;;
esac
cat >>confdefs.h <<_ACEOF
@@ -8566,28 +8470,6 @@ _ACEOF
################################################################################
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to include replicators" >&5
$as_echo_n "checking whether to include replicators... " >&6; }
# Check whether --with-replicators was given.
if test "${with_replicators+set}" = set; then :
withval=$with_replicators; REPLICATORS=$withval
else
REPLICATORS=none
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $REPLICATORS" >&5
$as_echo "$REPLICATORS" >&6; }
case "$REPLICATORS" in
none|shared) ;;
internal)
$as_echo "#define REPLICATOR_INTERNAL 1" >>confdefs.h
;;
*) as_fn_error $? "--with-replicators parameter invalid ($REPLICATORS)" "$LINENO" 5 ;;
esac
# Check whether --with-default-sparse-segtype was given.
if test "${with_default_sparse_segtype+set}" = set; then :
@@ -8687,7 +8569,7 @@ else
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
for as_dir in $PATH_SBIN
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
@@ -8730,7 +8612,7 @@ else
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
for as_dir in $PATH_SBIN
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
@@ -8811,7 +8693,7 @@ else
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
for as_dir in $PATH_SBIN
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
@@ -8854,7 +8736,7 @@ else
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
for as_dir in $PATH_SBIN
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
@@ -8918,7 +8800,7 @@ else
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
for as_dir in $PATH_SBIN
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
@@ -8961,7 +8843,7 @@ else
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
for as_dir in $PATH_SBIN
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
@@ -9025,7 +8907,7 @@ else
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
for as_dir in $PATH_SBIN
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
@@ -9068,7 +8950,7 @@ else
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
for as_dir in $PATH_SBIN
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
@@ -9236,7 +9118,7 @@ else
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
for as_dir in $PATH_SBIN
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
@@ -9279,7 +9161,7 @@ else
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
for as_dir in $PATH_SBIN
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
@@ -9372,7 +9254,7 @@ else
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
for as_dir in $PATH_SBIN
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
@@ -9415,7 +9297,7 @@ else
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
for as_dir in $PATH_SBIN
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
@@ -9479,7 +9361,7 @@ else
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
for as_dir in $PATH_SBIN
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
@@ -9522,7 +9404,7 @@ else
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
for as_dir in $PATH_SBIN
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
@@ -9586,7 +9468,7 @@ else
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
for as_dir in $PATH_SBIN
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
@@ -9629,7 +9511,7 @@ else
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
for as_dir in $PATH_SBIN
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
@@ -11606,114 +11488,6 @@ $as_echo "$as_me: WARNING: GD.pm perl module is not installed" >&2;}
fi
fi
################################################################################
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable unit testing" >&5
$as_echo_n "checking whether to enable unit testing... " >&6; }
# Check whether --enable-testing was given.
if test "${enable_testing+set}" = set; then :
enableval=$enable_testing; TESTING=$enableval
else
TESTING=no
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $TESTING" >&5
$as_echo "$TESTING" >&6; }
if test "$TESTING" = yes; then
pkg_config_init
pkg_failed=no
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for CUNIT" >&5
$as_echo_n "checking for CUNIT... " >&6; }
if test -n "$CUNIT_CFLAGS"; then
pkg_cv_CUNIT_CFLAGS="$CUNIT_CFLAGS"
elif test -n "$PKG_CONFIG"; then
if test -n "$PKG_CONFIG" && \
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"cunit >= 2.0\""; } >&5
($PKG_CONFIG --exists --print-errors "cunit >= 2.0") 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
pkg_cv_CUNIT_CFLAGS=`$PKG_CONFIG --cflags "cunit >= 2.0" 2>/dev/null`
test "x$?" != "x0" && pkg_failed=yes
else
pkg_failed=yes
fi
else
pkg_failed=untried
fi
if test -n "$CUNIT_LIBS"; then
pkg_cv_CUNIT_LIBS="$CUNIT_LIBS"
elif test -n "$PKG_CONFIG"; then
if test -n "$PKG_CONFIG" && \
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"cunit >= 2.0\""; } >&5
($PKG_CONFIG --exists --print-errors "cunit >= 2.0") 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
pkg_cv_CUNIT_LIBS=`$PKG_CONFIG --libs "cunit >= 2.0" 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
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "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
CUNIT_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "cunit >= 2.0" 2>&1`
else
CUNIT_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "cunit >= 2.0" 2>&1`
fi
# Put the nasty error message in config.log where it belongs
echo "$CUNIT_PKG_ERRORS" >&5
as_fn_error $? "Package requirements (cunit >= 2.0) were not met:
$CUNIT_PKG_ERRORS
Consider adjusting the PKG_CONFIG_PATH environment variable if you
installed software in a non-standard prefix.
Alternatively, you may set the environment variables CUNIT_CFLAGS
and CUNIT_LIBS to avoid the need to call pkg-config.
See the pkg-config man page for more details." "$LINENO" 5
elif test $pkg_failed = untried; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it
is in your PATH or set the PKG_CONFIG environment variable to the full
path to pkg-config.
Alternatively, you may set the environment variables CUNIT_CFLAGS
and CUNIT_LIBS to avoid the need to call pkg-config.
See the pkg-config man page for more details.
To get pkg-config, see <http://pkg-config.freedesktop.org/>.
See \`config.log' for more details" "$LINENO" 5; }
else
CUNIT_CFLAGS=$pkg_cv_CUNIT_CFLAGS
CUNIT_LIBS=$pkg_cv_CUNIT_LIBS
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
fi
fi
################################################################################
TESTSUITE_DATA='${datarootdir}/lvm2-testsuite'
# double eval needed ${datarootdir} -> ${prefix}/share -> real path
@@ -12791,6 +12565,10 @@ $as_echo "$APPLIB" >&6; }
test "$APPLIB" = yes \
&& LVM2APP_LIB=-llvm2app \
|| LVM2APP_LIB=
if test "$APPLIB"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: liblvm2app is deprecated. Use D-Bus API" >&5
$as_echo "$as_me: WARNING: liblvm2app is deprecated. Use D-Bus API" >&2;}
fi
################################################################################
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to compile liblvm2cmd.so" >&5
@@ -12821,6 +12599,10 @@ fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $BUILD_LVMDBUSD" >&5
$as_echo "$BUILD_LVMDBUSD" >&6; }
if test "$NOTIFYDBUS_SUPPORT" = yes && test "BUILD_LVMDBUSD" = yes; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Building D-Bus support without D-Bus notifications." >&5
$as_echo "$as_me: WARNING: Building D-Bus support without D-Bus notifications." >&2;}
fi
################################################################################
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build Python wrapper for liblvm2app.so" >&5
@@ -13798,7 +13580,7 @@ fi
PYTHON3_INCDIRS=`"$PYTHON3_CONFIG" --includes`
PYTHON3_LIBDIRS=`"$PYTHON3_CONFIG" --libs`
PYTHON3DIR=$pythondir
PYTHON_BINDINGS=yes
test "$PYTHON3_BINDINGS" = yes && PYTHON_BINDINGS=yes
fi
if test "$BUILD_LVMDBUSD" = yes; then
@@ -13868,6 +13650,8 @@ $as_echo "no" >&6; }
fi
if test "$PYTHON_BINDINGS" = yes -o "$PYTHON2_BINDINGS" = yes -o "$PYTHON3_BINDINGS" = yes; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Python bindings are deprecated. Use D-Bus API" >&5
$as_echo "$as_me: WARNING: Python bindings are deprecated. Use D-Bus API" >&2;}
test "$APPLIB" != yes && as_fn_error $? "Python_bindings require --enable-applib" "$LINENO" 5
fi
@@ -14027,9 +13811,6 @@ $as_echo "#define HAVE_CANONICALIZE_FILE_NAME 1" >>confdefs.h
fi
################################################################################
test "$exec_prefix" = NONE -a "$prefix" = NONE && exec_prefix=""
################################################################################
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
$as_echo_n "checking for dlopen in -ldl... " >&6; }
@@ -14081,8 +13862,6 @@ fi
################################################################################
if [ \( "$LVM1" = shared -o "$POOL" = shared -o "$CLUSTER" = shared \
-o "$SNAPSHOTS" = shared -o "$MIRRORS" = shared \
-o "$RAID" = shared -o "$CACHE" = shared \
\) -a "$STATIC_LINK" = yes ]; then
as_fn_error $? "Features cannot be 'shared' when building statically" "$LINENO" 5
fi
@@ -15318,7 +15097,7 @@ else
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
for as_dir in $PATH_SBIN
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
@@ -15361,7 +15140,7 @@ else
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
for as_dir in $PATH_SBIN
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
@@ -15411,28 +15190,25 @@ _ACEOF
fi
SYSCONFDIR="$(eval echo $(eval echo $sysconfdir))"
lvm_exec_prefix=$exec_prefix
test "$lvm_exec_prefix" = NONE && lvm_exec_prefix=$prefix
test "$lvm_exec_prefix" = NONE && lvm_exec_prefix=$ac_default_prefix
LVM_PATH="$lvm_exec_prefix/sbin/lvm"
SBINDIR="$(eval echo $(eval echo $sbindir))"
LVM_PATH="$SBINDIR/lvm"
cat >>confdefs.h <<_ACEOF
#define LVM_PATH "$LVM_PATH"
_ACEOF
clvmd_prefix=$ac_default_prefix
test "$prefix" != NONE && clvmd_prefix=$prefix
CLVMD_PATH="$clvmd_prefix/sbin/clvmd"
USRSBINDIR="$(eval echo $(eval echo $usrsbindir))"
CLVMD_PATH="$USRSBINDIR/clvmd"
cat >>confdefs.h <<_ACEOF
#define CLVMD_PATH "$CLVMD_PATH"
_ACEOF
FSADM_PATH="$lvm_exec_prefix/sbin/fsadm"
FSADM_PATH="$SBINDIR/fsadm"
cat >>confdefs.h <<_ACEOF
#define FSADM_PATH "$FSADM_PATH"
@@ -15462,7 +15238,7 @@ if test "$BUILD_DMEVENTD" = yes; then
if test "${with_dmeventd_path+set}" = set; then :
withval=$with_dmeventd_path; DMEVENTD_PATH=$withval
else
DMEVENTD_PATH="$lvm_exec_prefix/sbin/dmeventd"
DMEVENTD_PATH="$SBINDIR/dmeventd"
fi
@@ -15543,6 +15319,11 @@ cat >>confdefs.h <<_ACEOF
_ACEOF
# Select default system locking dir, prefer /run/lock over /var/lock
DEFAULT_SYS_LOCK_DIR="$RUN_DIR/lock"
test -d "$DEFAULT_SYS_LOCK_DIR" || DEFAULT_SYS_LOCK_DIR="/var/lock"
# Support configurable locking subdir for lvm
# Check whether --with-default-locking-dir was given.
if test "${with_default_locking_dir+set}" = set; then :
@@ -15550,8 +15331,7 @@ if test "${with_default_locking_dir+set}" = set; then :
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for default lock directory" >&5
$as_echo_n "checking for default lock directory... " >&6; }
DEFAULT_LOCK_DIR="$RUN_DIR/lock/lvm"
test -d "$RUN_DIR/lock" || DEFAULT_LOCK_DIR="/var/lock/lvm"
DEFAULT_LOCK_DIR="$DEFAULT_SYS_LOCK_DIR/lvm"
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $DEFAULT_LOCK_DIR" >&5
$as_echo "$DEFAULT_LOCK_DIR" >&6; }
fi
@@ -15775,13 +15555,11 @@ _ACEOF
################################################################################
ac_config_files="$ac_config_files Makefile make.tmpl daemons/Makefile daemons/clvmd/Makefile daemons/cmirrord/Makefile daemons/dmeventd/Makefile daemons/dmeventd/libdevmapper-event.pc daemons/dmeventd/plugins/Makefile daemons/dmeventd/plugins/lvm2/Makefile daemons/dmeventd/plugins/raid/Makefile daemons/dmeventd/plugins/mirror/Makefile daemons/dmeventd/plugins/snapshot/Makefile daemons/dmeventd/plugins/thin/Makefile daemons/dmfilemapd/Makefile daemons/lvmdbusd/Makefile daemons/lvmdbusd/path.py daemons/lvmetad/Makefile daemons/lvmpolld/Makefile daemons/lvmlockd/Makefile conf/Makefile conf/example.conf conf/lvmlocal.conf conf/command_profile_template.profile conf/metadata_profile_template.profile include/.symlinks include/Makefile lib/Makefile lib/format1/Makefile lib/format_pool/Makefile lib/locking/Makefile lib/mirror/Makefile lib/replicator/Makefile include/lvm-version.h lib/raid/Makefile lib/snapshot/Makefile lib/thin/Makefile lib/cache_segtype/Makefile libdaemon/Makefile libdaemon/client/Makefile libdaemon/server/Makefile libdm/Makefile libdm/libdevmapper.pc liblvm/Makefile liblvm/liblvm2app.pc man/Makefile po/Makefile python/Makefile python/setup.py scripts/blkdeactivate.sh scripts/blk_availability_init_red_hat scripts/blk_availability_systemd_red_hat.service scripts/clvmd_init_red_hat scripts/cmirrord_init_red_hat scripts/com.redhat.lvmdbus1.service scripts/dm_event_systemd_red_hat.service scripts/dm_event_systemd_red_hat.socket scripts/lvm2_cluster_activation_red_hat.sh scripts/lvm2_cluster_activation_systemd_red_hat.service scripts/lvm2_clvmd_systemd_red_hat.service scripts/lvm2_cmirrord_systemd_red_hat.service scripts/lvm2_lvmdbusd_systemd_red_hat.service scripts/lvm2_lvmetad_init_red_hat scripts/lvm2_lvmetad_systemd_red_hat.service scripts/lvm2_lvmetad_systemd_red_hat.socket scripts/lvm2_lvmpolld_init_red_hat scripts/lvm2_lvmpolld_systemd_red_hat.service scripts/lvm2_lvmpolld_systemd_red_hat.socket scripts/lvm2_lvmlockd_systemd_red_hat.service scripts/lvm2_lvmlocking_systemd_red_hat.service scripts/lvm2_monitoring_init_red_hat scripts/lvm2_monitoring_systemd_red_hat.service scripts/lvm2_pvscan_systemd_red_hat@.service scripts/lvm2_tmpfiles_red_hat.conf scripts/lvmdump.sh scripts/Makefile test/Makefile test/api/Makefile test/unit/Makefile tools/Makefile udev/Makefile unit-tests/datastruct/Makefile unit-tests/regex/Makefile unit-tests/mm/Makefile"
ac_config_files="$ac_config_files Makefile make.tmpl daemons/Makefile daemons/clvmd/Makefile daemons/cmirrord/Makefile daemons/dmeventd/Makefile daemons/dmeventd/libdevmapper-event.pc daemons/dmeventd/plugins/Makefile daemons/dmeventd/plugins/lvm2/Makefile daemons/dmeventd/plugins/raid/Makefile daemons/dmeventd/plugins/mirror/Makefile daemons/dmeventd/plugins/snapshot/Makefile daemons/dmeventd/plugins/thin/Makefile daemons/dmfilemapd/Makefile daemons/lvmdbusd/Makefile daemons/lvmdbusd/lvmdbusd daemons/lvmdbusd/lvmdb.py daemons/lvmdbusd/lvm_shell_proxy.py daemons/lvmdbusd/path.py daemons/lvmetad/Makefile daemons/lvmpolld/Makefile daemons/lvmlockd/Makefile device_mapper/Makefile conf/Makefile conf/example.conf conf/lvmlocal.conf conf/command_profile_template.profile conf/metadata_profile_template.profile include/.symlinks include/Makefile lib/Makefile lib/locking/Makefile include/lvm-version.h libdaemon/Makefile libdaemon/client/Makefile libdaemon/server/Makefile libdm/Makefile libdm/libdevmapper.pc liblvm/Makefile liblvm/liblvm2app.pc man/Makefile po/Makefile python/Makefile python/setup.py scripts/blkdeactivate.sh scripts/blk_availability_init_red_hat scripts/blk_availability_systemd_red_hat.service scripts/clvmd_init_red_hat scripts/cmirrord_init_red_hat scripts/com.redhat.lvmdbus1.service scripts/dm_event_systemd_red_hat.service scripts/dm_event_systemd_red_hat.socket scripts/lvm2_cluster_activation_red_hat.sh scripts/lvm2_cluster_activation_systemd_red_hat.service scripts/lvm2_clvmd_systemd_red_hat.service scripts/lvm2_cmirrord_systemd_red_hat.service scripts/lvm2_lvmdbusd_systemd_red_hat.service scripts/lvm2_lvmetad_init_red_hat scripts/lvm2_lvmetad_systemd_red_hat.service scripts/lvm2_lvmetad_systemd_red_hat.socket scripts/lvm2_lvmpolld_init_red_hat scripts/lvm2_lvmpolld_systemd_red_hat.service scripts/lvm2_lvmpolld_systemd_red_hat.socket scripts/lvm2_lvmlockd_systemd_red_hat.service scripts/lvm2_lvmlocking_systemd_red_hat.service scripts/lvm2_monitoring_init_red_hat scripts/lvm2_monitoring_systemd_red_hat.service scripts/lvm2_pvscan_systemd_red_hat@.service scripts/lvm2_tmpfiles_red_hat.conf scripts/lvmdump.sh scripts/Makefile test/Makefile test/api/Makefile test/api/python_lvm_unit.py test/unit/Makefile tools/Makefile udev/Makefile"
cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
@@ -16491,10 +16269,14 @@ do
"daemons/dmeventd/plugins/thin/Makefile") CONFIG_FILES="$CONFIG_FILES daemons/dmeventd/plugins/thin/Makefile" ;;
"daemons/dmfilemapd/Makefile") CONFIG_FILES="$CONFIG_FILES daemons/dmfilemapd/Makefile" ;;
"daemons/lvmdbusd/Makefile") CONFIG_FILES="$CONFIG_FILES daemons/lvmdbusd/Makefile" ;;
"daemons/lvmdbusd/lvmdbusd") CONFIG_FILES="$CONFIG_FILES daemons/lvmdbusd/lvmdbusd" ;;
"daemons/lvmdbusd/lvmdb.py") CONFIG_FILES="$CONFIG_FILES daemons/lvmdbusd/lvmdb.py" ;;
"daemons/lvmdbusd/lvm_shell_proxy.py") CONFIG_FILES="$CONFIG_FILES daemons/lvmdbusd/lvm_shell_proxy.py" ;;
"daemons/lvmdbusd/path.py") CONFIG_FILES="$CONFIG_FILES daemons/lvmdbusd/path.py" ;;
"daemons/lvmetad/Makefile") CONFIG_FILES="$CONFIG_FILES daemons/lvmetad/Makefile" ;;
"daemons/lvmpolld/Makefile") CONFIG_FILES="$CONFIG_FILES daemons/lvmpolld/Makefile" ;;
"daemons/lvmlockd/Makefile") CONFIG_FILES="$CONFIG_FILES daemons/lvmlockd/Makefile" ;;
"device_mapper/Makefile") CONFIG_FILES="$CONFIG_FILES device_mapper/Makefile" ;;
"conf/Makefile") CONFIG_FILES="$CONFIG_FILES conf/Makefile" ;;
"conf/example.conf") CONFIG_FILES="$CONFIG_FILES conf/example.conf" ;;
"conf/lvmlocal.conf") CONFIG_FILES="$CONFIG_FILES conf/lvmlocal.conf" ;;
@@ -16503,16 +16285,8 @@ do
"include/.symlinks") CONFIG_FILES="$CONFIG_FILES include/.symlinks" ;;
"include/Makefile") CONFIG_FILES="$CONFIG_FILES include/Makefile" ;;
"lib/Makefile") CONFIG_FILES="$CONFIG_FILES lib/Makefile" ;;
"lib/format1/Makefile") CONFIG_FILES="$CONFIG_FILES lib/format1/Makefile" ;;
"lib/format_pool/Makefile") CONFIG_FILES="$CONFIG_FILES lib/format_pool/Makefile" ;;
"lib/locking/Makefile") CONFIG_FILES="$CONFIG_FILES lib/locking/Makefile" ;;
"lib/mirror/Makefile") CONFIG_FILES="$CONFIG_FILES lib/mirror/Makefile" ;;
"lib/replicator/Makefile") CONFIG_FILES="$CONFIG_FILES lib/replicator/Makefile" ;;
"include/lvm-version.h") CONFIG_FILES="$CONFIG_FILES include/lvm-version.h" ;;
"lib/raid/Makefile") CONFIG_FILES="$CONFIG_FILES lib/raid/Makefile" ;;
"lib/snapshot/Makefile") CONFIG_FILES="$CONFIG_FILES lib/snapshot/Makefile" ;;
"lib/thin/Makefile") CONFIG_FILES="$CONFIG_FILES lib/thin/Makefile" ;;
"lib/cache_segtype/Makefile") CONFIG_FILES="$CONFIG_FILES lib/cache_segtype/Makefile" ;;
"libdaemon/Makefile") CONFIG_FILES="$CONFIG_FILES libdaemon/Makefile" ;;
"libdaemon/client/Makefile") CONFIG_FILES="$CONFIG_FILES libdaemon/client/Makefile" ;;
"libdaemon/server/Makefile") CONFIG_FILES="$CONFIG_FILES libdaemon/server/Makefile" ;;
@@ -16553,12 +16327,10 @@ do
"scripts/Makefile") CONFIG_FILES="$CONFIG_FILES scripts/Makefile" ;;
"test/Makefile") CONFIG_FILES="$CONFIG_FILES test/Makefile" ;;
"test/api/Makefile") CONFIG_FILES="$CONFIG_FILES test/api/Makefile" ;;
"test/api/python_lvm_unit.py") CONFIG_FILES="$CONFIG_FILES test/api/python_lvm_unit.py" ;;
"test/unit/Makefile") CONFIG_FILES="$CONFIG_FILES test/unit/Makefile" ;;
"tools/Makefile") CONFIG_FILES="$CONFIG_FILES tools/Makefile" ;;
"udev/Makefile") CONFIG_FILES="$CONFIG_FILES udev/Makefile" ;;
"unit-tests/datastruct/Makefile") CONFIG_FILES="$CONFIG_FILES unit-tests/datastruct/Makefile" ;;
"unit-tests/regex/Makefile") CONFIG_FILES="$CONFIG_FILES unit-tests/regex/Makefile" ;;
"unit-tests/mm/Makefile") CONFIG_FILES="$CONFIG_FILES unit-tests/mm/Makefile" ;;
*) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
esac

View File

@@ -77,6 +77,7 @@ AC_PROG_CC
AC_PROG_CXX
CFLAGS=$save_CFLAGS
CXXFLAGS=$save_CXXFLAGS
PATH_SBIN="$PATH:/usr/sbin:/sbin"
dnl probably no longer needed in 2008, but...
AC_PROG_GCC_TRADITIONAL
@@ -102,7 +103,7 @@ AC_HEADER_SYS_WAIT
AC_HEADER_TIME
AC_CHECK_HEADERS([assert.h ctype.h dirent.h errno.h fcntl.h float.h \
getopt.h inttypes.h langinfo.h libgen.h limits.h locale.h paths.h \
getopt.h inttypes.h langinfo.h libaio.h libgen.h limits.h locale.h paths.h \
signal.h stdarg.h stddef.h stdio.h stdlib.h string.h sys/file.h \
sys/ioctl.h syslog.h sys/mman.h sys/param.h sys/resource.h sys/stat.h \
sys/time.h sys/types.h sys/utsname.h sys/wait.h time.h \
@@ -191,9 +192,15 @@ AC_SUBST(HAVE_FULL_RELRO)
################################################################################
dnl -- Prefix is /usr by default, the exec_prefix default is setup later
AC_PREFIX_DEFAULT(/usr)
if test "$prefix" = NONE; then
datarootdir=${ac_default_prefix}/share
fi
################################################################################
dnl -- Clear default exec_prefix - install into /sbin rather than /usr/sbin
test "$exec_prefix" = NONE -a "$prefix" = NONE && exec_prefix=""
test "x$prefix" = xNONE && prefix=$ac_default_prefix
# Let make expand exec_prefix.
test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
################################################################################
dnl -- Setup the ownership of the files
@@ -275,58 +282,6 @@ esac
AC_MSG_RESULT($MANGLING)
AC_DEFINE_UNQUOTED([DEFAULT_DM_NAME_MANGLING], $mangling, [Define default name mangling behaviour])
################################################################################
dnl -- LVM1 tool fallback option
AC_MSG_CHECKING(whether to enable lvm1 fallback)
AC_ARG_ENABLE(lvm1_fallback,
AC_HELP_STRING([--enable-lvm1_fallback],
[use this to fall back and use LVM1 binaries if
device-mapper is missing from the kernel]),
LVM1_FALLBACK=$enableval, LVM1_FALLBACK=no)
AC_MSG_RESULT($LVM1_FALLBACK)
if test "$LVM1_FALLBACK" = yes; then
DEFAULT_FALLBACK_TO_LVM1=1
AC_DEFINE([LVM1_FALLBACK], 1, [Define to 1 if 'lvm' should fall back to using LVM1 binaries if device-mapper is missing from the kernel])
else
DEFAULT_FALLBACK_TO_LVM1=0
fi
AC_DEFINE_UNQUOTED(DEFAULT_FALLBACK_TO_LVM1, [$DEFAULT_FALLBACK_TO_LVM1],
[Fall back to LVM1 by default if device-mapper is missing from the kernel.])
################################################################################
dnl -- format1 inclusion type
AC_MSG_CHECKING(whether to include support for lvm1 metadata)
AC_ARG_WITH(lvm1,
AC_HELP_STRING([--with-lvm1=TYPE],
[LVM1 metadata support: internal/shared/none [internal]]),
LVM1=$withval, LVM1=internal)
AC_MSG_RESULT($LVM1)
case "$LVM1" in
none|shared) ;;
internal) AC_DEFINE([LVM1_INTERNAL], 1,
[Define to 1 to include built-in support for LVM1 metadata.]) ;;
*) AC_MSG_ERROR([--with-lvm1 parameter invalid]) ;;
esac
################################################################################
dnl -- format_pool inclusion type
AC_MSG_CHECKING(whether to include support for GFS pool metadata)
AC_ARG_WITH(pool,
AC_HELP_STRING([--with-pool=TYPE],
[GFS pool read-only support: internal/shared/none [internal]]),
POOL=$withval, POOL=internal)
AC_MSG_RESULT($POOL)
case "$POOL" in
none|shared) ;;
internal) AC_DEFINE([POOL_INTERNAL], 1,
[Define to 1 to include built-in support for GFS pool metadata.]) ;;
*) AC_MSG_ERROR([--with-pool parameter invalid])
esac
################################################################################
dnl -- cluster_locking inclusion type
AC_MSG_CHECKING(whether to include support for cluster locking)
@@ -377,13 +332,6 @@ esac
################################################################################
dnl -- raid inclusion type
AC_MSG_CHECKING(whether to include raid)
AC_ARG_WITH(raid,
AC_HELP_STRING([--with-raid=TYPE],
[raid support: internal/shared/none [internal]]),
RAID=$withval, RAID=internal)
AC_MSG_RESULT($RAID)
AC_ARG_WITH(default-mirror-segtype,
AC_HELP_STRING([--with-default-mirror-segtype=TYPE],
[default mirror segtype: raid1/mirror [raid1]]),
@@ -392,14 +340,9 @@ AC_ARG_WITH(default-raid10-segtype,
AC_HELP_STRING([--with-default-raid10-segtype=TYPE],
[default mirror segtype: raid10/mirror [raid10]]),
DEFAULT_RAID10_SEGTYPE=$withval, DEFAULT_RAID10_SEGTYPE="raid10")
case "$RAID" in
none) test "$DEFAULT_MIRROR_SEGTYPE" = "raid1" && DEFAULT_MIRROR_SEGTYPE="mirror"
test "$DEFAULT_RAID10_SEGTYPE" = "raid10" && DEFAULT_RAID10_SEGTYPE="mirror" ;;
shared) ;;
internal) AC_DEFINE([RAID_INTERNAL], 1,
[Define to 1 to include built-in support for raid.]) ;;
*) AC_MSG_ERROR([--with-raid parameter invalid]) ;;
esac
AC_DEFINE([RAID_INTERNAL], 1,
[Define to 1 to include built-in support for raid.])
AC_DEFINE_UNQUOTED([DEFAULT_MIRROR_SEGTYPE], ["$DEFAULT_MIRROR_SEGTYPE"],
[Default segtype used for mirror volumes.])
@@ -408,22 +351,6 @@ AC_DEFINE_UNQUOTED([DEFAULT_RAID10_SEGTYPE], ["$DEFAULT_RAID10_SEGTYPE"],
[Default segtype used for raid10 volumes.])
################################################################################
dnl -- asynchronous volume replicator inclusion type
AC_MSG_CHECKING(whether to include replicators)
AC_ARG_WITH(replicators,
AC_HELP_STRING([--with-replicators=TYPE],
[replicator support: internal/shared/none [none]]),
REPLICATORS=$withval, REPLICATORS=none)
AC_MSG_RESULT($REPLICATORS)
case "$REPLICATORS" in
none|shared) ;;
internal) AC_DEFINE([REPLICATOR_INTERNAL], 1,
[Define to 1 to include built-in support for replicators.]) ;;
*) AC_MSG_ERROR([--with-replicators parameter invalid ($REPLICATORS)]) ;;
esac
AC_ARG_WITH(default-sparse-segtype,
AC_HELP_STRING([--with-default-sparse-segtype=TYPE],
[default sparse segtype: thin/snapshot [thin]]),
@@ -478,7 +405,7 @@ case "$THIN" in
internal|shared)
# Empty means a config way to ignore thin checking
if test "$THIN_CHECK_CMD" = "autodetect"; then
AC_PATH_TOOL(THIN_CHECK_CMD, thin_check)
AC_PATH_TOOL(THIN_CHECK_CMD, thin_check, [], [$PATH_SBIN])
if test -z "$THIN_CHECK_CMD"; then
AC_MSG_WARN([thin_check not found in path $PATH])
THIN_CHECK_CMD=/usr/sbin/thin_check
@@ -502,7 +429,7 @@ case "$THIN" in
fi
# Empty means a config way to ignore thin dumping
if test "$THIN_DUMP_CMD" = "autodetect"; then
AC_PATH_TOOL(THIN_DUMP_CMD, thin_dump)
AC_PATH_TOOL(THIN_DUMP_CMD, thin_dump, [], [$PATH_SBIN])
test -z "$THIN_DUMP_CMD" && {
AC_MSG_WARN(thin_dump not found in path $PATH)
THIN_DUMP_CMD=/usr/sbin/thin_dump
@@ -511,7 +438,7 @@ case "$THIN" in
fi
# Empty means a config way to ignore thin repairing
if test "$THIN_REPAIR_CMD" = "autodetect"; then
AC_PATH_TOOL(THIN_REPAIR_CMD, thin_repair)
AC_PATH_TOOL(THIN_REPAIR_CMD, thin_repair, [], [$PATH_SBIN])
test -z "$THIN_REPAIR_CMD" && {
AC_MSG_WARN(thin_repair not found in path $PATH)
THIN_REPAIR_CMD=/usr/sbin/thin_repair
@@ -520,7 +447,7 @@ case "$THIN" in
fi
# Empty means a config way to ignore thin restoring
if test "$THIN_RESTORE_CMD" = "autodetect"; then
AC_PATH_TOOL(THIN_RESTORE_CMD, thin_restore)
AC_PATH_TOOL(THIN_RESTORE_CMD, thin_restore, [], [$PATH_SBIN])
test -z "$THIN_RESTORE_CMD" && {
AC_MSG_WARN(thin_restore not found in path $PATH)
THIN_RESTORE_CMD=/usr/sbin/thin_restore
@@ -592,7 +519,7 @@ case "$CACHE" in
internal|shared)
# Empty means a config way to ignore cache checking
if test "$CACHE_CHECK_CMD" = "autodetect"; then
AC_PATH_TOOL(CACHE_CHECK_CMD, cache_check)
AC_PATH_TOOL(CACHE_CHECK_CMD, cache_check, [], [$PATH_SBIN])
if test -z "$CACHE_CHECK_CMD"; then
AC_MSG_WARN([cache_check not found in path $PATH])
CACHE_CHECK_CMD=/usr/sbin/cache_check
@@ -627,7 +554,7 @@ case "$CACHE" in
fi
# Empty means a config way to ignore cache dumping
if test "$CACHE_DUMP_CMD" = "autodetect"; then
AC_PATH_TOOL(CACHE_DUMP_CMD, cache_dump)
AC_PATH_TOOL(CACHE_DUMP_CMD, cache_dump, [], [$PATH_SBIN])
test -z "$CACHE_DUMP_CMD" && {
AC_MSG_WARN(cache_dump not found in path $PATH)
CACHE_DUMP_CMD=/usr/sbin/cache_dump
@@ -636,7 +563,7 @@ case "$CACHE" in
fi
# Empty means a config way to ignore cache repairing
if test "$CACHE_REPAIR_CMD" = "autodetect"; then
AC_PATH_TOOL(CACHE_REPAIR_CMD, cache_repair)
AC_PATH_TOOL(CACHE_REPAIR_CMD, cache_repair, [], [$PATH_SBIN])
test -z "$CACHE_REPAIR_CMD" && {
AC_MSG_WARN(cache_repair not found in path $PATH)
CACHE_REPAIR_CMD=/usr/sbin/cache_repair
@@ -645,7 +572,7 @@ case "$CACHE" in
fi
# Empty means a config way to ignore cache restoring
if test "$CACHE_RESTORE_CMD" = "autodetect"; then
AC_PATH_TOOL(CACHE_RESTORE_CMD, cache_restore)
AC_PATH_TOOL(CACHE_RESTORE_CMD, cache_restore, [], [$PATH_SBIN])
test -z "$CACHE_RESTORE_CMD" && {
AC_MSG_WARN(cache_restore not found in path $PATH)
CACHE_RESTORE_CMD=/usr/sbin/cache_restore
@@ -1076,20 +1003,6 @@ if test "$PROFILING" = yes; then
fi
fi
################################################################################
dnl -- Enable testing
AC_MSG_CHECKING(whether to enable unit testing)
AC_ARG_ENABLE(testing,
AC_HELP_STRING([--enable-testing],
[enable testing targets in the makefile]),
TESTING=$enableval, TESTING=no)
AC_MSG_RESULT($TESTING)
if test "$TESTING" = yes; then
pkg_config_init
PKG_CHECK_MODULES(CUNIT, cunit >= 2.0)
fi
################################################################################
dnl -- Set LVM2 testsuite data
TESTSUITE_DATA='${datarootdir}/lvm2-testsuite'
@@ -1464,6 +1377,8 @@ AC_SUBST([LVM2APP_LIB])
test "$APPLIB" = yes \
&& LVM2APP_LIB=-llvm2app \
|| LVM2APP_LIB=
AS_IF([test "$APPLIB"],
[AC_MSG_WARN([liblvm2app is deprecated. Use D-Bus API])])
################################################################################
dnl -- Enable cmdlib
@@ -1484,6 +1399,8 @@ AC_ARG_ENABLE(dbus-service,
AC_HELP_STRING([--enable-dbus-service], [install D-Bus support]),
BUILD_LVMDBUSD=$enableval, BUILD_LVMDBUSD=no)
AC_MSG_RESULT($BUILD_LVMDBUSD)
AS_IF([test "$NOTIFYDBUS_SUPPORT" = yes && test "BUILD_LVMDBUSD" = yes],
[AC_MSG_WARN([Building D-Bus support without D-Bus notifications.])])
################################################################################
dnl -- Enable Python liblvm2app bindings
@@ -1536,7 +1453,7 @@ if test "$PYTHON3_BINDINGS" = yes -o "$BUILD_LVMDBUSD" = yes; then
PYTHON3_INCDIRS=`"$PYTHON3_CONFIG" --includes`
PYTHON3_LIBDIRS=`"$PYTHON3_CONFIG" --libs`
PYTHON3DIR=$pythondir
PYTHON_BINDINGS=yes
test "$PYTHON3_BINDINGS" = yes && PYTHON_BINDINGS=yes
fi
if test "$BUILD_LVMDBUSD" = yes; then
@@ -1546,6 +1463,7 @@ if test "$BUILD_LVMDBUSD" = yes; then
fi
if test "$PYTHON_BINDINGS" = yes -o "$PYTHON2_BINDINGS" = yes -o "$PYTHON3_BINDINGS" = yes; then
AC_MSG_WARN([Python bindings are deprecated. Use D-Bus API])
test "$APPLIB" != yes && AC_MSG_ERROR([Python_bindings require --enable-applib])
fi
@@ -1609,10 +1527,6 @@ AC_CHECK_LIB(c, canonicalize_file_name,
AC_DEFINE([HAVE_CANONICALIZE_FILE_NAME], 1,
[Define to 1 if canonicalize_file_name is available.]))
################################################################################
dnl -- Clear default exec_prefix - install into /sbin rather than /usr/sbin
test "$exec_prefix" = NONE -a "$prefix" = NONE && exec_prefix=""
################################################################################
dnl -- Check for dlopen
AC_CHECK_LIB(dl, dlopen,
@@ -1625,8 +1539,6 @@ AC_CHECK_LIB(dl, dlopen,
################################################################################
dnl -- Check for shared/static conflicts
if [[ \( "$LVM1" = shared -o "$POOL" = shared -o "$CLUSTER" = shared \
-o "$SNAPSHOTS" = shared -o "$MIRRORS" = shared \
-o "$RAID" = shared -o "$CACHE" = shared \
\) -a "$STATIC_LINK" = yes ]]; then
AC_MSG_ERROR([Features cannot be 'shared' when building statically])
fi
@@ -1879,26 +1791,23 @@ if test "$BUILD_DMFILEMAPD" = yes; then
fi
################################################################################
AC_PATH_TOOL(MODPROBE_CMD, modprobe)
AC_PATH_TOOL(MODPROBE_CMD, modprobe, [], [$PATH_SBIN])
if test -n "$MODPROBE_CMD"; then
AC_DEFINE_UNQUOTED([MODPROBE_CMD], ["$MODPROBE_CMD"], [The path to 'modprobe', if available.])
fi
SYSCONFDIR="$(eval echo $(eval echo $sysconfdir))"
lvm_exec_prefix=$exec_prefix
test "$lvm_exec_prefix" = NONE && lvm_exec_prefix=$prefix
test "$lvm_exec_prefix" = NONE && lvm_exec_prefix=$ac_default_prefix
LVM_PATH="$lvm_exec_prefix/sbin/lvm"
SBINDIR="$(eval echo $(eval echo $sbindir))"
LVM_PATH="$SBINDIR/lvm"
AC_DEFINE_UNQUOTED(LVM_PATH, ["$LVM_PATH"], [Path to lvm binary.])
clvmd_prefix=$ac_default_prefix
test "$prefix" != NONE && clvmd_prefix=$prefix
CLVMD_PATH="$clvmd_prefix/sbin/clvmd"
USRSBINDIR="$(eval echo $(eval echo $usrsbindir))"
CLVMD_PATH="$USRSBINDIR/clvmd"
AC_DEFINE_UNQUOTED(CLVMD_PATH, ["$CLVMD_PATH"], [Path to clvmd binary.])
FSADM_PATH="$lvm_exec_prefix/sbin/fsadm"
FSADM_PATH="$SBINDIR/fsadm"
AC_DEFINE_UNQUOTED(FSADM_PATH, ["$FSADM_PATH"], [Path to fsadm binary.])
################################################################################
@@ -1918,7 +1827,7 @@ if test "$BUILD_DMEVENTD" = yes; then
AC_HELP_STRING([--with-dmeventd-path=PATH],
[dmeventd path [EPREFIX/sbin/dmeventd]]),
DMEVENTD_PATH=$withval,
DMEVENTD_PATH="$lvm_exec_prefix/sbin/dmeventd")
DMEVENTD_PATH="$SBINDIR/dmeventd")
AC_DEFINE_UNQUOTED(DMEVENTD_PATH, ["$DMEVENTD_PATH"],
[Path to dmeventd binary.])
fi
@@ -1961,13 +1870,17 @@ AC_ARG_WITH(default-cache-subdir,
AC_DEFINE_UNQUOTED(DEFAULT_CACHE_SUBDIR, ["$DEFAULT_CACHE_SUBDIR"],
[Name of default metadata cache subdirectory.])
# Select default system locking dir, prefer /run/lock over /var/lock
DEFAULT_SYS_LOCK_DIR="$RUN_DIR/lock"
test -d "$DEFAULT_SYS_LOCK_DIR" || DEFAULT_SYS_LOCK_DIR="/var/lock"
# Support configurable locking subdir for lvm
AC_ARG_WITH(default-locking-dir,
AC_HELP_STRING([--with-default-locking-dir=DIR],
[default locking directory [autodetect_lock_dir/lvm]]),
DEFAULT_LOCK_DIR=$withval,
[AC_MSG_CHECKING(for default lock directory)
DEFAULT_LOCK_DIR="$RUN_DIR/lock/lvm"
test -d "$RUN_DIR/lock" || DEFAULT_LOCK_DIR="/var/lock/lvm"
DEFAULT_LOCK_DIR="$DEFAULT_SYS_LOCK_DIR/lvm"
AC_MSG_RESULT($DEFAULT_LOCK_DIR)])
AC_DEFINE_UNQUOTED(DEFAULT_LOCK_DIR, ["$DEFAULT_LOCK_DIR"],
[Name of default locking directory.])
@@ -2054,7 +1967,6 @@ AC_SUBST(DEFAULT_CACHE_SUBDIR)
AC_SUBST(DEFAULT_DATA_ALIGNMENT)
AC_SUBST(DEFAULT_DM_RUN_DIR)
AC_SUBST(DEFAULT_LOCK_DIR)
AC_SUBST(DEFAULT_FALLBACK_TO_LVM1)
AC_SUBST(DEFAULT_MIRROR_SEGTYPE)
AC_SUBST(DEFAULT_PID_DIR)
AC_SUBST(DEFAULT_PROFILE_SUBDIR)
@@ -2062,6 +1974,7 @@ AC_SUBST(DEFAULT_RAID10_SEGTYPE)
AC_SUBST(DEFAULT_RUN_DIR)
AC_SUBST(DEFAULT_SPARSE_SEGTYPE)
AC_SUBST(DEFAULT_SYS_DIR)
AC_SUBST(DEFAULT_SYS_LOCK_DIR)
AC_SUBST(DEFAULT_USE_BLKID_WIPING)
AC_SUBST(DEFAULT_USE_LVMETAD)
AC_SUBST(DEFAULT_USE_LVMPOLLD)
@@ -2084,8 +1997,6 @@ AC_SUBST(JOBS)
AC_SUBST(LDDEPS)
AC_SUBST(LIBS)
AC_SUBST(LIB_SUFFIX)
AC_SUBST(LVM1)
AC_SUBST(LVM1_FALLBACK)
AC_SUBST(LVM_VERSION)
AC_SUBST(LVM_LIBAPI)
AC_SUBST(LVM_MAJOR)
@@ -2102,7 +2013,6 @@ AC_SUBST(OCF)
AC_SUBST(OCFDIR)
AC_SUBST(ODIRECT)
AC_SUBST(PKGCONFIG)
AC_SUBST(POOL)
AC_SUBST(M_LIBS)
AC_SUBST(PTHREAD_LIBS)
AC_SUBST(PYTHON2)
@@ -2118,7 +2028,6 @@ AC_SUBST(PYTHON2DIR)
AC_SUBST(PYTHON3DIR)
AC_SUBST(QUORUM_CFLAGS)
AC_SUBST(QUORUM_LIBS)
AC_SUBST(RAID)
AC_SUBST(RT_LIBS)
AC_SUBST(READLINE_LIBS)
AC_SUBST(REPLICATORS)
@@ -2126,13 +2035,14 @@ AC_SUBST(SACKPT_CFLAGS)
AC_SUBST(SACKPT_LIBS)
AC_SUBST(SALCK_CFLAGS)
AC_SUBST(SALCK_LIBS)
AC_SUBST(SBINDIR)
AC_SUBST(SELINUX_LIBS)
AC_SUBST(SELINUX_PC)
AC_SUBST(SYSCONFDIR)
AC_SUBST(SYSTEMD_LIBS)
AC_SUBST(SNAPSHOTS)
AC_SUBST(STATICDIR)
AC_SUBST(STATIC_LINK)
AC_SUBST(TESTING)
AC_SUBST(TESTSUITE_DATA)
AC_SUBST(THIN)
AC_SUBST(THIN_CHECK_CMD)
@@ -2150,6 +2060,7 @@ AC_SUBST(UDEV_SYSTEMD_BACKGROUND_JOBS)
AC_SUBST(UDEV_RULE_EXEC_DETECTION)
AC_SUBST(UDEV_HAS_BUILTIN_BLKID)
AC_SUBST(USE_TRACKING)
AC_SUBST(USRSBINDIR)
AC_SUBST(VALGRIND_POOL)
AC_SUBST(WRITE_INSTALL)
AC_SUBST(DMEVENTD_PIDFILE)
@@ -2190,10 +2101,14 @@ daemons/dmeventd/plugins/snapshot/Makefile
daemons/dmeventd/plugins/thin/Makefile
daemons/dmfilemapd/Makefile
daemons/lvmdbusd/Makefile
daemons/lvmdbusd/lvmdbusd
daemons/lvmdbusd/lvmdb.py
daemons/lvmdbusd/lvm_shell_proxy.py
daemons/lvmdbusd/path.py
daemons/lvmetad/Makefile
daemons/lvmpolld/Makefile
daemons/lvmlockd/Makefile
device_mapper/Makefile
conf/Makefile
conf/example.conf
conf/lvmlocal.conf
@@ -2202,16 +2117,8 @@ conf/metadata_profile_template.profile
include/.symlinks
include/Makefile
lib/Makefile
lib/format1/Makefile
lib/format_pool/Makefile
lib/locking/Makefile
lib/mirror/Makefile
lib/replicator/Makefile
include/lvm-version.h
lib/raid/Makefile
lib/snapshot/Makefile
lib/thin/Makefile
lib/cache_segtype/Makefile
libdaemon/Makefile
libdaemon/client/Makefile
libdaemon/server/Makefile
@@ -2252,12 +2159,10 @@ scripts/lvmdump.sh
scripts/Makefile
test/Makefile
test/api/Makefile
test/api/python_lvm_unit.py
test/unit/Makefile
tools/Makefile
udev/Makefile
unit-tests/datastruct/Makefile
unit-tests/regex/Makefile
unit-tests/mm/Makefile
])
AC_OUTPUT

View File

@@ -74,7 +74,7 @@ TARGETS = \
include $(top_builddir)/make.tmpl
LIBS += $(LVMINTERNAL_LIBS) -ldevmapper $(PTHREAD_LIBS)
LIBS += $(LVMINTERNAL_LIBS) -ldevmapper $(PTHREAD_LIBS) -laio
CFLAGS += -fno-strict-aliasing $(EXTRA_EXEC_CFLAGS)
INSTALL_TARGETS = \

View File

@@ -108,7 +108,6 @@ int do_command(struct local_client *client, struct clvm_header *msg, int msglen,
lock_flags = args[1];
lockname = &args[2];
/* Check to see if the VG is in use by LVM1 */
status = do_check_lvm1(lockname);
do_lock_vg(lock_cmd, lock_flags, lockname);
break;
@@ -171,8 +170,10 @@ int do_command(struct local_client *client, struct clvm_header *msg, int msglen,
/* Check the status of the command and return the error text */
if (status) {
*retlen = 1 + ((*buf) ? dm_snprintf(*buf, buflen, "%s",
strerror(status)) : -1);
if (*buf)
*retlen = dm_snprintf(*buf, buflen, "%s", strerror(status)) + 1;
else
*retlen = 0;
}
return status;

View File

@@ -1105,31 +1105,31 @@ static void be_daemon(int timeout)
break;
default: /* Parent */
(void) close(devnull);
(void) close(child_pipe[1]);
wait_for_child(child_pipe[0], timeout);
wait_for_child(child_pipe[0], timeout); /* noreturn */
}
/* Detach ourself from the calling environment */
if (close(0) || close(1) || close(2)) {
perror("Error closing terminal FDs");
exit(4);
}
setsid();
if (dup2(devnull, 0) < 0 || dup2(devnull, 1) < 0
|| dup2(devnull, 2) < 0) {
if ((dup2(devnull, STDIN_FILENO) == -1) ||
(dup2(devnull, STDOUT_FILENO) == -1) ||
(dup2(devnull, STDERR_FILENO) == -1)) {
perror("Error setting terminal FDs to /dev/null");
log_error("Error setting terminal FDs to /dev/null: %m");
exit(5);
}
if ((devnull > STDERR_FILENO) && close(devnull)) {
log_sys_error("close", "/dev/null");
exit(7);
}
if (chdir("/")) {
log_error("Error setting current directory to /: %m");
exit(6);
}
setsid();
}
static int verify_message(char *buf, int len)
@@ -1999,6 +1999,9 @@ static int send_message(void *buf, int msglen, const char *csid, int fd,
return clops->cluster_send_message(buf, msglen, csid, errtext);
}
if (fd < 0)
return 0;
/* Make sure it all goes */
for (ptr = 0; ptr < msglen;) {
if ((len = write(fd, (char*)buf + ptr, msglen - ptr)) <= 0) {
@@ -2151,6 +2154,14 @@ static int add_to_lvmqueue(struct local_client *client, struct clvm_header *msg,
}
/* Return 0 if we can talk to an existing clvmd */
/*
* FIXME:
*
* This function returns only -1 or 0, but there are
* different levels of errors, some of them should stop
* further execution of clvmd thus another state is needed
* and some error message need to be only informational.
*/
static int check_local_clvmd(void)
{
int local_socket;
@@ -2170,7 +2181,11 @@ static int check_local_clvmd(void)
if (connect(local_socket,(struct sockaddr *) &sockaddr,
sizeof(sockaddr))) {
log_sys_error("connect", "local socket");
/* connection failure is expected state */
if (errno == ENOENT)
log_sys_debug("connect", "local socket");
else
log_sys_error("connect", "local socket");
ret = -1;
}

View File

@@ -639,16 +639,6 @@ int post_lock_lv(unsigned char command, unsigned char lock_flags,
return 0;
}
/* Check if a VG is in use by LVM1 so we don't stomp on it */
int do_check_lvm1(const char *vgname)
{
int status;
status = check_lvm1_vg_inactive(cmd, vgname);
return status == 1 ? 0 : EBUSY;
}
int do_refresh_cache(void)
{
DEBUGLOG("Refreshing context\n");
@@ -661,10 +651,9 @@ int do_refresh_cache(void)
return -1;
}
init_full_scan_done(0);
init_ignore_suspended_devices(1);
lvmcache_force_next_label_scan();
lvmcache_label_scan(cmd);
label_scan_destroy(cmd); /* destroys bcache (to close devs), keeps lvmcache */
dm_pool_empty(cmd->mem);
pthread_mutex_unlock(&lvm_lock);
@@ -807,8 +796,7 @@ static void lvm2_log_fn(int level, const char *file, int line, int dm_errno,
if (level != _LOG_ERR && level != _LOG_FATAL)
return;
strncpy(last_error, message, sizeof(last_error));
last_error[sizeof(last_error)-1] = '\0';
(void) dm_strncpy(last_error, message, sizeof(last_error));
}
/* This checks some basic cluster-LVM configuration stuff */
@@ -844,7 +832,7 @@ void lvm_do_backup(const char *vgname)
pthread_mutex_lock(&lvm_lock);
vg = vg_read_internal(cmd, vgname, NULL /*vgid*/, WARN_PV_READ, &consistent);
vg = vg_read_internal(cmd, vgname, NULL /*vgid*/, 0, 0, WARN_PV_READ, &consistent);
if (vg && consistent)
check_current_backup(vg);

View File

@@ -25,7 +25,6 @@ extern int do_lock_lv(unsigned char lock_cmd, unsigned char lock_flags,
extern const char *do_lock_query(char *resource);
extern int post_lock_lv(unsigned char lock_cmd, unsigned char lock_flags,
char *resource);
extern int do_check_lvm1(const char *vgname);
extern int do_refresh_cache(void);
extern int init_clvm(struct dm_hash_table *excl_uuid);
extern void destroy_lvm(void);

View File

@@ -166,6 +166,9 @@ int cluster_send(struct clog_request *rq)
{
int r;
int found = 0;
#if CMIRROR_HAS_CHECKPOINT
int count = 0;
#endif
struct iovec iov;
struct clog_cpg *entry;
@@ -203,8 +206,6 @@ int cluster_send(struct clog_request *rq)
#if CMIRROR_HAS_CHECKPOINT
do {
int count = 0;
r = cpg_mcast_joined(entry->handle, CPG_TYPE_AGREED, &iov, 1);
if (r != SA_AIS_ERR_TRY_AGAIN)
break;
@@ -1630,7 +1631,7 @@ int create_cluster_cpg(char *uuid, uint64_t luid)
size = ((strlen(uuid) + 1) > CPG_MAX_NAME_LENGTH) ?
CPG_MAX_NAME_LENGTH : (strlen(uuid) + 1);
strncpy(new->name.value, uuid, size);
(void) dm_strncpy(new->name.value, uuid, size);
new->name.length = (uint32_t)size;
new->luid = luid;

View File

@@ -451,15 +451,19 @@ static int _clog_ctr(char *uuid, uint64_t luid,
lc->skip_bit_warning = region_count;
lc->disk_fd = -1;
lc->log_dev_failed = 0;
strncpy(lc->uuid, uuid, DM_UUID_LEN);
if (!dm_strncpy(lc->uuid, uuid, DM_UUID_LEN)) {
LOG_ERROR("Cannot use too long UUID %s.", uuid);
r = -EINVAL;
goto fail;
}
lc->luid = luid;
if (get_log(lc->uuid, lc->luid) ||
get_pending_log(lc->uuid, lc->luid)) {
LOG_ERROR("[%s/%" PRIu64 "u] Log already exists, unable to create.",
SHORT_UUID(lc->uuid), lc->luid);
dm_free(lc);
return -EINVAL;
r = -EINVAL;
goto fail;
}
dm_list_init(&lc->mark_list);

View File

@@ -14,7 +14,6 @@
#define _LVM_CLOG_LOGGING_H
#define _GNU_SOURCE
#define _FILE_OFFSET_BITS 64
#include "configure.h"
#include <stdio.h>

View File

@@ -62,6 +62,8 @@
#include <syslog.h>
#define DM_SIGNALED_EXIT 1
#define DM_SCHEDULED_EXIT 2
static volatile sig_atomic_t _exit_now = 0; /* set to '1' when signal is given to exit */
/* List (un)link macros. */
@@ -752,6 +754,7 @@ static void *_timeout_thread(void *unused __attribute__((unused)))
struct thread_status *thread;
struct timespec timeout;
time_t curr_time;
int ret;
DEBUGLOG("Timeout thread starting.");
pthread_cleanup_push(_exit_timeout, NULL);
@@ -773,7 +776,10 @@ static void *_timeout_thread(void *unused __attribute__((unused)))
} else {
DEBUGLOG("Sending SIGALRM to Thr %x for timeout.",
(int) thread->thread);
pthread_kill(thread->thread, SIGALRM);
ret = pthread_kill(thread->thread, SIGALRM);
if (ret && (ret != ESRCH))
log_error("Unable to wakeup Thr %x for timeout: %s.",
(int) thread->thread, strerror(ret));
}
_unlock_mutex();
}
@@ -863,6 +869,7 @@ static int _event_wait(struct thread_status *thread)
* This is so that you can break out of waiting on an event,
* either for a timeout event, or to cancel the thread.
*/
sigemptyset(&old);
sigemptyset(&set);
sigaddset(&set, SIGALRM);
if (pthread_sigmask(SIG_UNBLOCK, &set, &old) != 0) {
@@ -1750,7 +1757,7 @@ static void _init_thread_signals(void)
*/
static void _exit_handler(int sig __attribute__((unused)))
{
_exit_now = 1;
_exit_now = DM_SIGNALED_EXIT;
}
#ifdef __linux__
@@ -2248,6 +2255,8 @@ int main(int argc, char *argv[])
for (;;) {
if (_idle_since) {
if (_exit_now) {
if (_exit_now == DM_SCHEDULED_EXIT)
break; /* Only prints shutdown message */
log_info("dmeventd detected break while being idle "
"for %ld second(s), exiting.",
(long) (time(NULL) - _idle_since));
@@ -2264,15 +2273,14 @@ int main(int argc, char *argv[])
break;
}
}
} else if (_exit_now) {
_exit_now = 0;
} else if (_exit_now == DM_SIGNALED_EXIT) {
_exit_now = DM_SCHEDULED_EXIT;
/*
* When '_exit_now' is set, signal has been received,
* but can not simply exit unless all
* threads are done processing.
*/
log_warn("WARNING: There are still devices being monitored.");
log_warn("WARNING: Refusing to exit.");
log_info("dmeventd received break, scheduling exit.");
}
_process_request(&fifos);
_cleanup_unused_threads();

View File

@@ -754,11 +754,10 @@ int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next)
uuid = dm_task_get_uuid(dmt);
/* FIXME Distinguish errors connecting to daemon */
if (_do_event(next ? DM_EVENT_CMD_GET_NEXT_REGISTERED_DEVICE :
DM_EVENT_CMD_GET_REGISTERED_DEVICE, dmevh->dmeventd_path,
&msg, dmevh->dso, uuid, dmevh->mask, 0)) {
if ((ret = _do_event(next ? DM_EVENT_CMD_GET_NEXT_REGISTERED_DEVICE :
DM_EVENT_CMD_GET_REGISTERED_DEVICE, dmevh->dmeventd_path,
&msg, dmevh->dso, uuid, dmevh->mask, 0))) {
log_debug("%s: device not registered.", dm_task_get_name(dmt));
ret = -ENOENT;
goto fail;
}

View File

@@ -16,23 +16,7 @@ srcdir = @srcdir@
top_srcdir = @top_srcdir@
top_builddir = @top_builddir@
SUBDIRS += lvm2
ifneq ("@MIRRORS@", "none")
SUBDIRS += mirror
endif
ifneq ("@SNAPSHOTS@", "none")
SUBDIRS += snapshot
endif
ifneq ("@RAID@", "none")
SUBDIRS += raid
endif
ifneq ("@THIN@", "none")
SUBDIRS += thin
endif
SUBDIRS += lvm2 snapshot raid thin mirror
ifeq ($(MAKECMDGOALS),distclean)
SUBDIRS = lvm2 mirror snapshot raid thin

View File

@@ -62,27 +62,25 @@ struct dso_state {
DM_EVENT_LOG_FN("thin")
#define UUID_PREFIX "LVM-"
static int _run_command(struct dso_state *state)
{
char val[3][36];
char *env[] = { val[0], val[1], val[2], NULL };
char val[16];
int i;
/* Mark for possible lvm2 command we are running from dmeventd
* lvm2 will not try to talk back to dmeventd while processing it */
(void) dm_snprintf(val[0], sizeof(val[0]), "LVM_RUN_BY_DMEVENTD=1");
(void) setenv("LVM_RUN_BY_DMEVENTD", "1", 1);
if (state->data_percent) {
/* Prepare some known data to env vars for easy use */
(void) dm_snprintf(val[1], sizeof(val[1]), "DMEVENTD_THIN_POOL_DATA=%d",
state->data_percent / DM_PERCENT_1);
(void) dm_snprintf(val[2], sizeof(val[2]), "DMEVENTD_THIN_POOL_METADATA=%d",
state->metadata_percent / DM_PERCENT_1);
if (dm_snprintf(val, sizeof(val), "%d",
state->data_percent / DM_PERCENT_1) != -1)
(void) setenv("DMEVENTD_THIN_POOL_DATA", val, 1);
if (dm_snprintf(val, sizeof(val), "%d",
state->metadata_percent / DM_PERCENT_1) != -1)
(void) setenv("DMEVENTD_THIN_POOL_METADATA", val, 1);
} else {
/* For an error event it's for a user to check status and decide */
env[1] = NULL;
log_debug("Error event processing.");
}
@@ -97,7 +95,7 @@ static int _run_command(struct dso_state *state)
/* child */
(void) close(0);
for (i = 3; i < 255; ++i) (void) close(i);
execve(state->argv[0], state->argv, env);
execvp(state->argv[0], state->argv);
_exit(errno);
} else if (state->pid == -1) {
log_error("Can't fork command %s.", state->cmd_str);

View File

@@ -802,7 +802,7 @@ bad:
return 1;
}
static const char * _mode_names[] = {
static const char * const _mode_names[] = {
"inode",
"path"
};
@@ -827,8 +827,10 @@ int main(int argc, char **argv)
"mode=%s, path=%s", fm.fd, fm.group_id,
_mode_names[fm.mode], fm.path);
if (!_foreground && !_daemonise(&fm))
if (!_foreground && !_daemonise(&fm)) {
dm_free(fm.path);
return 1;
}
return _dmfilemapd(&fm);
}

View File

@@ -1 +1,4 @@
path.py
lvmdbusd
lvmdb.py
lvm_shell_proxy.py

View File

@@ -26,9 +26,7 @@ LVMDBUS_SRCDIR_FILES = \
__init__.py \
job.py \
loader.py \
lvmdb.py \
main.py \
lvm_shell_proxy.py \
lv.py \
manager.py \
objectmanager.py \
@@ -40,14 +38,21 @@ LVMDBUS_SRCDIR_FILES = \
vg.py
LVMDBUS_BUILDDIR_FILES = \
lvmdb.py \
lvm_shell_proxy.py \
path.py
LVMDBUSD = $(srcdir)/lvmdbusd
LVMDBUSD = lvmdbusd
CLEAN_DIRS += __pycache__
include $(top_builddir)/make.tmpl
.PHONY: install_lvmdbusd
all:
test -x $(LVMDBUSD) || chmod 755 $(LVMDBUSD)
install_lvmdbusd:
$(INSTALL_DIR) $(sbindir)
$(INSTALL_SCRIPT) $(LVMDBUSD) $(sbindir)
@@ -63,4 +68,5 @@ install_lvm2: install_lvmdbusd
install: install_lvm2
DISTCLEAN_TARGETS+= \
$(LVMDBUS_BUILDDIR_FILES)
$(LVMDBUS_BUILDDIR_FILES) \
$(LVMDBUSD)

View File

@@ -158,5 +158,6 @@ def _run_cmd(req):
def cmd_runner(request):
t = threading.Thread(target=_run_cmd, args=(request,))
t = threading.Thread(target=_run_cmd, args=(request,),
name="cmd_runner %s" % str(request.method))
t.start()

View File

@@ -152,7 +152,8 @@ class StateUpdate(object):
load(refresh=False, emit_signal=False, need_main_thread=False)
self.thread = threading.Thread(target=StateUpdate.update_thread,
args=(self,))
args=(self,),
name="StateUpdate.update_thread")
def load(self, refresh=True, emit_signal=True, cache_refresh=True,
log=True, need_main_thread=True):

View File

@@ -8,7 +8,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from .automatedproperties import AutomatedProperties
from .utils import job_obj_path_generate, mt_async_result, mt_run_no_wait
from .utils import job_obj_path_generate, mt_async_call
from . import cfg
from .cfg import JOB_INTERFACE
import dbus
@@ -30,7 +30,7 @@ class WaitingClient(object):
# Remove ourselves from waiting client
wc.job_state.remove_waiting_client(wc)
wc.timer_id = -1
mt_async_result(wc.cb, wc.job_state.Complete)
mt_async_call(wc.cb, wc.job_state.Complete)
wc.job_state = None
def __init__(self, job_state, tmo, cb, cbe):
@@ -55,7 +55,7 @@ class WaitingClient(object):
GLib.source_remove(self.timer_id)
self.timer_id = -1
mt_async_result(self.cb, self.job_state.Complete)
mt_async_call(self.cb, self.job_state.Complete)
self.job_state = None
@@ -188,7 +188,7 @@ class Job(AutomatedProperties):
@Complete.setter
def Complete(self, value):
self.state.Complete = value
mt_run_no_wait(Job._signal_complete, self)
mt_async_call(Job._signal_complete, self)
@property
def GetError(self):

View File

@@ -232,7 +232,6 @@ class LvState(State):
@utils.dbus_property(LV_COMMON_INTERFACE, 'Attr', 's')
@utils.dbus_property(LV_COMMON_INTERFACE, 'DataPercent', 'u')
@utils.dbus_property(LV_COMMON_INTERFACE, 'SnapPercent', 'u')
@utils.dbus_property(LV_COMMON_INTERFACE, 'DataPercent', 'u')
@utils.dbus_property(LV_COMMON_INTERFACE, 'MetaDataPercent', 'u')
@utils.dbus_property(LV_COMMON_INTERFACE, 'CopyPercent', 'u')
@utils.dbus_property(LV_COMMON_INTERFACE, 'SyncPercent', 'u')
@@ -498,7 +497,7 @@ class Lv(LvCommon):
# it is a thin lv
if not dbo.IsThinVolume:
if optional_size == 0:
space = dbo.SizeBytes / 80
space = dbo.SizeBytes // 80
remainder = space % 512
optional_size = space + 512 - remainder

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python3
#!@PYTHON3@
# Copyright (C) 2015-2016 Red Hat, Inc. All rights reserved.
#

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python3
#!@PYTHON3@
# Copyright (C) 2015-2016 Red Hat, Inc. All rights reserved.
#

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python3
#!@PYTHON3@
# Copyright (C) 2015-2016 Red Hat, Inc. All rights reserved.
#

View File

@@ -63,6 +63,24 @@ def check_bb_size(value):
return v
def install_signal_handlers():
# Because of the glib main loop stuff the python signal handler code is
# apparently not usable and we need to use the glib calls instead
signal_add = None
if hasattr(GLib, 'unix_signal_add'):
signal_add = GLib.unix_signal_add
elif hasattr(GLib, 'unix_signal_add_full'):
signal_add = GLib.unix_signal_add_full
if signal_add:
signal_add(GLib.PRIORITY_HIGH, signal.SIGHUP, utils.handler, signal.SIGHUP)
signal_add(GLib.PRIORITY_HIGH, signal.SIGINT, utils.handler, signal.SIGINT)
signal_add(GLib.PRIORITY_HIGH, signal.SIGUSR1, utils.handler, signal.SIGUSR1)
else:
log_error("GLib.unix_signal_[add|add_full] are NOT available!")
def main():
start = time.time()
# Add simple command line handling
@@ -112,12 +130,7 @@ def main():
# List of threads that we start up
thread_list = []
# Install signal handlers
for s in [signal.SIGHUP, signal.SIGINT]:
try:
signal.signal(s, utils.handler)
except RuntimeError:
pass
install_signal_handlers()
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
dbus.mainloop.glib.threads_init()
@@ -138,7 +151,8 @@ def main():
# Using a thread to process requests, we cannot hang the dbus library
# thread that is handling the dbus interface
thread_list.append(threading.Thread(target=process_request))
thread_list.append(threading.Thread(target=process_request,
name='process_request'))
# Have a single thread handling updating lvm and the dbus model so we
# don't have multiple threads doing this as the same time
@@ -176,5 +190,7 @@ def main():
for thread in thread_list:
thread.join()
except KeyboardInterrupt:
utils.handler(signal.SIGINT, None)
# If we are unable to register signal handler, we will end up here when
# the service gets a ^C or a kill -2 <parent pid>
utils.handler(signal.SIGINT)
return 0

View File

@@ -79,7 +79,9 @@ class PvState(State):
self.lv = self._lv_object_list(vg_name)
if vg_name:
# It's possible to have a vg_name and no uuid with the main example
# being when the vg_name == '[unknown]'
if vg_uuid and vg_name:
self.vg_path = cfg.om.get_object_path_by_uuid_lvm_id(
vg_uuid, vg_name, vg_obj_path_generate)
else:

View File

@@ -13,7 +13,7 @@ from gi.repository import GLib
from .job import Job
from . import cfg
import traceback
from .utils import log_error, mt_async_result
from .utils import log_error, mt_async_call
class RequestEntry(object):
@@ -116,9 +116,9 @@ class RequestEntry(object):
if error_rc == 0:
if self.cb:
if self._return_tuple:
mt_async_result(self.cb, (result, '/'))
mt_async_call(self.cb, (result, '/'))
else:
mt_async_result(self.cb, result)
mt_async_call(self.cb, result)
else:
if self.cb_error:
if not error_exception:
@@ -129,7 +129,7 @@ class RequestEntry(object):
else:
error_exception = Exception(error_msg)
mt_async_result(self.cb_error, error_exception)
mt_async_call(self.cb_error, error_exception)
else:
# We have a job and it's complete, indicate that it's done.
self._job.Complete = True

View File

@@ -20,7 +20,8 @@ from lvmdbusd import cfg
# noinspection PyUnresolvedReferences
from gi.repository import GLib
import threading
import traceback
import signal
STDOUT_TTY = os.isatty(sys.stdout.fileno())
@@ -281,12 +282,47 @@ def log_error(msg, *attributes):
_common_log(msg, *attributes)
def dump_threads_stackframe():
ident_to_name = {}
for thread_object in threading.enumerate():
ident_to_name[thread_object.ident] = thread_object
stacks = []
for thread_ident, frame in sys._current_frames().items():
stack = traceback.format_list(traceback.extract_stack(frame))
# There is a possibility that a thread gets created after we have
# enumerated all threads, so this lookup table may be incomplete, so
# account for this
if thread_ident in ident_to_name:
thread_name = ident_to_name[thread_ident].name
else:
thread_name = "unknown"
stacks.append("Thread: %s" % (thread_name))
stacks.append("".join(stack))
log_error("Dumping thread stack frames!\n" + "\n".join(stacks))
# noinspection PyUnusedLocal
def handler(signum, frame):
cfg.run.value = 0
log_debug('Signal handler called with signal %d' % signum)
if cfg.loop is not None:
cfg.loop.quit()
def handler(signum):
try:
if signum == signal.SIGUSR1:
dump_threads_stackframe()
else:
cfg.run.value = 0
log_debug('Exiting daemon with signal %d' % signum)
if cfg.loop is not None:
cfg.loop.quit()
except:
st = traceback.format_exc()
log_error("signal handler: exception (logged, not reported!) \n %s" % st)
# It's important we report that we handled the exception for the exception
# handler to continue to work, especially for signal 10 (SIGUSR1)
return True
def pv_obj_path_generate():
@@ -534,21 +570,27 @@ def add_no_notify(cmdline):
# ensure all dbus library interaction is done from the same thread!
def _async_result(call_back, results):
log_debug('Results = %s' % str(results))
call_back(results)
def _async_handler(call_back, parameters):
params_str = ", ".join(str(x) for x in parameters)
log_debug('Main thread execution, callback = %s, parameters = (%s)' %
(str(call_back), params_str))
try:
if parameters:
call_back(*parameters)
else:
call_back()
except:
st = traceback.format_exc()
log_error("mt_async_call: exception (logged, not reported!) \n %s" % st)
# Return result in main thread
def mt_async_result(call_back, results):
GLib.idle_add(_async_result, call_back, results)
# Execute the function on the main thread with the provided parameters, do
# not return *any* value or wait for the execution to complete!
def mt_async_call(function_call_back, *parameters):
GLib.idle_add(_async_handler, function_call_back, parameters)
# Take the supplied function and run it on the main thread and not wait for
# a result!
def mt_run_no_wait(function, param):
GLib.idle_add(function, param)
# Run the supplied function and arguments on the main thread and wait for them
# to complete while allowing the ability to get the return value too.
#
@@ -568,6 +610,7 @@ class MThreadRunner(object):
def __init__(self, function, *args):
self.f = function
self.rc = None
self.exception = None
self.args = args
self.function_complete = False
self.cond = threading.Condition(threading.Lock())
@@ -577,13 +620,21 @@ class MThreadRunner(object):
with self.cond:
if not self.function_complete:
self.cond.wait()
if self.exception:
raise self.exception
return self.rc
def _run(self):
if len(self.args):
self.rc = self.f(*self.args)
else:
self.rc = self.f()
try:
if self.args:
self.rc = self.f(*self.args)
else:
self.rc = self.f()
except BaseException as be:
self.exception = be
st = traceback.format_exc()
log_error("MThreadRunner: exception \n %s" % st)
log_error("Exception will be raised in calling thread!")
def _remove_objects(dbus_objects_rm):

View File

@@ -22,7 +22,6 @@
#define LVMETAD_TOKEN_UPDATE_IN_PROGRESS "update in progress"
#define LVMETAD_DISABLE_REASON_DIRECT "DIRECT"
#define LVMETAD_DISABLE_REASON_LVM1 "LVM1"
#define LVMETAD_DISABLE_REASON_DUPLICATES "DUPLICATES"
#define LVMETAD_DISABLE_REASON_VGRESTORE "VGRESTORE"
#define LVMETAD_DISABLE_REASON_REPAIR "REPAIR"

View File

@@ -200,12 +200,12 @@ struct vg_info {
#define GLFL_INVALID 0x00000001
#define GLFL_DISABLE 0x00000002
#define GLFL_DISABLE_REASON_DIRECT 0x00000004
#define GLFL_DISABLE_REASON_LVM1 0x00000008
/* 0x00000008 */
#define GLFL_DISABLE_REASON_DUPLICATES 0x00000010
#define GLFL_DISABLE_REASON_VGRESTORE 0x00000020
#define GLFL_DISABLE_REASON_REPAIR 0x00000040
#define GLFL_DISABLE_REASON_ALL (GLFL_DISABLE_REASON_DIRECT | GLFL_DISABLE_REASON_REPAIR | GLFL_DISABLE_REASON_LVM1 | GLFL_DISABLE_REASON_DUPLICATES | GLFL_DISABLE_REASON_VGRESTORE)
#define GLFL_DISABLE_REASON_ALL (GLFL_DISABLE_REASON_DIRECT | GLFL_DISABLE_REASON_REPAIR | GLFL_DISABLE_REASON_DUPLICATES | GLFL_DISABLE_REASON_VGRESTORE)
#define VGFL_INVALID 0x00000001
@@ -2369,8 +2369,6 @@ static response set_global_info(lvmetad_state *s, request r)
reason_flags |= GLFL_DISABLE_REASON_DIRECT;
if (strstr(reason, LVMETAD_DISABLE_REASON_REPAIR))
reason_flags |= GLFL_DISABLE_REASON_REPAIR;
if (strstr(reason, LVMETAD_DISABLE_REASON_LVM1))
reason_flags |= GLFL_DISABLE_REASON_LVM1;
if (strstr(reason, LVMETAD_DISABLE_REASON_DUPLICATES))
reason_flags |= GLFL_DISABLE_REASON_DUPLICATES;
if (strstr(reason, LVMETAD_DISABLE_REASON_VGRESTORE))
@@ -2421,21 +2419,17 @@ static response set_global_info(lvmetad_state *s, request r)
static response get_global_info(lvmetad_state *s, request r)
{
char reason[REASON_BUF_SIZE];
/* This buffer should be large enough to hold all the possible reasons. */
char reason[REASON_BUF_SIZE] = { 0 };
char flag_str[64];
int pid;
/* This buffer should be large enough to hold all the possible reasons. */
memset(reason, 0, sizeof(reason));
pid = (int)daemon_request_int(r, "pid", 0);
if (s->flags & GLFL_DISABLE) {
snprintf(reason, REASON_BUF_SIZE - 1, "%s%s%s%s%s",
snprintf(reason, REASON_BUF_SIZE, "%s%s%s%s",
(s->flags & GLFL_DISABLE_REASON_DIRECT) ? LVMETAD_DISABLE_REASON_DIRECT "," : "",
(s->flags & GLFL_DISABLE_REASON_REPAIR) ? LVMETAD_DISABLE_REASON_REPAIR "," : "",
(s->flags & GLFL_DISABLE_REASON_LVM1) ? LVMETAD_DISABLE_REASON_LVM1 "," : "",
(s->flags & GLFL_DISABLE_REASON_DUPLICATES) ? LVMETAD_DISABLE_REASON_DUPLICATES "," : "",
(s->flags & GLFL_DISABLE_REASON_VGRESTORE) ? LVMETAD_DISABLE_REASON_VGRESTORE "," : "");
}
@@ -2531,10 +2525,8 @@ inval:
info = dm_hash_lookup(s->vgid_to_info, uuid);
if (!info) {
info = malloc(sizeof(struct vg_info));
if (!info)
if (!(info = dm_zalloc(sizeof(struct vg_info))))
goto bad;
memset(info, 0, sizeof(struct vg_info));
if (!dm_hash_insert(s->vgid_to_info, uuid, (void*)info))
goto bad;
}
@@ -2705,9 +2697,8 @@ static response handler(daemon_state s, client_handle h, request r)
if (!prev_in_progress && this_in_progress) {
/* New update is starting (filter token is replaced by update token) */
memcpy(prev_token, state->token, 128);
strncpy(state->token, token, 128);
state->token[127] = 0;
(void) dm_strncpy(prev_token, state->token, sizeof(prev_token));
(void) dm_strncpy(state->token, token, sizeof(state->token));
state->update_begin = _monotonic_seconds();
state->update_timeout = update_timeout;
state->update_pid = pid;
@@ -2728,9 +2719,8 @@ static response handler(daemon_state s, client_handle h, request r)
(int)(_monotonic_seconds() - state->update_begin),
state->update_cmd);
memcpy(prev_token, state->token, 128);
strncpy(state->token, token, 128);
state->token[127] = 0;
(void) dm_strncpy(prev_token, state->token, sizeof(prev_token));
(void) dm_strncpy(state->token, token, sizeof(state->token));
state->update_begin = _monotonic_seconds();
state->update_timeout = update_timeout;
state->update_pid = pid;
@@ -2762,9 +2752,8 @@ static response handler(daemon_state s, client_handle h, request r)
(int)(_monotonic_seconds() - state->update_begin),
state->update_pid, token);
memcpy(prev_token, state->token, 128);
strncpy(state->token, token, 128);
state->token[127] = 0;
(void) dm_strncpy(prev_token, state->token, sizeof(prev_token));
(void) dm_strncpy(state->token, token, sizeof(state->token));
state->update_begin = 0;
state->update_timeout = 0;
state->update_pid = 0;

View File

@@ -27,6 +27,8 @@ ifeq ("@BUILD_LOCKDDLM@", "yes")
LOCK_LIBS += -ldlm_lt
endif
SOURCES2 = lvmlockctl.c
TARGETS = lvmlockd lvmlockctl
.PHONY: install_lvmlockd

View File

@@ -379,7 +379,7 @@ static int setup_dump_socket(void)
rv = bind(s, (struct sockaddr *) &dump_addr, dump_addrlen);
if (rv < 0) {
rv = -errno;
if (!close(s))
if (close(s))
log_error("failed to close dump socket");
return rv;
}

View File

@@ -48,5 +48,7 @@ static inline void lvmlockd_close(daemon_handle h)
#define EVGKILLED 217 /* sanlock lost access to leases and VG is killed. */
#define ELOCKIO 218 /* sanlock io errors during lock op, may be transient. */
#define EREMOVED 219
#define EDEVOPEN 220 /* sanlock failed to open lvmlock LV */
#define ELMERR 221
#endif /* _LVM_LVMLOCKD_CLIENT_H */

View File

@@ -1009,6 +1009,8 @@ static void add_work_action(struct action *act)
pthread_mutex_unlock(&worker_mutex);
}
#define ERR_LVMETAD_NOT_RUNNING -200
static daemon_reply send_lvmetad(const char *id, ...)
{
daemon_reply reply;
@@ -1029,9 +1031,9 @@ retry:
if (lvmetad_handle.error || lvmetad_handle.socket_fd < 0) {
err = lvmetad_handle.error ?: lvmetad_handle.socket_fd;
pthread_mutex_unlock(&lvmetad_mutex);
log_error("lvmetad_open reconnect error %d", err);
log_debug("lvmetad_open reconnect error %d", err);
memset(&reply, 0, sizeof(reply));
reply.error = err;
reply.error = ERR_LVMETAD_NOT_RUNNING;
va_end(ap);
return reply;
} else {
@@ -1265,6 +1267,15 @@ static int res_lock(struct lockspace *ls, struct resource *r, struct action *act
* caches, and tell lvmetad to set global invalid to 0.
*/
/*
* lvmetad not running:
* Even if we have not previously found lvmetad running,
* we attempt to connect and invalidate in case it has
* been started while lvmlockd is running. We don't
* want to allow lvmetad to be used with invalid data if
* it happens to be enabled and started after lvmlockd.
*/
if (inval_meta && (r->type == LD_RT_VG)) {
daemon_reply reply;
char *uuid;
@@ -1284,8 +1295,10 @@ static int res_lock(struct lockspace *ls, struct resource *r, struct action *act
"version = " FMTd64, (int64_t)new_version,
NULL);
if (reply.error || strcmp(daemon_reply_str(reply, "response", ""), "OK"))
log_error("set_vg_info in lvmetad failed %d", reply.error);
if (reply.error || strcmp(daemon_reply_str(reply, "response", ""), "OK")) {
if (reply.error != ERR_LVMETAD_NOT_RUNNING)
log_error("set_vg_info in lvmetad failed %d", reply.error);
}
daemon_reply_destroy(reply);
}
@@ -1300,8 +1313,10 @@ static int res_lock(struct lockspace *ls, struct resource *r, struct action *act
"global_invalid = " FMTd64, INT64_C(1),
NULL);
if (reply.error || strcmp(daemon_reply_str(reply, "response", ""), "OK"))
log_error("set_global_info in lvmetad failed %d", reply.error);
if (reply.error || strcmp(daemon_reply_str(reply, "response", ""), "OK")) {
if (reply.error != ERR_LVMETAD_NOT_RUNNING)
log_error("set_global_info in lvmetad failed %d", reply.error);
}
daemon_reply_destroy(reply);
}
@@ -1389,12 +1404,11 @@ static int res_convert(struct lockspace *ls, struct resource *r,
}
rv = lm_convert(ls, r, act->mode, act, r_version);
if (rv < 0) {
log_error("S %s R %s res_convert lm error %d", ls->name, r->name, rv);
return rv;
}
log_debug("S %s R %s res_convert lm done", ls->name, r->name);
log_debug("S %s R %s res_convert rv %d", ls->name, r->name, rv);
if (rv < 0)
return rv;
if (lk->mode == LD_LK_EX && act->mode == LD_LK_SH) {
r->sh_count = 1;
@@ -2652,10 +2666,16 @@ out_act:
ls->drop_vg = drop_vg;
if (ls->lm_type == LD_LM_DLM && !strcmp(ls->name, gl_lsname_dlm))
global_dlm_lockspace_exists = 0;
/* Avoid a name collision of the same lockspace is added again before this thread is cleaned up. */
memset(tmp_name, 0, sizeof(tmp_name));
snprintf(tmp_name, MAX_NAME, "REM:%s", ls->name);
memcpy(ls->name, tmp_name, MAX_NAME);
/*
* Avoid a name collision of the same lockspace is added again before
* this thread is cleaned up. We just set ls->name to a "junk" value
* for the short period until the struct is freed. We could make it
* blank or fill it with garbage, but instead set it to REM:<name>
* to make it easier to follow progress of freeing is via log_debug.
*/
dm_strncpy(tmp_name, ls->name, sizeof(tmp_name));
snprintf(ls->name, sizeof(ls->name), "REM:%s", tmp_name);
pthread_mutex_unlock(&lockspaces_mutex);
/* worker_thread will join this thread, and free the ls */
@@ -3533,11 +3553,15 @@ static int setup_worker_thread(void)
static void close_worker_thread(void)
{
int perrno;
pthread_mutex_lock(&worker_mutex);
worker_stop = 1;
pthread_cond_signal(&worker_cond);
pthread_mutex_unlock(&worker_mutex);
pthread_join(worker_thread, NULL);
if ((perrno = pthread_join(worker_thread, NULL)))
log_error("pthread_join worker_thread error %d", perrno);
}
/* client_mutex is locked */
@@ -3666,7 +3690,17 @@ static int client_send_result(struct client *cl, struct action *act)
if (!gl_lsname_dlm[0])
strcat(result_flags, "NO_GL_LS,");
} else {
strcat(result_flags, "NO_GL_LS,");
int found_lm = 0;
if (lm_support_dlm() && lm_is_running_dlm())
found_lm++;
if (lm_support_sanlock() && lm_is_running_sanlock())
found_lm++;
if (!found_lm)
strcat(result_flags, "NO_GL_LS,NO_LM");
else
strcat(result_flags, "NO_GL_LS");
}
}
@@ -3763,7 +3797,8 @@ static int client_send_result(struct client *cl, struct action *act)
if (dump_fd >= 0) {
/* To avoid deadlock, send data here after the reply. */
send_dump_buf(dump_fd, dump_len);
close(dump_fd);
if (close(dump_fd))
log_error("failed to close dump socket %d", dump_fd);
}
return rv;
@@ -3836,8 +3871,9 @@ static int add_lock_action(struct action *act)
pthread_mutex_lock(&lockspaces_mutex);
if (ls_name[0])
ls = find_lockspace_name(ls_name);
pthread_mutex_unlock(&lockspaces_mutex);
if (!ls) {
pthread_mutex_unlock(&lockspaces_mutex);
if (act->op == LD_OP_UPDATE && act->rt == LD_RT_VG) {
log_debug("lockspace \"%s\" not found ignored for vg update", ls_name);
return -ENOLS;
@@ -4754,8 +4790,8 @@ static void *client_thread_main(void *arg_in)
} else {
pthread_mutex_unlock(&cl->mutex);
}
}
pthread_mutex_unlock(&client_mutex);
} else
pthread_mutex_unlock(&client_mutex);
}
out:
return NULL;
@@ -4779,11 +4815,15 @@ static int setup_client_thread(void)
static void close_client_thread(void)
{
int perrno;
pthread_mutex_lock(&client_mutex);
client_stop = 1;
pthread_cond_signal(&client_cond);
pthread_mutex_unlock(&client_mutex);
pthread_join(client_thread, NULL);
if ((perrno = pthread_join(client_thread, NULL)))
log_error("pthread_join client_thread error %d", perrno);
}
/*
@@ -5823,7 +5863,7 @@ static int main_loop(daemon_state *ds_arg)
pthread_mutex_init(&lvmetad_mutex, NULL);
lvmetad_handle = lvmetad_open(NULL);
if (lvmetad_handle.error || lvmetad_handle.socket_fd < 0)
log_error("lvmetad_open error %d", lvmetad_handle.error);
log_debug("lvmetad_open error %d", lvmetad_handle.error);
else
lvmetad_connected = 1;
@@ -5831,8 +5871,13 @@ static int main_loop(daemon_state *ds_arg)
* Attempt to rejoin lockspaces and adopt locks from a previous
* instance of lvmlockd that left behind lockspaces/locks.
*/
if (adopt_opt)
adopt_locks();
if (adopt_opt) {
/* FIXME: implement this without lvmetad */
if (!lvmetad_connected)
log_error("Cannot adopt locks without lvmetad running.");
else
adopt_locks();
}
while (1) {
rv = poll(pollfd, pollfd_maxi + 1, -1);

View File

@@ -508,7 +508,7 @@ lockrv:
}
if (rv < 0) {
log_error("S %s R %s lock_dlm acquire error %d errno %d", ls->name, r->name, rv, errno);
return rv;
return -ELMERR;
}
if (rdd->vb) {
@@ -581,6 +581,7 @@ int lm_convert_dlm(struct lockspace *ls, struct resource *r,
}
if (rv < 0) {
log_error("S %s R %s convert_dlm error %d", ls->name, r->name, rv);
rv = -ELMERR;
}
return rv;
}
@@ -654,6 +655,7 @@ int lm_unlock_dlm(struct lockspace *ls, struct resource *r,
0, NULL, NULL, NULL);
if (rv < 0) {
log_error("S %s R %s unlock_dlm error %d", ls->name, r->name, rv);
rv = -ELMERR;
}
return rv;
@@ -697,7 +699,7 @@ int lm_hosts_dlm(struct lockspace *ls, int notify)
return 0;
memset(ls_nodes_path, 0, sizeof(ls_nodes_path));
snprintf(ls_nodes_path, PATH_MAX-1, "%s/%s/nodes",
snprintf(ls_nodes_path, PATH_MAX, "%s/%s/nodes",
DLM_LOCKSPACES_PATH, ls->name);
if (!(ls_dir = opendir(ls_nodes_path)))

View File

@@ -294,6 +294,36 @@ out:
return host_id;
}
/* Prepare valid /dev/mapper/vgname-lvname with all the mangling */
static int build_dm_path(char *path, size_t path_len,
const char *vg_name, const char *lv_name)
{
struct dm_pool *mem;
char *dm_name;
int rv = 0;
if (!(mem = dm_pool_create("namepool", 1024))) {
log_error("Failed to create mempool.");
return -ENOMEM;
}
if (!(dm_name = dm_build_dm_name(mem, vg_name, lv_name, NULL))) {
log_error("Failed to build dm name for %s/%s.", vg_name, lv_name);
rv = -EINVAL;
goto fail;
}
if ((dm_snprintf(path, path_len, "%s/%s", dm_dir(), dm_name) < 0)) {
log_error("Failed to create path %s/%s.", dm_dir(), dm_name);
rv = -EINVAL;
}
fail:
dm_pool_destroy(mem);
return rv;
}
/*
* vgcreate
*
@@ -336,7 +366,8 @@ int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_ar
if (strlen(lock_lv_name) + strlen(lock_args_version) + 2 > MAX_ARGS)
return -EARGS;
snprintf(disk.path, SANLK_PATH_LEN-1, "/dev/mapper/%s-%s", vg_name, lock_lv_name);
if ((rv = build_dm_path(disk.path, SANLK_PATH_LEN, vg_name, lock_lv_name)))
return rv;
log_debug("S %s init_vg_san path %s", ls_name, disk.path);
@@ -356,12 +387,19 @@ int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_ar
log_debug("sanlock daemon version %08x proto %08x",
daemon_version, daemon_proto);
align_size = sanlock_align(&disk);
if (align_size <= 0) {
log_error("S %s init_vg_san bad disk align size %d %s",
ls_name, align_size, disk.path);
return -EARGS;
}
rv = sanlock_align(&disk);
if (rv <= 0) {
if (rv == -EACCES) {
log_error("S %s init_vg_san sanlock error -EACCES: no permission to access %s",
ls_name, disk.path);
return -EDEVOPEN;
} else {
log_error("S %s init_vg_san sanlock error %d trying to get align size of %s",
ls_name, rv, disk.path);
return -EARGS;
}
} else
align_size = rv;
strncpy(ss.name, ls_name, SANLK_NAME_LEN);
memcpy(ss.host_id_disk.path, disk.path, SANLK_PATH_LEN);
@@ -506,7 +544,8 @@ int lm_init_lv_sanlock(char *ls_name, char *vg_name, char *lv_name,
strncpy(rd.rs.lockspace_name, ls_name, SANLK_NAME_LEN);
rd.rs.num_disks = 1;
snprintf(rd.rs.disks[0].path, SANLK_PATH_LEN-1, "/dev/mapper/%s-%s", vg_name, lock_lv_name);
if ((rv = build_dm_path(rd.rs.disks[0].path, SANLK_PATH_LEN, vg_name, lock_lv_name)))
return rv;
align_size = sanlock_align(&rd.rs.disks[0]);
if (align_size <= 0) {
@@ -605,7 +644,8 @@ int lm_rename_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_
return rv;
}
snprintf(disk.path, SANLK_PATH_LEN-1, "/dev/mapper/%s-%s", vg_name, lock_lv_name);
if ((rv = build_dm_path(disk.path, SANLK_PATH_LEN, vg_name, lock_lv_name)))
return rv;
log_debug("S %s rename_vg_san path %s", ls_name, disk.path);
@@ -1062,10 +1102,10 @@ int lm_prepare_lockspace_sanlock(struct lockspace *ls)
* and appending "lockctl" to get /path/to/lvmlockctl.
*/
memset(killpath, 0, sizeof(killpath));
snprintf(killpath, SANLK_PATH_LEN - 1, "%slockctl", LVM_PATH);
snprintf(killpath, SANLK_PATH_LEN, "%slockctl", LVM_PATH);
memset(killargs, 0, sizeof(killargs));
snprintf(killargs, SANLK_PATH_LEN - 1, "--kill %s", ls->vg_name);
snprintf(killargs, SANLK_PATH_LEN, "--kill %s", ls->vg_name);
rv = check_args_version(ls->vg_args, VG_LOCK_ARGS_MAJOR);
if (rv < 0) {
@@ -1081,8 +1121,8 @@ int lm_prepare_lockspace_sanlock(struct lockspace *ls)
goto fail;
}
snprintf(disk_path, SANLK_PATH_LEN-1, "/dev/mapper/%s-%s",
ls->vg_name, lock_lv_name);
if ((ret = build_dm_path(disk_path, SANLK_PATH_LEN, ls->vg_name, lock_lv_name)))
goto fail;
/*
* When a vg is started, the internal sanlock lv should be
@@ -1453,6 +1493,12 @@ int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode,
rv = sanlock_acquire(lms->sock, -1, flags, 1, &rs, &opt);
/*
* errors: translate the sanlock error number to an lvmlockd error.
* We don't want to return an sanlock-specific error number from
* this function to code that doesn't recognize sanlock error numbers.
*/
if (rv == -EAGAIN) {
/*
* It appears that sanlock_acquire returns EAGAIN when we request
@@ -1521,6 +1567,26 @@ int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode,
return -EAGAIN;
}
if (rv == SANLK_AIO_TIMEOUT) {
/*
* sanlock got an i/o timeout when trying to acquire the
* lease on disk.
*/
log_debug("S %s R %s lock_san acquire mode %d rv %d", ls->name, r->name, ld_mode, rv);
*retry = 0;
return -EAGAIN;
}
if (rv == SANLK_DBLOCK_LVER || rv == SANLK_DBLOCK_MBAL) {
/*
* There was contention with another host for the lease,
* and we lost.
*/
log_debug("S %s R %s lock_san acquire mode %d rv %d", ls->name, r->name, ld_mode, rv);
*retry = 0;
return -EAGAIN;
}
if (rv == SANLK_ACQUIRE_OWNED_RETRY) {
/*
* The lock is held by a failed host, and will eventually
@@ -1571,15 +1637,25 @@ int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode,
if (rv == -ENOSPC)
rv = -ELOCKIO;
return rv;
/*
* generic error number for sanlock errors that we are not
* catching above.
*/
return -ELMERR;
}
/*
* sanlock acquire success (rv 0)
*/
if (rds->vb) {
rv = sanlock_get_lvb(0, rs, (char *)&vb, sizeof(vb));
if (rv < 0) {
log_error("S %s R %s lock_san get_lvb error %d", ls->name, r->name, rv);
memset(rds->vb, 0, sizeof(struct val_blk));
memset(vb_out, 0, sizeof(struct val_blk));
/* the lock is still acquired, the vb values considered invalid */
rv = 0;
goto out;
}
@@ -1632,6 +1708,7 @@ int lm_convert_sanlock(struct lockspace *ls, struct resource *r,
if (rv < 0) {
log_error("S %s R %s convert_san set_lvb error %d",
ls->name, r->name, rv);
return -ELMERR;
}
}
@@ -1644,14 +1721,35 @@ int lm_convert_sanlock(struct lockspace *ls, struct resource *r,
if (daemon_test)
return 0;
/*
* Don't block waiting for a failed lease to expire since it causes
* sanlock_convert to block for a long time, which would prevent this
* thread from processing other lock requests.
*
* FIXME: SANLK_CONVERT_OWNER_NOWAIT is the same as SANLK_ACQUIRE_OWNER_NOWAIT.
* Change to use the CONVERT define when the latest sanlock version has it.
*/
flags |= SANLK_ACQUIRE_OWNER_NOWAIT;
rv = sanlock_convert(lms->sock, -1, flags, rs);
if (rv == -EAGAIN) {
/* FIXME: When could this happen? Should something different be done? */
log_error("S %s R %s convert_san EAGAIN", ls->name, r->name);
if (!rv)
return 0;
switch (rv) {
case -EAGAIN:
case SANLK_ACQUIRE_IDLIVE:
case SANLK_ACQUIRE_OWNED:
case SANLK_ACQUIRE_OWNED_RETRY:
case SANLK_ACQUIRE_OTHER:
case SANLK_AIO_TIMEOUT:
case SANLK_DBLOCK_LVER:
case SANLK_DBLOCK_MBAL:
/* expected errors from known/normal cases like lock contention or io timeouts */
log_debug("S %s R %s convert_san error %d", ls->name, r->name, rv);
return -EAGAIN;
}
if (rv < 0) {
default:
log_error("S %s R %s convert_san convert error %d", ls->name, r->name, rv);
rv = -ELMERR;
}
return rv;
@@ -1688,6 +1786,7 @@ static int release_rename(struct lockspace *ls, struct resource *r)
rv = sanlock_release(lms->sock, -1, SANLK_REL_RENAME, 2, res_args);
if (rv < 0) {
log_error("S %s R %s unlock_san release rename error %d", ls->name, r->name, rv);
rv = -ELMERR;
}
free(res_args);
@@ -1744,6 +1843,7 @@ int lm_unlock_sanlock(struct lockspace *ls, struct resource *r,
if (rv < 0) {
log_error("S %s R %s unlock_san set_lvb error %d",
ls->name, r->name, rv);
return -ELMERR;
}
}
@@ -1762,6 +1862,8 @@ int lm_unlock_sanlock(struct lockspace *ls, struct resource *r,
if (rv == -EIO)
rv = -ELOCKIO;
else if (rv < 0)
rv = -ELMERR;
return rv;
}

View File

@@ -1,4 +1,4 @@
# Copyright (C) 2013-2014 Red Hat, Inc. All rights reserved.
# Copyright (C) 2018 Red Hat, Inc. All rights reserved.
#
# This file is part of LVM2.
#
@@ -14,11 +14,10 @@ srcdir = @srcdir@
top_srcdir = @top_srcdir@
top_builddir = @top_builddir@
SOURCES = cache.c
LIB_SHARED = liblvm2cache.$(LIB_SUFFIX)
LIB_VERSION = $(LIB_VERSION_LVM)
SOURCES=\
vdo/status.c
include $(top_builddir)/make.tmpl
install: install_lvm2_plugin
LIB_NAME = libdevicemapper
LIB_STATIC = $(LIB_NAME).a

248
device_mapper/vdo/status.c Normal file
View File

@@ -0,0 +1,248 @@
#include "target.h"
// For DM_ARRAY_SIZE!
#include "libdevmapper.h"
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
//----------------------------------------------------------------
static char *_tok_cpy(const char *b, const char *e)
{
char *new = malloc((e - b) + 1);
char *ptr = new;
if (new) {
while (b != e)
*ptr++ = *b++;
*ptr = '\0';
}
return new;
}
static bool _tok_eq(const char *b, const char *e, const char *str)
{
while (b != e) {
if (!*str || *b != *str)
return false;
b++;
str++;
}
return !*str;
}
static bool _parse_operating_mode(const char *b, const char *e, void *context)
{
static struct {
const char *str;
enum vdo_operating_mode mode;
} _table[] = {
{"recovering", VDO_MODE_RECOVERING},
{"read-only", VDO_MODE_READ_ONLY},
{"normal", VDO_MODE_NORMAL}
};
enum vdo_operating_mode *r = context;
unsigned i;
for (i = 0; i < DM_ARRAY_SIZE(_table); i++) {
if (_tok_eq(b, e, _table[i].str)) {
*r = _table[i].mode;
return true;
}
}
return false;
}
static bool _parse_compression_state(const char *b, const char *e, void *context)
{
static struct {
const char *str;
enum vdo_compression_state state;
} _table[] = {
{"online", VDO_COMPRESSION_ONLINE},
{"offline", VDO_COMPRESSION_OFFLINE}
};
enum vdo_compression_state *r = context;
unsigned i;
for (i = 0; i < DM_ARRAY_SIZE(_table); i++) {
if (_tok_eq(b, e, _table[i].str)) {
*r = _table[i].state;
return true;
}
}
return false;
}
static bool _parse_recovering(const char *b, const char *e, void *context)
{
bool *r = context;
if (_tok_eq(b, e, "recovering"))
*r = true;
else if (_tok_eq(b, e, "-"))
*r = false;
else
return false;
return true;
}
static bool _parse_index_state(const char *b, const char *e, void *context)
{
static struct {
const char *str;
enum vdo_index_state state;
} _table[] = {
{"error", VDO_INDEX_ERROR},
{"closed", VDO_INDEX_CLOSED},
{"opening", VDO_INDEX_OPENING},
{"closing", VDO_INDEX_CLOSING},
{"offline", VDO_INDEX_OFFLINE},
{"online", VDO_INDEX_ONLINE},
{"unknown", VDO_INDEX_UNKNOWN}
};
enum vdo_index_state *r = context;
unsigned i;
for (i = 0; i < DM_ARRAY_SIZE(_table); i++) {
if (_tok_eq(b, e, _table[i].str)) {
*r = _table[i].state;
return true;
}
}
return false;
}
static bool _parse_uint64(const char *b, const char *e, void *context)
{
uint64_t *r = context, n;
n = 0;
while (b != e) {
if (!isdigit(*b))
return false;
n = (n * 10) + (*b - '0');
b++;
}
*r = n;
return true;
}
static const char *_eat_space(const char *b, const char *e)
{
while (b != e && isspace(*b))
b++;
return b;
}
static const char *_next_tok(const char *b, const char *e)
{
const char *te = b;
while (te != e && !isspace(*te))
te++;
return te == b ? NULL : te;
}
static void _set_error(struct vdo_status_parse_result *result, const char *fmt, ...)
__attribute__ ((format(printf, 2, 3)));
static void _set_error(struct vdo_status_parse_result *result, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vsnprintf(result->error, sizeof(result->error), fmt, ap);
va_end(ap);
}
static bool _parse_field(const char **b, const char *e,
bool (*p_fn)(const char *, const char *, void *),
void *field, const char *field_name,
struct vdo_status_parse_result *result)
{
const char *te;
te = _next_tok(*b, e);
if (!te) {
_set_error(result, "couldn't get token for '%s'", field_name);
return false;
}
if (!p_fn(*b, te, field)) {
_set_error(result, "couldn't parse '%s'", field_name);
return false;
}
*b = _eat_space(te, e);
return true;
}
bool vdo_status_parse(const char *input, struct vdo_status_parse_result *result)
{
const char *b = b = input;
const char *e = input + strlen(input);
const char *te;
struct vdo_status *s = malloc(sizeof(*s));
if (!s) {
_set_error(result, "out of memory");
return false;
}
b = _eat_space(b, e);
te = _next_tok(b, e);
if (!te) {
_set_error(result, "couldn't get token for device");
free(s);
return false;
}
s->device = _tok_cpy(b, te);
if (!s->device) {
_set_error(result, "out of memory");
free(s);
return false;
}
b = _eat_space(te, e);
#define XX(p, f, fn) if (!_parse_field(&b, e, p, f, fn, result)) goto bad;
XX(_parse_operating_mode, &s->operating_mode, "operating mode");
XX(_parse_recovering, &s->recovering, "recovering");
XX(_parse_index_state, &s->index_state, "index state");
XX(_parse_compression_state, &s->compression_state, "compression state");
XX(_parse_uint64, &s->used_blocks, "used blocks");
XX(_parse_uint64, &s->total_blocks, "total blocks");
#undef XX
if (b != e) {
_set_error(result, "too many tokens");
goto bad;
}
result->status = s;
return true;
bad:
free(s->device);
free(s);
return false;
}
//----------------------------------------------------------------

View File

@@ -0,0 +1,68 @@
/*
* Copyright (C) 2018 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_VDO_TARGET_H
#define DEVICE_MAPPER_VDO_TARGET_H
#include <stdbool.h>
#include <stdint.h>
//----------------------------------------------------------------
enum vdo_operating_mode {
VDO_MODE_RECOVERING,
VDO_MODE_READ_ONLY,
VDO_MODE_NORMAL
};
enum vdo_compression_state {
VDO_COMPRESSION_ONLINE,
VDO_COMPRESSION_OFFLINE
};
enum vdo_index_state {
VDO_INDEX_ERROR,
VDO_INDEX_CLOSED,
VDO_INDEX_OPENING,
VDO_INDEX_CLOSING,
VDO_INDEX_OFFLINE,
VDO_INDEX_ONLINE,
VDO_INDEX_UNKNOWN
};
struct vdo_status {
char *device;
enum vdo_operating_mode operating_mode;
bool recovering;
enum vdo_index_state index_state;
enum vdo_compression_state compression_state;
uint64_t used_blocks;
uint64_t total_blocks;
};
void vdo_status_destroy(struct vdo_status *s);
#define VDO_MAX_ERROR 256
struct vdo_status_parse_result {
char error[VDO_MAX_ERROR];
struct vdo_status *status;
};
// Parses the status line from the kernel target.
bool vdo_status_parse(const char *input, struct vdo_status_parse_result *result);
//----------------------------------------------------------------
#endif

338
doc/lvm-disk-reading.txt Normal file
View File

@@ -0,0 +1,338 @@
LVM disk reading
Reading disks happens in two phases. The first is a discovery phase,
which determines what's on the disks. The second is a working phase,
which does a particular job for the command.
Phase 1: Discovery
------------------
Read all the disks on the system to find out:
- What are the LVM devices?
- What VG's exist on those devices?
This phase is called "label scan" (although it reads and scans everything,
not just the label.) It stores the information it discovers (what LVM
devices exist, and what VGs exist on them) in lvmcache. The devs/VGs info
in lvmcache is the starting point for phase two.
Phase 1 in outline:
For each device:
a. Read the first <N> KB of the device. (N is configurable.)
b. Look for the lvm label_header in the first four sectors,
if none exists, it's not an lvm device, so quit looking at it.
(By default, label_header is in the second sector.)
c. Look at the pv_header, which follows the label_header.
This tells us the location of VG metadata on the device.
There can be 0, 1 or 2 copies of VG metadata. The first
is always at the start of the device, the second (if used)
is at the end.
d. Look at the first mda_header (location came from pv_header
in the previous step). This is by default in sector 8,
4096 bytes from the start of the device. This tells us the
location of the actual VG metadata text.
e. Look at the first copy of the text VG metadata (location came
from mda_header in the previous step). This is by default
in sector 9, 4608 bytes from the start of the device.
The VG metadata is only partially analyzed to create a basic
summary of the VG.
f. Store an "info" entry in lvmcache for this device,
indicating that it is an lvm device, and store a "vginfo"
entry in lvmcache indicating the name of the VG seen
in the metadata in step e.
g. If the pv_header in step c shows a second mda_header
location at the end of the device, then read that as
in step d, and repeat steps e-f for it.
At the end of phase 1, lvmcache will have a list of devices
that belong to LVM, and a list of VG names that exist on
those devices. Each device (info struct) is associated
with the VG (vginfo struct) it is used in.
Phase 1 in code:
The most relevant functions are listed for each step in the outline.
lvmcache_label_scan()
label_scan()
. dev_cache_scan()
choose which devices on the system to look at
. for each dev in dev_cache: bcache prefetch/read
. _process_block() to process data from bcache
_find_lvm_header() checks if this is an lvm dev by looking at label_header
_text_read() via ops->read() looks at mda/pv/vg data to populate lvmcache
. _read_mda_header_and_metadata()
raw_read_mda_header()
. _read_mda_header_and_metadata()
read_metadata_location()
text_read_metadata_summary()
config_file_read_fd()
_read_vgsummary() via ops->read_vgsummary()
. _text_read(): lvmcache_add()
[adds this device to list of lvm devices]
_read_mda_header_and_metadata(): lvmcache_update_vgname_and_id()
[adds the VG name to list of VGs]
Phase 2: Work
-------------
This phase carries out the operation requested by the command that was
run.
Whereas the first phase is based on iterating through each device on the
system, this phase is based on iterating through each VG name. The list
of VG names comes from phase 1, which stored the list in lvmcache to be
used by phase 2.
Some commands may need to iterate through all VG names, while others may
need to iterate through just one or two.
This phase includes locking each VG as work is done on it, so that two
commands do not interfere with each other.
Phase 2 in outline:
For each VG name:
a. Lock the VG.
b. Repeat the phase 1 scan steps for each device in this VG.
The phase 1 information in lvmcache may have changed because no VG lock
was held during phase 1. So, repeat the phase 1 steps, but only for the
devices in this VG. N.B. for commands that are just reporting data,
we skip this step if the data from phase 1 was complete and consistent.
c. Get the list of on-disk metadata locations for this VG.
Phase 1 created this list in lvmcache to be used here. At this
point we copy it out of lvmcache. In the simple/common case,
this is a list of devices in the VG. But, some devices may
have 0 or 2 metadata locations instead of the default 1, so it
is not always equal to the list of devices. We want to read
every copy of the metadata for this VG.
d. For each metadata location on each device in the VG
(the list from the previous step):
1) Look at the mda_header. The location of the mda_header was saved
in the lvmcache info struct by phase 1 (where it came from the
pv_header.) The mda_header tells us where the text VG metadata is
located.
2) Look at the text VG metadata. The location came from mda_header
in the previous step. The VG metadata is fully analyzed and used
to create an in-memory 'struct volume_group'.
e. Compare the copies of VG metadata that were found in each location.
If some copies are older, choose the newest one to use, and update
any older copies.
f. Update details about the devices/VG in lvmcache.
g. Pass the 'vg' struct to the command-specific code to work with.
Phase 2 in code:
The most relevant functions are listed for each step in the outline.
For each VG name:
process_each_vg()
. vg_read()
lock_vol()
. vg_read()
lvmcache_label_rescan_vg() (if needed)
[insert phase 1 steps for scanning devs, but only devs in this vg]
. vg_read()
create_instance()
_text_create_text_instance()
_create_vg_text_instance()
lvmcache_fid_add_mdas_vg()
[Copies mda locations from info->mdas where it was saved
by phase 1, into fid->metadata_areas_in_use. This is
the key connection between phase 1 and phase 2.]
. dm_list_iterate_items(mda, &fid->metadata_areas_in_use)
. _vg_read_raw() via ops->vg_read()
raw_read_mda_header()
. _vg_read_raw()
text_read_metadata()
config_file_read_fd()
_read_vg() via ops->read_vg()
. return the 'vg' struct from vg_read() and use it to do
command-specific work
Filter i/o
----------
Some filters must be applied before reading a device, and other filters
must be applied after reading a device. In all cases, the filters must be
applied before lvm processes the device, i.e. before it looks for an lvm
label.
1. Some filters need to be applied prior to reading any devices
because the purpose of the filter is to avoid submitting any
io on the excluded devices. The regex filter is the primary
example. Other filters benefit from being applied prior to
reading devices because they can tell which devices to
exclude without doing io to the device. An example of this
is the mpath filter.
2. Some filters need to be applied after reading a device because
they are based on data/signatures seen on the device.
The partitioned filter is an example of this; lvm needs to
read a device to see if it has a partition table before it can
know whether to exclude the device from further processing.
We apply filters from 1 before reading devices, and we apply filters from
2 after populating bcache, but before processing the device (i.e. before
checking for an lvm label, which is the first step in processing.)
The current implementation of this makes filters return -EAGAIN if they
want to read the device, but bcache data is not yet available. This will
happen when filtering runs prior to populating bcache. In this case the
device is flagged. After bcache is populated, the filters are reapplied
to the flagged devices. The filters which need to look at device content
are now able to get it from bcache. Devices that do not pass filters at
this point are excluded just like devices which were excluded earlier.
(Some filters from 2 can be skipped by consulting udev for the information
instead of reading the device. This is not entirely reliable, so it is
disabled by default with the config setting external_device_info_source.
It may be worthwhile to change the filters to use the udev info as a hint,
or only use udev info for filtering in reporting commands where
inaccuracies are not a big problem.)
I/O Performance
---------------
. 400 loop devices used as PVs
. 40 VGs each with 10 PVs
. each VG has one active LV
. each of the 10 PVs in vg0 has an artificial 100 ms read delay
. read/write/io_submit are system call counts using strace
. old is lvm 2.2.175
. new is lvm 2.2.178 (shortly before)
Command: pvs
------------
old: 0m17.422s
new: 0m0.331s
old: read 7773 write 497
new: read 2807 write 495 io_submit 448
Command: vgs
------------
old: 0m20.383s
new: 0m0.325s
old: read 10684 write 129
new: read 2807 write 129 io_submit 448
Command: vgck vg0
-----------------
old: 0m16.212s
new: 0m1.290s
old: read 6372 write 4
new: read 2807 write 4 io_submit 458
Command: lvcreate -n test -l1 -an vg0
-------------------------------------
old: 0m29.271s
new: 0m1.351s
old: read 6503 write 39
new: read 2808 write 9 io_submit 488
Command: lvremove vg0/test
--------------------------
old: 0m29.262s
new: 0m1.348s
old: read 6502 write 36
new: read 2807 write 6 io_submit 488
io_submit sources
-----------------
vgs:
reads:
- 400 for each PV
- 40 for each LV
- 8 for other devs on the system
vgck vg0:
reads:
- 400 for each PV
- 40 for each LV
- 10 for each PV in vg0 (rescan)
- 8 for other devs on the system
lvcreate -n test -l1 -an vg0
reads:
- 400 for each PV
- 40 for each LV
- 10 for each PV in vg0 (rescan)
- 8 for other devs on the system
writes:
- 10 for metadata on each PV in vg0
- 10 for precommit on each PV in vg0
- 10 for commit on each PV in vg0
With lvmetad
------------
Command: pvs
------------
old: 0m5.405s
new: 0m1.404s
Command: vgs
------------
old: 0m0.222s
new: 0m0.223s
Command: lvcreate -n test -l1 -an vg0
-------------------------------------
old: 0m10.128s
new: 0m1.137s

158
doc/refactoring.txt Normal file
View File

@@ -0,0 +1,158 @@
Over time, I'd like to refactor the LVM code into these high level modules.
+-------------------------------------------+
| |
| User Interface |
| |
| |
+-------------------+-----------------------+
|
+--------------------v-----------------------+
| |
| LVM Core |
| |
| |
+----+----------------+-----------------+----+
| | |
+-----v-----+ +-----v------+ +------v----+
| | | | | |
| Device | | Metadata | | System |
| Mapper | | | | |
| | | | | |
| | | | | |
| | | | | |
+-----------+ +------------+ +-----------+
+---------------------------------------------------------+
+------------------------------------+
| |
| Base |
| |
| |
| |
| |
+------------------------------------+
Going from the bottom up we have:
Base
----
This holds all our general purpose code such as data structures, regex engine,
memory allocators. In fact pretty much everything in libdevmapper apart from
the dm code and config.
This can be used by any code in the system, which is why I've drawn a line
between it and the code above rather than using arrows.
If anyone can come up with a better name please do. I'm trying to stay away
from 'utils'.
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
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.
It should not know anything about the LVM abstractions or metadata (no PVs, LVs
or VGs). It just knows about the dm world.
Code in here is only allowed to use base.
Metadata model
--------------
Here we have all the format handling, labelling, config parsing etc. We try
and put *everything* to do with LVM in here that doesn't actually require dm.
System
------
Code that interfaces with the system (udev etc).
LVM Core
--------
[terrible name]
This ties together the last 3 units. It should just be glue. We need to be
strict about pushing code down from here to keep this as small as possible.
User interface
--------------
Self explanatory.
Headers
-------
Headers will be included using sub directories to make it clearer where they
are in the tree.
eg,
#include "base/mm/pool.h"
#include "base/data-struct/list.h"
#include "dm/thin-provisioning.h"
#include "core/pvmove.h"
Getting there
=============
+-------------------------------------------+
| |
| |
| Tools |
| |
| |
| |
+---------+------------------------------+--+
| |
| +---------------v---------------------------+
| | |
| | |
| | Lib |
| | |
| | |
| | |
| | |
| +----------------+--------------------------+
| |
| |
+-----v-------------------------------v-----+
| |
| |
| libdevmapper |
| |
| |
| |
| |
+-------------------------------------------+
This is where I see us now.
'base' should be easy to factor out, it's just the non-dm part of libdevmapper
(ie. the bulk of it). But we have the problem that libdevmapper is a public
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
files, and probably functions. Certainly not something that can be done in one
go. System should just be a question of cherry picking functions.
I'm not too familiar with the tools dir. Hopefully it just corresponds with
the User Interface module and doesn't contain any business logic.

View File

@@ -0,0 +1,53 @@
Version 2.02.178
================
There are going to be some large changes to the lvm2 codebase
over the next year or so. Starting with this release. These
changes should be internal rather than having a big effect on
the command line. Inevitably these changes will increase the
chance of bugs, so please be on the alert.
Remove support for obsolete metadata formats
--------------------------------------------
Support for the GFS pool format, and format used by the
original 1990's version of LVM1 have been removed.
Use asynchronous IO
-------------------
Almost all IO uses libaio now.
Rewrite label scanning
----------------------
Dave Teigland has reworked the label scanning and metadata reading
logic to minimise the amount of IOs issued. Combined with the aio changes
this can greatly improve scanning speed for some systems.
./configure options
-------------------
We're going to try and remove as many options from ./configure as we
can. Each option multiplies the number of possible configurations
that we should test (this testing is currently not occurring).
The first batch to be removed are:
--enable-testing
--with-snapshots
--with-mirrors
--with-raid
--with-thin
--with-cache
Stable targets that are in the upstream kernel will just be supported.
In future optional target flags will be given in two situations:
1) The target is experimental, or not upstream at all (eg, vdo).
2) The target is deprecated and support will be removed at some future date.
This decision could well be contentious, so could distro maintainers feel
free to comment.

257
doc/unit-tests.txt Normal file
View File

@@ -0,0 +1,257 @@
Building unit tests
===================
make unit-unit/unit-test
Running unit tests
==================
The tests leave no artifacts at the moment, so you can just run
unit-test/unit-test from wherever you want.
./unit-test <list|run> [pattern]
Listing tests
-------------
Every test has a symbolic path associated with it. Just like file paths they
are split into components separated by '/'s. The 'list' command will show you
a tree of these tests, along with some description text.
ejt@devel-vm1:~/lvm2/unit-test/$ ./unit-test list
base
data-struct
bitset
and ................................................. and all bits
equal ............................................... equality
get_next ............................................ get next set bit
list
splice .............................................. joining lists together
string
asprint ............................................. tests asprint
strncpy ............................................. tests string copying
device
bcache
block-size-multiple-page ............................ block size must be a multiple of page size
block-size-positive ................................. block size must be positive
blocks-get-evicted .................................. block get evicted with many reads
cache-blocks-positive ............................... nr cache blocks must be positive
create-destroy ...................................... simple create/destroy
flush-waits ......................................... flush waits for all dirty
get-reads ........................................... bcache_get() triggers read
prefetch-never-waits ................................ too many prefetches does not trigger a wait
prefetch-reads ...................................... prefetch issues a read
read-multiple-files ................................. read from multiple files
reads-cached ........................................ repeated reads are cached
writeback-occurs .................................... dirty data gets written back
zero-flag-dirties ................................... zeroed data counts as dirty
formatting
percent
0 ................................................... Pretty printing of percentages near 0%
100 ................................................. Pretty printing of percentages near 100%
regex
fingerprints .......................................... not sure
matching .............................................. test the matcher with a variety of regexes
dm
target
mirror
status .............................................. parsing mirror status
metadata
config
cascade ............................................... cascade
clone ................................................. duplicating a config tree
parse ................................................. parsing various
An optional 'pattern' argument may be specified to select subsets of tests.
This pattern is a posix regex and does a substring match, so you will need to
use anchors if you particularly want the match at the beginning or end of the
string.
ejt@devel-vm1:~/lvm2/unit-test/$ ./unit-test list data-struct
base
data-struct
bitset
and ................................................. and all bits
equal ............................................... equality
get_next ............................................ get next set bit
list
splice .............................................. joining lists together
string
asprint ............................................. tests asprint
strncpy ............................................. tests string copying
ejt@devel-vm1:~/lvm2/unit-test/$ ./unit-test list s$
base
device
bcache
flush-waits ......................................... flush waits for all dirty
get-reads ........................................... bcache_get() triggers read
prefetch-never-waits ................................ too many prefetches does not trigger a wait
prefetch-reads ...................................... prefetch issues a read
read-multiple-files ................................. read from multiple files
writeback-occurs .................................... dirty data gets written back
zero-flag-dirties ................................... zeroed data counts as dirty
regex
fingerprints .......................................... not sure
dm
target
mirror
status .............................................. parsing mirror status
Running tests
=============
'make run-unit-test' from the top level will run all unit tests. But I tend to
run it by hand to I can select just the tests I'm working on.
Use the 'run' command to run the tests. Currently all logging goes to stderr,
so the test runner prints a line at the start of the test and a line
indicating success or failure at the end.
ejt@devel-vm1:~/lvm2/unit-test/$ ./unit-test run bcache/block-size
[RUN ] /base/device/bcache/block-size-multiple-page
bcache block size must be a multiple of page size
bcache block size must be a multiple of page size
bcache block size must be a multiple of page size
bcache block size must be a multiple of page size
[ OK] /base/device/bcache/block-size-multiple-page
[RUN ] /base/device/bcache/block-size-positive
bcache must have a non zero block size
[ OK] /base/device/bcache/block-size-positive
2/2 tests passed
ejt@devel-vm1:~/lvm2/unit-test/$ ./unit-test run data-struct
[RUN ] /base/data-struct/bitset/and
[ OK] /base/data-struct/bitset/and
[RUN ] /base/data-struct/bitset/equal
[ OK] /base/data-struct/bitset/equal
[RUN ] /base/data-struct/bitset/get_next
[ OK] /base/data-struct/bitset/get_next
[RUN ] /base/data-struct/list/splice
[ OK] /base/data-struct/list/splice
[RUN ] /base/data-struct/string/asprint
[ OK] /base/data-struct/string/asprint
[RUN ] /base/data-struct/string/strncpy
[ OK] /base/data-struct/string/strncpy
6/6 tests passed
Writing tests
=============
[See unit-test/framework.h and unit-test/units.h for the details]
Tests are grouped together into 'suites', all tests in a suite share a
'fixture'. A fixture is a void * to any object you want; use it to set up any
common environment that you need for the tests to run (eg, creating a dm_pool).
Test suites have nothing to do with the test paths, you can have tests from
different suites with similar paths, the runner sorts things for you.
Put your tests in a file in unit-test/, with '_t' at the end of the name
(convention only, nothing relies on this).
#include "units.h"
Then write any fixtures you need:
eg,
static void *_mem_init(void) {
struct dm_pool *mem = dm_pool_create("bitset test", 1024);
if (!mem) {
fprintf(stderr, "out of memory\n");
exit(1);
}
return mem;
}
static void _mem_exit(void *mem)
{
dm_pool_destroy(mem);
}
Then write your tests, which should take the void * that was returned by your
fixture. Use the T_ASSERT* macros to indicate failure.
eg,
static void test_equal(void *fixture)
{
struct dm_pool *mem = fixture;
dm_bitset_t bs1 = dm_bitset_create(mem, NR_BITS);
dm_bitset_t bs2 = dm_bitset_create(mem, NR_BITS);
int i, j;
for (i = 0, j = 1; i < NR_BITS; i += j, j++) {
dm_bit_set(bs1, i);
dm_bit_set(bs2, i);
}
T_ASSERT(dm_bitset_equal(bs1, bs2));
T_ASSERT(dm_bitset_equal(bs2, bs1));
for (i = 0; i < NR_BITS; i++) {
bit_flip(bs1, i);
T_ASSERT(!dm_bitset_equal(bs1, bs2));
T_ASSERT(!dm_bitset_equal(bs2, bs1));
T_ASSERT(dm_bitset_equal(bs1, bs1)); /* comparing with self */
bit_flip(bs1, i);
}
}
At the end of your test file you should write a function that builds one or
more test suites and adds them to the list of all suites that is passed in. I
tend to write a little macro (T) to save typing the same test path repeatedly.
eg,
#define T(path, desc, fn) register_test(ts, "/base/data-struct/bitset/" path, desc, fn)
void bitset_tests(struct dm_list *all_tests)
{
struct test_suite *ts = test_suite_create(_mem_init, _mem_exit);
if (!ts) {
fprintf(stderr, "out of memory\n");
exit(1);
}
T("get_next", "get next set bit", test_get_next);
T("equal", "equality", test_equal);
T("and", "and all bits", test_and);
dm_list_add(all_tests, &ts->list);
}
Then you need to declare your registration function and call it in units.h.
// Declare the function that adds tests suites here ...
...
void bitset_tests(struct dm_list *suites);
...
// ... and call it in here.
static inline void register_all_tests(struct dm_list *suites)
{
...
bitset_tests(suites);
...
}
Finally add your test file to the Makefile.in and rerun configure.

104
doc/vdo.md Normal file
View File

@@ -0,0 +1,104 @@
# VDO - Compression and deduplication.
Currently device stacking looks like this:
Physical x [multipath] x [partition] x [mdadm] x [LUKS] x [LVS] x [LUKS] x [FS|Database|...]
Adding VDO:
Physical x [multipath] x [partition] x [mdadm] x [LUKS] x [LVS] x [LUKS] x VDO x [LVS] x [FS|Database|...]
## Where VDO fits (and where it does not):
### Backing devices for VDO volumes:
1. Physical x [multipath] x [partition] x [mdadm],
2. LUKS over (1) - full disk encryption.
3. LVs (raids|mirror|stripe|linear) x [cache] over (1).
4. LUKS over (3) - especially when using raids.
Usual limitations apply:
- Never layer LUKS over another LUKS - it makes no sense.
- LUKS is better over the raids, than under.
Devices which are not best suitable as backing device:
- thin volumes - at the moment it is not possible to take snapshot of active VDO volume on top of thin volume.
### Using VDO as a PV:
1. under tdata
- The best fit - it will deduplicate additional redundancies among all
snapshots and will reduce the footprint.
- Risks: Resize! dmevent will not be able to handle resizing of tpool ATM.
2. under corig
- This is useful to keep the most frequently used data in cache
uncompressed or without deduplication if that happens to be a bottleneck.
- Cache may fit better under VDO device, depending on compressibility and
amount of duplicates, as
- compression will reduce amount of data, thus effectively increasing
size of cache,
- and deduplication may emphasize hotspots.
- Performance testing of your particular workload is strongly recommended.
3. under (multiple) linear LVs - e.g. used for VMs.
### And where VDO does not fit:
- *never* use VDO under LUKS volumes
- these are random data and do not compress nor deduplicate well,
- *never* use VDO under cmeta and tmeta LVs
- these are random data and do not compress nor deduplicate well,
- under raids
- raid{4,5,6} scrambles data, so they do not deduplicate well,
- raid{1,4,5,6,10} also causes amount of data grow, so more (duplicit in
case of raid{1,10}) work has to be done in order to find less duplicates.
### And where it could be useful:
- under snapshot CoW device - when there are multiple of those it could deduplicate
## Development
### Things to decide
- under integrity devices
- VDO should work well for data blocks,
- but hashes are mostly unique and not compressible - were it possible it
would make sense to have separate imeta and idata volumes for integrity
devices.
### Future Integration of VDO into LVM:
One issue is using both LUKS and RAID under VDO. We have two options:
- use mdadm x LUKS x VDO+LV
- use LV RAID x LUKS x VDO+LV
In both cases dmeventd will not be able to resize the volume at the moment.
Another issue is duality of VDO - it can be used as a top level LV (with a
filesystem on top) but it can be used as "pool" for multiple devices too.
This will be solved in similar way thin pools allow multiple volumes.
Also VDO, has two sizes - its physical size and virtual size - and when
overprovisioning, just like tpool, we face same problems - VDO can get full,
without exposing it to a FS. dmeventd monitoring will be needed.
Another possible RFE is to split data and metadata - keep data on HDD and metadata on SSD.
## Issues / Testing
- fstrim/discard pass down - does it work with VDO?
- VDO can run in synchronous vs. asynchronous mode:
- synchronous for devices where write is safe after it is confirmed. Some
devices are lying.
- asynchronous for devices requiring flush.
- Multiple devices under VDO - need to find and expose common properties, or
not allow grouping them together. (This is same for all volumes with more
physical devices below.)
- pvmove changing characteristics of underlying device.
- autoactivation during boot?
- Q: can we use VDO for RootFS? Dracut!

View File

@@ -14,6 +14,7 @@
@top_srcdir@/lib/config/defaults.h
@top_srcdir@/lib/datastruct/btree.h
@top_srcdir@/lib/datastruct/str_list.h
@top_srcdir@/lib/device/bcache.h
@top_srcdir@/lib/device/dev-cache.h
@top_srcdir@/lib/device/dev-ext-udev-constants.h
@top_srcdir@/lib/device/dev-type.h

View File

@@ -1,4 +1,4 @@
/* include/configure.h.in. Generated from configure.in by autoheader. */
/* include/configure.h.in. Generated from configure.ac by autoheader. */
/* Define to 1 to use libblkid detection of signatures when wiping. */
#undef BLKID_WIPING_SUPPORT
@@ -72,10 +72,6 @@
/* Default system configuration directory. */
#undef DEFAULT_ETC_DIR
/* Fall back to LVM1 by default if device-mapper is missing from the kernel.
*/
#undef DEFAULT_FALLBACK_TO_LVM1
/* Name of default locking directory. */
#undef DEFAULT_LOCK_DIR
@@ -249,6 +245,9 @@
/* Define to 1 if you have the <langinfo.h> header file. */
#undef HAVE_LANGINFO_H
/* Define to 1 if you have the <libaio.h> header file. */
#undef HAVE_LIBAIO_H
/* Define to 1 if you have the <libcman.h> header file. */
#undef HAVE_LIBCMAN_H
@@ -347,9 +346,6 @@
/* Define to 1 if the system has the type `ptrdiff_t'. */
#undef HAVE_PTRDIFF_T
/* Define to 1 if the compiler has the `__builtin_clz` builtin. */
#undef HAVE___BUILTIN_CLZ
/* Define to 1 if you have the <readline/history.h> header file. */
#undef HAVE_READLINE_HISTORY_H
@@ -478,9 +474,16 @@
/* Define to 1 if you have the `strtoull' function. */
#undef HAVE_STRTOULL
/* Define to 1 if `st_blocks' is a member of `struct stat'. */
#undef HAVE_STRUCT_STAT_ST_BLOCKS
/* Define to 1 if `st_rdev' is a member of `struct stat'. */
#undef HAVE_STRUCT_STAT_ST_RDEV
/* Define to 1 if your `struct stat' has `st_blocks'. Deprecated, use
`HAVE_STRUCT_STAT_ST_BLOCKS' instead. */
#undef HAVE_ST_BLOCKS
/* Define to 1 if you have the <syslog.h> header file. */
#undef HAVE_SYSLOG_H
@@ -552,6 +555,9 @@
/* Define to 1 if you have the <sys/utsname.h> header file. */
#undef HAVE_SYS_UTSNAME_H
/* Define to 1 if you have the <sys/vfs.h> header file. */
#undef HAVE_SYS_VFS_H
/* Define to 1 if you have the <sys/wait.h> header file. */
#undef HAVE_SYS_WAIT_H
@@ -591,6 +597,9 @@
/* Define to 1 if the system has the type `_Bool'. */
#undef HAVE__BOOL
/* Define to 1 if the system has the `__builtin_clz' built-in function */
#undef HAVE___BUILTIN_CLZ
/* Internalization package */
#undef INTL_PACKAGE
@@ -607,13 +616,6 @@
slash. */
#undef LSTAT_FOLLOWS_SLASHED_SYMLINK
/* Define to 1 if 'lvm' should fall back to using LVM1 binaries if
device-mapper is missing from the kernel */
#undef LVM1_FALLBACK
/* Define to 1 to include built-in support for LVM1 metadata. */
#undef LVM1_INTERNAL
/* Path to lvmetad pidfile. */
#undef LVMETAD_PIDFILE
@@ -676,18 +678,12 @@
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* Define to 1 to include built-in support for GFS pool metadata. */
#undef POOL_INTERNAL
/* Define to 1 to include built-in support for raid. */
#undef RAID_INTERNAL
/* Define to 1 to include the LVM readline shell. */
#undef READLINE_SUPPORT
/* Define to 1 to include built-in support for replicators. */
#undef REPLICATOR_INTERNAL
/* Define as the return type of signal handlers (`int' or `void'). */
#undef RETSIGTYPE

View File

@@ -16,38 +16,6 @@ srcdir = @srcdir@
top_srcdir = @top_srcdir@
top_builddir = @top_builddir@
ifeq ("@LVM1@", "shared")
SUBDIRS = format1
endif
ifeq ("@POOL@", "shared")
SUBDIRS += format_pool
endif
ifeq ("@SNAPSHOTS@", "shared")
SUBDIRS += snapshot
endif
ifeq ("@MIRRORS@", "shared")
SUBDIRS += mirror
endif
ifeq ("@RAID@", "shared")
SUBDIRS += raid
endif
ifeq ("@REPLICATORS@", "shared")
SUBDIRS += replicator
endif
ifeq ("@THIN@", "shared")
SUBDIRS += thin
endif
ifeq ("@CACHE@", "shared")
SUBDIRS += cache_segtype
endif
ifeq ("@CLUSTER@", "shared")
SUBDIRS += locking
endif
@@ -55,10 +23,13 @@ endif
SOURCES =\
activate/activate.c \
cache/lvmcache.c \
cache_segtype/cache.c \
commands/toolcontext.c \
config/config.c \
datastruct/btree.c \
datastruct/str_list.c \
device/bcache.c \
device/bcache-utils.c \
device/dev-cache.c \
device/dev-ext.c \
device/dev-io.c \
@@ -67,6 +38,7 @@ SOURCES =\
device/dev-type.c \
device/dev-luks.c \
device/dev-dasd.c \
device/dev-lvm1-pool.c \
display/display.c \
error/errseg.c \
unknown/unknown.c \
@@ -81,6 +53,7 @@ SOURCES =\
filters/filter-type.c \
filters/filter-usable.c \
filters/filter-internal.c \
filters/filter-signature.c \
format_text/archive.c \
format_text/archiver.c \
format_text/export.c \
@@ -100,17 +73,18 @@ SOURCES =\
metadata/lv_manip.c \
metadata/merge.c \
metadata/metadata.c \
metadata/metadata-liblvm.c \
metadata/mirror.c \
metadata/pool_manip.c \
metadata/pv.c \
metadata/pv_manip.c \
metadata/pv_map.c \
metadata/raid_manip.c \
metadata/replicator_manip.c \
metadata/segtype.c \
metadata/snapshot_manip.c \
metadata/thin_manip.c \
metadata/vg.c \
mirror/mirrored.c \
misc/crc.c \
misc/lvm-exec.c \
misc/lvm-file.c \
@@ -124,59 +98,19 @@ SOURCES =\
mm/memlock.c \
notify/lvmnotify.c \
properties/prop_common.c \
raid/raid.c \
report/properties.c \
report/report.c \
snapshot/snapshot.c \
striped/striped.c \
thin/thin.c \
uuid/uuid.c \
zero/zero.c
ifeq ("@LVM1@", "internal")
SOURCES +=\
format1/disk-rep.c \
format1/format1.c \
format1/import-export.c \
format1/import-extents.c \
format1/layout.c \
format1/lvm1-label.c \
format1/vg_number.c
endif
ifeq ("@POOL@", "internal")
SOURCES +=\
format_pool/disk_rep.c \
format_pool/format_pool.c \
format_pool/import_export.c \
format_pool/pool_label.c
endif
ifeq ("@CLUSTER@", "internal")
SOURCES += locking/cluster_locking.c
endif
ifeq ("@SNAPSHOTS@", "internal")
SOURCES += snapshot/snapshot.c
endif
ifeq ("@MIRRORS@", "internal")
SOURCES += mirror/mirrored.c
endif
ifeq ("@RAID@", "internal")
SOURCES += raid/raid.c
endif
ifeq ("@REPLICATORS@", "internal")
SOURCES += replicator/replicator.c
endif
ifeq ("@THIN@", "internal")
SOURCES += thin/thin.c
endif
ifeq ("@CACHE@", "internal")
SOURCES += cache_segtype/cache.c
endif
ifeq ("@DEVMAPPER@", "yes")
SOURCES +=\
activate/dev_manager.c \
@@ -209,15 +143,7 @@ LIB_STATIC = $(LIB_NAME).a
ifeq ($(MAKECMDGOALS),distclean)
SUBDIRS =\
format1 \
format_pool \
snapshot \
mirror \
notify \
raid \
replicator \
thin \
cache_segtype \
locking
endif

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004-2017 Red Hat, Inc. All rights reserved.
* Copyright (C) 2004-2018 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
@@ -28,6 +28,8 @@
#include "config.h"
#include "segtype.h"
#include "sharedlib.h"
#include "lvmcache.h"
#include "metadata.h"
#include <limits.h>
#include <fcntl.h>
@@ -35,19 +37,6 @@
#define _skip(fmt, args...) log_very_verbose("Skipping: " fmt , ## args)
int lvm1_present(struct cmd_context *cmd)
{
static char path[PATH_MAX];
if (dm_snprintf(path, sizeof(path), "%s/lvm/global", cmd->proc_dir)
< 0) {
log_error("LVM1 proc global snprintf failed");
return 0;
}
return (path_exists(path)) ? 1 : 0;
}
int list_segment_modules(struct dm_pool *mem, const struct lv_segment *seg,
struct dm_list *modules)
{
@@ -323,12 +312,6 @@ int lvs_in_vg_opened(const struct volume_group *vg)
{
return 0;
}
/******
int lv_suspend(struct cmd_context *cmd, const char *lvid_s)
{
return 1;
}
*******/
int lv_suspend_if_active(struct cmd_context *cmd, const char *lvid_s, unsigned origin_only, unsigned exclusive,
const struct logical_volume *lv, const struct logical_volume *lv_pre)
{
@@ -612,7 +595,7 @@ int module_present(struct cmd_context *cmd, const char *target_name)
#endif
struct stat st;
char path[PATH_MAX];
int i = dm_snprintf(path, (sizeof(path) - 1), "%smodule/dm_%s",
int i = dm_snprintf(path, sizeof(path), "%smodule/dm_%s",
dm_sysfs_dir(), target_name);
if (i > 0) {
@@ -1012,8 +995,10 @@ int lv_raid_data_offset(const struct logical_volume *lv, uint64_t *data_offset)
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1)))
return_0;
if (!(r = dev_manager_raid_status(dm, lv, &status)))
stack;
if (!(r = dev_manager_raid_status(dm, lv, &status))) {
dev_manager_destroy(dm);
return_0;
}
*data_offset = status->data_offset;
@@ -1549,8 +1534,11 @@ static int _lv_is_active(const struct logical_volume *lv,
if (skip_cluster_query)
goto out;
if ((r = cluster_lock_held(lv->lvid.s, "", &e)) >= 0)
if ((r = cluster_lock_held(lv->lvid.s, "", &e)) >= 0) {
if (l && e)
r = 0; /* exclusive locally */
goto out;
}
/*
* If lock query is not supported (due to interfacing with old
@@ -1668,7 +1656,10 @@ static struct dm_event_handler *_create_dm_event_handler(struct cmd_context *cmd
if (!(dmevh = dm_event_handler_create()))
return_NULL;
if (dm_event_handler_set_dmeventd_path(dmevh, find_config_tree_str(cmd, dmeventd_executable_CFG, NULL)))
if (!cmd->default_settings.dmeventd_executable)
cmd->default_settings.dmeventd_executable = find_config_tree_str(cmd, dmeventd_executable_CFG, NULL);
if (dm_event_handler_set_dmeventd_path(dmevh, cmd->default_settings.dmeventd_executable))
goto_bad;
if (dso && dm_event_handler_set_dso(dmevh, dso))
@@ -1684,21 +1675,18 @@ static struct dm_event_handler *_create_dm_event_handler(struct cmd_context *cmd
bad:
dm_event_handler_destroy(dmevh);
return NULL;
}
char *get_monitor_dso_path(struct cmd_context *cmd, const char *libpath)
char *get_monitor_dso_path(struct cmd_context *cmd, int id)
{
char *path;
const char *libpath = find_config_tree_str(cmd, id, NULL);
char path[PATH_MAX];
if (!(path = dm_pool_alloc(cmd->mem, PATH_MAX))) {
log_error("Failed to allocate dmeventd library path.");
return NULL;
}
get_shared_library_path(cmd, libpath, path, sizeof(path));
get_shared_library_path(cmd, libpath, path, PATH_MAX);
return path;
return dm_strdup(path);
}
static char *_build_target_uuid(struct cmd_context *cmd, const struct logical_volume *lv)
@@ -1707,7 +1695,7 @@ static char *_build_target_uuid(struct cmd_context *cmd, const struct logical_vo
if (lv_is_thin_pool(lv))
layer = "tpool"; /* Monitor "tpool" for the "thin pool". */
else if (lv_is_origin(lv))
else if (lv_is_origin(lv) || lv_is_external_origin(lv))
layer = "real"; /* Monitor "real" for "snapshot-origin". */
else
layer = NULL;
@@ -1715,13 +1703,18 @@ static char *_build_target_uuid(struct cmd_context *cmd, const struct logical_vo
return build_dm_uuid(cmd->mem, lv, layer);
}
static int _device_registered_with_dmeventd(struct cmd_context *cmd, const struct logical_volume *lv, int *pending, const char **dso)
static int _device_registered_with_dmeventd(struct cmd_context *cmd,
const struct logical_volume *lv,
const char **dso,
int *pending, int *monitored)
{
char *uuid;
enum dm_event_mask evmask = 0;
enum dm_event_mask evmask;
struct dm_event_handler *dmevh;
int r;
*pending = 0;
*monitored = 0;
if (!(uuid = _build_target_uuid(cmd, lv)))
return_0;
@@ -1729,9 +1722,20 @@ static int _device_registered_with_dmeventd(struct cmd_context *cmd, const struc
if (!(dmevh = _create_dm_event_handler(cmd, uuid, NULL, 0, DM_EVENT_ALL_ERRORS)))
return_0;
if (dm_event_get_registered_device(dmevh, 0)) {
dm_event_handler_destroy(dmevh);
return 0;
if ((r = dm_event_get_registered_device(dmevh, 0))) {
if (r == -ENOENT) {
r = 1;
goto out;
}
r = 0;
goto_out;
}
/* FIXME: why do we care which 'dso' is monitoring? */
if (dso && (*dso = dm_event_handler_get_dso(dmevh)) &&
!(*dso = dm_pool_strdup(cmd->mem, *dso))) {
r = 0;
goto_out;
}
evmask = dm_event_handler_get_event_mask(dmevh);
@@ -1740,21 +1744,25 @@ static int _device_registered_with_dmeventd(struct cmd_context *cmd, const struc
evmask &= ~DM_EVENT_REGISTRATION_PENDING;
}
if (dso && (*dso = dm_event_handler_get_dso(dmevh)) && !(*dso = dm_pool_strdup(cmd->mem, *dso)))
log_error("Failed to duplicate dso name.");
*monitored = evmask;
r = 1;
out:
dm_event_handler_destroy(dmevh);
return evmask;
return r;
}
int target_registered_with_dmeventd(struct cmd_context *cmd, const char *dso,
const struct logical_volume *lv, int *pending)
const struct logical_volume *lv,
int *pending, int *monitored)
{
char *uuid;
enum dm_event_mask evmask = 0;
enum dm_event_mask evmask;
struct dm_event_handler *dmevh;
int r;
*pending = 0;
*monitored = 0;
if (!dso)
return_0;
@@ -1765,9 +1773,13 @@ int target_registered_with_dmeventd(struct cmd_context *cmd, const char *dso,
if (!(dmevh = _create_dm_event_handler(cmd, uuid, dso, 0, DM_EVENT_ALL_ERRORS)))
return_0;
if (dm_event_get_registered_device(dmevh, 0)) {
dm_event_handler_destroy(dmevh);
return 0;
if ((r = dm_event_get_registered_device(dmevh, 0))) {
if (r == -ENOENT) {
r = 1;
goto out;
}
r = 0;
goto_out;
}
evmask = dm_event_handler_get_event_mask(dmevh);
@@ -1776,9 +1788,12 @@ int target_registered_with_dmeventd(struct cmd_context *cmd, const char *dso,
evmask &= ~DM_EVENT_REGISTRATION_PENDING;
}
*monitored = evmask;
r = 1;
out:
dm_event_handler_destroy(dmevh);
return evmask;
return r;
}
int target_register_events(struct cmd_context *cmd, const char *dso, const struct logical_volume *lv,
@@ -1806,7 +1821,7 @@ int target_register_events(struct cmd_context *cmd, const char *dso, const struc
if (!r)
return_0;
log_very_verbose("%s %s for events", set ? "Monitored" : "Unmonitored", uuid);
log_verbose("%s %s for events", set ? "Monitored" : "Unmonitored", uuid);
return 1;
}
@@ -1821,7 +1836,7 @@ int monitor_dev_for_events(struct cmd_context *cmd, const struct logical_volume
const struct lv_activate_opts *laopts, int monitor)
{
#ifdef DMEVENTD
int i, pending = 0, monitored;
int i, pending = 0, monitored = 0;
int r = 1;
struct dm_list *snh, *snht;
struct lv_segment *seg;
@@ -1829,6 +1844,7 @@ int monitor_dev_for_events(struct cmd_context *cmd, const struct logical_volume
int (*monitor_fn) (struct lv_segment *s, int e);
uint32_t s;
static const struct lv_activate_opts zlaopts = { 0 };
struct lv_activate_opts mirr_laopts = { .origin_only = 1 };
struct lvinfo info;
const char *dso = NULL;
int new_unmonitor;
@@ -1891,7 +1907,8 @@ int monitor_dev_for_events(struct cmd_context *cmd, const struct logical_volume
* In case of a snapshot device, we monitor lv->snapshot->lv,
* not the actual LV itself.
*/
if (lv_is_cow(lv) && (laopts->no_merging || !lv_is_merging_cow(lv))) {
if (lv_is_cow(lv) && (laopts->no_merging || !lv_is_merging_cow(lv) ||
lv_has_target_type(lv->vg->cmd->mem, lv, NULL, TARGET_NAME_SNAPSHOT))) {
if (!(r = monitor_dev_for_events(cmd, lv->snapshot->lv, NULL, monitor)))
stack;
return r;
@@ -1930,9 +1947,7 @@ int monitor_dev_for_events(struct cmd_context *cmd, const struct logical_volume
continue;
if (!monitor_dev_for_events(cmd, seg_lv(seg, s), NULL,
monitor)) {
log_error("Failed to %smonitor %s",
monitor ? "" : "un",
display_lvname(seg_lv(seg, s)));
stack;
r = 0;
}
}
@@ -1949,6 +1964,13 @@ int monitor_dev_for_events(struct cmd_context *cmd, const struct logical_volume
r = 0;
}
if (seg->external_lv &&
!monitor_dev_for_events(cmd, seg->external_lv,
(!monitor) ? laopts : NULL, monitor)) {
stack;
r = 0;
}
if (seg->metadata_lv &&
!monitor_dev_for_events(cmd, seg->metadata_lv, NULL, monitor)) {
stack;
@@ -1960,11 +1982,21 @@ int monitor_dev_for_events(struct cmd_context *cmd, const struct logical_volume
!seg->segtype->ops->target_monitored) /* doesn't support registration */
continue;
if (!monitor)
if (!monitor) {
/* When unmonitoring, obtain existing dso being used. */
monitored = _device_registered_with_dmeventd(cmd, seg_is_snapshot(seg) ? seg->cow : seg->lv, &pending, &dso);
else
monitored = seg->segtype->ops->target_monitored(seg, &pending);
if (!_device_registered_with_dmeventd(cmd, seg_is_snapshot(seg) ? seg->cow : seg->lv,
&dso, &pending, &monitored)) {
log_warn("WARNING: Failed to %smonitor %s.",
monitor ? "" : "un",
display_lvname(seg_is_snapshot(seg) ? seg->cow : seg->lv));
return 0;
}
} else if (!seg->segtype->ops->target_monitored(seg, &pending, &monitored)) {
log_warn("WARNING: Failed to %smonitor %s.",
monitor ? "" : "un",
display_lvname(seg->lv));
return 0;
}
/* FIXME: We should really try again if pending */
monitored = (pending) ? 0 : monitored;
@@ -1976,7 +2008,9 @@ int monitor_dev_for_events(struct cmd_context *cmd, const struct logical_volume
if (monitored)
log_verbose("%s already monitored.", display_lvname(lv));
else if (seg->segtype->ops->target_monitor_events) {
log_verbose("Monitoring %s%s", display_lvname(lv), test_mode() ? " [Test mode: skipping this]" : "");
log_very_verbose("Monitoring %s with %s.%s", display_lvname(lv),
seg->segtype->dso,
test_mode() ? " [Test mode: skipping this]" : "");
monitor_fn = seg->segtype->ops->target_monitor_events;
}
} else {
@@ -1998,26 +2032,42 @@ int monitor_dev_for_events(struct cmd_context *cmd, const struct logical_volume
if (new_unmonitor) {
if (!target_register_events(cmd, dso, seg_is_snapshot(seg) ? seg->cow : lv, 0, 0, 10)) {
log_error("%s: segment unmonitoring failed.",
display_lvname(lv));
log_warn("WARNING: %s: segment unmonitoring failed.",
display_lvname(lv));
return 0;
}
} else if (monitor_fn) {
/* FIXME specify events */
if (!monitor_fn(seg, 0)) {
log_error("%s: %s segment monitoring function failed.",
display_lvname(lv), lvseg_name(seg));
log_warn("WARNING: %s: %s segment monitoring function failed.",
display_lvname(lv), lvseg_name(seg));
return 0;
}
} else
continue;
if (!vg_write_lock_held() && lv_is_mirror(lv)) {
mirr_laopts.exclusive = lv_is_active_exclusive_locally(lv) ? 1 : 0;
/*
* Commands vgchange and lvchange do use read-only lock when changing
* monitoring (--monitor y|n). All other use cases hold 'write-lock'
* so they skip this dm mirror table refreshing step.
*/
if (!_lv_activate_lv(lv, &mirr_laopts)) {
stack;
r = 0;
}
}
/* Check [un]monitor results */
/* Try a couple times if pending, but not forever... */
for (i = 0;; i++) {
pending = 0;
monitored = seg->segtype->ops->target_monitored(seg, &pending);
if (!seg->segtype->ops->target_monitored(seg, &pending, &monitored)) {
stack;
r = 0;
break;
}
if (!pending || i >= 40)
break;
log_very_verbose("%s %smonitoring still pending: waiting...",
@@ -2030,8 +2080,8 @@ int monitor_dev_for_events(struct cmd_context *cmd, const struct logical_volume
}
if (!r && !error_message_produced())
log_error("%sonitoring %s failed.", monitor ? "M" : "Not m",
display_lvname(lv));
log_warn("WARNING: %sonitoring %s failed.", monitor ? "M" : "Not m",
display_lvname(lv));
return r;
#else
return 1;
@@ -2062,6 +2112,12 @@ static int _preload_detached_lv(struct logical_volume *lv, void *data)
return_0;
}
if (!lv_is_visible(lv) && (lv_pre = find_lv(detached->lv_pre->vg, lv->name)) &&
lv_is_visible(lv_pre)) {
if (!_lv_preload(lv_pre, detached->laopts, detached->flush_required))
return_0;
}
/* FIXME: condition here should be far more limiting to really
* detect detached LVs */
if ((lv_pre = find_lv(detached->lv_pre->vg, lv->name))) {
@@ -2082,16 +2138,76 @@ static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
const struct logical_volume *pvmove_lv = NULL;
const struct logical_volume *lv_to_free = NULL;
const struct logical_volume *lv_pre_to_free = NULL;
struct logical_volume *lv_pre_tmp;
struct logical_volume *lv_pre_tmp, *lv_tmp;
struct seg_list *sl;
struct lv_segment *snap_seg;
struct lvinfo info;
int r = 0, lockfs = 0, flush_required = 0;
struct detached_lv_data detached;
struct dm_pool *mem = NULL;
struct dm_list suspend_lvs;
struct lv_list *lvl;
const union lvid *lvid = (const union lvid *) lvid_s;
const char *vgid = (const char *)lvid->id[0].uuid;
struct volume_group *vg;
struct volume_group *vg_pre;
int found;
if (!activation())
return 1;
if (!cmd->is_clvmd)
goto skip_read;
if (lv && lv_pre)
goto skip_read;
if (!(vg = lvmcache_get_saved_vg(vgid, 0))) {
log_debug("lv_suspend did not find saved_vg %.8s so reading", vgid);
if (!(vg = vg_read_by_vgid(cmd, vgid, 0))) {
log_error("lv_suspend could not read vgid %.8s", vgid);
goto out;
}
log_debug("lv_suspend using read vg %s %d %p", vg->name, vg->seqno, vg);
} else {
log_debug("lv_suspend using saved_vg %s %d %p", vg->name, vg->seqno, vg);
}
if (!(vg_pre = lvmcache_get_saved_vg(vgid, 1))) {
log_debug("lv_suspend did not find pre saved_vg %.8s so reading", vgid);
if (!(vg_pre = vg_read_by_vgid(cmd, vgid, 1))) {
log_error("lv_suspend could not read pre vgid %.8s", vgid);
goto out;
}
log_debug("lv_suspend using pre read vg %s %d %p", vg_pre->name, vg_pre->seqno, vg_pre);
} else {
log_debug("lv_suspend using pre saved_vg %s %d %p", vg_pre->name, vg_pre->seqno, vg_pre);
}
/*
* Note that vg and vg_pre returned by vg_read_by_vgid will
* not be the same as saved_vg_old/saved_vg_new that would
* be returned by lvmcache_get_saved_vg() because the saved_vg's
* are copies of the vg struct that is created by _vg_read.
* (Should we grab and use the saved_vg to use here instead of
* the vg returned by vg_read_by_vgid?)
*/
if ((vg->status & EXPORTED_VG) || (vg_pre->status & EXPORTED_VG)) {
log_error("Volume group \"%s\" is exported", vg->name);
goto out;
}
lv = lv_to_free = find_lv_in_vg_by_lvid(vg, lvid);
lv_pre = lv_pre_to_free = find_lv_in_vg_by_lvid(vg_pre, lvid);
if (!lv || !lv_pre) {
log_error("lv_suspend could not find lv %p lv_pre %p vg %p vg_pre %p vgid %s",
lv, lv_pre, vg, vg_pre, vgid);
goto out;
}
skip_read:
/* lv comes from committed metadata */
if (!lv && !(lv_to_free = lv = lv_from_lvid(cmd, lvid_s, 0)))
goto_out;
@@ -2116,6 +2232,19 @@ static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
if (!lv_info(cmd, lv, laopts->origin_only, &info, 0, 0))
goto_out;
/*
* Save old and new (current and precommitted) versions of the
* VG metadata for lv_resume() to use, since lv_resume can't
* read metadata given that devices are suspended. lv_resume()
* will resume LVs using the old/current metadata if the vg_commit
* did happen (or failed), and it will resume LVs using the
* new/precommitted metadata if the vg_commit succeeded.
*/
if (cmd->is_clvmd) {
lvmcache_save_vg(lv->vg, 0);
lvmcache_save_vg(lv_pre->vg, 1);
}
if (!info.exists || info.suspended) {
if (!error_if_not_suspended) {
r = 1;
@@ -2125,9 +2254,6 @@ static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
goto out;
}
if (!lv_read_replicator_vgs(lv))
goto_out;
lv_calculate_readahead(lv, NULL);
/*
@@ -2157,6 +2283,12 @@ static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
}
if (!_lv_preload(lv_pre_tmp, laopts, &flush_required))
goto_out;
/* Suspending 1st. LV above PVMOVE suspends whole tree */
dm_list_iterate_items(sl, &pvmove_lv->segs_using_this_lv) {
lv = sl->seg->lv;
break;
}
} else {
if (!_lv_preload(lv_pre, laopts, &flush_required))
/* FIXME Revert preloading */
@@ -2194,7 +2326,7 @@ static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
* NOTE: Mirror repair requires noflush for proper repair!
* TODO: Relax this limiting condition further */
if (!flush_required &&
(lv_is_pvmove(lv) ||
(lv_is_pvmove(lv) || pvmove_lv ||
(!lv_is_mirror(lv) && !lv_is_thin_pool(lv) && !lv_is_thin_volume(lv)))) {
log_debug("Requiring flush for LV %s.", display_lvname(lv));
flush_required = 1;
@@ -2204,10 +2336,6 @@ static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
/* FIXME Consider aborting here */
stack;
critical_section_inc(cmd, "suspending");
if (pvmove_lv)
critical_section_inc(cmd, "suspending pvmove LV");
if (!laopts->origin_only &&
(lv_is_origin(lv_pre) || lv_is_cow(lv_pre)))
lockfs = 1;
@@ -2219,40 +2347,68 @@ static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
if (laopts->origin_only && lv_is_thin_volume(lv) && lv_is_thin_volume(lv_pre))
lockfs = 1;
/*
* Suspending an LV directly above a PVMOVE LV also
* suspends other LVs using that same PVMOVE LV.
* FIXME Remove this and delay the 'clear node' until
* after the code knows whether there's a different
* inactive table to load or not instead so lv_suspend
* can be called separately for each LV safely.
*/
if ((lv_pre->vg->status & PRECOMMITTED) &&
lv_is_locked(lv_pre) && find_pvmove_lv_in_lv(lv_pre)) {
if (!_lv_suspend_lv(lv_pre, laopts, lockfs, flush_required)) {
critical_section_dec(cmd, "failed precommitted suspend");
if (pvmove_lv)
critical_section_dec(cmd, "failed precommitted suspend (pvmove)");
critical_section_inc(cmd, "suspending");
if (!lv_is_locked(lv) && lv_is_locked(lv_pre) &&
(pvmove_lv = find_pvmove_lv_in_lv(lv_pre))) {
/*
* When starting PVMOVE, suspend participating LVs first
* with committed metadata by looking at precommited pvmove list.
* In committed metadata these LVs are not connected in any way.
*
* TODO: prepare list of LVs needed to be suspended and pass them
* via 'struct laopts' directly to _lv_suspend_lv() and handle this
* with a single 'dmtree' call.
*/
if (!(mem = dm_pool_create("suspend_lvs", 128)))
goto_out;
/* Prepare list of all LVs for suspend ahead */
dm_list_init(&suspend_lvs);
dm_list_iterate_items(sl, &pvmove_lv->segs_using_this_lv) {
lv_tmp = sl->seg->lv;
if (lv_is_cow(lv_tmp))
/* Never suspend COW, always has to be origin */
lv_tmp = origin_from_cow(lv_tmp);
found = 0;
dm_list_iterate_items(lvl, &suspend_lvs)
if (strcmp(lvl->lv->name, lv_tmp->name) == 0) {
found = 1;
break;
}
if (found)
continue; /* LV is already in the list */
if (!(lvl = dm_pool_alloc(mem, sizeof(*lvl)))) {
log_error("lv_list alloc failed.");
goto out;
}
/* Look for precommitted LV name in commmitted VG */
if (!(lvl->lv = find_lv(lv->vg, lv_tmp->name))) {
log_error(INTERNAL_ERROR "LV %s missing from preload metadata.",
display_lvname(lv_tmp));
goto out;
}
dm_list_add(&suspend_lvs, &lvl->list);
}
} else {
/* Normal suspend */
dm_list_iterate_items(lvl, &suspend_lvs)
if (!_lv_suspend_lv(lvl->lv, laopts, lockfs, 1)) {
critical_section_dec(cmd, "failed suspend");
goto_out; /* FIXME: resume on recovery path? */
}
} else /* Standard suspend */
if (!_lv_suspend_lv(lv, laopts, lockfs, flush_required)) {
critical_section_dec(cmd, "failed suspend");
if (pvmove_lv)
critical_section_dec(cmd, "failed suspend (pvmove)");
goto_out;
}
}
r = 1;
out:
if (mem)
dm_pool_destroy(mem);
if (lv_pre_to_free)
release_vg(lv_pre_to_free->vg);
if (lv_to_free) {
lv_release_replicator_vgs(lv_to_free);
if (lv_to_free)
release_vg(lv_to_free->vg);
}
return r;
}
@@ -2274,20 +2430,76 @@ int lv_suspend_if_active(struct cmd_context *cmd, const char *lvid_s, unsigned o
return _lv_suspend(cmd, lvid_s, &laopts, 0, lv, lv_pre);
}
static int _check_suspended_lv(struct logical_volume *lv, void *data)
{
struct lvinfo info;
if (lv_info(lv->vg->cmd, lv, 0, &info, 0, 0) && info.exists && info.suspended) {
log_debug("Found suspended LV %s in critical section().", display_lvname(lv));
return 0; /* There is suspended subLV in the tree */
}
if (lv_layer(lv) && lv_info(lv->vg->cmd, lv, 1, &info, 0, 0) && info.exists && info.suspended) {
log_debug("Found suspended layered LV %s in critical section().", display_lvname(lv));
return 0; /* There is suspended subLV in the tree */
}
return 1;
}
static int _lv_resume(struct cmd_context *cmd, const char *lvid_s,
struct lv_activate_opts *laopts, int error_if_not_active,
const struct logical_volume *lv)
{
const struct logical_volume *lv_to_free = NULL;
struct dm_list *snh;
struct volume_group *vg = NULL;
struct logical_volume *lv_found = NULL;
const union lvid *lvid;
const char *vgid;
struct lvinfo info;
int r = 0;
if (!activation())
return 1;
if (!lv && !(lv_to_free = lv = lv_from_lvid(cmd, lvid_s, 0)))
goto_out;
/*
* When called in clvmd, lvid_s is set and lv is not. We need to
* get the VG metadata without reading disks because devs are
* suspended. lv_suspend() saved old and new VG metadata for us
* to use here. If vg_commit() happened, lvmcache_get_saved_vg_latest
* will return the new metadata for us to use in resuming LVs.
* If vg_commit() did not happen, lvmcache_get_saved_vg_latest
* returns the old metadata which we use to resume LVs.
*/
if (!lv && lvid_s) {
lvid = (const union lvid *) lvid_s;
vgid = (const char *)lvid->id[0].uuid;
if ((vg = lvmcache_get_saved_vg_latest(vgid))) {
log_debug_activation("Resuming LVID %s found saved vg seqno %d %s", lvid_s, vg->seqno, vg->name);
if ((lv_found = find_lv_in_vg_by_lvid(vg, lvid))) {
log_debug_activation("Resuming LVID %s found saved LV %s", lvid_s, display_lvname(lv_found));
lv = lv_found;
} else
log_debug_activation("Resuming LVID %s did not find saved LV", lvid_s);
} else
log_debug_activation("Resuming LVID %s did not find saved VG", lvid_s);
/*
* resume must have been called without a preceding suspend,
* so we need to read the vg.
*/
if (!lv) {
log_debug_activation("Resuming LVID %s reading VG", lvid_s);
if (!(lv_found = lv_from_lvid(cmd, lvid_s, 0))) {
log_debug_activation("Resuming LVID %s failed to read VG", lvid_s);
goto out;
}
lv = lv_found;
}
}
if (!lv_is_origin(lv) && !lv_is_thin_volume(lv) && !lv_is_thin_pool(lv))
laopts->origin_only = 0;
@@ -2313,12 +2525,28 @@ static int _lv_resume(struct cmd_context *cmd, const char *lvid_s,
if (!info.exists || !info.suspended) {
if (error_if_not_active)
goto_out;
r = 1;
if (!info.suspended)
critical_section_dec(cmd, "already resumed");
goto out;
}
/* ATM only thin-pool with origin-only suspend does not really suspend anything
* it's used only for message passing to thin-pool */
if (laopts->origin_only && lv_is_thin_pool(lv))
critical_section_dec(cmd, "resumed");
if (!info.suspended && critical_section()) {
/* Validation check if any subLV is suspended */
if (!laopts->origin_only && lv_is_origin(lv)) {
/* Check all snapshots for this origin LV */
dm_list_iterate(snh, &lv->snapshot_segs)
if (!_check_suspended_lv(dm_list_struct_base(snh, struct lv_segment, origin_list)->cow, NULL))
goto needs_resume; /* Found suspended snapshot */
}
if ((r = for_each_sub_lv((struct logical_volume *)lv, &_check_suspended_lv, NULL)))
goto out; /* Nothing was found suspended */
} else {
r = 1;
goto out;
}
}
needs_resume:
laopts->read_only = _passes_readonly_filter(cmd, lv);
laopts->resuming = 1;
@@ -2332,9 +2560,6 @@ static int _lv_resume(struct cmd_context *cmd, const char *lvid_s,
r = 1;
out:
if (lv_to_free)
release_vg(lv_to_free->vg);
return r;
}
@@ -2436,14 +2661,21 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s, const struct logi
goto_out;
}
if (!lv_read_replicator_vgs(lv))
goto_out;
if (!monitor_dev_for_events(cmd, lv, &laopts, 0))
stack;
critical_section_inc(cmd, "deactivating");
r = _lv_deactivate(lv);
/*
* Remove any transiently activated error
* devices which arean't used any more.
*/
if (r && lv_is_raid(lv) && !lv_deactivate_any_missing_subdevs(lv)) {
log_error("Failed to remove temporary SubLVs from %s",
display_lvname(lv));
r = 0;
}
critical_section_dec(cmd, "deactivated");
if (!lv_info(cmd, lv, 0, &info, 0, 0) || info.exists) {
@@ -2453,10 +2685,8 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s, const struct logi
r = 0;
}
out:
if (lv_to_free) {
lv_release_replicator_vgs(lv_to_free);
if (lv_to_free)
release_vg(lv_to_free->vg);
}
return r;
}
@@ -2504,6 +2734,15 @@ static int _lv_activate(struct cmd_context *cmd, const char *lvid_s,
if (!lv && !(lv_to_free = lv = lv_from_lvid(cmd, lvid_s, 0)))
goto out;
if (!laopts->exclusive &&
(lv_is_origin(lv) ||
seg_only_exclusive(first_seg(lv)))) {
log_error(INTERNAL_ERROR "Trying non-exlusive activation of %s with "
"a volume type %s requiring exclusive activation.",
display_lvname(lv), lvseg_name(first_seg(lv)));
return 0;
}
if (filter && !_passes_activation_filter(cmd, lv)) {
log_verbose("Not activating %s since it does not pass "
"activation filter.", display_lvname(lv));
@@ -2549,7 +2788,12 @@ static int _lv_activate(struct cmd_context *cmd, const char *lvid_s,
goto out;
}
if (filter)
/* Component LV activation is enforced to be 'read-only' */
/* TODO: should not apply for LVs in maintenance mode */
if (!lv_is_visible(lv) && lv_is_component(lv)) {
laopts->read_only = 1;
laopts->component_lv = lv;
} else if (filter)
laopts->read_only = _passes_readonly_filter(cmd, lv);
log_debug_activation("Activating %s%s%s%s%s.", display_lvname(lv),
@@ -2565,15 +2809,12 @@ static int _lv_activate(struct cmd_context *cmd, const char *lvid_s,
* Nothing to do?
*/
if (info.exists && !info.suspended && info.live_table &&
(info.read_only == read_only_lv(lv, laopts))) {
(info.read_only == read_only_lv(lv, laopts, NULL))) {
r = 1;
log_debug_activation("LV %s is already active.", display_lvname(lv));
goto out;
}
if (!lv_read_replicator_vgs(lv))
goto_out;
lv_calculate_readahead(lv, NULL);
critical_section_inc(cmd, "activating");
@@ -2585,10 +2826,8 @@ static int _lv_activate(struct cmd_context *cmd, const char *lvid_s,
stack;
out:
if (lv_to_free) {
lv_release_replicator_vgs(lv_to_free);
if (lv_to_free)
release_vg(lv_to_free->vg);
}
return r;
}
@@ -2680,10 +2919,8 @@ static int _lv_remove_any_missing_subdevs(struct logical_volume *lv)
struct lv_segment *seg;
dm_list_iterate_items(seg, &lv->segments) {
if (seg->area_count != 1)
return_0;
if (dm_snprintf(name, sizeof(name), "%s-%s-missing_%u_0", seg->lv->vg->name, seg->lv->name, seg_no) < 0)
return 0;
return_0;
if (!_remove_dm_dev_by_name(name))
return 0;
@@ -2743,3 +2980,112 @@ void activation_exit(void)
dev_manager_exit();
}
#endif
static int _component_cb(struct logical_volume *lv, void *data)
{
struct logical_volume **component_lv = (struct logical_volume **) data;
if (lv_is_locked(lv) || lv_is_pvmove(lv) ||/* ignoring */
/* thin-pool is special and it's using layered device */
(lv_is_thin_pool(lv) && pool_is_active(lv)))
return -1;
if (lv_is_active(lv)) {
if (!lv_is_component(lv) || lv_is_visible(lv))
return -1; /* skip whole subtree */
log_debug_activation("Found active component LV %s.", display_lvname(lv));
*component_lv = lv;
return 0; /* break any further processing */
}
return 1;
}
/*
* Finds out for any LV if any of its component LVs are active.
* Function first checks if an existing LV is visible and active eventually
* it's lock holding LV is already active. In such case sub LV cannot be
* actived alone and no further checking is needed.
*
* Returns active component LV if there is such.
*/
const struct logical_volume *lv_component_is_active(const struct logical_volume *lv)
{
const struct logical_volume *component_lv = NULL;
const struct logical_volume *holder_lv = lv_lock_holder(lv);
if ((holder_lv != lv) && lv_is_active(holder_lv))
return NULL; /* Lock holding LV is active, do not check components */
if (_component_cb((struct logical_volume *) lv, &holder_lv) == 1)
(void) for_each_sub_lv((struct logical_volume *) lv, _component_cb,
(void*) &component_lv);
return component_lv;
}
/*
* Finds out if any LV above is active, as stacked device tree can be composed of
* chained set of LVs.
*
* Returns active holder LV if there is such.
*/
const struct logical_volume *lv_holder_is_active(const struct logical_volume *lv)
{
const struct logical_volume *holder;
const struct seg_list *sl;
if (lv_is_locked(lv) || lv_is_pvmove(lv))
return NULL; /* Skip pvmove/locked LV tracking */
dm_list_iterate_items(sl, &lv->segs_using_this_lv) {
/* Recursive call for upper-stack holder */
if ((holder = lv_holder_is_active(sl->seg->lv)))
return holder;
if (lv_is_active(sl->seg->lv)) {
log_debug_activation("Found active holder LV %s.", display_lvname(sl->seg->lv));
return sl->seg->lv;
}
}
return NULL;
}
static int _deactivate_sub_lv_cb(struct logical_volume *lv, void *data)
{
struct logical_volume **slv = data;
if (lv_is_thin_pool(lv) || lv_is_external_origin(lv))
return -1;
if (!deactivate_lv(lv->vg->cmd, lv)) {
*slv = lv;
return 0;
}
return 1;
}
/*
* Deactivates LV toghether with explicit deactivation call made also for all its component LVs.
*/
int deactivate_lv_with_sub_lv(const struct logical_volume *lv)
{
struct logical_volume *flv;
if (!deactivate_lv(lv->vg->cmd, lv)) {
log_error("Cannot deactivate logical volume %s.",
display_lvname(lv));
return 0;
}
if (!for_each_sub_lv((struct logical_volume *)lv, _deactivate_sub_lv_cb, &flv)) {
log_error("Cannot deactivate subvolume %s of logical volume %s.",
display_lvname(flv), display_lvname(lv));
return 0;
}
return 1;
}

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004-2016 Red Hat, Inc. All rights reserved.
* Copyright (C) 2004-2018 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
@@ -83,6 +83,7 @@ struct lv_activate_opts {
* flags are persistent in udev db for any spurious event
* that follows. */
unsigned resuming; /* Set when resuming after a suspend. */
const struct logical_volume *component_lv;
};
void set_activation(int activation, int silent);
@@ -90,7 +91,6 @@ int activation(void);
int driver_version(char *version, size_t size);
int library_version(char *version, size_t size);
int lvm1_present(struct cmd_context *cmd);
int module_present(struct cmd_context *cmd, const char *target_name);
int target_present_version(struct cmd_context *cmd, const char *target_name,
@@ -198,6 +198,11 @@ int lv_is_active_exclusive(const struct logical_volume *lv);
int lv_is_active_exclusive_locally(const struct logical_volume *lv);
int lv_is_active_exclusive_remotely(const struct logical_volume *lv);
/* Check is any component LV is active */
const struct logical_volume *lv_component_is_active(const struct logical_volume *lv);
const struct logical_volume *lv_holder_is_active(const struct logical_volume *lv);
int deactivate_lv_with_sub_lv(const struct logical_volume *lv);
int lv_has_target_type(struct dm_pool *mem, const struct logical_volume *lv,
const char *layer, const char *target_type);
@@ -206,9 +211,9 @@ int monitor_dev_for_events(struct cmd_context *cmd, const struct logical_volume
#ifdef DMEVENTD
# include "libdevmapper-event.h"
char *get_monitor_dso_path(struct cmd_context *cmd, const char *libpath);
char *get_monitor_dso_path(struct cmd_context *cmd, int id);
int target_registered_with_dmeventd(struct cmd_context *cmd, const char *dso,
const struct logical_volume *lv, int *pending);
const struct logical_volume *lv, int *pending, int *monitored);
int target_register_events(struct cmd_context *cmd, const char *dso, const struct logical_volume *lv,
int evmask __attribute__((unused)), int set, int timeout);
#endif

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004-2017 Red Hat, Inc. All rights reserved.
* Copyright (C) 2004-2018 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
@@ -32,6 +32,8 @@
#define MAX_TARGET_PARAMSIZE 50000
#define LVM_UDEV_NOSCAN_FLAG DM_SUBSYSTEM_UDEV_FLAG0
#define CRYPT_TEMP "CRYPT-TEMP"
#define STRATIS "stratis-"
typedef enum {
PRELOAD,
@@ -72,10 +74,17 @@ struct dev_manager {
struct lv_layer {
const struct logical_volume *lv;
const char *old_name;
int visible_component;
};
int read_only_lv(const struct logical_volume *lv, const struct lv_activate_opts *laopts)
int read_only_lv(const struct logical_volume *lv, const struct lv_activate_opts *laopts, const char *layer)
{
if (layer && lv_is_cow(lv))
return 0; /* Keep snapshot's COW volume writable */
if (lv_is_raid_image(lv) || lv_is_raid_metadata(lv))
return 0; /* Keep RAID SubLvs writable */
return (laopts->read_only || !(lv->status & LVM_WRITE));
}
@@ -169,7 +178,8 @@ static int _get_segment_status_from_target_params(const char *target_name,
}
/* Validate target_name segtype from DM table with lvm2 metadata segtype */
if (strcmp(segtype->name, target_name) &&
if (!lv_is_locked(seg->lv) &&
strcmp(segtype->name, target_name) &&
/* If kernel's type isn't an exact match is it compatible? */
(!segtype->ops->target_status_compatible ||
!segtype->ops->target_status_compatible(target_name))) {
@@ -441,15 +451,21 @@ static int _ignore_suspended_snapshot_component(struct device *dev)
do {
next = dm_get_next_target(dmt, next, &start, &length, &target_type, &params);
if (!target_type || !strcmp(target_type, TARGET_NAME_SNAPSHOT)) {
if (!target_type)
continue;
if (!strcmp(target_type, TARGET_NAME_SNAPSHOT)) {
if (!params || sscanf(params, "%d:%d %d:%d", &major1, &minor1, &major2, &minor2) != 4) {
log_error("Incorrect snapshot table found.");
log_warn("WARNING: Incorrect snapshot table found for %d:%d.",
(int)MAJOR(dev->dev), (int)MINOR(dev->dev));
goto out;
}
r = r || _device_is_suspended(major1, minor1) || _device_is_suspended(major2, minor2);
} else if (!strcmp(target_type, TARGET_NAME_SNAPSHOT_ORIGIN)) {
if (!params || sscanf(params, "%d:%d", &major1, &minor1) != 2) {
log_error("Incorrect snapshot-origin table found.");
log_warn("WARNING: Incorrect snapshot-origin table found for %d:%d.",
(int)MAJOR(dev->dev), (int)MINOR(dev->dev));
goto out;
}
r = r || _device_is_suspended(major1, minor1);
@@ -484,7 +500,7 @@ static int _ignore_unusable_thins(struct device *dev)
dm_get_next_target(dmt, next, &start, &length, &target_type, &params);
if (!params || sscanf(params, "%d:%d", &major, &minor) != 2) {
log_error("Failed to get thin-pool major:minor for thin device %d:%d.",
log_warn("WARNING: Cannot get thin-pool major:minor for thin device %d:%d.",
(int)MAJOR(dev->dev), (int)MINOR(dev->dev));
goto out;
}
@@ -514,6 +530,47 @@ out:
return r;
}
static int _ignore_invalid_snapshot(const char *params)
{
struct dm_status_snapshot *s;
struct dm_pool *mem;
int r = 0;
if (!(mem = dm_pool_create("invalid snapshots", 128)))
return_0;
if (!dm_get_status_snapshot(mem, params, &s))
stack;
else
r = s->invalid;
dm_pool_destroy(mem);
return r;
}
static int _ignore_frozen_raid(struct device *dev, const char *params)
{
struct dm_status_raid *s;
struct dm_pool *mem;
int r = 0;
if (!(mem = dm_pool_create("frozen raid", 128)))
return_0;
if (!dm_get_status_raid(mem, params, &s))
stack;
else if (s->sync_action && !strcmp(s->sync_action, "frozen")) {
log_warn("WARNING: %s frozen raid device (%d:%d) needs inspection.",
dev_name(dev), (int)MAJOR(dev->dev), (int)MINOR(dev->dev));
r = 1;
}
dm_pool_destroy(mem);
return r;
}
/*
* device_is_usable
* @dev
@@ -583,12 +640,26 @@ int device_is_usable(struct device *dev, struct dev_usable_check_params check)
}
}
if (check.check_reserved && uuid &&
(!strncmp(uuid, CRYPT_TEMP, sizeof(CRYPT_TEMP) - 1) ||
!strncmp(uuid, STRATIS, sizeof(STRATIS) - 1))) {
/* Skip private crypto devices */
log_debug_activation("%s: Reserved uuid %s on %s device %s not usable.",
dev_name(dev), uuid,
uuid[0] == 'C' ? "crypto" : "stratis",
name);
goto out;
}
/* FIXME Also check for mpath no paths */
do {
next = dm_get_next_target(dmt, next, &start, &length,
&target_type, &params);
if (check.check_blocked && target_type && !strcmp(target_type, TARGET_NAME_MIRROR)) {
if (!target_type)
continue;
if (check.check_blocked && !strcmp(target_type, TARGET_NAME_MIRROR)) {
if (ignore_lvm_mirrors()) {
log_debug_activation("%s: Scanning mirror devices is disabled.", dev_name(dev));
goto out;
@@ -622,21 +693,33 @@ int device_is_usable(struct device *dev, struct dev_usable_check_params check)
* correctly, not just snapshots but any cobimnation possible
* in a stack - use proper dm tree to check this instead.
*/
if (check.check_suspended && target_type &&
if (check.check_suspended &&
(!strcmp(target_type, TARGET_NAME_SNAPSHOT) || !strcmp(target_type, TARGET_NAME_SNAPSHOT_ORIGIN)) &&
_ignore_suspended_snapshot_component(dev)) {
log_debug_activation("%s: %s device %s not usable.", dev_name(dev), target_type, name);
goto out;
}
if (!strcmp(target_type, TARGET_NAME_SNAPSHOT) &&
_ignore_invalid_snapshot(params)) {
log_debug_activation("%s: Invalid %s device %s not usable.", dev_name(dev), target_type, name);
goto out;
}
if (!strncmp(target_type, TARGET_NAME_RAID, 4) && _ignore_frozen_raid(dev, params)) {
log_debug_activation("%s: Frozen %s device %s not usable.",
dev_name(dev), target_type, name);
goto out;
}
/* TODO: extend check struct ? */
if (target_type && !strcmp(target_type, TARGET_NAME_THIN) &&
if (!strcmp(target_type, TARGET_NAME_THIN) &&
!_ignore_unusable_thins(dev)) {
log_debug_activation("%s: %s device %s not usable.", dev_name(dev), target_type, name);
goto out;
}
if (target_type && strcmp(target_type, TARGET_NAME_ERROR))
if (strcmp(target_type, TARGET_NAME_ERROR))
only_error_target = 0;
} while (next);
@@ -1590,7 +1673,8 @@ int dev_manager_mknodes(const struct logical_volume *lv)
return_0;
if (dminfo.exists) {
if (_lv_has_mknode(lv))
/* read-only component LV is also made visible */
if (_lv_has_mknode(lv) || (dminfo.read_only && lv_is_component(lv)))
r = _dev_manager_lv_mknodes(lv);
} else
r = _dev_manager_lv_rmnodes(lv);
@@ -1652,7 +1736,8 @@ static int _check_udev_fallback(struct cmd_context *cmd)
#endif /* UDEV_SYNC_SUPPORT */
static uint16_t _get_udev_flags(struct dev_manager *dm, const struct logical_volume *lv,
const char *layer, int noscan, int temporary)
const char *layer, int noscan, int temporary,
int visible_component)
{
uint16_t udev_flags = 0;
@@ -1668,7 +1753,7 @@ static uint16_t _get_udev_flags(struct dev_manager *dm, const struct logical_vol
* If not, create just the /dev/mapper content.
*/
/* FIXME: add target's method for this */
if (lv_is_new_thin_pool(lv))
if (lv_is_new_thin_pool(lv) || visible_component)
/* New thin-pool is regular LV with -tpool UUID suffix. */
udev_flags |= DM_UDEV_DISABLE_DISK_RULES_FLAG |
DM_UDEV_DISABLE_OTHER_RULES_FLAG;
@@ -1717,6 +1802,114 @@ static uint16_t _get_udev_flags(struct dev_manager *dm, const struct logical_vol
return udev_flags;
}
static int _add_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
const struct logical_volume *lv, int origin_only);
static int _check_holder(struct dev_manager *dm, struct dm_tree *dtree,
const struct logical_volume *lv, uint32_t major,
const char *d_name)
{
const char *default_uuid_prefix = dm_uuid_prefix();
const size_t default_uuid_prefix_len = strlen(default_uuid_prefix);
const char *name;
const char *uuid;
struct dm_info info;
struct dm_task *dmt;
struct logical_volume *lv_det;
union lvid id;
int dev, r = 0;
errno = 0;
dev = strtoll(d_name + 3, NULL, 10);
if (errno) {
log_error("Failed to parse dm device minor number from %s.", d_name);
return 0;
}
if (!(dmt = _setup_task_run(DM_DEVICE_INFO, &info, NULL, NULL, NULL,
major, dev, 0, 0, 0)))
return_0;
if (info.exists) {
uuid = dm_task_get_uuid(dmt);
name = dm_task_get_name(dmt);
log_debug_activation("Checking holder of %s %s (" FMTu32 ":" FMTu32 ") %s.",
display_lvname(lv), uuid, info.major, info.minor,
name);
/* Skip common uuid prefix */
if (!strncmp(default_uuid_prefix, uuid, default_uuid_prefix_len))
uuid += default_uuid_prefix_len;
if (!strncmp(uuid, (char*)&lv->vg->id, sizeof(lv->vg->id)) &&
!dm_tree_find_node_by_uuid(dtree, uuid)) {
dm_strncpy((char*)&id, uuid, 2 * sizeof(struct id) + 1);
/* If UUID is not yet in dtree, look for matching LV */
if (!(lv_det = find_lv_in_vg_by_lvid(lv->vg, &id))) {
log_error("Cannot find holder with device name %s in VG %s.",
name, lv->vg->name);
goto out;
}
if (lv_is_cow(lv_det))
lv_det = origin_from_cow(lv_det);
log_debug_activation("Found holder %s of %s.",
display_lvname(lv_det),
display_lvname(lv));
if (!_add_lv_to_dtree(dm, dtree, lv_det, 0))
goto_out;
}
}
r = 1;
out:
dm_task_destroy(dmt);
return r;
}
/*
* Add exiting devices which holds given LV device open.
* This is used in case when metadata already do not contain information
* i.e. PVMOVE is being finished and final table is going to be resumed.
*/
static int _add_holders_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
const struct logical_volume *lv, struct dm_info *info)
{
const char *sysfs_dir = dm_sysfs_dir();
char sysfs_path[PATH_MAX];
struct dirent *dirent;
DIR *d;
int r = 0;
/* Sysfs path of holders */
if (dm_snprintf(sysfs_path, sizeof(sysfs_path), "%sblock/dm-" FMTu32
"/holders", sysfs_dir, info->minor) < 0) {
log_error("sysfs_path dm_snprintf failed.");
return 0;
}
if (!(d = opendir(sysfs_path))) {
log_sys_error("opendir", sysfs_path);
return 0;
}
while ((dirent = readdir(d)))
/* Expects minor is added to 'dm-' prefix */
if (!strncmp(dirent->d_name, "dm-", 3) &&
!_check_holder(dm, dtree, lv, info->major, dirent->d_name))
goto_out;
r = 1;
out:
if (closedir(d))
log_sys_debug("closedir", "holders");
return r;
}
static int _add_dev_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
const struct logical_volume *lv, const char *layer)
{
@@ -1758,7 +1951,8 @@ static int _add_dev_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
}
if (info.exists && !dm_tree_add_dev_with_udev_flags(dtree, info.major, info.minor,
_get_udev_flags(dm, lv, layer, 0, 0))) {
_get_udev_flags(dm, lv, layer,
0, 0, 0))) {
log_error("Failed to add device (%" PRIu32 ":%" PRIu32") to dtree.",
info.major, info.minor);
return 0;
@@ -1771,83 +1965,14 @@ static int _add_dev_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
return_0;
}
return 1;
}
/*
* Add replicator devices
*
* Using _add_dev_to_dtree() directly instead of _add_lv_to_dtree()
* to avoid extra checks with extensions.
*/
static int _add_partial_replicator_to_dtree(struct dev_manager *dm,
struct dm_tree *dtree,
const struct logical_volume *lv)
{
struct logical_volume *rlv = first_seg(lv)->replicator;
struct replicator_device *rdev;
struct replicator_site *rsite;
struct dm_tree_node *rep_node, *rdev_node;
const char *uuid;
if (!lv_is_active_replicator_dev(lv)) {
if (!_add_dev_to_dtree(dm, dtree, lv->rdevice->lv,
NULL))
/*
* Find holders of existing active LV where name starts with 'pvmove',
* but it's not anymore PVMOVE LV and also it's not PVMOVE _mimage
*/
if (info.exists && !lv_is_pvmove(lv) &&
!strchr(lv->name, '_') && !strncmp(lv->name, "pvmove", 6))
if (!_add_holders_to_dtree(dm, dtree, lv, &info))
return_0;
return 1;
}
/* Add _rlog and replicator device */
if (!_add_dev_to_dtree(dm, dtree, first_seg(rlv)->rlog_lv, NULL))
return_0;
if (!_add_dev_to_dtree(dm, dtree, rlv, NULL))
return_0;
if (!(uuid = build_dm_uuid(dm->mem, rlv, NULL)))
return_0;
rep_node = dm_tree_find_node_by_uuid(dtree, uuid);
/* Add all related devices for replicator */
dm_list_iterate_items(rsite, &rlv->rsites)
dm_list_iterate_items(rdev, &rsite->rdevices) {
if (rsite->state == REPLICATOR_STATE_ACTIVE) {
/* Add _rimage LV */
if (!_add_dev_to_dtree(dm, dtree, rdev->lv, NULL))
return_0;
/* Add replicator-dev LV, except of the already added one */
if ((lv != rdev->replicator_dev->lv) &&
!_add_dev_to_dtree(dm, dtree,
rdev->replicator_dev->lv, NULL))
return_0;
/* If replicator exists - try connect existing heads */
if (rep_node) {
uuid = build_dm_uuid(dm->mem,
rdev->replicator_dev->lv,
NULL);
if (!uuid)
return_0;
rdev_node = dm_tree_find_node_by_uuid(dtree, uuid);
if (rdev_node)
dm_tree_node_set_presuspend_node(rdev_node,
rep_node);
}
}
if (!rdev->rsite->vg_name)
continue;
if (!_add_dev_to_dtree(dm, dtree, rdev->lv, NULL))
return_0;
if (rdev->slog &&
!_add_dev_to_dtree(dm, dtree, rdev->slog, NULL))
return_0;
}
return 1;
}
@@ -1859,13 +1984,60 @@ struct pool_cb_data {
int skip_zero; /* to skip zeroed device header (check first 64B) */
int exec; /* which binary to call */
int opts;
struct {
unsigned maj;
unsigned min;
unsigned patch;
} version;
const char *global;
};
/*
* Simple version of check function calling 'tool -V'
*
* Returns 1 if the tool's version is equal or better to given.
* Otherwise it returns 0.
*/
static int _check_tool_version(struct cmd_context *cmd, const char *tool,
unsigned maj, unsigned min, unsigned patch)
{
const char *argv[] = { tool, "-V", NULL };
struct pipe_data pdata;
FILE *f;
char buf[128] = { 0 };
char *nl;
unsigned v_maj, v_min, v_patch;
int ret = 0;
if (!(f = pipe_open(cmd, argv, 0, &pdata))) {
log_warn("WARNING: Cannot read output from %s.", argv[0]);
} else {
if (fgets(buf, sizeof(buf) - 1, f) &&
(sscanf(buf, "%u.%u.%u", &v_maj, &v_min, &v_patch) == 3)) {
if ((v_maj > maj) ||
((v_maj == maj) &&
((v_min > min) ||
(v_min == min && v_patch >= patch))))
ret = 1;
if ((nl = strchr(buf, '\n')))
nl[0] = 0; /* cut newline away */
log_verbose("Found version of %s %s is %s then requested %u.%u.%u.",
argv[0], buf, ret ? "better" : "older", maj, min, patch);
} else
log_warn("WARNING: Cannot parse output '%s' from %s.", buf, argv[0]);
(void) pipe_close(&pdata);
}
return ret;
}
static int _pool_callback(struct dm_tree_node *node,
dm_node_callback_t type, void *cb_data)
{
int ret, status, fd;
int ret, status = 0, fd;
const struct dm_config_node *cn;
const struct dm_config_value *cv;
const struct pool_cb_data *data = cb_data;
@@ -1873,12 +2045,45 @@ static int _pool_callback(struct dm_tree_node *node,
const struct logical_volume *mlv = first_seg(pool_lv)->metadata_lv;
long buf[64 / sizeof(long)]; /* buffer for short disk header (64B) */
int args = 0;
char *mpath;
const char *argv[19] = { /* Max supported 15 args */
find_config_tree_str_allow_empty(pool_lv->vg->cmd, data->exec, NULL) /* argv[0] */
find_config_tree_str_allow_empty(pool_lv->vg->cmd, data->exec, NULL)
};
if (!*argv[0])
return 1; /* Checking disabled */
if (!*argv[0]) /* *_check tool is unconfigured/disabled with "" setting */
return 1;
if (!(mpath = lv_dmpath_dup(data->dm->mem, mlv))) {
log_error("Failed to build device path for checking pool metadata %s.",
display_lvname(mlv));
return 0;
}
if (data->skip_zero) {
if ((fd = open(mpath, O_RDONLY)) < 0) {
log_sys_error("open", mpath);
return 0;
}
/* let's assume there is no problem to read 64 bytes */
if (read(fd, buf, sizeof(buf)) < (int)sizeof(buf)) {
log_sys_error("read", mpath);
if (close(fd))
log_sys_error("close", mpath);
return 0;
}
for (ret = 0; ret < (int) DM_ARRAY_SIZE(buf); ++ret)
if (buf[ret])
break;
if (close(fd))
log_sys_error("close", mpath);
if (ret == (int) DM_ARRAY_SIZE(buf)) {
log_debug_activation("Metadata checking skipped, detected empty disk header on %s.",
mpath);
return 1;
}
}
if (!(cn = find_config_tree_array(mlv->vg->cmd, data->opts, NULL))) {
log_error(INTERNAL_ERROR "Unable to find configuration for pool check options.");
@@ -1900,39 +2105,23 @@ static int _pool_callback(struct dm_tree_node *node,
return 0;
}
if (!(argv[++args] = lv_dmpath_dup(data->dm->mem, mlv))) {
log_error("Failed to build pool metadata path.");
return 0;
}
if (data->skip_zero) {
if ((fd = open(argv[args], O_RDONLY)) < 0) {
log_sys_error("open", argv[args]);
return 0;
}
/* let's assume there is no problem to read 64 bytes */
if (read(fd, buf, sizeof(buf)) < (int)sizeof(buf)) {
log_sys_error("read", argv[args]);
if (close(fd))
log_sys_error("close", argv[args]);
return 0;
}
for (ret = 0; ret < (int) DM_ARRAY_SIZE(buf); ++ret)
if (buf[ret])
break;
if (close(fd))
log_sys_error("close", argv[args]);
if (ret == (int) DM_ARRAY_SIZE(buf)) {
log_debug_activation("%s skipped, detect empty disk header on %s.",
argv[0], argv[args]);
return 1;
}
}
argv[++args] = mpath;
if (!(ret = exec_cmd(pool_lv->vg->cmd, (const char * const *)argv,
&status, 0))) {
if (status == ENOENT) {
log_warn("WARNING: Check is skipped, please install recommended missing binary %s!",
argv[0]);
return 1;
}
if ((data->version.maj || data->version.min || data->version.patch) &&
!_check_tool_version(pool_lv->vg->cmd, argv[0],
data->version.maj, data->version.min, data->version.patch)) {
log_warn("WARNING: Check is skipped, please upgrade installed version of %s!",
argv[0]);
return 1;
}
switch (type) {
case DM_NODE_CALLBACK_PRELOADED:
log_err_once("Check of pool %s failed (status:%d). "
@@ -1990,6 +2179,10 @@ static int _pool_register_callback(struct dev_manager *dm,
data->exec = global_cache_check_executable_CFG;
data->opts = global_cache_check_options_CFG;
data->global = "cache";
if (first_seg(first_seg(lv)->pool_lv)->cache_metadata_format > 1) {
data->version.maj = 0;
data->version.min = 7;
}
} else {
log_error(INTERNAL_ERROR "Registering unsupported pool callback.");
return 0;
@@ -2017,6 +2210,10 @@ static int _add_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
struct lv_segment *seg;
struct dm_tree_node *node;
const char *uuid;
const struct logical_volume *plv;
if (lv_is_pvmove(lv) && (dm->track_pvmove_deps == 2))
return 1; /* Avoid rechecking of already seen pvmove LV */
if (lv_is_cache_pool(lv)) {
if (!dm_list_empty(&lv->segs_using_this_lv)) {
@@ -2137,11 +2334,14 @@ static int _add_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
return_0;
/* Add any LVs referencing a PVMOVE LV unless told not to. */
if (dm->track_pvmove_deps && lv_is_pvmove(lv)) {
dm->track_pvmove_deps = 0;
dm_list_iterate_items(sl, &lv->segs_using_this_lv)
if (!_add_lv_to_dtree(dm, dtree, sl->seg->lv, origin_only))
if ((dm->track_pvmove_deps == 1) && lv_is_pvmove(lv)) {
dm->track_pvmove_deps = 2; /* Mark as already seen */
dm_list_iterate_items(sl, &lv->segs_using_this_lv) {
/* If LV is snapshot COW - whole snapshot needs reload */
plv = lv_is_cow(sl->seg->lv) ? origin_from_cow(sl->seg->lv) : sl->seg->lv;
if (!_add_lv_to_dtree(dm, dtree, plv, 0))
return_0;
}
dm->track_pvmove_deps = 1;
}
@@ -2156,11 +2356,6 @@ static int _add_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
}
}
/* Adding LV head of replicator adds all other related devs */
if (lv_is_replicator_dev(lv) &&
!_add_partial_replicator_to_dtree(dm, dtree, lv))
return_0;
/* Add any LVs used by segments in this LV */
dm_list_iterate_items(seg, &lv->segments) {
if (seg->external_lv && dm->track_external_lv_deps &&
@@ -2524,64 +2719,6 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
struct lv_activate_opts *laopts,
const char *layer);
/* Add all replicators' LVs */
static int _add_replicator_dev_target_to_dtree(struct dev_manager *dm,
struct dm_tree *dtree,
struct lv_segment *seg,
struct lv_activate_opts *laopts)
{
struct replicator_device *rdev;
struct replicator_site *rsite;
/* For inactive replicator add linear mapping */
if (!lv_is_active_replicator_dev(seg->lv)) {
if (!_add_new_lv_to_dtree(dm, dtree, seg->lv->rdevice->lv, laopts, NULL))
return_0;
return 1;
}
/* Add rlog and replicator nodes */
if (!seg->replicator ||
!first_seg(seg->replicator)->rlog_lv ||
!_add_new_lv_to_dtree(dm, dtree,
first_seg(seg->replicator)->rlog_lv,
laopts, NULL) ||
!_add_new_lv_to_dtree(dm, dtree, seg->replicator, laopts, NULL))
return_0;
/* Activation of one replicator_dev node activates all other nodes */
dm_list_iterate_items(rsite, &seg->replicator->rsites) {
dm_list_iterate_items(rdev, &rsite->rdevices) {
if (rdev->lv &&
!_add_new_lv_to_dtree(dm, dtree, rdev->lv,
laopts, NULL))
return_0;
if (rdev->slog &&
!_add_new_lv_to_dtree(dm, dtree, rdev->slog,
laopts, NULL))
return_0;
}
}
/* Add remaining replicator-dev nodes in the second loop
* to avoid multiple retries for inserting all elements */
dm_list_iterate_items(rsite, &seg->replicator->rsites) {
if (rsite->state != REPLICATOR_STATE_ACTIVE)
continue;
dm_list_iterate_items(rdev, &rsite->rdevices) {
if (rdev->replicator_dev->lv == seg->lv)
continue;
if (!rdev->replicator_dev->lv ||
!_add_new_lv_to_dtree(dm, dtree,
rdev->replicator_dev->lv,
laopts, NULL))
return_0;
}
}
return 1;
}
static int _add_new_external_lv_to_dtree(struct dev_manager *dm,
struct dm_tree *dtree,
struct logical_volume *external_lv,
@@ -2682,11 +2819,6 @@ static int _add_segment_to_dtree(struct dev_manager *dm,
lv_layer(seg->pool_lv)))
return_0;
if (seg_is_replicator_dev(seg)) {
if (!_add_replicator_dev_target_to_dtree(dm, dtree, seg, laopts))
return_0;
}
/* Add any LVs used by this segment */
for (s = 0; s < seg->area_count; ++s) {
if ((seg_type(seg, s) == AREA_LV) &&
@@ -2824,6 +2956,7 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
}
lvlayer->lv = lv;
lvlayer->visible_component = (laopts->component_lv == lv) ? 1 : 0;
/*
* Add LV to dtree.
@@ -2837,10 +2970,11 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
if (!(dnode = dm_tree_add_new_dev_with_udev_flags(dtree, name, dlid,
layer ? UINT32_C(0) : (uint32_t) lv->major,
layer ? UINT32_C(0) : (uint32_t) lv->minor,
read_only_lv(lv, laopts),
read_only_lv(lv, laopts, layer),
((lv->vg->status & PRECOMMITTED) | laopts->revert) ? 1 : 0,
lvlayer,
_get_udev_flags(dm, lv, layer, laopts->noscan, laopts->temporary))))
_get_udev_flags(dm, lv, layer, laopts->noscan, laopts->temporary,
lvlayer->visible_component))))
return_0;
/* Store existing name so we can do rename later */
@@ -2984,7 +3118,7 @@ static int _create_lv_symlinks(struct dev_manager *dm, struct dm_tree_node *root
r = 0;
continue;
}
if (_lv_has_mknode(lvlayer->lv)) {
if (_lv_has_mknode(lvlayer->lv) || lvlayer->visible_component) {
if (!_dev_manager_lv_mknodes(lvlayer->lv))
r = 0;
continue;
@@ -3156,8 +3290,6 @@ static int _tree_action(struct dev_manager *dm, const struct logical_volume *lv,
if (!dm_tree_preload_children(root, dlid, DLID_SIZE))
goto_out;
//if (action == PRELOAD) { log_debug("SLEEP"); sleep(7); }
if ((dm_tree_node_size_changed(root) < 0))
dm->flush_required = 1;
/* Currently keep the code require flush for any

View File

@@ -27,7 +27,7 @@ struct dm_info;
struct device;
struct lv_seg_status;
int read_only_lv(const struct logical_volume *lv, const struct lv_activate_opts *laopts);
int read_only_lv(const struct logical_volume *lv, const struct lv_activate_opts *laopts, const char *layer);
/*
* Constructor and destructor.

View File

@@ -441,7 +441,7 @@ static int _fs_op(fs_op_t type, const char *dev_dir, const char *vg_name,
const char *lv_name, const char *dev, const char *old_lv_name,
int check_udev)
{
if (critical_section()) {
if (prioritized_section()) {
if (!_stack_fs_op(type, dev_dir, vg_name, lv_name, dev,
old_lv_name, check_udev))
return_0;
@@ -487,7 +487,7 @@ int fs_rename_lv(const struct logical_volume *lv, const char *dev,
void fs_unlock(void)
{
if (!critical_section()) {
if (!prioritized_section()) {
log_debug_activation("Syncing device names");
/* Wait for all processed udev devices */
if (!dm_udev_wait(_fs_cookie))

1497
lib/cache/lvmcache.c vendored

File diff suppressed because it is too large Load Diff

48
lib/cache/lvmcache.h vendored
View File

@@ -59,21 +59,17 @@ struct lvmcache_vgsummary {
const char *lock_type;
uint32_t mda_checksum;
size_t mda_size;
int zero_offset;
int seqno;
};
int lvmcache_init(void);
int lvmcache_init(struct cmd_context *cmd);
void lvmcache_allow_reads_with_lvmetad(void);
void lvmcache_destroy(struct cmd_context *cmd, int retain_orphans, int reset);
/*
* lvmcache_label_scan() will scan labels the first time it's
* called, but not on subsequent calls, unless
* lvmcache_force_next_label_scan() is called first
* to force the next lvmcache_label_scan() to scan again.
*/
void lvmcache_force_next_label_scan(void);
int lvmcache_label_scan(struct cmd_context *cmd);
int lvmcache_label_rescan_vg(struct cmd_context *cmd, const char *vgname, const char *vgid, int open_rw);
/* Add/delete a device */
struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
@@ -82,6 +78,7 @@ struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
uint32_t vgstatus);
int lvmcache_add_orphan_vginfo(const char *vgname, struct format_type *fmt);
void lvmcache_del(struct lvmcache_info *info);
void lvmcache_del_dev(struct device *dev);
/* Update things */
int lvmcache_update_vgname_and_id(struct lvmcache_info *info,
@@ -105,10 +102,8 @@ struct lvmcache_vginfo *lvmcache_vginfo_from_vgid(const char *vgid);
struct lvmcache_info *lvmcache_info_from_pvid(const char *pvid, struct device *dev, int valid_only);
const char *lvmcache_vgname_from_vgid(struct dm_pool *mem, const char *vgid);
const char *lvmcache_vgid_from_vgname(struct cmd_context *cmd, const char *vgname);
struct device *lvmcache_device_from_pvid(struct cmd_context *cmd, const struct id *pvid,
unsigned *scan_done_once, uint64_t *label_sector);
const char *lvmcache_pvid_from_devname(struct cmd_context *cmd,
const char *devname);
struct device *lvmcache_device_from_pvid(struct cmd_context *cmd, const struct id *pvid, uint64_t *label_sector);
const char *lvmcache_pvid_from_devname(struct cmd_context *cmd, const char *devname);
char *lvmcache_vgname_from_pvid(struct cmd_context *cmd, const char *pvid);
const char *lvmcache_vgname_from_info(struct lvmcache_info *info);
const struct format_type *lvmcache_fmt_from_info(struct lvmcache_info *info);
@@ -134,20 +129,16 @@ int lvmcache_get_vgnameids(struct cmd_context *cmd, int include_internal,
struct dm_list *lvmcache_get_pvids(struct cmd_context *cmd, const char *vgname,
const char *vgid);
/* Returns cached volume group metadata. */
struct volume_group *lvmcache_get_vg(struct cmd_context *cmd, const char *vgname,
const char *vgid, unsigned precommitted);
void lvmcache_drop_metadata(const char *vgname, int drop_precommitted);
void lvmcache_commit_metadata(const char *vgname);
int lvmcache_pvid_is_locked(const char *pvid);
int lvmcache_fid_add_mdas(struct lvmcache_info *info, struct format_instance *fid,
const char *id, int id_len);
int lvmcache_fid_add_mdas_pv(struct lvmcache_info *info, struct format_instance *fid);
int lvmcache_fid_add_mdas_vg(struct lvmcache_vginfo *vginfo, struct format_instance *fid);
int lvmcache_populate_pv_fields(struct lvmcache_info *info,
struct physical_volume *pv,
int scan_label_only);
struct volume_group *vg,
struct physical_volume *pv);
int lvmcache_check_format(struct lvmcache_info *info, const struct format_type *fmt);
void lvmcache_del_mdas(struct lvmcache_info *info);
void lvmcache_del_das(struct lvmcache_info *info);
@@ -164,6 +155,8 @@ uint32_t lvmcache_ext_flags(struct lvmcache_info *info);
const struct format_type *lvmcache_fmt(struct lvmcache_info *info);
struct label *lvmcache_get_label(struct lvmcache_info *info);
struct label *lvmcache_get_dev_label(struct device *dev);
int lvmcache_has_dev_info(struct device *dev);
void lvmcache_update_pv(struct lvmcache_info *info, struct physical_volume *pv,
const struct format_type *fmt);
@@ -187,7 +180,6 @@ int lvmcache_foreach_pv(struct lvmcache_vginfo *vginfo,
uint64_t lvmcache_device_size(struct lvmcache_info *info);
void lvmcache_set_device_size(struct lvmcache_info *info, uint64_t size);
struct device *lvmcache_device(struct lvmcache_info *info);
void lvmcache_make_valid(struct lvmcache_info *info);
int lvmcache_is_orphan(struct lvmcache_info *info);
int lvmcache_uncertain_ownership(struct lvmcache_info *info);
unsigned lvmcache_mda_count(struct lvmcache_info *info);
@@ -196,6 +188,8 @@ uint64_t lvmcache_smallest_mda_size(struct lvmcache_info *info);
int lvmcache_found_duplicate_pvs(void);
void lvmcache_pvscan_duplicate_check(struct cmd_context *cmd);
int lvmcache_get_unused_duplicate_devs(struct cmd_context *cmd, struct dm_list *head);
int vg_has_duplicate_pvs(struct volume_group *vg);
@@ -215,4 +209,20 @@ void lvmcache_remove_unchosen_duplicate(struct device *dev);
int lvmcache_pvid_in_unchosen_duplicates(const char *pvid);
int lvmcache_get_vg_devs(struct cmd_context *cmd,
struct lvmcache_vginfo *vginfo,
struct dm_list *devs);
void lvmcache_set_independent_location(const char *vgname);
int lvmcache_scan_mismatch(struct cmd_context *cmd, const char *vgname, const char *vgid);
/*
* These are clvmd-specific functions and are not related to lvmcache.
* FIXME: rename these with a clvm_ prefix in place of lvmcache_
*/
void lvmcache_save_vg(struct volume_group *vg, int precommitted);
struct volume_group *lvmcache_get_saved_vg(const char *vgid, int precommitted);
struct volume_group *lvmcache_get_saved_vg_latest(const char *vgid);
void lvmcache_drop_saved_vgid(const char *vgid);
#endif

547
lib/cache/lvmetad.c vendored
View File

@@ -37,9 +37,7 @@ static const char *_lvmetad_socket = NULL;
static struct cmd_context *_lvmetad_cmd = NULL;
static int64_t _lvmetad_update_timeout;
static int _found_lvm1_metadata = 0;
static struct volume_group *lvmetad_pvscan_vg(struct cmd_context *cmd, struct volume_group *vg);
static struct volume_group *_lvmetad_pvscan_vg(struct cmd_context *cmd, struct volume_group *vg, const char *vgid, struct format_type *fmt);
static uint64_t _monotonic_seconds(void)
{
@@ -551,6 +549,7 @@ static int _token_update(int *replaced_update)
daemon_reply reply;
const char *token_expected;
const char *prev_token;
const char *reply_str;
int update_pid;
int ending_our_update;
@@ -567,13 +566,14 @@ static int _token_update(int *replaced_update)
}
update_pid = (int)daemon_reply_int(reply, "update_pid", 0);
reply_str = daemon_reply_str(reply, "response", "");
/*
* A mismatch can only happen when this command attempts to set the
* token to filter:<hash> at the end of its update, but the update has
* been preempted in lvmetad by a new one (from update_pid).
*/
if (!strcmp(daemon_reply_str(reply, "response", ""), "token_mismatch")) {
if (!strcmp(reply_str, "token_mismatch")) {
token_expected = daemon_reply_str(reply, "expected", "");
ending_our_update = strcmp(_lvmetad_token, LVMETAD_TOKEN_UPDATE_IN_PROGRESS);
@@ -599,7 +599,7 @@ static int _token_update(int *replaced_update)
return 0;
}
if (strcmp(daemon_reply_str(reply, "response", ""), "OK")) {
if (strcmp(reply_str, "OK")) {
log_error("Failed response from lvmetad for token update.");
daemon_reply_destroy(reply);
return 0;
@@ -626,6 +626,7 @@ static int _lvmetad_handle_reply(daemon_reply reply, const char *id, const char
{
const char *token_expected;
const char *action;
const char *reply_str;
int action_modifies = 0;
int daemon_in_update;
int we_are_in_update;
@@ -670,8 +671,8 @@ static int _lvmetad_handle_reply(daemon_reply reply, const char *id, const char
/*
* Errors related to token mismatch.
*/
if (!strcmp(daemon_reply_str(reply, "response", ""), "token_mismatch")) {
reply_str = daemon_reply_str(reply, "response", "");
if (!strcmp(reply_str, "token_mismatch")) {
token_expected = daemon_reply_str(reply, "expected", "");
update_pid = (int)daemon_reply_int(reply, "update_pid", 0);
@@ -769,14 +770,14 @@ static int _lvmetad_handle_reply(daemon_reply reply, const char *id, const char
*/
/* All OK? */
if (!strcmp(daemon_reply_str(reply, "response", ""), "OK")) {
if (!strcmp(reply_str, "OK")) {
if (found)
*found = 1;
return 1;
}
/* Unknown device permitted? */
if (found && !strcmp(daemon_reply_str(reply, "response", ""), "unknown")) {
if (found && !strcmp(reply_str, "unknown")) {
log_very_verbose("Request to %s %s%sin lvmetad did not find any matching object.",
action, object, *object ? " " : "");
*found = 0;
@@ -784,7 +785,7 @@ static int _lvmetad_handle_reply(daemon_reply reply, const char *id, const char
}
/* Multiple VGs with the same name were found. */
if (found && !strcmp(daemon_reply_str(reply, "response", ""), "multiple")) {
if (found && !strcmp(reply_str, "multiple")) {
log_very_verbose("Request to %s %s%sin lvmetad found multiple matching objects.",
action, object, *object ? " " : "");
if (found)
@@ -1090,14 +1091,17 @@ struct volume_group *lvmetad_vg_lookup(struct cmd_context *cmd, const char *vgna
* invalidated the cached vg.
*/
if (rescan) {
if (!(vg2 = lvmetad_pvscan_vg(cmd, vg))) {
if (!(vg2 = _lvmetad_pvscan_vg(cmd, vg, vgid, fmt))) {
log_debug_lvmetad("VG %s from lvmetad not found during rescan.", vgname);
fid = NULL;
release_vg(vg);
vg = NULL;
goto out;
}
fid->ref_count++;
release_vg(vg);
fid->ref_count--;
fmt->ops->destroy_instance(fid);
vg = vg2;
fid = vg2->fid;
}
@@ -1105,14 +1109,14 @@ struct volume_group *lvmetad_vg_lookup(struct cmd_context *cmd, const char *vgna
dm_list_iterate_items(pvl, &vg->pvs) {
if (!_pv_update_struct_pv(pvl->pv, fid)) {
vg = NULL;
goto_out; /* FIXME error path */
goto_out; /* FIXME: use an error path that disables lvmetad */
}
}
dm_list_iterate_items(pvl, &vg->pvs_outdated) {
if (!_pv_update_struct_pv(pvl->pv, fid)) {
vg = NULL;
goto_out; /* FIXME error path */
goto_out; /* FIXME: use an error path that disables lvmetad */
}
}
@@ -1281,7 +1285,7 @@ int lvmetad_vg_update_finish(struct volume_group *vg)
if (pvl->pv->dev && !lvmetad_pv_found(vg->cmd, &pvl->pv->id, pvl->pv->dev,
vgu->fid ? vgu->fid->fmt : pvl->pv->fmt,
pvl->pv->label_sector, NULL, NULL, NULL))
return 0;
return_0;
}
vg->lvmetad_update_pending = 0;
@@ -1516,7 +1520,7 @@ int lvmetad_vg_list_to_lvmcache(struct cmd_context *cmd)
return 1;
}
struct _extract_dl_baton {
struct extract_dl_baton {
int i;
struct dm_config_tree *cft;
struct dm_config_node *pre_sib;
@@ -1524,7 +1528,7 @@ struct _extract_dl_baton {
static int _extract_mda(struct metadata_area *mda, void *baton)
{
struct _extract_dl_baton *b = baton;
struct extract_dl_baton *b = baton;
struct dm_config_node *cn;
char id[32];
@@ -1545,7 +1549,7 @@ static int _extract_mda(struct metadata_area *mda, void *baton)
static int _extract_disk_location(const char *name, struct disk_locn *dl, void *baton)
{
struct _extract_dl_baton *b = baton;
struct extract_dl_baton *b = baton;
struct dm_config_node *cn;
char id[32];
@@ -1580,7 +1584,7 @@ static int _extract_ba(struct disk_locn *ba, void *baton)
static int _extract_mdas(struct lvmcache_info *info, struct dm_config_tree *cft,
struct dm_config_node *pre_sib)
{
struct _extract_dl_baton baton = { .cft = cft };
struct extract_dl_baton baton = { .cft = cft };
if (!lvmcache_foreach_mda(info, &_extract_mda, &baton))
return 0;
@@ -1607,7 +1611,7 @@ int lvmetad_pv_found(struct cmd_context *cmd, const struct id *pvid, struct devi
struct dm_config_tree *pvmeta, *vgmeta;
const char *status = NULL, *vgname = NULL;
int64_t changed = 0;
int result;
int result, seqno_after;
if (!lvmetad_used() || test_mode())
return 1;
@@ -1672,10 +1676,12 @@ int lvmetad_pv_found(struct cmd_context *cmd, const struct id *pvid, struct devi
result = _lvmetad_handle_reply(reply, "pv_found", uuid, NULL);
if (vg && result &&
(daemon_reply_int(reply, "seqno_after", -1) != vg->seqno ||
daemon_reply_int(reply, "seqno_after", -1) != daemon_reply_int(reply, "seqno_before", -1)))
log_warn("WARNING: Inconsistent metadata found for VG %s", vg->name);
if (vg && result) {
seqno_after = daemon_reply_int(reply, "seqno_after", -1);
if ((seqno_after != (int) vg->seqno) ||
(seqno_after != daemon_reply_int(reply, "seqno_before", -1)))
log_warn("WARNING: Inconsistent metadata found for VG %s", vg->name);
}
if (result && found_vgnames) {
status = daemon_reply_str(reply, "status", NULL);
@@ -1756,6 +1762,7 @@ int lvmetad_pv_gone_by_dev(struct device *dev)
*/
struct _lvmetad_pvscan_baton {
struct cmd_context *cmd;
struct volume_group *vg;
struct format_instance *fid;
};
@@ -1766,7 +1773,7 @@ static int _lvmetad_pvscan_single(struct metadata_area *mda, void *baton)
struct volume_group *vg;
if (mda_is_ignored(mda) ||
!(vg = mda->ops->vg_read(b->fid, "", mda, NULL, NULL, 1)))
!(vg = mda->ops->vg_read(b->fid, "", mda, NULL, NULL)))
return 1;
/* FIXME Also ensure contents match etc. */
@@ -1778,6 +1785,33 @@ static int _lvmetad_pvscan_single(struct metadata_area *mda, void *baton)
return 1;
}
/*
* FIXME: handle errors and do proper comparison of metadata from each area
* like vg_read and fall back to real vg_read from disk if there's any problem.
*/
static int _lvmetad_pvscan_vg_single(struct metadata_area *mda, void *baton)
{
struct _lvmetad_pvscan_baton *b = baton;
struct volume_group *vg = NULL;
if (mda_is_ignored(mda))
return 1;
if (!(vg = mda->ops->vg_read(b->fid, "", mda, NULL, NULL)))
return 1;
if (!b->vg)
b->vg = vg;
else if (vg->seqno > b->vg->seqno) {
release_vg(b->vg);
b->vg = vg;
} else
release_vg(vg);
return 1;
}
/*
* The lock manager may detect that the vg cached in lvmetad is out of date,
* due to something like an lvcreate from another host.
@@ -1787,41 +1821,41 @@ static int _lvmetad_pvscan_single(struct metadata_area *mda, void *baton)
* the VG, and that PV may have been reused for another VG.
*/
static struct volume_group *lvmetad_pvscan_vg(struct cmd_context *cmd, struct volume_group *vg)
static struct volume_group *_lvmetad_pvscan_vg(struct cmd_context *cmd, struct volume_group *vg,
const char *vgid, struct format_type *fmt)
{
char pvid_s[ID_LEN + 1] __attribute__((aligned(8)));
char uuid[64] __attribute__((aligned(8)));
struct label *label;
struct volume_group *vg_ret = NULL;
struct dm_config_tree *vgmeta_ret = NULL;
struct dm_config_tree *vgmeta;
struct pv_list *pvl, *pvl_new;
struct device_list *devl, *devl_new, *devlsafe;
struct device_list *devl, *devlsafe;
struct dm_list pvs_scan;
struct dm_list pvs_drop;
struct dm_list pvs_new;
struct lvmcache_vginfo *vginfo = NULL;
struct lvmcache_info *info = NULL;
struct format_instance *fid;
struct format_instance_ctx fic = { .type = 0 };
struct _lvmetad_pvscan_baton baton;
struct volume_group *save_vg;
struct dm_config_tree *save_meta;
struct device *save_dev = NULL;
uint32_t save_seqno = 0;
int missing_devs = 0;
int check_new_pvs = 0;
int found_new_pvs = 0;
int retried_reads = 0;
int found;
save_vg = NULL;
save_meta = NULL;
save_dev = NULL;
save_seqno = 0;
dm_list_init(&pvs_scan);
dm_list_init(&pvs_drop);
dm_list_init(&pvs_new);
log_debug_lvmetad("Rescanning VG %s (seqno %u).", vg->name, vg->seqno);
log_debug_lvmetad("Rescan VG %s to update lvmetad (seqno %u).", vg->name, vg->seqno);
/*
* Another host may have added a PV to the VG, and some
* commands do not always populate their lvmcache with
* all devs from lvmetad, so they would fail to find
* the new PV when scanning the VG. So make sure this
* command knows about all PVs from lvmetad.
* Make sure this command knows about all PVs from lvmetad.
*/
lvmcache_seed_infos_from_lvmetad(cmd);
@@ -1836,54 +1870,111 @@ static struct volume_group *lvmetad_pvscan_vg(struct cmd_context *cmd, struct vo
dm_list_add(&pvs_scan, &devl->list);
}
scan_more:
/*
* Rescan labels/metadata only from devs that we previously
* saw in the VG. If we find below that there are new PVs
* in the VG, we'll have to rescan all devices to find which
* device(s) are now being used.
*/
log_debug_lvmetad("Rescan VG %s scanning data from devs in previous metadata.", vg->name);
label_scan_devs(cmd, cmd->full_filter, &pvs_scan);
/*
* Run the equivalent of lvmetad_pvscan_single on each dev in the VG.
* Check if any pvs_scan entries are no longer PVs.
* In that case, label_read/_find_label_header will have
* found no label_header, and would have dropped the
* info struct for the device from lvmcache. So, if
* we look up the info struct here and don't find it,
* we can infer it's no longer a PV.
*
* FIXME: we should record specific results from the
* label_read and then check specifically for whatever
* result means "no label was found", rather than going
* about this indirectly via the lvmcache side effects.
*/
dm_list_iterate_items_safe(devl, devlsafe, &pvs_scan) {
if (!(info = lvmcache_info_from_pvid(devl->dev->pvid, devl->dev, 0))) {
/* Another host removed this PV from the VG. */
log_debug_lvmetad("Rescan VG %s from %s dropping dev (no label).",
vg->name, dev_name(devl->dev));
dm_list_move(&pvs_drop, &devl->list);
}
}
fic.type = FMT_INSTANCE_MDAS | FMT_INSTANCE_AUX_MDAS;
fic.context.vg_ref.vg_name = vg->name;
fic.context.vg_ref.vg_id = vgid;
retry_reads:
if (!(fid = fmt->ops->create_instance(fmt, &fic))) {
/* FIXME: are there only internal reasons for failures here? */
log_error("Reading VG %s failed to create format instance.", vg->name);
return NULL;
}
/* FIXME: not sure if this is necessary */
fid->ref_count++;
baton.fid = fid;
baton.cmd = cmd;
/*
* FIXME: this vg_read path does not have the ability to repair
* any problems with the VG, e.g. VG on one dev has an older
* seqno. When vg_read() is reworked, we need to fall back
* to using that from here (and vg_read's from lvmetad) when
* there is a problem. Perhaps by disabling lvmetad when a
* VG problem is detected, causing commands to fully fall
* back to disk, which will repair the VG. Then lvmetad can
* be repopulated and re-enabled (possibly automatically.)
*/
/*
* Do a low level vg_read on each dev, verify the vg returned
* from metadata on each device is for the VG being read
* (the PV may have been removed from the VG being read and
* added to a different one), and return this vg to the caller
* as the current vg to use.
*
* The label scan above will have saved in lvmcache which
* vg each device is used in, so we could figure that part
* out without doing the vg_read.
*/
dm_list_iterate_items_safe(devl, devlsafe, &pvs_scan) {
if (!devl->dev)
continue;
log_debug_lvmetad("Rescan VG %s scanning %s.", vg->name, dev_name(devl->dev));
if (!label_read(devl->dev, &label, 0)) {
/* Another host removed this PV from the VG. */
log_debug_lvmetad("Rescan VG %s found %s was removed.", vg->name, dev_name(devl->dev));
if ((info = lvmcache_info_from_pvid(devl->dev->pvid, NULL, 0)))
lvmcache_del(info);
log_debug_lvmetad("Rescan VG %s getting metadata from %s.",
vg->name, dev_name(devl->dev));
/*
* The info struct for this dev knows what and where
* the mdas are for this dev (the label scan saved
* the mda locations for this dev on the lvmcache info struct).
*/
if (!(info = lvmcache_info_from_pvid(devl->dev->pvid, devl->dev, 0))) {
log_debug_lvmetad("Rescan VG %s from %s dropping dev (no info).",
vg->name, dev_name(devl->dev));
dm_list_move(&pvs_drop, &devl->list);
continue;
}
info = (struct lvmcache_info *) label->info;
baton.vg = NULL;
baton.fid = lvmcache_fmt(info)->ops->create_instance(lvmcache_fmt(info), &fic);
if (!baton.fid)
return_NULL;
if (baton.fid->fmt->features & FMT_OBSOLETE) {
log_debug_lvmetad("Ignoring obsolete format on PV %s in VG %s.", dev_name(devl->dev), vg->name);
lvmcache_fmt(info)->ops->destroy_instance(baton.fid);
dm_list_move(&pvs_drop, &devl->list);
continue;
}
/*
* Read VG metadata from this dev's mdas.
*/
lvmcache_foreach_mda(info, _lvmetad_pvscan_single, &baton);
lvmcache_foreach_mda(info, _lvmetad_pvscan_vg_single, &baton);
/*
* The PV may have been removed from the VG by another host
* since we last read the VG.
*/
if (!baton.vg) {
log_debug_lvmetad("Rescan VG %s did not find %s.", vg->name, dev_name(devl->dev));
lvmcache_fmt(info)->ops->destroy_instance(baton.fid);
log_debug_lvmetad("Rescan VG %s from %s dropping dev (no metadata).",
vg->name, dev_name(devl->dev));
dm_list_move(&pvs_drop, &devl->list);
continue;
}
@@ -1893,10 +1984,15 @@ scan_more:
* different VG since we last read the VG.
*/
if (strcmp(baton.vg->name, vg->name)) {
log_debug_lvmetad("Rescan VG %s found different VG %s on PV %s.",
vg->name, baton.vg->name, dev_name(devl->dev));
log_debug_lvmetad("Rescan VG %s from %s dropping dev (other VG %s).",
vg->name, dev_name(devl->dev), baton.vg->name);
release_vg(baton.vg);
continue;
}
if (!(vgmeta = export_vg_to_config_tree(baton.vg))) {
log_error("VG export to config tree failed");
release_vg(baton.vg);
dm_list_move(&pvs_drop, &devl->list);
continue;
}
@@ -1906,20 +2002,35 @@ scan_more:
* read from each other dev.
*/
if (!save_seqno)
save_seqno = baton.vg->seqno;
if (save_vg && (save_seqno != baton.vg->seqno)) {
/* FIXME: fall back to vg_read to correct this. */
log_warn("WARNING: inconsistent metadata for VG %s on devices %s seqno %u and %s seqno %u.",
vg->name, dev_name(save_dev), save_seqno,
dev_name(devl->dev), baton.vg->seqno);
log_warn("WARNING: temporarily disable lvmetad to repair metadata.");
if (!(vgmeta = export_vg_to_config_tree(baton.vg))) {
log_error("VG export to config tree failed");
release_vg(baton.vg);
return NULL;
/* Use the most recent */
if (save_seqno < baton.vg->seqno) {
release_vg(save_vg);
dm_config_destroy(save_meta);
save_vg = baton.vg;
save_meta = vgmeta;
save_seqno = baton.vg->seqno;
save_dev = devl->dev;
} else {
release_vg(baton.vg);
dm_config_destroy(vgmeta);
}
continue;
}
if (!vgmeta_ret) {
vgmeta_ret = vgmeta;
if (!save_vg) {
save_vg = baton.vg;
save_meta = vgmeta;
save_seqno = baton.vg->seqno;
save_dev = devl->dev;
} else {
struct dm_config_node *meta1 = vgmeta_ret->root;
struct dm_config_node *meta1 = save_meta->root;
struct dm_config_node *meta2 = vgmeta->root;
struct dm_config_node *sib1 = meta1->sib;
struct dm_config_node *sib2 = meta2->sib;
@@ -1944,73 +2055,128 @@ scan_more:
meta2->sib = NULL;
if (compare_config(meta1, meta2)) {
/* FIXME: fall back to vg_read to correct this. */
log_warn("WARNING: inconsistent metadata for VG %s on devices %s seqno %u and %s seqno %u.",
vg->name, dev_name(save_dev), save_seqno,
dev_name(devl->dev), baton.vg->seqno);
log_warn("WARNING: temporarily disable lvmetad to repair metadata.");
log_error("VG %s metadata comparison failed for device %s vs %s",
vg->name, dev_name(devl->dev), save_dev ? dev_name(save_dev) : "none");
_log_debug_inequality(vg->name, vgmeta_ret->root, vgmeta->root);
_log_debug_inequality(vg->name, save_meta->root, vgmeta->root);
meta1->sib = sib1;
meta2->sib = sib2;
dm_config_destroy(vgmeta);
dm_config_destroy(vgmeta_ret);
/* no right choice, just use the previous copy */
release_vg(baton.vg);
return NULL;
dm_config_destroy(vgmeta);
}
meta1->sib = sib1;
meta2->sib = sib2;
release_vg(baton.vg);
dm_config_destroy(vgmeta);
}
}
/*
* Look for any new PVs in the VG metadata that were not in our
* previous version of the VG. Add them to pvs_new to be
* scanned in this loop just like the old PVs.
*/
if (!check_new_pvs) {
check_new_pvs = 1;
dm_list_iterate_items(pvl_new, &baton.vg->pvs) {
found = 0;
dm_list_iterate_items(pvl, &vg->pvs) {
if (pvl_new->pv->dev != pvl->pv->dev)
continue;
found = 1;
break;
}
if (found)
/* FIXME: see above */
fid->ref_count--;
/*
* Look for any new PVs in the VG metadata that were not in our
* previous version of the VG.
*
* (Don't look for new PVs after a rescan and retry.)
*/
found_new_pvs = 0;
if (save_vg && !retried_reads) {
dm_list_iterate_items(pvl_new, &save_vg->pvs) {
found = 0;
dm_list_iterate_items(pvl, &vg->pvs) {
if (pvl_new->pv->dev != pvl->pv->dev)
continue;
if (!pvl_new->pv->dev) {
strncpy(pvid_s, (char *) &pvl_new->pv->id, sizeof(pvid_s) - 1);
if (!id_write_format((const struct id *)&pvid_s, uuid, sizeof(uuid)))
stack;
log_error("Device not found for PV %s in VG %s", uuid, vg->name);
missing_devs++;
continue;
}
if (!(devl_new = dm_pool_zalloc(cmd->mem, sizeof(*devl_new))))
return_NULL;
devl_new->dev = pvl_new->pv->dev;
dm_list_add(&pvs_new, &devl_new->list);
log_debug_lvmetad("Rescan VG %s found %s was added.", vg->name, dev_name(devl_new->dev));
found = 1;
break;
}
/*
* PV in new VG metadata not found in old VG metadata.
* There's a good chance we don't know about this new
* PV or what device it's on; a label scan is needed
* of all devices so we know which device the VG is
* now using.
*/
if (!found) {
found_new_pvs++;
strncpy(pvid_s, (char *) &pvl_new->pv->id, sizeof(pvid_s) - 1);
if (!id_write_format((const struct id *)&pvid_s, uuid, sizeof(uuid)))
stack;
log_debug_lvmetad("Rescan VG %s found new PV %s.", vg->name, uuid);
}
}
}
release_vg(baton.vg);
if (!save_vg && retried_reads) {
log_error("VG %s not found after rescanning devices.", vg->name);
goto out;
}
/*
* Do the same scanning above for any new PVs.
* Do a full rescan of devices, then look up which devices the
* scan found for this VG name, and select those devices to
* read metadata from in the loop above (rather than the list
* of devices we created from our last copy of the vg metadata.)
*
* Case 1: VG we knew is no longer on any of the devices we knew it
* to be on (save_vg is NULL, which means the metadata wasn't found
* when reading mdas on each of the initial pvs_scan devices).
* Rescan all devs and then retry reading metadata from the devs that
* the scan finds associated with this VG.
*
* Case 2: VG has new PVs but we don't know what devices they are
* so rescan all devs and then retry reading metadata from the devs
* that the scan finds associated with this VG.
*
* (N.B. after a retry, we don't check for found_new_pvs.)
*/
if (!dm_list_empty(&pvs_new)) {
dm_list_init(&pvs_scan);
dm_list_splice(&pvs_scan, &pvs_new);
dm_list_init(&pvs_new);
log_debug_lvmetad("Rescan VG %s found new PVs to scan.", vg->name);
goto scan_more;
}
if (!save_vg || found_new_pvs) {
if (!save_vg)
log_debug_lvmetad("Rescan VG %s did not find VG on previous devs.", vg->name);
if (found_new_pvs)
log_debug_lvmetad("Rescan VG %s scanning all devs to find new PVs.", vg->name);
if (missing_devs) {
if (vgmeta_ret)
dm_config_destroy(vgmeta_ret);
return_NULL;
label_scan(cmd);
if (!(vginfo = lvmcache_vginfo_from_vgname(vg->name, NULL))) {
log_error("VG %s vg info not found after rescanning devices.", vg->name);
goto out;
}
/*
* Set pvs_scan to devs that the label scan found
* in the VG and retry the metadata reading loop.
*/
dm_list_init(&pvs_scan);
if (!lvmcache_get_vg_devs(cmd, vginfo, &pvs_scan)) {
log_error("VG %s info devs not found after rescanning devices.", vg->name);
goto out;
}
log_debug_lvmetad("Rescan VG %s has %d PVs after label scan.",
vg->name, dm_list_size(&pvs_scan));
if (save_vg)
release_vg(save_vg);
if (save_meta)
dm_config_destroy(save_meta);
save_vg = NULL;
save_meta = NULL;
save_dev = NULL;
save_seqno = 0;
found_new_pvs = 0;
retried_reads = 1;
goto retry_reads;
}
/*
@@ -2019,52 +2185,50 @@ scan_more:
dm_list_iterate_items(devl, &pvs_drop) {
if (!devl->dev)
continue;
log_debug_lvmetad("Rescan VG %s dropping %s.", vg->name, dev_name(devl->dev));
if (!lvmetad_pv_gone_by_dev(devl->dev))
return_NULL;
log_debug_lvmetad("Rescan VG %s removing %s from lvmetad.", vg->name, dev_name(devl->dev));
if (!lvmetad_pv_gone_by_dev(devl->dev)) {
/* FIXME: use an error path that disables lvmetad */
log_error("Failed to remove %s from lvmetad.", dev_name(devl->dev));
}
}
/*
* Update the VG in lvmetad.
* Update lvmetad with the newly read version of the VG.
* When the seqno is unchanged the cached VG can be left.
*/
if (vgmeta_ret) {
fid = lvmcache_fmt(info)->ops->create_instance(lvmcache_fmt(info), &fic);
if (!(vg_ret = import_vg_from_config_tree(vgmeta_ret, fid))) {
log_error("VG import from config tree failed");
lvmcache_fmt(info)->ops->destroy_instance(fid);
goto out;
if (save_vg && (save_seqno != vg->seqno)) {
dm_list_iterate_items(devl, &pvs_scan) {
if (!devl->dev)
continue;
log_debug_lvmetad("Rescan VG %s removing %s from lvmetad to replace.",
vg->name, dev_name(devl->dev));
if (!lvmetad_pv_gone_by_dev(devl->dev)) {
/* FIXME: use an error path that disables lvmetad */
log_error("Failed to remove %s from lvmetad.", dev_name(devl->dev));
}
}
log_debug_lvmetad("Rescan VG %s updating lvmetad from seqno %u to seqno %u.",
vg->name, vg->seqno, save_seqno);
/*
* Update lvmetad with the newly read version of the VG.
* When the seqno is unchanged the cached VG can be left.
* If this vg_update fails the cached metadata in
* lvmetad will remain invalid.
*/
if (save_seqno != vg->seqno) {
dm_list_iterate_items(devl, &pvs_scan) {
if (!devl->dev)
continue;
log_debug_lvmetad("Rescan VG %s dropping to replace %s.", vg->name, dev_name(devl->dev));
if (!lvmetad_pv_gone_by_dev(devl->dev))
return_NULL;
}
log_debug_lvmetad("Rescan VG %s updating lvmetad from seqno %u to seqno %u.",
vg->name, vg->seqno, save_seqno);
/*
* If this vg_update fails the cached metadata in
* lvmetad will remain invalid.
*/
vg_ret->lvmetad_update_pending = 1;
if (!lvmetad_vg_update_finish(vg_ret))
log_error("Failed to update lvmetad with new VG meta");
save_vg->lvmetad_update_pending = 1;
if (!lvmetad_vg_update_finish(save_vg)) {
/* FIXME: use an error path that disables lvmetad */
log_error("Failed to update lvmetad with new VG meta");
}
dm_config_destroy(vgmeta_ret);
}
out:
if (vg_ret)
log_debug_lvmetad("Rescan VG %s done (seqno %u).", vg_ret->name, vg_ret->seqno);
return vg_ret;
if (!save_vg && fid)
fmt->ops->destroy_instance(fid);
if (save_meta)
dm_config_destroy(save_meta);
if (save_vg)
log_debug_lvmetad("Rescan VG %s done (new seqno %u).", save_vg->name, save_vg->seqno);
return save_vg;
}
int lvmetad_pvscan_single(struct cmd_context *cmd, struct device *dev,
@@ -2074,9 +2238,12 @@ int lvmetad_pvscan_single(struct cmd_context *cmd, struct device *dev,
struct label *label;
struct lvmcache_info *info;
struct _lvmetad_pvscan_baton baton;
const struct format_type *fmt;
/* Create a dummy instance. */
struct format_instance_ctx fic = { .type = 0 };
log_debug_lvmetad("Scan metadata from dev %s", dev_name(dev));
if (!lvmetad_used()) {
log_error("Cannot proceed since lvmetad is not active.");
return 0;
@@ -2087,39 +2254,35 @@ int lvmetad_pvscan_single(struct cmd_context *cmd, struct device *dev,
return 1;
}
if (!label_read(dev, &label, 0)) {
log_print_unless_silent("No PV label found on %s.", dev_name(dev));
if (!(info = lvmcache_info_from_pvid(dev->pvid, dev, 0))) {
log_print_unless_silent("No PV info found on %s for PVID %s.", dev_name(dev), dev->pvid);
if (!lvmetad_pv_gone_by_dev(dev))
goto_bad;
return 1;
}
info = (struct lvmcache_info *) label->info;
if (!(label = lvmcache_get_label(info))) {
log_print_unless_silent("No PV label found for %s.", dev_name(dev));
if (!lvmetad_pv_gone_by_dev(dev))
goto_bad;
return 1;
}
fmt = lvmcache_fmt(info);
baton.cmd = cmd;
baton.vg = NULL;
baton.fid = lvmcache_fmt(info)->ops->create_instance(lvmcache_fmt(info), &fic);
baton.fid = fmt->ops->create_instance(fmt, &fic);
if (!baton.fid)
goto_bad;
if (baton.fid->fmt->features & FMT_OBSOLETE) {
lvmcache_fmt(info)->ops->destroy_instance(baton.fid);
log_warn("WARNING: Disabling lvmetad cache which does not support obsolete (lvm1) metadata.");
lvmetad_set_disabled(cmd, LVMETAD_DISABLE_REASON_LVM1);
_found_lvm1_metadata = 1;
/*
* return 1 (success) so that we'll continue to populate lvmetad
* instead of leaving the update incomplete.
*/
return 1;
}
lvmcache_foreach_mda(info, _lvmetad_pvscan_single, &baton);
if (!baton.vg)
lvmcache_fmt(info)->ops->destroy_instance(baton.fid);
fmt->ops->destroy_instance(baton.fid);
if (!lvmetad_pv_found(cmd, (const struct id *) &dev->pvid, dev, lvmcache_fmt(info),
if (!lvmetad_pv_found(cmd, (const struct id *) &dev->pvid, dev, fmt,
label->sector, baton.vg, found_vgnames, changed_vgnames)) {
release_vg(baton.vg);
goto_bad;
@@ -2185,6 +2348,15 @@ int lvmetad_pvscan_all_devs(struct cmd_context *cmd, int do_wait)
replacing_other_update = 1;
}
label_scan(cmd);
lvmcache_pvscan_duplicate_check(cmd);
if (lvmcache_found_duplicate_pvs()) {
log_warn("WARNING: Scan found duplicate PVs.");
return 0;
}
log_verbose("Scanning all devices to update lvmetad.");
if (!(iter = dev_iter_create(cmd->lvmetad_filter, 1))) {
@@ -2268,11 +2440,9 @@ int lvmetad_pvscan_all_devs(struct cmd_context *cmd, int do_wait)
}
/*
* If lvmetad is disabled, and no lvm1 metadata was seen and no
* duplicate PVs were seen, then re-enable lvmetad.
* If lvmetad is disabled, and no duplicate PVs were seen, then re-enable lvmetad.
*/
if (lvmetad_is_disabled(cmd, &reason) &&
!lvmcache_found_duplicate_pvs() && !_found_lvm1_metadata) {
if (lvmetad_is_disabled(cmd, &reason) && !lvmcache_found_duplicate_pvs()) {
log_debug_lvmetad("Enabling lvmetad which was previously disabled.");
lvmetad_clear_disabled(cmd);
}
@@ -2367,11 +2537,18 @@ static int _lvmetad_get_pv_cache_list(struct cmd_context *cmd, struct dm_list *p
*/
static void _update_pv_in_udev(struct cmd_context *cmd, dev_t devt)
{
struct device *dev;
log_debug_devs("device %d:%d open to update udev",
/*
* FIXME: this is diabled as part of removing dev_opens
* to integrate bcache. If this is really needed, we
* can do a separate open/close here.
*/
log_debug_devs("SKIP device %d:%d open to update udev",
(int)MAJOR(devt), (int)MINOR(devt));
#if 0
struct device *dev;
if (!(dev = dev_cache_get_by_devt(devt, cmd->lvmetad_filter))) {
log_error("_update_pv_in_udev no dev found");
return;
@@ -2384,6 +2561,7 @@ static void _update_pv_in_udev(struct cmd_context *cmd, dev_t devt)
if (!dev_close(dev))
stack;
#endif
}
/*
@@ -2555,6 +2733,8 @@ void lvmetad_validate_global_cache(struct cmd_context *cmd, int force)
*/
_lvmetad_get_pv_cache_list(cmd, &pvc_before);
log_debug_lvmetad("Rescan all devices to validate global cache.");
/*
* Update the local lvmetad cache so it correctly reflects any
* changes made on remote hosts. (It's possible that this command
@@ -2623,7 +2803,7 @@ void lvmetad_validate_global_cache(struct cmd_context *cmd, int force)
_update_changed_pvs_in_udev(cmd, &pvc_before, &pvc_after);
}
log_debug_lvmetad("Validating global lvmetad cache finished");
log_debug_lvmetad("Rescanned all devices");
}
int lvmetad_vg_is_foreign(struct cmd_context *cmd, const char *vgname, const char *vgid)
@@ -2878,9 +3058,6 @@ int lvmetad_is_disabled(struct cmd_context *cmd, const char **reason)
} else if (strstr(reply_reason, LVMETAD_DISABLE_REASON_REPAIR)) {
*reason = "a repair command was run";
} else if (strstr(reply_reason, LVMETAD_DISABLE_REASON_LVM1)) {
*reason = "LVM1 metadata was found";
} else if (strstr(reply_reason, LVMETAD_DISABLE_REASON_DUPLICATES)) {
*reason = "duplicate PVs were found";

76
lib/cache/lvmetad.h vendored
View File

@@ -17,6 +17,8 @@
#include "config-util.h"
#include <stdint.h>
struct volume_group;
struct cmd_context;
struct dm_config_tree;
@@ -163,38 +165,48 @@ void lvmetad_clear_disabled(struct cmd_context *cmd);
# else /* LVMETAD_SUPPORT */
# define lvmetad_disconnect() do { } while (0)
# define lvmetad_connect(cmd) (0)
# define lvmetad_make_unused(cmd) do { } while (0)
# define lvmetad_used() (0)
# define lvmetad_set_socket(a) do { } while (0)
# define lvmetad_socket_present() (0)
# define lvmetad_pidfile_present() (0)
# define lvmetad_set_token(a) do { } while (0)
# define lvmetad_release_token() do { } while (0)
# define lvmetad_vg_update(vg) (1)
# define lvmetad_vg_update_pending(vg) (1)
# define lvmetad_vg_update_finish(vg) (1)
# define lvmetad_vg_remove_pending(vg) (1)
# define lvmetad_vg_remove_finish(vg) (1)
# define lvmetad_pv_found(cmd, pvid, dev, fmt, label_sector, vg, found_vgnames, changed_vgnames) (1)
# define lvmetad_pv_gone(devno, pv_name) (1)
# define lvmetad_pv_gone_by_dev(dev) (1)
# define lvmetad_pv_list_to_lvmcache(cmd) (1)
# define lvmetad_pv_lookup(cmd, pvid, found) (0)
# define lvmetad_pv_lookup_by_dev(cmd, dev, found) (0)
# define lvmetad_vg_list_to_lvmcache(cmd) (1)
# define lvmetad_get_vgnameids(cmd, vgnameids) do { } while (0)
# define lvmetad_vg_lookup(cmd, vgname, vgid) (NULL)
# define lvmetad_pvscan_single(cmd, dev, found_vgnames, changed_vgnames) (0)
# define lvmetad_pvscan_all_devs(cmd, do_wait) (0)
# define lvmetad_vg_clear_outdated_pvs(vg) do { } while (0)
# define lvmetad_validate_global_cache(cmd, force) do { } while (0)
# define lvmetad_vg_is_foreign(cmd, vgname, vgid) (0)
# define lvmetad_token_matches(cmd) (1)
# define lvmetad_is_disabled(cmd, reason) (0)
# define lvmetad_set_disabled(cmd, reason) do { } while (0)
# define lvmetad_clear_disabled(cmd) do { } while (0)
static inline int lvmetad_connect(struct cmd_context *cmd) {return 0;}
static inline void lvmetad_disconnect(void) {}
static inline void lvmetad_make_unused(struct cmd_context *cmd) {}
static inline int lvmetad_used(void) {return 0;}
static inline void lvmetad_set_socket(const char *thing) {}
static inline int lvmetad_socket_present(void) {return 0;}
static inline int lvmetad_pidfile_present(void) {return 0;}
static inline void lvmetad_set_token(const struct dm_config_value *filter) {}
static inline void lvmetad_release_token(void) {}
static inline int lvmetad_vg_update_pending(struct volume_group *vg) {return 1;}
static inline int lvmetad_vg_update_finish(struct volume_group *vg) {return 1;}
static inline int lvmetad_vg_remove_pending(struct volume_group *vg) {return 1;}
static inline int lvmetad_vg_remove_finish(struct volume_group *vg) {return 1;}
static inline int lvmetad_pv_found(struct cmd_context *cmd, const struct id *pvid, struct device *dev,
const struct format_type *fmt, uint64_t label_sector,
struct volume_group *vg,
struct dm_list *found_vgnames,
struct dm_list *changed_vgnames) {return 1;}
static inline int lvmetad_pv_gone(dev_t devno, const char *pv_name) {return 1;}
static inline int lvmetad_pv_gone_by_dev(struct device *dev) {return 1;}
static inline int lvmetad_pv_list_to_lvmcache(struct cmd_context *cmd) {return 1;}
static inline int lvmetad_pv_lookup(struct cmd_context *cmd, struct id pvid, int *found) {return 0;}
static inline int lvmetad_pv_lookup_by_dev(struct cmd_context *cmd, struct device *dev, int *found) {return 0;}
static inline int lvmetad_vg_list_to_lvmcache(struct cmd_context *cmd) {return 1;}
static inline int lvmetad_get_vgnameids(struct cmd_context *cmd, struct dm_list *vgnameids) {return 0;}
static inline struct volume_group *lvmetad_vg_lookup(struct cmd_context *cmd,
const char *vgname, const char *vgid) {return NULL;}
static inline int lvmetad_pvscan_single(struct cmd_context *cmd, struct device *dev,
struct dm_list *found_vgnames,
struct dm_list *changed_vgnames) {return 0;}
static inline int lvmetad_pvscan_all_devs(struct cmd_context *cmd, int do_wait) {return 0;}
static inline int lvmetad_vg_clear_outdated_pvs(struct volume_group *vg) {return 0;}
static inline void lvmetad_validate_global_cache(struct cmd_context *cmd, int force) {}
static inline int lvmetad_token_matches(struct cmd_context *cmd) {return 1;}
static inline int lvmetad_vg_is_foreign(struct cmd_context *cmd, const char *vgname, const char *vgid) {return 0;}
static inline int lvmetad_is_disabled(struct cmd_context *cmd, const char **reason) {return 0;}
static inline void lvmetad_set_disabled(struct cmd_context *cmd, const char *reason) {}
static inline void lvmetad_clear_disabled(struct cmd_context *cmd) {}
# endif /* LVMETAD_SUPPORT */

View File

@@ -36,16 +36,9 @@
#include "sharedlib.h"
#endif
#ifdef LVM1_INTERNAL
#include "format1.h"
#endif
#ifdef POOL_INTERNAL
#include "format_pool.h"
#endif
#include <locale.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/utsname.h>
#include <syslog.h>
#include <time.h>
@@ -54,7 +47,7 @@
# include <malloc.h>
#endif
static const size_t linebuffer_size = 4096;
static const size_t _linebuffer_size = 4096;
/*
* Copy the input string, removing invalid characters.
@@ -283,6 +276,8 @@ static int _parse_debug_classes(struct cmd_context *cmd)
debug_classes |= LOG_CLASS_LVMPOLLD;
else if (!strcasecmp(cv->v.str, "dbus"))
debug_classes |= LOG_CLASS_DBUS;
else if (!strcasecmp(cv->v.str, "io"))
debug_classes |= LOG_CLASS_IO;
else
log_verbose("Unrecognised value for log/debug_classes: %s", cv->v.str);
}
@@ -564,7 +559,7 @@ static int _process_config(struct cmd_context *cmd)
#ifdef DEVMAPPER_SUPPORT
dm_set_dev_dir(cmd->dev_dir);
if (!dm_set_uuid_prefix("LVM-"))
if (!dm_set_uuid_prefix(UUID_PREFIX))
return_0;
#endif
@@ -685,9 +680,6 @@ static int _process_config(struct cmd_context *cmd)
if (find_config_tree_bool(cmd, report_two_word_unknown_device_CFG, NULL))
init_unknown_device_name("unknown device");
init_detect_internal_vg_cache_corruption
(find_config_tree_bool(cmd, global_detect_internal_vg_cache_corruption_CFG, NULL));
if (!_init_system_id(cmd))
return_0;
@@ -1061,7 +1053,7 @@ static int _init_dev_cache(struct cmd_context *cmd)
return 1;
}
#define MAX_FILTERS 9
#define MAX_FILTERS 10
static struct dev_filter *_init_lvmetad_filter_chain(struct cmd_context *cmd)
{
@@ -1142,10 +1134,17 @@ static struct dev_filter *_init_lvmetad_filter_chain(struct cmd_context *cmd)
}
nr_filt++;
/* signature filter. Required. */
if (!(filters[nr_filt] = signature_filter_create(cmd->dev_types))) {
log_error("Failed to create signature device filter");
goto bad;
}
nr_filt++;
/* md component filter. Optional, non-critical. */
if (find_config_tree_bool(cmd, devices_md_component_detection_CFG, NULL)) {
init_md_filtering(1);
if ((filters[nr_filt] = md_filter_create(cmd->dev_types)))
if ((filters[nr_filt] = md_filter_create(cmd, cmd->dev_types)))
nr_filt++;
}
@@ -1341,20 +1340,6 @@ static int _init_formats(struct cmd_context *cmd)
const struct dm_config_node *cn;
#endif
#ifdef LVM1_INTERNAL
if (!(fmt = init_lvm1_format(cmd)))
return 0;
fmt->library = NULL;
dm_list_add(&cmd->formats, &fmt->list);
#endif
#ifdef POOL_INTERNAL
if (!(fmt = init_pool_format(cmd)))
return 0;
fmt->library = NULL;
dm_list_add(&cmd->formats, &fmt->list);
#endif
#ifdef HAVE_LIBDL
/* Load any formats in shared libs if not static */
if (!is_static() &&
@@ -1477,6 +1462,7 @@ static int _init_segtypes(struct cmd_context *cmd)
struct segment_type *segtype;
struct segtype_library seglib = { .cmd = cmd, .lib = NULL };
struct segment_type *(*init_segtype_array[])(struct cmd_context *cmd) = {
init_linear_segtype,
init_striped_segtype,
init_zero_segtype,
init_error_segtype,
@@ -1501,11 +1487,6 @@ static int _init_segtypes(struct cmd_context *cmd)
dm_list_add(&cmd->segtypes, &segtype->list);
}
#ifdef REPLICATOR_INTERNAL
if (!init_replicator_segtype(cmd, &seglib))
return 0;
#endif
#ifdef RAID_INTERNAL
if (!init_raid_segtypes(cmd, &seglib))
return 0;
@@ -1653,7 +1634,6 @@ static void _init_rand(struct cmd_context *cmd)
static void _init_globals(struct cmd_context *cmd)
{
init_full_scan_done(0);
init_mirror_in_sync(0);
}
@@ -1784,6 +1764,8 @@ void destroy_config_context(struct cmd_context *cmd)
/*
* A "config context" is a very light weight toolcontext that
* is only used for reading config settings from lvm.conf.
*
* FIXME: this needs to go back to parametrized create_toolcontext()
*/
struct cmd_context *create_config_context(void)
{
@@ -1800,6 +1782,9 @@ struct cmd_context *create_config_context(void)
if (!(cmd->libmem = dm_pool_create("library", 4 * 1024)))
goto_out;
if (!(cmd->mem = dm_pool_create("command", 4 * 1024)))
goto out;
dm_list_init(&cmd->config_files);
dm_list_init(&cmd->tags);
@@ -1830,7 +1815,7 @@ out:
}
/* Entry point */
struct cmd_context *create_toolcontext(unsigned is_long_lived,
struct cmd_context *create_toolcontext(unsigned is_clvmd,
const char *system_dir,
unsigned set_buffering,
unsigned threaded,
@@ -1857,7 +1842,8 @@ struct cmd_context *create_toolcontext(unsigned is_long_lived,
log_error("Failed to allocate command context");
return NULL;
}
cmd->is_long_lived = is_long_lived;
cmd->is_long_lived = is_clvmd;
cmd->is_clvmd = is_clvmd;
cmd->threaded = threaded ? 1 : 0;
cmd->handles_missing_pvs = 0;
cmd->handles_unknown_segments = 0;
@@ -1876,9 +1862,15 @@ struct cmd_context *create_toolcontext(unsigned is_long_lived,
#ifndef VALGRIND_POOL
/* Set in/out stream buffering before glibc */
if (set_buffering) {
if (set_buffering
#ifdef SYS_gettid
/* For threaded programs no changes of streams */
/* On linux gettid() is implemented only via syscall */
&& (syscall(SYS_gettid) == getpid())
#endif
) {
/* Allocate 2 buffers */
if (!(cmd->linebuffer = dm_malloc(2 * linebuffer_size))) {
if (!(cmd->linebuffer = dm_malloc(2 * _linebuffer_size))) {
log_error("Failed to allocate line buffer.");
goto out;
}
@@ -1889,7 +1881,7 @@ struct cmd_context *create_toolcontext(unsigned is_long_lived,
(flags & O_ACCMODE) != O_WRONLY) {
if (!reopen_standard_stream(&stdin, "r"))
goto_out;
if (setvbuf(stdin, cmd->linebuffer, _IOLBF, linebuffer_size)) {
if (setvbuf(stdin, cmd->linebuffer, _IOLBF, _linebuffer_size)) {
log_sys_error("setvbuf", "");
goto out;
}
@@ -1900,14 +1892,14 @@ struct cmd_context *create_toolcontext(unsigned is_long_lived,
(flags & O_ACCMODE) != O_RDONLY) {
if (!reopen_standard_stream(&stdout, "w"))
goto_out;
if (setvbuf(stdout, cmd->linebuffer + linebuffer_size,
_IOLBF, linebuffer_size)) {
if (setvbuf(stdout, cmd->linebuffer + _linebuffer_size,
_IOLBF, _linebuffer_size)) {
log_sys_error("setvbuf", "");
goto out;
}
}
/* Buffers are used for lines without '\n' */
} else
} else if (!set_buffering)
/* Without buffering, must not use stdin/stdout */
init_silent(1);
#endif
@@ -1980,6 +1972,10 @@ struct cmd_context *create_toolcontext(unsigned is_long_lived,
if (!_init_formats(cmd))
goto_out;
if (!lvmcache_init(cmd))
goto_out;
/* FIXME: move into lvmcache_init */
if (!init_lvmcache_orphans(cmd))
goto_out;
@@ -2001,7 +1997,6 @@ struct cmd_context *create_toolcontext(unsigned is_long_lived,
if (set_filters && !init_filters(cmd, 1))
goto_out;
cmd->default_settings.cache_vgmetadata = 1;
cmd->current_settings = cmd->default_settings;
cmd->initialized.config = 1;
@@ -2115,6 +2110,7 @@ int refresh_toolcontext(struct cmd_context *cmd)
activation_release();
lvmcache_destroy(cmd, 0, 0);
label_scan_destroy(cmd);
label_exit();
_destroy_segtypes(&cmd->segtypes);
_destroy_formats(cmd, &cmd->formats);
@@ -2201,6 +2197,9 @@ int refresh_toolcontext(struct cmd_context *cmd)
if (!_init_formats(cmd))
return_0;
if (!lvmcache_init(cmd))
return_0;
if (!init_lvmcache_orphans(cmd))
return_0;
@@ -2234,6 +2233,7 @@ void destroy_toolcontext(struct cmd_context *cmd)
archive_exit(cmd);
backup_exit(cmd);
lvmcache_destroy(cmd, 0, 0);
label_scan_destroy(cmd);
label_exit();
_destroy_segtypes(&cmd->segtypes);
_destroy_formats(cmd, &cmd->formats);

View File

@@ -42,6 +42,7 @@ struct config_info {
int cache_vgmetadata;
const char *msg_prefix;
const char *fmt_name;
const char *dmeventd_executable;
uint64_t unit_factor;
int cmd_name; /* Show command name? */
mode_t umask;
@@ -153,6 +154,7 @@ struct cmd_context {
unsigned include_shared_vgs:1; /* report/display cmds can reveal lockd VGs */
unsigned include_active_foreign_vgs:1; /* cmd should process foreign VGs with active LVs */
unsigned vg_read_print_access_error:1; /* print access errors from vg_read */
unsigned force_access_clustered:1;
unsigned lockd_gl_disable:1;
unsigned lockd_vg_disable:1;
unsigned lockd_lv_disable:1;
@@ -160,9 +162,17 @@ struct cmd_context {
unsigned lockd_vg_rescan:1;
unsigned lockd_vg_default_sh:1;
unsigned lockd_vg_enforce_sh:1;
unsigned lockd_lv_sh:1;
unsigned vg_notify:1;
unsigned lv_notify:1;
unsigned pv_notify:1;
unsigned activate_component:1; /* command activates component LV */
unsigned process_component_lvs:1; /* command processes also component LVs */
unsigned mirror_warn_printed:1; /* command already printed warning about non-monitored mirrors */
unsigned pvscan_cache_single:1;
unsigned can_use_one_scan:1;
unsigned is_clvmd:1;
unsigned use_full_md_check:1;
/*
* Filtering.
@@ -228,7 +238,7 @@ struct cmd_context {
* system_dir may be NULL to use the default value.
* The environment variable LVM_SYSTEM_DIR always takes precedence.
*/
struct cmd_context *create_toolcontext(unsigned is_long_lived,
struct cmd_context *create_toolcontext(unsigned is_clvmd,
const char *system_dir,
unsigned set_buffering,
unsigned threaded,

View File

@@ -23,6 +23,7 @@
#include "toolcontext.h"
#include "lvm-file.h"
#include "memlock.h"
#include "label.h"
#include <sys/stat.h>
#include <sys/mman.h>
@@ -494,7 +495,7 @@ int override_config_tree_from_profile(struct cmd_context *cmd,
* and function avoids parsing of mda into config tree which
* remains unmodified and should not be used.
*/
int config_file_read_fd(struct dm_config_tree *cft, struct device *dev,
int config_file_read_fd(struct dm_config_tree *cft, struct device *dev, dev_io_reason_t reason,
off_t offset, size_t size, off_t offset2, size_t size2,
checksum_fn_t checksum_fn, uint32_t checksum,
int checksum_only, int no_dup_node_check)
@@ -532,17 +533,28 @@ int config_file_read_fd(struct dm_config_tree *cft, struct device *dev,
log_error("Failed to allocate circular buffer.");
return 0;
}
if (!dev_read_circular(dev, (uint64_t) offset, size,
(uint64_t) offset2, size2, buf)) {
if (!dev_read_bytes(dev, offset, size, buf))
goto out;
if (size2) {
if (!dev_read_bytes(dev, offset2, size2, buf + size))
goto out;
}
fb = buf;
}
/*
* The checksum passed in is the checksum from the mda_header
* preceding this metadata. They should always match.
* FIXME: handle case where mda_header checksum is bad,
* but the checksum calculated here is correct.
*/
if (checksum_fn && checksum !=
(checksum_fn(checksum_fn(INITIAL_CRC, (const uint8_t *)fb, size),
(const uint8_t *)(fb + size), size2))) {
log_error("%s: Checksum error", dev_name(dev));
log_error("%s: Checksum error at offset %" PRIu64, dev_name(dev), (uint64_t) offset);
goto out;
}
@@ -601,7 +613,7 @@ int config_file_read(struct dm_config_tree *cft)
}
}
r = config_file_read_fd(cft, cf->dev, 0, (size_t) info.st_size, 0, 0,
r = config_file_read_fd(cft, cf->dev, DEV_IO_MDA_CONTENT, 0, (size_t) info.st_size, 0, 0,
(checksum_fn_t) NULL, 0, 0, 0);
if (!cf->keep_open) {

View File

@@ -17,12 +17,12 @@
#define _LVM_CONFIG_H
#include "libdevmapper.h"
#include "device.h"
/* 16 bits: 3 bits for major, 4 bits for minor, 9 bits for patchlevel */
/* FIXME Max LVM version supported: 7.15.511. Extend bits when needed. */
#define vsn(major, minor, patchlevel) (major << 13 | minor << 9 | patchlevel)
struct device;
struct cmd_context;
typedef enum {
@@ -239,7 +239,7 @@ config_source_t config_get_source_type(struct dm_config_tree *cft);
typedef uint32_t (*checksum_fn_t) (uint32_t initial, const uint8_t *buf, uint32_t size);
struct dm_config_tree *config_open(config_source_t source, const char *filename, int keep_open);
int config_file_read_fd(struct dm_config_tree *cft, struct device *dev,
int config_file_read_fd(struct dm_config_tree *cft, struct device *dev, dev_io_reason_t reason,
off_t offset, size_t size, off_t offset2, size_t size2,
checksum_fn_t checksum_fn, uint32_t checksum,
int skip_parse, int no_dup_node_check);

View File

@@ -705,11 +705,11 @@ cfg(log_activation_CFG, "activation", log_CFG_SECTION, 0, CFG_TYPE_BOOL, 0, vsn(
cfg(log_activate_file_CFG, "activate_file", log_CFG_SECTION, CFG_DEFAULT_UNDEFINED | CFG_UNSUPPORTED, CFG_TYPE_STRING, NULL, vsn(1, 0, 0), NULL, 0, NULL, NULL)
cfg_array(log_debug_classes_CFG, "debug_classes", log_CFG_SECTION, CFG_ALLOW_EMPTY, CFG_TYPE_STRING, "#Smemory#Sdevices#Sactivation#Sallocation#Slvmetad#Smetadata#Scache#Slocking#Slvmpolld#Sdbus", vsn(2, 2, 99), NULL, 0, NULL,
cfg_array(log_debug_classes_CFG, "debug_classes", log_CFG_SECTION, CFG_ALLOW_EMPTY, CFG_TYPE_STRING, "#Smemory#Sdevices#Sio#Sactivation#Sallocation#Slvmetad#Smetadata#Scache#Slocking#Slvmpolld#Sdbus", vsn(2, 2, 99), NULL, 0, NULL,
"Select log messages by class.\n"
"Some debugging messages are assigned to a class and only appear in\n"
"debug output if the class is listed here. Classes currently\n"
"available: memory, devices, activation, allocation, lvmetad,\n"
"available: memory, devices, io, activation, allocation, lvmetad,\n"
"metadata, cache, locking, lvmpolld. Use \"all\" to see everything.\n")
cfg(backup_backup_CFG, "backup", backup_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_BACKUP_ENABLED, vsn(1, 0, 0), NULL, 0, NULL,
@@ -767,26 +767,14 @@ cfg(global_activation_CFG, "activation", global_CFG_SECTION, 0, CFG_TYPE_BOOL, D
"is not present in the kernel, disabling this should suppress\n"
"the error messages.\n")
cfg(global_fallback_to_lvm1_CFG, "fallback_to_lvm1", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_FALLBACK_TO_LVM1, vsn(1, 0, 18), "@DEFAULT_FALLBACK_TO_LVM1@", 0, NULL,
"Try running LVM1 tools if LVM cannot communicate with DM.\n"
"This option only applies to 2.4 kernels and is provided to help\n"
"switch between device-mapper kernels and LVM1 kernels. The LVM1\n"
"tools need to be installed with .lvm1 suffices, e.g. vgscan.lvm1.\n"
"They will stop working once the lvm2 on-disk metadata format is used.\n")
cfg(global_fallback_to_lvm1_CFG, "fallback_to_lvm1", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, 0, vsn(1, 0, 18), NULL, 0, NULL,
"This setting is no longer used.\n")
cfg(global_format_CFG, "format", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_FORMAT, vsn(1, 0, 0), NULL, 0, NULL,
"The default metadata format that commands should use.\n"
"The -M 1|2 option overrides this setting.\n"
"#\n"
"Accepted values:\n"
" lvm1\n"
" lvm2\n"
"#\n")
"This setting is no longer used.\n")
cfg_array(global_format_libraries_CFG, "format_libraries", global_CFG_SECTION, CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(1, 0, 0), NULL, 0, NULL,
"Shared libraries that process different metadata formats.\n"
"If support for LVM1 metadata was compiled as a shared library use\n"
"format_libraries = \"liblvm2format1.so\"\n")
"This setting is no longer used.")
cfg_array(global_segment_libraries_CFG, "segment_libraries", global_CFG_SECTION, CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(1, 0, 18), NULL, 0, NULL, NULL)
@@ -868,11 +856,8 @@ cfg(global_abort_on_internal_errors_CFG, "abort_on_internal_errors", global_CFG_
"Treat any internal errors as fatal errors, aborting the process that\n"
"encountered the internal error. Please only enable for debugging.\n")
cfg(global_detect_internal_vg_cache_corruption_CFG, "detect_internal_vg_cache_corruption", global_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_DETECT_INTERNAL_VG_CACHE_CORRUPTION, vsn(2, 2, 96), NULL, 0, NULL,
"Internal verification of VG structures.\n"
"Check if CRC matches when a parsed VG is used multiple times. This\n"
"is useful to catch unexpected changes to cached VG structures.\n"
"Please only enable for debugging.\n")
cfg(global_detect_internal_vg_cache_corruption_CFG, "detect_internal_vg_cache_corruption", global_CFG_SECTION, 0, CFG_TYPE_BOOL, 0, vsn(2, 2, 96), NULL, vsn(2, 2, 174), NULL,
"No longer used.\n")
cfg(global_metadata_read_only_CFG, "metadata_read_only", global_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_METADATA_READ_ONLY, vsn(2, 2, 75), NULL, 0, NULL,
"No operations that change on-disk metadata are permitted.\n"

View File

@@ -179,7 +179,6 @@
#define DEFAULT_LOGLEVEL 0
#define DEFAULT_INDENT 1
#define DEFAULT_ABORT_ON_INTERNAL_ERRORS 0
#define DEFAULT_DETECT_INTERNAL_VG_CACHE_CORRUPTION 0
#define DEFAULT_UNITS "r"
#define DEFAULT_SUFFIX 1
#define DEFAULT_HOSTTAGS 0

272
lib/device/bcache-utils.c Normal file
View File

@@ -0,0 +1,272 @@
/*
* 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,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "bcache.h"
// FIXME: need to define this in a common place (that doesn't pull in deps)
#ifndef SECTOR_SHIFT
#define SECTOR_SHIFT 9
#endif
//----------------------------------------------------------------
static void byte_range_to_block_range(struct bcache *cache, uint64_t start, size_t len,
block_address *bb, block_address *be)
{
block_address block_size = bcache_block_sectors(cache) << SECTOR_SHIFT;
*bb = start / block_size;
*be = (start + len + block_size - 1) / block_size;
}
static uint64_t _min(uint64_t lhs, uint64_t rhs)
{
if (rhs < lhs)
return rhs;
return lhs;
}
//----------------------------------------------------------------
void bcache_prefetch_bytes(struct bcache *cache, int fd, uint64_t start, size_t len)
{
block_address bb, be;
byte_range_to_block_range(cache, start, len, &bb, &be);
while (bb < be) {
bcache_prefetch(cache, fd, bb);
bb++;
}
}
//----------------------------------------------------------------
bool bcache_read_bytes(struct bcache *cache, int fd, uint64_t start, size_t len, void *data)
{
struct block *b;
block_address bb, be;
uint64_t block_size = bcache_block_sectors(cache) << SECTOR_SHIFT;
uint64_t block_offset = start % block_size;
bcache_prefetch_bytes(cache, fd, start, len);
byte_range_to_block_range(cache, start, len, &bb, &be);
for (; bb != be; bb++) {
if (!bcache_get(cache, fd, bb, 0, &b))
return false;
size_t blen = _min(block_size - block_offset, len);
memcpy(data, ((unsigned char *) b->data) + block_offset, blen);
bcache_put(b);
block_offset = 0;
len -= blen;
data = ((unsigned char *) data) + blen;
}
return true;
}
//----------------------------------------------------------------
// Writing bytes and zeroing bytes are very similar, so we factor out
// this common code.
struct updater;
typedef bool (*partial_update_fn)(struct updater *u, int fd, block_address bb, uint64_t offset, size_t len);
typedef bool (*whole_update_fn)(struct updater *u, int fd, block_address bb, block_address be);
struct updater {
struct bcache *cache;
partial_update_fn partial_fn;
whole_update_fn whole_fn;
void *data;
};
static bool _update_bytes(struct updater *u, int fd, uint64_t start, size_t len)
{
struct bcache *cache = u->cache;
block_address bb, be;
uint64_t block_size = bcache_block_sectors(cache) << SECTOR_SHIFT;
uint64_t block_offset = start % block_size;
uint64_t nr_whole;
byte_range_to_block_range(cache, start, len, &bb, &be);
// If the last block is partial, we will require a read, so let's
// prefetch it.
if ((start + len) % block_size)
bcache_prefetch(cache, fd, (start + len) / block_size);
// First block may be partial
if (block_offset) {
size_t blen = _min(block_size - block_offset, len);
if (!u->partial_fn(u, fd, bb, block_offset, blen))
return false;
len -= blen;
if (!len)
return true;
bb++;
}
// Now we write out a set of whole blocks
nr_whole = len / block_size;
if (!u->whole_fn(u, fd, bb, bb + nr_whole))
return false;
bb += nr_whole;
len -= nr_whole * block_size;
if (!len)
return true;
// Finally we write a partial end block
return u->partial_fn(u, fd, bb, 0, len);
}
//----------------------------------------------------------------
static bool _write_partial(struct updater *u, int fd, block_address bb,
uint64_t offset, size_t len)
{
struct block *b;
if (!bcache_get(u->cache, fd, bb, GF_DIRTY, &b))
return false;
memcpy(((unsigned char *) b->data) + offset, u->data, len);
u->data = ((unsigned char *) u->data) + len;
bcache_put(b);
return true;
}
static bool _write_whole(struct updater *u, int fd, block_address bb, block_address be)
{
struct block *b;
uint64_t block_size = bcache_block_sectors(u->cache) << SECTOR_SHIFT;
for (; bb != be; bb++) {
// We don't need to read the block since we are overwriting
// it completely.
if (!bcache_get(u->cache, fd, bb, GF_ZERO, &b))
return false;
memcpy(b->data, u->data, block_size);
u->data = ((unsigned char *) u->data) + block_size;
bcache_put(b);
}
return true;
}
bool bcache_write_bytes(struct bcache *cache, int fd, uint64_t start, size_t len, void *data)
{
struct updater u;
u.cache = cache;
u.partial_fn = _write_partial;
u.whole_fn = _write_whole;
u.data = data;
return _update_bytes(&u, fd, start, len);
}
//----------------------------------------------------------------
static bool _zero_partial(struct updater *u, int fd, block_address bb, uint64_t offset, size_t len)
{
struct block *b;
if (!bcache_get(u->cache, fd, bb, GF_DIRTY, &b))
return false;
memset(((unsigned char *) b->data) + offset, 0, len);
bcache_put(b);
return true;
}
static bool _zero_whole(struct updater *u, int fd, block_address bb, block_address be)
{
struct block *b;
for (; bb != be; bb++) {
if (!bcache_get(u->cache, fd, bb, GF_ZERO, &b))
return false;
bcache_put(b);
}
return true;
}
bool bcache_zero_bytes(struct bcache *cache, int fd, uint64_t start, size_t len)
{
struct updater u;
u.cache = cache;
u.partial_fn = _zero_partial;
u.whole_fn = _zero_whole;
u.data = NULL;
return _update_bytes(&u, fd, start, len);
}
//----------------------------------------------------------------
static bool _set_partial(struct updater *u, int fd, block_address bb, uint64_t offset, size_t len)
{
struct block *b;
uint8_t val = *((uint8_t *) u->data);
if (!bcache_get(u->cache, fd, bb, GF_DIRTY, &b))
return false;
memset(((unsigned char *) b->data) + offset, val, len);
bcache_put(b);
return true;
}
static bool _set_whole(struct updater *u, int fd, block_address bb, block_address be)
{
struct block *b;
uint8_t val = *((uint8_t *) u->data);
uint64_t len = bcache_block_sectors(u->cache) * 512;
for (; bb != be; bb++) {
if (!bcache_get(u->cache, fd, bb, GF_ZERO, &b))
return false;
memset((unsigned char *) b->data, val, len);
bcache_put(b);
}
return true;
}
bool bcache_set_bytes(struct bcache *cache, int fd, uint64_t start, size_t len, uint8_t val)
{
struct updater u;
u.cache = cache;
u.partial_fn = _set_partial;
u.whole_fn = _set_whole;
u.data = &val;
return _update_bytes(&u, fd, start, len);
}

1147
lib/device/bcache.c Normal file

File diff suppressed because it is too large Load Diff

163
lib/device/bcache.h Normal file
View File

@@ -0,0 +1,163 @@
/*
* 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,
* 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 BCACHE_H
#define BCACHE_H
#include "libdevmapper.h"
#include <linux/fs.h>
#include <stdint.h>
#include <stdbool.h>
/*----------------------------------------------------------------*/
// FIXME: move somewhere more sensible
#define container_of(v, t, head) \
((t *)((const char *)(v) - (const char *)&((t *) 0)->head))
/*----------------------------------------------------------------*/
enum dir {
DIR_READ,
DIR_WRITE
};
typedef uint64_t block_address;
typedef uint64_t sector_t;
typedef void io_complete_fn(void *context, int io_error);
struct io_engine {
void (*destroy)(struct io_engine *e);
bool (*issue)(struct io_engine *e, enum dir d, int fd,
sector_t sb, sector_t se, void *data, void *context);
bool (*wait)(struct io_engine *e, io_complete_fn fn);
unsigned (*max_io)(struct io_engine *e);
};
struct io_engine *create_async_io_engine(void);
struct io_engine *create_sync_io_engine(void);
/*----------------------------------------------------------------*/
struct bcache;
struct block {
/* clients may only access these three fields */
int fd;
uint64_t index;
void *data;
struct bcache *cache;
struct dm_list list;
struct dm_list hash;
unsigned flags;
unsigned ref_count;
int error;
enum dir io_dir;
};
/*
* Ownership of engine passes. Engine will be destroyed even if this fails.
*/
struct bcache *bcache_create(sector_t block_size, unsigned nr_cache_blocks,
struct io_engine *engine);
void bcache_destroy(struct bcache *cache);
enum bcache_get_flags {
/*
* The block will be zeroed before get_block returns it. This
* potentially avoids a read if the block is not already in the cache.
* GF_DIRTY is implicit.
*/
GF_ZERO = (1 << 0),
/*
* Indicates the caller is intending to change the data in the block, a
* writeback will occur after the block is released.
*/
GF_DIRTY = (1 << 1)
};
sector_t bcache_block_sectors(struct bcache *cache);
unsigned bcache_nr_cache_blocks(struct bcache *cache);
unsigned bcache_max_prefetches(struct bcache *cache);
/*
* Use the prefetch method to take advantage of asynchronous IO. For example,
* if you wanted to read a block from many devices concurrently you'd do
* something like this:
*
* dm_list_iterate_items (dev, &devices)
* bcache_prefetch(cache, dev->fd, block);
*
* dm_list_iterate_items (dev, &devices) {
* if (!bcache_get(cache, dev->fd, block, &b))
* fail();
*
* process_block(b);
* }
*
* It's slightly sub optimal, since you may not run the gets in the order that
* they complete. But we're talking a very small difference, and it's worth it
* to keep callbacks out of this interface.
*/
void bcache_prefetch(struct bcache *cache, int fd, block_address index);
/*
* Returns true on success.
*/
bool bcache_get(struct bcache *cache, int fd, block_address index,
unsigned flags, struct block **result);
void bcache_put(struct block *b);
/*
* flush() does not attempt to writeback locked blocks. flush will fail
* (return false), if any unlocked dirty data cannot be written back.
*/
bool bcache_flush(struct bcache *cache);
/*
* Removes a block from the cache.
*
* If the block is dirty it will be written back first. If the writeback fails
* false will be returned.
*
* If the block is currently held false will be returned.
*/
bool bcache_invalidate(struct bcache *cache, int fd, block_address index);
/*
* Invalidates all blocks on the given descriptor. Call this before closing
* the descriptor to make sure everything is written back.
*/
bool bcache_invalidate_fd(struct bcache *cache, int fd);
//----------------------------------------------------------------
// The next four functions are utilities written in terms of the above api.
// Prefetches the blocks neccessary to satisfy a byte range.
void bcache_prefetch_bytes(struct bcache *cache, int fd, uint64_t start, size_t len);
// Reads, writes and zeroes bytes. Returns false if errors occur.
bool bcache_read_bytes(struct bcache *cache, int fd, uint64_t start, size_t len, void *data);
bool bcache_write_bytes(struct bcache *cache, int fd, uint64_t start, size_t len, void *data);
bool bcache_zero_bytes(struct bcache *cache, int fd, uint64_t start, size_t len);
bool bcache_set_bytes(struct bcache *cache, int fd, uint64_t start, size_t len, uint8_t val);
//----------------------------------------------------------------
#endif

View File

@@ -73,7 +73,6 @@ static void _dev_init(struct device *dev, int max_error_count)
dev->ext.src = DEV_EXT_NONE;
dm_list_init(&dev->aliases);
dm_list_init(&dev->open_list);
}
void dev_destroy_file(struct device *dev)
@@ -275,10 +274,8 @@ static int _compare_paths(const char *path0, const char *path1)
if (slash1 < slash0)
return 1;
strncpy(p0, path0, sizeof(p0) - 1);
p0[sizeof(p0) - 1] = '\0';
strncpy(p1, path1, sizeof(p1) - 1);
p1[sizeof(p1) - 1] = '\0';
(void) dm_strncpy(p0, path0, sizeof(p0));
(void) dm_strncpy(p1, path1, sizeof(p1));
s0 = p0 + 1;
s1 = p1 + 1;
@@ -336,10 +333,8 @@ static int _add_alias(struct device *dev, const char *path)
/* Is name already there? */
dm_list_iterate_items(strl, &dev->aliases) {
if (!strcmp(strl->str, path)) {
log_debug_devs("%s: Already in device cache", path);
if (!strcmp(strl->str, path))
return 1;
}
}
sl->str = path;
@@ -347,13 +342,7 @@ static int _add_alias(struct device *dev, const char *path)
if (!dm_list_empty(&dev->aliases)) {
oldpath = dm_list_item(dev->aliases.n, struct dm_str_list)->str;
prefer_old = _compare_paths(path, oldpath);
log_debug_devs("%s: Aliased to %s in device cache%s (%d:%d)",
path, oldpath, prefer_old ? "" : " (preferred name)",
(int) MAJOR(dev->dev), (int) MINOR(dev->dev));
} else
log_debug_devs("%s: Added to device cache (%d:%d)", path,
(int) MAJOR(dev->dev), (int) MINOR(dev->dev));
}
if (prefer_old)
dm_list_add(&dev->aliases, &sl->list);
@@ -669,6 +658,29 @@ struct dm_list *dev_cache_get_dev_list_for_lvid(const char *lvid)
return dm_hash_lookup(_cache.lvid_index, lvid);
}
/*
* Scanning code calls this when it fails to open a device using
* this path. The path is dropped from dev-cache. In the next
* dev_cache_scan it may be added again, but it could be for a
* different device.
*/
void dev_cache_failed_path(struct device *dev, const char *path)
{
struct device *dev_by_path;
struct dm_str_list *strl;
if ((dev_by_path = (struct device *) dm_hash_lookup(_cache.names, path)))
dm_hash_remove(_cache.names, path);
dm_list_iterate_items(strl, &dev->aliases) {
if (!strcmp(strl->str, path)) {
dm_list_del(&strl->list);
break;
}
}
}
/*
* Either creates a new dev, or adds an alias to
* an existing dev.
@@ -676,6 +688,8 @@ struct dm_list *dev_cache_get_dev_list_for_lvid(const char *lvid)
static int _insert_dev(const char *path, dev_t d)
{
struct device *dev;
struct device *dev_by_devt;
struct device *dev_by_path;
static dev_t loopfile_count = 0;
int loopfile = 0;
char *path_copy;
@@ -688,8 +702,26 @@ static int _insert_dev(const char *path, dev_t d)
loopfile = 1;
}
/* is this device already registered ? */
if (!(dev = (struct device *) btree_lookup(_cache.devices, (uint32_t) d))) {
dev_by_devt = (struct device *) btree_lookup(_cache.devices, (uint32_t) d);
dev_by_path = (struct device *) dm_hash_lookup(_cache.names, path);
dev = dev_by_devt;
/*
* Existing device, existing path points to the same device.
*/
if (dev_by_devt && dev_by_path && (dev_by_devt == dev_by_path)) {
log_debug_devs("Found dev %d:%d %s - exists. %.8s",
(int)MAJOR(d), (int)MINOR(d), path, dev->pvid);
return 1;
}
/*
* No device or path found, add devt to cache.devices, add name to cache.names.
*/
if (!dev_by_devt && !dev_by_path) {
log_debug_devs("Found dev %d:%d %s - new.",
(int)MAJOR(d), (int)MINOR(d), path);
if (!(dev = (struct device *) btree_lookup(_cache.sysfs_only_devices, (uint32_t) d))) {
/* create new device */
if (loopfile) {
@@ -704,30 +736,126 @@ static int _insert_dev(const char *path, dev_t d)
_free(dev);
return 0;
}
}
if (dm_hash_lookup(_cache.names, path) == dev) {
/* Hash already has matching entry present */
log_debug("Path already cached %s.", path);
if (!(path_copy = dm_pool_strdup(_cache.mem, path))) {
log_error("Failed to duplicate path string.");
return 0;
}
if (!loopfile && !_add_alias(dev, path_copy)) {
log_error("Couldn't add alias to dev cache.");
return 0;
}
if (!dm_hash_insert(_cache.names, path_copy, dev)) {
log_error("Couldn't add name to hash in dev cache.");
return 0;
}
return 1;
}
if (!(path_copy = dm_pool_strdup(_cache.mem, path))) {
log_error("Failed to duplicate path string.");
return 0;
/*
* Existing device, path is new, add path as a new alias for the device.
*/
if (dev_by_devt && !dev_by_path) {
log_debug_devs("Found dev %d:%d %s - new alias.",
(int)MAJOR(d), (int)MINOR(d), path);
if (!(path_copy = dm_pool_strdup(_cache.mem, path))) {
log_error("Failed to duplicate path string.");
return 0;
}
if (!loopfile && !_add_alias(dev, path_copy)) {
log_error("Couldn't add alias to dev cache.");
return 0;
}
if (!dm_hash_insert(_cache.names, path_copy, dev)) {
log_error("Couldn't add name to hash in dev cache.");
return 0;
}
return 1;
}
if (!loopfile && !_add_alias(dev, path_copy)) {
log_error("Couldn't add alias to dev cache.");
return 0;
/*
* No existing device, but path exists and previously pointed
* to a different device.
*/
if (!dev_by_devt && dev_by_path) {
log_debug_devs("Found dev %d:%d %s - new device, path was previously %d:%d.",
(int)MAJOR(d), (int)MINOR(d), path,
(int)MAJOR(dev_by_path->dev), (int)MINOR(dev_by_path->dev));
if (!(dev = (struct device *) btree_lookup(_cache.sysfs_only_devices, (uint32_t) d))) {
/* create new device */
if (loopfile) {
if (!(dev = dev_create_file(path, NULL, NULL, 0)))
return_0;
} else if (!(dev = _dev_create(d)))
return_0;
}
if (!(btree_insert(_cache.devices, (uint32_t) d, dev))) {
log_error("Couldn't insert device into binary tree.");
_free(dev);
return 0;
}
if (!(path_copy = dm_pool_strdup(_cache.mem, path))) {
log_error("Failed to duplicate path string.");
return 0;
}
if (!loopfile && !_add_alias(dev, path_copy)) {
log_error("Couldn't add alias to dev cache.");
return 0;
}
dm_hash_remove(_cache.names, path);
if (!dm_hash_insert(_cache.names, path_copy, dev)) {
log_error("Couldn't add name to hash in dev cache.");
return 0;
}
return 1;
}
if (!dm_hash_insert(_cache.names, path_copy, dev)) {
log_error("Couldn't add name to hash in dev cache.");
return 0;
/*
* Existing device, and path exists and previously pointed to
* a different device.
*/
if (dev_by_devt && dev_by_path) {
log_debug_devs("Found dev %d:%d %s - existing device, path was previously %d:%d.",
(int)MAJOR(d), (int)MINOR(d), path,
(int)MAJOR(dev_by_path->dev), (int)MINOR(dev_by_path->dev));
if (!(path_copy = dm_pool_strdup(_cache.mem, path))) {
log_error("Failed to duplicate path string.");
return 0;
}
if (!loopfile && !_add_alias(dev, path_copy)) {
log_error("Couldn't add alias to dev cache.");
return 0;
}
dm_hash_remove(_cache.names, path);
if (!dm_hash_insert(_cache.names, path_copy, dev)) {
log_error("Couldn't add name to hash in dev cache.");
return 0;
}
return 1;
}
return 1;
log_error("Found dev %d:%d %s - failed to use.", (int)MAJOR(d), (int)MINOR(d), path);
return 0;
}
static char *_join(const char *dir, const char *name)
@@ -939,12 +1067,20 @@ static int _insert_udev_dir(struct udev *udev, const char *dir)
struct udev_device *device;
int r = 1;
if (!(udev_enum = udev_enumerate_new(udev)))
goto bad;
if (!(udev_enum = udev_enumerate_new(udev))) {
log_error("Failed to udev_enumerate_new.");
return 0;
}
if (udev_enumerate_add_match_subsystem(udev_enum, "block") ||
udev_enumerate_scan_devices(udev_enum))
goto bad;
if (udev_enumerate_add_match_subsystem(udev_enum, "block")) {
log_error("Failed to udev_enumerate_add_match_subsystem.");
goto out;
}
if (udev_enumerate_scan_devices(udev_enum)) {
log_error("Failed to udev_enumerate_scan_devices.");
goto out;
}
/*
* Report any missing information as "log_very_verbose" only, do not
@@ -981,13 +1117,10 @@ static int _insert_udev_dir(struct udev *udev, const char *dir)
udev_device_unref(device);
}
out:
udev_enumerate_unref(udev_enum);
return r;
bad:
log_error("Failed to enumerate udev device list.");
udev_enumerate_unref(udev_enum);
return 0;
return r;
}
static void _insert_dirs(struct dm_list *dirs)
@@ -1062,10 +1195,8 @@ static int _insert(const char *path, const struct stat *info,
if (rec && !_insert_dir(path))
return_0;
} else { /* add a device */
if (!S_ISBLK(info->st_mode)) {
log_debug_devs("%s: Not a block device", path);
if (!S_ISBLK(info->st_mode))
return 1;
}
if (!_insert_dev(path, info->st_rdev))
return_0;
@@ -1074,12 +1205,13 @@ static int _insert(const char *path, const struct stat *info,
return 1;
}
static void _full_scan(int dev_scan)
void dev_cache_scan(void)
{
struct dir_list *dl;
log_debug_devs("Creating list of system devices.");
if (_cache.has_scanned && !dev_scan)
return;
_cache.has_scanned = 1;
_insert_dirs(&_cache.dirs);
@@ -1087,9 +1219,6 @@ static void _full_scan(int dev_scan)
dm_list_iterate_items(dl, &_cache.files)
_insert_file(dl->dir);
_cache.has_scanned = 1;
init_full_scan_done(1);
}
int dev_cache_has_scanned(void)
@@ -1097,14 +1226,6 @@ int dev_cache_has_scanned(void)
return _cache.has_scanned;
}
void dev_cache_scan(int do_scan)
{
if (!do_scan)
_cache.has_scanned = 1;
else
_full_scan(1);
}
static int _init_preferred_names(struct cmd_context *cmd)
{
const struct dm_config_node *cn;
@@ -1168,7 +1289,6 @@ out:
int dev_cache_init(struct cmd_context *cmd)
{
_cache.names = NULL;
_cache.has_scanned = 0;
if (!(_cache.mem = dm_pool_create("dev_cache", 10 * 1024)))
return_0;
@@ -1370,11 +1490,25 @@ const char *dev_name_confirmed(struct device *dev, int quiet)
return dev_name(dev);
}
/* Provide a custom reason when a device is ignored */
const char *dev_cache_filtered_reason(const char *name)
{
const char *reason = "not found";
struct device *d = (struct device *) dm_hash_lookup(_cache.names, name);
if (d)
/* FIXME Record which filter caused the exclusion */
reason = "excluded by a filter";
return reason;
}
struct device *dev_cache_get(const char *name, struct dev_filter *f)
{
struct stat buf;
struct device *d = (struct device *) dm_hash_lookup(_cache.names, name);
int info_available = 0;
int ret = 1;
if (d && (d->flags & DEV_REGULAR))
return d;
@@ -1397,15 +1531,30 @@ struct device *dev_cache_get(const char *name, struct dev_filter *f)
_insert(name, info_available ? &buf : NULL, 0, obtain_device_list_from_udev());
d = (struct device *) dm_hash_lookup(_cache.names, name);
if (!d) {
_full_scan(0);
dev_cache_scan();
d = (struct device *) dm_hash_lookup(_cache.names, name);
}
}
if (!d || (f && !(d->flags & DEV_REGULAR) && !(f->passes_filter(f, d))))
if (!d)
return NULL;
if (d && (d->flags & DEV_REGULAR))
return d;
if (f && !(d->flags & DEV_REGULAR)) {
ret = f->passes_filter(f, d);
if (ret == -EAGAIN) {
log_debug_devs("get device by name defer filter %s", dev_name(d));
d->flags |= DEV_FILTER_AFTER_SCAN;
ret = 1;
}
}
if (f && !(d->flags & DEV_REGULAR) && !ret)
return NULL;
log_debug_devs("Using %s", dev_name(d));
return d;
}
@@ -1432,6 +1581,7 @@ struct device *dev_cache_get_by_devt(dev_t dev, struct dev_filter *f)
const char *sysfs_dir;
struct stat info;
struct device *d = _dev_cache_seek_devt(dev);
int ret;
if (d && (d->flags & DEV_REGULAR))
return d;
@@ -1447,31 +1597,40 @@ struct device *dev_cache_get_by_devt(dev_t dev, struct dev_filter *f)
}
if (lstat(path, &info)) {
log_debug("No sysfs entry for %d:%d.",
(int)MAJOR(dev), (int)MINOR(dev));
log_debug("No sysfs entry for %d:%d errno %d at %s.",
(int)MAJOR(dev), (int)MINOR(dev), errno, path);
return NULL;
}
}
_full_scan(0);
dev_cache_scan();
d = _dev_cache_seek_devt(dev);
}
return (d && (!f || (d->flags & DEV_REGULAR) ||
f->passes_filter(f, d))) ? d : NULL;
if (!d)
return NULL;
if (d->flags & DEV_REGULAR)
return d;
if (!f)
return d;
ret = f->passes_filter(f, d);
if (ret == -EAGAIN) {
log_debug_devs("get device by number defer filter %s", dev_name(d));
d->flags |= DEV_FILTER_AFTER_SCAN;
ret = 1;
}
if (ret)
return d;
return NULL;
}
void dev_cache_full_scan(struct dev_filter *f)
{
if (f && f->wipe) {
f->wipe(f); /* might call _full_scan(1) */
if (!full_scan_done())
_full_scan(1);
} else
_full_scan(1);
}
struct dev_iter *dev_iter_create(struct dev_filter *f, int dev_scan)
struct dev_iter *dev_iter_create(struct dev_filter *f, int unused)
{
struct dev_iter *di = dm_malloc(sizeof(*di));
@@ -1480,13 +1639,6 @@ struct dev_iter *dev_iter_create(struct dev_filter *f, int dev_scan)
return NULL;
}
if (dev_scan && !trust_cache()) {
/* Flag gets reset between each command */
if (!full_scan_done())
dev_cache_full_scan(f);
} else
_full_scan(0);
di->current = btree_first(_cache.devices);
di->filter = f;
if (di->filter)
@@ -1511,13 +1663,27 @@ static struct device *_iter_next(struct dev_iter *iter)
struct device *dev_iter_get(struct dev_iter *iter)
{
struct dev_filter *f;
int ret;
while (iter->current) {
struct device *d = _iter_next(iter);
if (!iter->filter || (d->flags & DEV_REGULAR) ||
iter->filter->passes_filter(iter->filter, d)) {
log_debug_devs("Using %s", dev_name(d));
return d;
ret = 1;
f = iter->filter;
if (f && !(d->flags & DEV_REGULAR)) {
ret = f->passes_filter(f, d);
if (ret == -EAGAIN) {
log_debug_devs("get device by iter defer filter %s", dev_name(d));
d->flags |= DEV_FILTER_AFTER_SCAN;
ret = 1;
}
}
if (!f || (d->flags & DEV_REGULAR) || ret)
return d;
}
return NULL;

View File

@@ -46,15 +46,14 @@ int dev_cache_exit(void);
*/
int dev_cache_check_for_open_devices(void);
/* Trigger(1) or avoid(0) a scan */
void dev_cache_scan(int do_scan);
void dev_cache_scan(void);
int dev_cache_has_scanned(void);
void dev_cache_full_scan(struct dev_filter *f);
int dev_cache_add_dir(const char *path);
int dev_cache_add_loopfile(const char *path);
__attribute__((nonnull(1)))
struct device *dev_cache_get(const char *name, struct dev_filter *f);
const char *dev_cache_filtered_reason(const char *name);
// TODO
struct device *dev_cache_get_by_devt(dev_t device, struct dev_filter *f);
@@ -65,10 +64,12 @@ void dev_set_preferred_name(struct dm_str_list *sl, struct device *dev);
* Object for iterating through the cache.
*/
struct dev_iter;
struct dev_iter *dev_iter_create(struct dev_filter *f, int dev_scan);
struct dev_iter *dev_iter_create(struct dev_filter *f, int unused);
void dev_iter_destroy(struct dev_iter *iter);
struct device *dev_iter_get(struct dev_iter *iter);
void dev_reset_error_count(struct cmd_context *cmd);
void dev_cache_failed_path(struct device *dev, const char *path);
#endif

View File

@@ -100,8 +100,6 @@ const char *dev_ext_name(struct device *dev)
return _ext_registry[dev->ext.src].name;
}
static const char *_ext_attached_msg = "External handle attached to device";
struct dev_ext *dev_ext_get(struct device *dev)
{
struct dev_ext *ext;
@@ -110,10 +108,10 @@ struct dev_ext *dev_ext_get(struct device *dev)
handle_ptr = dev->ext.handle;
if (!(ext = _ext_registry[dev->ext.src].dev_ext_get(dev)))
log_error("Failed to get external handle for device %s [%s].",
log_error("%s: Failed to get external handle [%s].",
dev_name(dev), dev_ext_name(dev));
else if (handle_ptr != dev->ext.handle)
log_debug_devs("%s %s [%s:%p]", _ext_attached_msg, dev_name(dev),
log_debug_devs("%s: External handle [%s:%p] attached", dev_name(dev),
dev_ext_name(dev), dev->ext.handle);
return ext;
@@ -131,10 +129,10 @@ int dev_ext_release(struct device *dev)
handle_ptr = dev->ext.handle;
if (!(r = _ext_registry[dev->ext.src].dev_ext_release(dev)))
log_error("Failed to release external handle for device %s [%s:%p].",
log_error("%s: Failed to release external handle [%s:%p]",
dev_name(dev), dev_ext_name(dev), dev->ext.handle);
else
log_debug_devs("External handle detached from device %s [%s:%p]",
log_debug_devs("%s: External handle [%s:%p] detached",
dev_name(dev), dev_ext_name(dev), handle_ptr);
return r;
@@ -143,7 +141,7 @@ int dev_ext_release(struct device *dev)
int dev_ext_enable(struct device *dev, dev_ext_t src)
{
if (dev->ext.enabled && (dev->ext.src != src) && !dev_ext_release(dev)) {
log_error("Failed to enable external handle for device %s [%s].",
log_error("%s: Failed to enable external handle [%s].",
dev_name(dev), _ext_registry[src].name);
return 0;
}
@@ -160,7 +158,7 @@ int dev_ext_disable(struct device *dev)
return 1;
if (!dev_ext_release(dev)) {
log_error("Failed to disable external handle for device %s [%s].",
log_error("%s: Failed to disable external handle [%s].",
dev_name(dev), dev_ext_name(dev));
return 0;
}

View File

@@ -16,7 +16,6 @@
#include "lib.h"
#include "device.h"
#include "metadata.h"
#include "lvmcache.h"
#include "memlock.h"
#include "locking.h"
@@ -53,14 +52,31 @@
# endif
#endif
static DM_LIST_INIT(_open_devices);
static unsigned _dev_size_seqno = 1;
static const char *_reasons[] = {
"dev signatures",
"PV labels",
"VG metadata header",
"VG metadata content",
"extra VG metadata header",
"extra VG metadata content",
"LVM1 metadata",
"pool metadata",
"LV content",
"logging",
};
static const char *_reason_text(dev_io_reason_t reason)
{
return _reasons[(unsigned) reason];
}
/*-----------------------------------------------------------------
* The standard io loop that keeps submitting an io until it's
* all gone.
*---------------------------------------------------------------*/
static int _io(struct device_area *where, char *buffer, int should_write)
static int _io(struct device_area *where, char *buffer, int should_write, dev_io_reason_t reason)
{
int fd = dev_fd(where->dev);
ssize_t n = 0;
@@ -72,6 +88,11 @@ static int _io(struct device_area *where, char *buffer, int should_write)
return 0;
}
log_debug_io("%s %s:%8" PRIu64 " bytes (sync) at %" PRIu64 "%s (for %s)",
should_write ? "Write" : "Read ", dev_name(where->dev),
where->size, (uint64_t) where->start,
(should_write && test_mode()) ? " (test mode - suppressed)" : "", _reason_text(reason));
/*
* Skip all writes in test mode.
*/
@@ -142,7 +163,7 @@ int dev_get_block_size(struct device *dev, unsigned int *physical_block_size, un
r = 0;
goto out;
}
log_debug_devs("%s: block size is %u bytes", name, dev->block_size);
log_debug_devs("%s: Block size is %u bytes", name, dev->block_size);
}
#ifdef BLKPBSZGET
@@ -153,7 +174,7 @@ int dev_get_block_size(struct device *dev, unsigned int *physical_block_size, un
r = 0;
goto out;
}
log_debug_devs("%s: physical block size is %u bytes", name, dev->phys_block_size);
log_debug_devs("%s: Physical block size is %u bytes", name, dev->phys_block_size);
}
#elif defined (BLKSSZGET)
/* if we can't get physical block size, just use logical block size instead */
@@ -163,22 +184,20 @@ int dev_get_block_size(struct device *dev, unsigned int *physical_block_size, un
r = 0;
goto out;
}
log_debug_devs("%s: physical block size can't be determined, using logical "
"block size of %u bytes", name, dev->phys_block_size);
log_debug_devs("%s: Physical block size can't be determined: Using logical block size of %u bytes", name, dev->phys_block_size);
}
#else
/* if even BLKSSZGET is not available, use default 512b */
if (dev->phys_block_size == -1) {
dev->phys_block_size = 512;
log_debug_devs("%s: physical block size can't be determined, using block "
"size of %u bytes instead", name, dev->phys_block_size);
log_debug_devs("%s: Physical block size can't be determined: Using block size of %u bytes instead", name, dev->phys_block_size);
}
#endif
*physical_block_size = (unsigned int) dev->phys_block_size;
*block_size = (unsigned int) dev->block_size;
out:
if (needs_open && !dev_close(dev))
if (needs_open && !dev_close_immediate(dev))
stack;
return r;
@@ -207,11 +226,12 @@ static void _widen_region(unsigned int block_size, struct device_area *region,
}
static int _aligned_io(struct device_area *where, char *buffer,
int should_write)
int should_write, dev_io_reason_t reason)
{
char *bounce, *bounce_buf;
unsigned int physical_block_size = 0;
unsigned int block_size = 0;
unsigned buffer_was_widened = 0;
uintptr_t mask;
struct device_area widened;
int r = 0;
@@ -222,14 +242,18 @@ static int _aligned_io(struct device_area *where, char *buffer,
if (!block_size)
block_size = lvm_getpagesize();
mask = block_size - 1;
_widen_region(block_size, where, &widened);
/* Do we need to use a bounce buffer? */
mask = block_size - 1;
if (!memcmp(where, &widened, sizeof(widened)) &&
!((uintptr_t) buffer & mask))
return _io(where, buffer, should_write);
/* Did we widen the buffer? When writing, this means means read-modify-write. */
if (where->size != widened.size || where->start != widened.start) {
buffer_was_widened = 1;
log_debug_io("Widening request for %" PRIu64 " bytes at %" PRIu64 " to %" PRIu64 " bytes at %" PRIu64 " on %s (for %s)",
where->size, (uint64_t) where->start, widened.size, (uint64_t) widened.start, dev_name(where->dev), _reason_text(reason));
} else if (!((uintptr_t) buffer & mask))
/* Perform the I/O directly. */
return _io(where, buffer, should_write, reason);
/* Allocate a bounce buffer with an extra block */
if (!(bounce_buf = bounce = dm_malloc((size_t) widened.size + block_size))) {
@@ -243,10 +267,12 @@ static int _aligned_io(struct device_area *where, char *buffer,
if (((uintptr_t) bounce) & mask)
bounce = (char *) ((((uintptr_t) bounce) + mask) & ~mask);
/* channel the io through the bounce buffer */
if (!_io(&widened, bounce, 0)) {
/* Do we need to read into the bounce buffer? */
if ((!should_write || buffer_was_widened) &&
!_io(&widened, bounce, 0, reason)) {
if (!should_write)
goto_out;
/* FIXME Handle errors properly! */
/* FIXME pre-extend the file */
memset(bounce, '\n', widened.size);
}
@@ -256,7 +282,7 @@ static int _aligned_io(struct device_area *where, char *buffer,
(size_t) where->size);
/* ... then we write */
if (!(r = _io(&widened, bounce, 1)))
if (!(r = _io(&widened, bounce, 1, reason)))
stack;
goto out;
@@ -302,6 +328,8 @@ static int _dev_get_size_file(struct device *dev, uint64_t *size)
static int _dev_get_size_dev(struct device *dev, uint64_t *size)
{
const char *name = dev_name(dev);
int fd = dev->bcache_fd;
int do_close = 0;
if (dev->size_seqno == _dev_size_seqno) {
log_very_verbose("%s: using cached size %" PRIu64 " sectors",
@@ -310,12 +338,16 @@ static int _dev_get_size_dev(struct device *dev, uint64_t *size)
return 1;
}
if (!dev_open_readonly(dev))
return_0;
if (fd <= 0) {
if (!dev_open_readonly(dev))
return_0;
fd = dev_fd(dev);
do_close = 1;
}
if (ioctl(dev_fd(dev), BLKGETSIZE64, size) < 0) {
if (ioctl(fd, BLKGETSIZE64, size) < 0) {
log_sys_error("ioctl BLKGETSIZE64", name);
if (!dev_close(dev))
if (do_close && !dev_close_immediate(dev))
log_sys_error("close", name);
return 0;
}
@@ -324,29 +356,35 @@ static int _dev_get_size_dev(struct device *dev, uint64_t *size)
dev->size = *size;
dev->size_seqno = _dev_size_seqno;
if (!dev_close(dev))
log_sys_error("close", name);
log_very_verbose("%s: size is %" PRIu64 " sectors", name, *size);
if (do_close && !dev_close_immediate(dev))
log_sys_error("close", name);
return 1;
}
static int _dev_read_ahead_dev(struct device *dev, uint32_t *read_ahead)
{
long read_ahead_long;
int fd = dev->bcache_fd;
int do_close = 0;
if (dev->read_ahead != -1) {
*read_ahead = (uint32_t) dev->read_ahead;
return 1;
}
if (!dev_open_readonly(dev))
return_0;
if (fd <= 0) {
if (!dev_open_readonly(dev))
return_0;
fd = dev_fd(dev);
do_close = 1;
}
if (ioctl(dev->fd, BLKRAGET, &read_ahead_long) < 0) {
if (ioctl(fd, BLKRAGET, &read_ahead_long) < 0) {
log_sys_error("ioctl BLKRAGET", dev_name(dev));
if (!dev_close(dev))
if (do_close && !dev_close_immediate(dev))
stack;
return 0;
}
@@ -357,8 +395,8 @@ static int _dev_read_ahead_dev(struct device *dev, uint32_t *read_ahead)
log_very_verbose("%s: read_ahead is %u sectors",
dev_name(dev), *read_ahead);
if (!dev_close(dev))
stack;
if (do_close && !dev_close_immediate(dev))
log_sys_error("close", dev_name(dev));
return 1;
}
@@ -373,18 +411,20 @@ static int _dev_discard_blocks(struct device *dev, uint64_t offset_bytes, uint64
discard_range[0] = offset_bytes;
discard_range[1] = size_bytes;
log_debug_devs("Discarding %" PRIu64 " bytes offset %" PRIu64 " bytes on %s.",
size_bytes, offset_bytes, dev_name(dev));
if (ioctl(dev->fd, BLKDISCARD, &discard_range) < 0) {
log_debug_devs("Discarding %" PRIu64 " bytes offset %" PRIu64 " bytes on %s. %s",
size_bytes, offset_bytes, dev_name(dev),
test_mode() ? " (test mode - suppressed)" : "");
if (!test_mode() && ioctl(dev->fd, BLKDISCARD, &discard_range) < 0) {
log_error("%s: BLKDISCARD ioctl at offset %" PRIu64 " size %" PRIu64 " failed: %s.",
dev_name(dev), offset_bytes, size_bytes, strerror(errno));
if (!dev_close(dev))
if (!dev_close_immediate(dev))
stack;
/* It doesn't matter if discard failed, so return success. */
return 1;
}
if (!dev_close(dev))
if (!dev_close_immediate(dev))
stack;
return 1;
@@ -463,11 +503,12 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet)
return 1;
}
if (dev->open_count && !need_excl) {
log_debug_devs("%s already opened read-only. Upgrading "
if (dev->open_count && !need_excl)
log_debug_devs("%s: Already opened read-only. Upgrading "
"to read-write.", dev_name(dev));
dev->open_count++;
}
/* dev_close_immediate will decrement this */
dev->open_count++;
dev_close_immediate(dev);
// FIXME: dev with DEV_ALLOCED is released
@@ -562,8 +603,6 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet)
if ((flags & O_CREAT) && !(flags & O_TRUNC))
dev->end = lseek(dev->fd, (off_t) 0, SEEK_END);
dm_list_add(&_open_devices, &dev->open_list);
log_debug_devs("Opened %s %s%s%s", dev_name(dev),
dev->flags & DEV_OPENED_RW ? "RW" : "RO",
dev->flags & DEV_OPENED_EXCL ? " O_EXCL" : "",
@@ -600,17 +639,12 @@ int dev_open_readonly_quiet(struct device *dev)
int dev_test_excl(struct device *dev)
{
int flags;
int r;
int flags = 0;
flags = vg_write_lock_held() ? O_RDWR : O_RDONLY;
flags |= O_EXCL;
flags |= O_RDWR;
r = dev_open_flags(dev, flags, 1, 1);
if (r)
dev_close_immediate(dev);
return r;
return dev_open_flags(dev, flags, 1, 1);
}
static void _close(struct device *dev)
@@ -620,7 +654,6 @@ static void _close(struct device *dev)
dev->fd = -1;
dev->phys_block_size = -1;
dev->block_size = -1;
dm_list_del(&dev->open_list);
log_debug_devs("Closed %s", dev_name(dev));
@@ -630,7 +663,6 @@ static void _close(struct device *dev)
static int _dev_close(struct device *dev, int immediate)
{
if (dev->fd < 0) {
log_error("Attempt to close device '%s' "
"which is not open.", dev_name(dev));
@@ -649,9 +681,7 @@ static int _dev_close(struct device *dev, int immediate)
log_debug_devs("%s: Immediate close attempt while still referenced",
dev_name(dev));
/* Close unless device is known to belong to a locked VG */
if (immediate ||
(dev->open_count < 1 && !lvmcache_pvid_is_locked(dev->pvid)))
if (immediate || (dev->open_count < 1))
_close(dev);
return 1;
@@ -667,18 +697,6 @@ int dev_close_immediate(struct device *dev)
return _dev_close(dev, 1);
}
void dev_close_all(void)
{
struct dm_list *doh, *doht;
struct device *dev;
dm_list_iterate_safe(doh, doht, &_open_devices) {
dev = dm_list_struct_base(doh, struct device, open_list);
if (dev->open_count < 1)
_close(dev);
}
}
static inline int _dev_is_valid(struct device *dev)
{
return (dev->max_error_count == NO_DEV_ERROR_COUNT_LIMIT ||
@@ -693,7 +711,7 @@ static void _dev_inc_error_count(struct device *dev)
dev->max_error_count, dev_name(dev));
}
int dev_read(struct device *dev, uint64_t offset, size_t len, void *buffer)
int dev_read(struct device *dev, uint64_t offset, size_t len, dev_io_reason_t reason, void *buffer)
{
struct device_area where;
int ret;
@@ -708,9 +726,7 @@ int dev_read(struct device *dev, uint64_t offset, size_t len, void *buffer)
where.start = offset;
where.size = len;
// fprintf(stderr, "READ: %s, %lld, %d\n", dev_name(dev), offset, len);
ret = _aligned_io(&where, buffer, 0);
ret = _aligned_io(&where, buffer, 0, reason);
if (!ret)
_dev_inc_error_count(dev);
@@ -723,9 +739,9 @@ int dev_read(struct device *dev, uint64_t offset, size_t len, void *buffer)
* 'buf' should be len+len2.
*/
int dev_read_circular(struct device *dev, uint64_t offset, size_t len,
uint64_t offset2, size_t len2, char *buf)
uint64_t offset2, size_t len2, dev_io_reason_t reason, char *buf)
{
if (!dev_read(dev, offset, len, buf)) {
if (!dev_read(dev, offset, len, reason, buf)) {
log_error("Read from %s failed", dev_name(dev));
return 0;
}
@@ -737,7 +753,7 @@ int dev_read_circular(struct device *dev, uint64_t offset, size_t len,
if (!len2)
return 1;
if (!dev_read(dev, offset2, len2, buf + len)) {
if (!dev_read(dev, offset2, len2, reason, buf + len)) {
log_error("Circular read from %s failed",
dev_name(dev));
return 0;
@@ -751,14 +767,14 @@ int dev_read_circular(struct device *dev, uint64_t offset, size_t len,
*/
/* FIXME pre-extend the file */
int dev_append(struct device *dev, size_t len, char *buffer)
int dev_append(struct device *dev, size_t len, dev_io_reason_t reason, char *buffer)
{
int r;
if (!dev->open_count)
return_0;
r = dev_write(dev, dev->end, len, buffer);
r = dev_write(dev, dev->end, len, reason, buffer);
dev->end += (uint64_t) len;
#ifndef O_DIRECT_SUPPORT
@@ -767,7 +783,7 @@ int dev_append(struct device *dev, size_t len, char *buffer)
return r;
}
int dev_write(struct device *dev, uint64_t offset, size_t len, void *buffer)
int dev_write(struct device *dev, uint64_t offset, size_t len, dev_io_reason_t reason, void *buffer)
{
struct device_area where;
int ret;
@@ -778,20 +794,25 @@ int dev_write(struct device *dev, uint64_t offset, size_t len, void *buffer)
if (!_dev_is_valid(dev))
return 0;
if (!len) {
log_error(INTERNAL_ERROR "Attempted to write 0 bytes to %s at " FMTu64, dev_name(dev), offset);
return 0;
}
where.dev = dev;
where.start = offset;
where.size = len;
dev->flags |= DEV_ACCESSED_W;
ret = _aligned_io(&where, buffer, 1);
ret = _aligned_io(&where, buffer, 1, reason);
if (!ret)
_dev_inc_error_count(dev);
return ret;
}
int dev_set(struct device *dev, uint64_t offset, size_t len, int value)
int dev_set(struct device *dev, uint64_t offset, size_t len, dev_io_reason_t reason, int value)
{
size_t s;
char buffer[4096] __attribute__((aligned(8)));
@@ -810,7 +831,7 @@ int dev_set(struct device *dev, uint64_t offset, size_t len, int value)
memset(buffer, value, sizeof(buffer));
while (1) {
s = len > sizeof(buffer) ? sizeof(buffer) : len;
if (!dev_write(dev, offset, s, buffer))
if (!dev_write(dev, offset, s, reason, buffer))
break;
len -= s;

View File

@@ -18,27 +18,22 @@
#define LUKS_SIGNATURE "LUKS\xba\xbe"
#define LUKS_SIGNATURE_SIZE 6
int dev_is_luks(struct device *dev, uint64_t *offset_found)
int dev_is_luks(struct device *dev, uint64_t *offset_found, int full)
{
char buf[LUKS_SIGNATURE_SIZE];
int ret = -1;
if (!dev_open_readonly(dev)) {
stack;
return -1;
}
if (!scan_bcache)
return -EAGAIN;
if (offset_found)
*offset_found = 0;
if (!dev_read(dev, 0, LUKS_SIGNATURE_SIZE, buf))
if (!dev_read_bytes(dev, 0, LUKS_SIGNATURE_SIZE, buf))
goto_out;
ret = memcmp(buf, LUKS_SIGNATURE, LUKS_SIGNATURE_SIZE) ? 0 : 1;
out:
if (!dev_close(dev))
stack;
return ret;
}

174
lib/device/dev-lvm1-pool.c Normal file
View File

@@ -0,0 +1,174 @@
/*
* 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,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "lib.h"
#include "dev-type.h"
#include "xlate.h"
/*
* These lvm1 structs just used NAME_LEN in the previous format1 lvm2 code, but
* NAME_LEN was defined as 128 in generic lvm2 code that was not lvm1-specific
* and not disk-format-specific.
*/
#define LVM1_NAME_LEN 128
struct data_area {
uint32_t base;
uint32_t size;
} __attribute__ ((packed));
struct pv_disk {
int8_t id[2];
uint16_t version; /* lvm version */
struct data_area pv_on_disk;
struct data_area vg_on_disk;
struct data_area pv_uuidlist_on_disk;
struct data_area lv_on_disk;
struct data_area pe_on_disk;
int8_t pv_uuid[LVM1_NAME_LEN];
int8_t vg_name[LVM1_NAME_LEN];
int8_t system_id[LVM1_NAME_LEN]; /* for vgexport/vgimport */
uint32_t pv_major;
uint32_t pv_number;
uint32_t pv_status;
uint32_t pv_allocatable;
uint32_t pv_size;
uint32_t lv_cur;
uint32_t pe_size;
uint32_t pe_total;
uint32_t pe_allocated;
/* only present on version == 2 pv's */
uint32_t pe_start;
} __attribute__ ((packed));
int dev_is_lvm1(struct device *dev, char *buf, int buflen)
{
struct pv_disk *pvd = (struct pv_disk *) buf;
uint32_t version;
int ret;
version = xlate16(pvd->version);
if (pvd->id[0] == 'H' && pvd->id[1] == 'M' &&
(version == 1 || version == 2))
ret = 1;
else
ret = 0;
return ret;
}
#define POOL_MAGIC 0x011670
#define POOL_NAME_SIZE 256
#define NSPMajorVersion 4
#define NSPMinorVersion 1
#define NSPUpdateLevel 3
/* When checking for version matching, the first two numbers **
** are important for metadata formats, a.k.a pool labels. **
** All the numbers are important when checking if the user **
** space tools match up with the kernel module............. */
#define POOL_VERSION (NSPMajorVersion << 16 | \
NSPMinorVersion << 8 | \
NSPUpdateLevel)
struct pool_disk {
uint64_t pl_magic; /* Pool magic number */
uint64_t pl_pool_id; /* Unique pool identifier */
char pl_pool_name[POOL_NAME_SIZE]; /* Name of pool */
uint32_t pl_version; /* Pool version */
uint32_t pl_subpools; /* Number of subpools in this pool */
uint32_t pl_sp_id; /* Subpool number within pool */
uint32_t pl_sp_devs; /* Number of data partitions in this subpool */
uint32_t pl_sp_devid; /* Partition number within subpool */
uint32_t pl_sp_type; /* Partition type */
uint64_t pl_blocks; /* Number of blocks in this partition */
uint32_t pl_striping; /* Striping size within subpool */
/*
* If the number of DMEP devices is zero, then the next field **
* ** (pl_sp_dmepid) becomes the subpool ID for redirection. In **
* ** other words, if this subpool does not have the capability **
* ** to do DMEP, then it must specify which subpool will do it **
* ** in it's place
*/
/*
* While the next 3 field are no longer used, they must stay to keep **
* ** backward compatibility...........................................
*/
uint32_t pl_sp_dmepdevs;/* Number of dmep devices in this subpool */
uint32_t pl_sp_dmepid; /* Dmep device number within subpool */
uint32_t pl_sp_weight; /* if dmep dev, pref to using it */
uint32_t pl_minor; /* the pool minor number */
uint32_t pl_padding; /* reminder - think about alignment */
/*
* Even though we're zeroing out 8k at the front of the disk before
* writing the label, putting this in
*/
char pl_reserve[184]; /* bump the structure size out to 512 bytes */
};
#define CPIN_8(x, y, z) {memcpy((x), (y), (z));}
#define CPIN_16(x, y) {(x) = xlate16_be((y));}
#define CPIN_32(x, y) {(x) = xlate32_be((y));}
#define CPIN_64(x, y) {(x) = xlate64_be((y));}
static void pool_label_in(struct pool_disk *pl, void *buf)
{
struct pool_disk *bufpl = (struct pool_disk *) buf;
CPIN_64(pl->pl_magic, bufpl->pl_magic);
CPIN_64(pl->pl_pool_id, bufpl->pl_pool_id);
CPIN_8(pl->pl_pool_name, bufpl->pl_pool_name, POOL_NAME_SIZE);
CPIN_32(pl->pl_version, bufpl->pl_version);
CPIN_32(pl->pl_subpools, bufpl->pl_subpools);
CPIN_32(pl->pl_sp_id, bufpl->pl_sp_id);
CPIN_32(pl->pl_sp_devs, bufpl->pl_sp_devs);
CPIN_32(pl->pl_sp_devid, bufpl->pl_sp_devid);
CPIN_32(pl->pl_sp_type, bufpl->pl_sp_type);
CPIN_64(pl->pl_blocks, bufpl->pl_blocks);
CPIN_32(pl->pl_striping, bufpl->pl_striping);
CPIN_32(pl->pl_sp_dmepdevs, bufpl->pl_sp_dmepdevs);
CPIN_32(pl->pl_sp_dmepid, bufpl->pl_sp_dmepid);
CPIN_32(pl->pl_sp_weight, bufpl->pl_sp_weight);
CPIN_32(pl->pl_minor, bufpl->pl_minor);
CPIN_32(pl->pl_padding, bufpl->pl_padding);
CPIN_8(pl->pl_reserve, bufpl->pl_reserve, 184);
}
int dev_is_pool(struct device *dev, char *buf, int buflen)
{
struct pool_disk pd;
int ret;
pool_label_in(&pd, buf);
/* can ignore 8 rightmost bits for ondisk format check */
if ((pd.pl_magic == POOL_MAGIC) &&
(pd.pl_version >> 8 == POOL_VERSION >> 8))
ret = 1;
else
ret = 0;
return ret;
}

View File

@@ -37,9 +37,12 @@ static int _dev_has_md_magic(struct device *dev, uint64_t sb_offset)
uint32_t md_magic;
/* Version 1 is little endian; version 0.90.0 is machine endian */
if (dev_read(dev, sb_offset, sizeof(uint32_t), &md_magic) &&
((md_magic == MD_SB_MAGIC) ||
((MD_SB_MAGIC != xlate32(MD_SB_MAGIC)) && (md_magic == xlate32(MD_SB_MAGIC)))))
if (!dev_read_bytes(dev, sb_offset, sizeof(uint32_t), &md_magic))
return_0;
if ((md_magic == MD_SB_MAGIC) ||
((MD_SB_MAGIC != xlate32(MD_SB_MAGIC)) && (md_magic == xlate32(MD_SB_MAGIC))))
return 1;
return 0;
@@ -109,11 +112,14 @@ static int _udev_dev_is_md(struct device *dev)
/*
* Returns -1 on error
*/
static int _native_dev_is_md(struct device *dev, uint64_t *offset_found)
static int _native_dev_is_md(struct device *dev, uint64_t *offset_found, int full)
{
int ret = 1;
md_minor_version_t minor;
uint64_t size, sb_offset;
int ret;
if (!scan_bcache)
return -EAGAIN;
if (!dev_get_size(dev, &size)) {
stack;
@@ -123,38 +129,73 @@ static int _native_dev_is_md(struct device *dev, uint64_t *offset_found)
if (size < MD_RESERVED_SECTORS * 2)
return 0;
if (!dev_open_readonly(dev)) {
stack;
return -1;
/*
* Old md versions locate the magic number at the end of the device.
* Those checks can't be satisfied with the initial bcache data, and
* would require an extra read i/o at the end of every device. Issuing
* an extra read to every device in every command, just to check for
* the old md format is a bad tradeoff.
*
* When "full" is set, we check a the start and end of the device for
* md magic numbers. When "full" is not set, we only check at the
* start of the device for the magic numbers. We decide for each
* command if it should do a full check (cmd->use_full_md_check),
* and set it for commands that could possibly write to an md dev
* (pvcreate/vgcreate/vgextend).
*
* For old md versions with magic numbers at the end of devices,
* the md dev components won't be filtered out here when full is 0,
* so they will be scanned, and appear as duplicate PVs in lvmcache.
* The md device itself will be chosen as the primary duplicate,
* and the components are dropped from the list of duplicates in,
* i.e. a kind of post-scan filtering.
*/
if (!full) {
sb_offset = 0;
if (_dev_has_md_magic(dev, sb_offset)) {
log_debug_devs("Found md magic number at offset 0 of %s.", dev_name(dev));
ret = 1;
goto out;
}
sb_offset = 8 << SECTOR_SHIFT;
if (_dev_has_md_magic(dev, sb_offset)) {
log_debug_devs("Found md magic number at offset %d of %s.", (int)sb_offset, dev_name(dev));
ret = 1;
goto out;
}
ret = 0;
goto out;
}
/* Check if it is an md component device. */
/* Version 0.90.0 */
sb_offset = MD_NEW_SIZE_SECTORS(size) << SECTOR_SHIFT;
if (_dev_has_md_magic(dev, sb_offset))
if (_dev_has_md_magic(dev, sb_offset)) {
ret = 1;
goto out;
}
minor = MD_MINOR_VERSION_MIN;
/* Version 1, try v1.0 -> v1.2 */
do {
sb_offset = _v1_sb_offset(size, minor);
if (_dev_has_md_magic(dev, sb_offset))
if (_dev_has_md_magic(dev, sb_offset)) {
ret = 1;
goto out;
}
} while (++minor <= MD_MINOR_VERSION_MAX);
ret = 0;
out:
if (!dev_close(dev))
stack;
if (ret && offset_found)
*offset_found = sb_offset;
return ret;
}
int dev_is_md(struct device *dev, uint64_t *offset_found)
int dev_is_md(struct device *dev, uint64_t *offset_found, int full)
{
/*
@@ -163,7 +204,7 @@ int dev_is_md(struct device *dev, uint64_t *offset_found)
* information is not in udev db.
*/
if ((dev->ext.src == DEV_EXT_NONE) || offset_found)
return _native_dev_is_md(dev, offset_found);
return _native_dev_is_md(dev, offset_found, full);
if (dev->ext.src == DEV_EXT_UDEV)
return _udev_dev_is_md(dev);
@@ -261,8 +302,7 @@ out:
/*
* Retrieve chunk size from md device using sysfs.
*/
static unsigned long dev_md_chunk_size(struct dev_types *dt,
struct device *dev)
static unsigned long _dev_md_chunk_size(struct dev_types *dt, struct device *dev)
{
const char *attribute = "chunk_size";
unsigned long chunk_size_bytes = 0UL;
@@ -280,7 +320,7 @@ static unsigned long dev_md_chunk_size(struct dev_types *dt,
/*
* Retrieve level from md device using sysfs.
*/
static int dev_md_level(struct dev_types *dt, struct device *dev)
static int _dev_md_level(struct dev_types *dt, struct device *dev)
{
char level_string[MD_MAX_SYSFS_SIZE];
const char *attribute = "level";
@@ -303,7 +343,7 @@ static int dev_md_level(struct dev_types *dt, struct device *dev)
/*
* Retrieve raid_disks from md device using sysfs.
*/
static int dev_md_raid_disks(struct dev_types *dt, struct device *dev)
static int _dev_md_raid_disks(struct dev_types *dt, struct device *dev)
{
const char *attribute = "raid_disks";
int raid_disks = 0;
@@ -327,15 +367,15 @@ unsigned long dev_md_stripe_width(struct dev_types *dt, struct device *dev)
unsigned long stripe_width_sectors = 0UL;
int level, raid_disks, data_disks;
chunk_size_sectors = dev_md_chunk_size(dt, dev);
chunk_size_sectors = _dev_md_chunk_size(dt, dev);
if (!chunk_size_sectors)
return 0;
level = dev_md_level(dt, dev);
level = _dev_md_level(dt, dev);
if (level < 0)
return 0;
raid_disks = dev_md_raid_disks(dt, dev);
raid_disks = _dev_md_raid_disks(dt, dev);
if (!raid_disks)
return 0;

View File

@@ -20,8 +20,7 @@
#define MAX_PAGESIZE (64 * 1024)
#define SIGNATURE_SIZE 10
static int
_swap_detect_signature(const char *buf)
static int _swap_detect_signature(const char *buf)
{
if (memcmp(buf, "SWAP-SPACE", 10) == 0 ||
memcmp(buf, "SWAPSPACE2", 10) == 0)
@@ -36,19 +35,17 @@ _swap_detect_signature(const char *buf)
return 0;
}
int dev_is_swap(struct device *dev, uint64_t *offset_found)
int dev_is_swap(struct device *dev, uint64_t *offset_found, int full)
{
char buf[10];
uint64_t size;
unsigned page;
int ret = 0;
if (!dev_get_size(dev, &size)) {
stack;
return -1;
}
if (!scan_bcache)
return -EAGAIN;
if (!dev_open_readonly(dev)) {
if (!dev_get_size(dev, &size)) {
stack;
return -1;
}
@@ -61,8 +58,7 @@ int dev_is_swap(struct device *dev, uint64_t *offset_found)
continue;
if (size < (page >> SECTOR_SHIFT))
break;
if (!dev_read(dev, page - SIGNATURE_SIZE,
SIGNATURE_SIZE, buf)) {
if (!dev_read_bytes(dev, page - SIGNATURE_SIZE, SIGNATURE_SIZE, buf)) {
ret = -1;
break;
}
@@ -74,9 +70,6 @@ int dev_is_swap(struct device *dev, uint64_t *offset_found)
}
}
if (!dev_close(dev))
stack;
return ret;
}

View File

@@ -17,6 +17,8 @@
#include "xlate.h"
#include "config.h"
#include "metadata.h"
#include "bcache.h"
#include "label.h"
#include <libgen.h>
#include <ctype.h>
@@ -213,6 +215,9 @@ int dev_subsystem_part_major(struct dev_types *dt, struct device *dev)
if (MAJOR(dev->dev) == dt->device_mapper_major)
return 1;
if (MAJOR(dev->dev) == dt->md_major)
return 1;
if (MAJOR(dev->dev) == dt->drbd_major)
return 1;
@@ -363,7 +368,7 @@ static int _has_partition_table(struct device *dev)
uint16_t magic;
} __attribute__((packed)) buf; /* sizeof() == SECTOR_SIZE */
if (!dev_read(dev, UINT64_C(0), sizeof(buf), &buf))
if (!dev_read_bytes(dev, UINT64_C(0), sizeof(buf), &buf))
return_0;
/* FIXME Check for other types of partition table too */
@@ -432,6 +437,9 @@ static int _native_dev_is_partitioned(struct dev_types *dt, struct device *dev)
{
int r;
if (!scan_bcache)
return -EAGAIN;
if (!_is_partitionable(dt, dev))
return 0;
@@ -439,17 +447,8 @@ static int _native_dev_is_partitioned(struct dev_types *dt, struct device *dev)
if ((MAJOR(dev->dev) == dt->dasd_major) && dasd_is_cdl_formatted(dev))
return 1;
if (!dev_open_readonly_quiet(dev)) {
log_debug_devs("%s: failed to open device, considering device "
"is partitioned", dev_name(dev));
return 1;
}
r = _has_partition_table(dev);
if (!dev_close(dev))
stack;
return r;
}
@@ -675,7 +674,7 @@ static int _blkid_wipe(blkid_probe probe, struct device *dev, const char *name,
} else
log_verbose(_msg_wiping, type, name);
if (!dev_set(dev, offset_value, len, 0)) {
if (!dev_write_zeros(dev, offset_value, len)) {
log_error("Failed to wipe %s signature on %s.", type, name);
return 0;
}
@@ -748,12 +747,12 @@ out:
static int _wipe_signature(struct device *dev, const char *type, const char *name,
int wipe_len, int yes, force_t force, int *wiped,
int (*signature_detection_fn)(struct device *dev, uint64_t *offset_found))
int (*signature_detection_fn)(struct device *dev, uint64_t *offset_found, int full))
{
int wipe;
uint64_t offset_found;
wipe = signature_detection_fn(dev, &offset_found);
wipe = signature_detection_fn(dev, &offset_found, 1);
if (wipe == -1) {
log_error("Fatal error while trying to detect %s on %s.",
type, name);
@@ -772,7 +771,7 @@ static int _wipe_signature(struct device *dev, const char *type, const char *nam
}
log_print_unless_silent("Wiping %s on %s.", type, name);
if (!dev_set(dev, offset_found, wipe_len, 0)) {
if (!dev_write_zeros(dev, offset_found, wipe_len)) {
log_error("Failed to wipe %s on %s.", type, name);
return 0;
}

View File

@@ -17,6 +17,7 @@
#include "device.h"
#include "display.h"
#include "label.h"
#define NUMBER_OF_MAJORS 4096
@@ -56,12 +57,15 @@ const char *dev_subsystem_name(struct dev_types *dt, struct device *dev);
int major_is_scsi_device(struct dev_types *dt, int major);
/* Signature/superblock recognition with position returned where found. */
int dev_is_md(struct device *dev, uint64_t *sb);
int dev_is_swap(struct device *dev, uint64_t *signature);
int dev_is_luks(struct device *dev, uint64_t *signature);
int dev_is_md(struct device *dev, uint64_t *sb, int full);
int dev_is_swap(struct device *dev, uint64_t *signature, int full);
int dev_is_luks(struct device *dev, uint64_t *signature, int full);
int dasd_is_cdl_formatted(struct device *dev);
int udev_dev_is_mpath_component(struct device *dev);
int dev_is_lvm1(struct device *dev, char *buf, int buflen);
int dev_is_pool(struct device *dev, char *buf, int buflen);
/* Signature wiping. */
#define TYPE_LVM1_MEMBER 0x001
#define TYPE_LVM2_MEMBER 0x002

View File

@@ -31,6 +31,11 @@
#define DEV_USED_FOR_LV 0x00000100 /* Is device used for an LV */
#define DEV_ASSUMED_FOR_LV 0x00000200 /* Is device assumed for an LV */
#define DEV_NOT_O_NOATIME 0x00000400 /* Don't use O_NOATIME */
#define DEV_IN_BCACHE 0x00000800 /* dev fd is open and used in bcache */
#define DEV_BCACHE_EXCL 0x00001000 /* bcache_fd should be open EXCL */
#define DEV_FILTER_AFTER_SCAN 0x00002000 /* apply filter after bcache has data */
#define DEV_FILTER_OUT_SCAN 0x00004000 /* filtered out during label scan */
#define DEV_BCACHE_WRITE 0x00008000 /* bcache_fd is open with RDWR */
/*
* Support for external device info.
@@ -65,12 +70,13 @@ struct device {
int phys_block_size;
int block_size;
int read_ahead;
int bcache_fd;
uint32_t flags;
unsigned size_seqno;
uint64_t size;
uint64_t end;
struct dm_list open_list;
struct dev_ext ext;
const char *duplicate_prefer_reason;
const char *vgid; /* if device is an LV */
const char *lvid; /* if device is an LV */
@@ -79,6 +85,22 @@ struct device {
char _padding[7];
};
/*
* All I/O is annotated with the reason it is performed.
*/
typedef enum dev_io_reason {
DEV_IO_SIGNATURES = 0, /* Scanning device signatures */
DEV_IO_LABEL, /* LVM PV disk label */
DEV_IO_MDA_HEADER, /* Text format metadata area header */
DEV_IO_MDA_CONTENT, /* Text format metadata area content */
DEV_IO_MDA_EXTRA_HEADER, /* Header of any extra metadata areas on device */
DEV_IO_MDA_EXTRA_CONTENT, /* Content of any extra metadata areas on device */
DEV_IO_FMT1, /* Original LVM1 metadata format */
DEV_IO_POOL, /* Pool metadata format */
DEV_IO_LV, /* Content written to an LV */
DEV_IO_LOG /* Logging messages */
} dev_io_reason_t;
struct device_list {
struct dm_list list;
struct device *dev;
@@ -123,18 +145,17 @@ int dev_open_readonly_buffered(struct device *dev);
int dev_open_readonly_quiet(struct device *dev);
int dev_close(struct device *dev);
int dev_close_immediate(struct device *dev);
void dev_close_all(void);
int dev_test_excl(struct device *dev);
int dev_fd(struct device *dev);
const char *dev_name(const struct device *dev);
int dev_read(struct device *dev, uint64_t offset, size_t len, void *buffer);
int dev_read(struct device *dev, uint64_t offset, size_t len, dev_io_reason_t reason, void *buffer);
int dev_read_circular(struct device *dev, uint64_t offset, size_t len,
uint64_t offset2, size_t len2, char *buf);
int dev_write(struct device *dev, uint64_t offset, size_t len, void *buffer);
int dev_append(struct device *dev, size_t len, char *buffer);
int dev_set(struct device *dev, uint64_t offset, size_t len, int value);
uint64_t offset2, size_t len2, dev_io_reason_t reason, char *buf);
int dev_write(struct device *dev, uint64_t offset, size_t len, dev_io_reason_t reason, void *buffer);
int dev_append(struct device *dev, size_t len, dev_io_reason_t reason, char *buffer);
int dev_set(struct device *dev, uint64_t offset, size_t len, dev_io_reason_t reason, int value);
void dev_flush(struct device *dev);
struct device *dev_create_file(const char *filename, struct device *dev,

View File

@@ -705,13 +705,10 @@ void vgdisplay_full(const struct volume_group *vg)
log_print("--- Volume group ---");
log_print("VG Name %s", vg->name);
log_print("System ID %s", (vg->system_id && *vg->system_id) ? vg->system_id : vg->lvm1_system_id ? : "");
log_print("System ID %s", (vg->system_id && *vg->system_id) ? vg->system_id : "");
log_print("Format %s", vg->fid->fmt->name);
if (vg->fid->fmt->features & FMT_MDAS) {
log_print("Metadata Areas %d",
vg_mda_count(vg));
log_print("Metadata Sequence No %d", vg->seqno);
}
log_print("Metadata Areas %d", vg_mda_count(vg));
log_print("Metadata Sequence No %d", vg->seqno);
access_str = vg->status & (LVM_READ | LVM_WRITE);
log_print("VG Access %s%s%s%s",
access_str == (LVM_READ | LVM_WRITE) ? "read/write" : "",

View File

@@ -15,14 +15,19 @@
#include "lib.h"
#include "filter.h"
#include "device.h"
static int _and_p(struct dev_filter *f, struct device *dev)
{
struct dev_filter **filters;
int ret;
for (filters = (struct dev_filter **) f->private; *filters; ++filters)
if (!(*filters)->passes_filter(*filters, dev))
for (filters = (struct dev_filter **) f->private; *filters; ++filters) {
ret = (*filters)->passes_filter(*filters, dev);
if (!ret)
return 0; /* No 'stack': a filter, not an error. */
}
return 1;
}

View File

@@ -74,7 +74,7 @@ struct dev_filter *internal_filter_create(void)
f->destroy = _destroy;
f->use_count = 0;
log_debug_devs("internal filter initialised.");
log_debug_devs("Internal filter initialised.");
return f;
}

View File

@@ -20,15 +20,88 @@
#define MSG_SKIPPING "%s: Skipping md component device"
static int _ignore_md(struct dev_filter *f __attribute__((unused)),
struct device *dev)
/*
* The purpose of these functions is to ignore md component devices,
* e.g. if /dev/md0 is a raid1 composed of /dev/loop0 and /dev/loop1,
* lvm wants to deal with md0 and ignore loop0 and loop1. md0 should
* pass the filter, and loop0,loop1 should not pass the filter so lvm
* will ignore them.
*
* (This is assuming lvm.conf md_component_detection=1.)
*
* If lvm does *not* ignore the components, then lvm will read lvm
* labels from the md dev and from the component devs, and will see
* them all as duplicates of each other. LVM duplicate resolution
* will then kick in and keep the md dev around to use and ignore
* the components.
*
* It is better to exclude the components as early as possible during
* lvm processing, ideally before lvm even looks for labels on the
* components, so that duplicate resolution can be avoided. There are
* a number of ways that md components can be excluded earlier than
* the duplicate resolution phase:
*
* - When external_device_info_source="udev", lvm discovers a device is
* an md component by asking udev during the initial filtering phase.
* However, lvm's default is to not use udev for this. The
* alternative is "native" detection in which lvm tries to detect
* md components itself.
*
* - When using native detection, lvm's md filter looks for the md
* superblock at the start of devices. It will see the md superblock
* on the components, exclude them in the md filter, and avoid
* handling them later in duplicate resolution.
*
* - When using native detection, lvm's md filter will not detect
* components when the md device has an older superblock version that
* places the superblock at the end of the device. This case will
* fall back to duplicate resolution to exclude components.
*
* A variation of the description above occurs for lvm commands that
* intend to create new PVs on devices (pvcreate, vgcreate, vgextend).
* For these commands, the native md filter also reads the end of all
* devices to check for the odd md superblocks.
*
* (The reason that external_device_info_source is not set to udev by
* default is that there have be issues with udev not being promptly
* or reliably updated about md state changes, causing the udev info
* that lvm uses to be occasionally wrong.)
*/
/*
* Returns 0 if:
* the device is an md component and it should be ignored.
*
* Returns 1 if:
* the device is not md component and should not be ignored.
*
* The actual md device will pass this filter and should be used,
* it is the md component devices that we are trying to exclude
* that will not pass.
*/
static int _passes_md_filter(struct device *dev, int full)
{
int ret;
/*
* When md_component_dectection=0, don't even try to skip md
* components.
*/
if (!md_filtering())
return 1;
ret = dev_is_md(dev, NULL);
ret = dev_is_md(dev, NULL, full);
if (ret == -EAGAIN) {
/* let pass, call again after scan */
dev->flags |= DEV_FILTER_AFTER_SCAN;
log_debug_devs("filter md deferred %s", dev_name(dev));
return 1;
}
if (ret == 0)
return 1;
if (ret == 1) {
if (dev->ext.src == DEV_EXT_NONE)
@@ -48,6 +121,18 @@ static int _ignore_md(struct dev_filter *f __attribute__((unused)),
return 1;
}
static int _passes_md_filter_lite(struct dev_filter *f __attribute__((unused)),
struct device *dev)
{
return _passes_md_filter(dev, 0);
}
static int _passes_md_filter_full(struct dev_filter *f __attribute__((unused)),
struct device *dev)
{
return _passes_md_filter(dev, 1);
}
static void _destroy(struct dev_filter *f)
{
if (f->use_count)
@@ -56,7 +141,7 @@ static void _destroy(struct dev_filter *f)
dm_free(f);
}
struct dev_filter *md_filter_create(struct dev_types *dt)
struct dev_filter *md_filter_create(struct cmd_context *cmd, struct dev_types *dt)
{
struct dev_filter *f;
@@ -65,7 +150,18 @@ struct dev_filter *md_filter_create(struct dev_types *dt)
return NULL;
}
f->passes_filter = _ignore_md;
/*
* FIXME: for commands that want a full md check (pvcreate, vgcreate,
* vgextend), we do an extra read at the end of every device that the
* filter looks at. This isn't necessary; we only need to do the full
* md check on the PVs that these commands are trying to use.
*/
if (cmd->use_full_md_check)
f->passes_filter = _passes_md_filter_full;
else
f->passes_filter = _passes_md_filter_lite;
f->destroy = _destroy;
f->use_count = 0;
f->private = dt;

View File

@@ -21,8 +21,18 @@
static int _passes_partitioned_filter(struct dev_filter *f, struct device *dev)
{
struct dev_types *dt = (struct dev_types *) f->private;
int ret;
if (dev_is_partitioned(dt, dev)) {
ret = dev_is_partitioned(dt, dev);
if (ret == -EAGAIN) {
/* let pass, call again after scan */
log_debug_devs("filter partitioned deferred %s", dev_name(dev));
dev->flags |= DEV_FILTER_AFTER_SCAN;
return 1;
}
if (ret) {
if (dev->ext.src == DEV_EXT_NONE)
log_debug_devs(MSG_SKIPPING, dev_name(dev));
else

View File

@@ -26,12 +26,39 @@ struct pfilter {
struct dev_types *dt;
};
/*
* The persistent filter is filter layer that sits above the other filters and
* caches the final result of those other filters. When a device is first
* checked against filters, it will not be in this cache, so this filter will
* pass the device down to the other filters to check it. The other filters
* will run and either include the device (good/pass) or exclude the device
* (bad/fail). That good or bad result propagates up through this filter which
* saves the result. The next time some code checks the filters against the
* device, this persistent/cache filter is checked first. This filter finds
* the previous result in its cache and returns it without reevaluating the
* other real filters.
*
* FIXME: a cache like this should not be needed. The fact it's needed is a
* symptom of code that should be fixed to not reevaluate filters multiple
* times. A device should be checked against the filter once, and then not
* need to be checked again. With scanning now controlled, we could probably
* do this.
*
* FIXME: "persistent" isn't a great name for this caching filter. This filter
* at one time saved its cache results to a file, which is how it got the name.
* That .cache file does not work well, causes problems, and is no longer used
* by default. The old code for it should be removed.
*/
static char* _good_device = "good";
static char* _bad_device = "bad";
/*
* The hash table holds one of these two states
* against each entry.
*/
#define PF_BAD_DEVICE ((void *) 1)
#define PF_GOOD_DEVICE ((void *) 2)
#define PF_BAD_DEVICE ((void *) &_good_device)
#define PF_GOOD_DEVICE ((void *) &_bad_device)
static int _init_hash(struct pfilter *pf)
{
@@ -48,11 +75,7 @@ static void _persistent_filter_wipe(struct dev_filter *f)
{
struct pfilter *pf = (struct pfilter *) f->private;
log_verbose("Wiping cache of LVM-capable devices");
dm_hash_wipe(pf->devices);
/* Trigger complete device scan */
dev_cache_scan(1);
}
static int _read_array(struct pfilter *pf, struct dm_config_tree *cft,
@@ -119,21 +142,13 @@ int persistent_filter_load(struct dev_filter *f, struct dm_config_tree **cft_out
if (!config_file_read(cft))
goto_out;
log_debug_devs("Loading persistent filter cache from %s", pf->file);
_read_array(pf, cft, "persistent_filter_cache/valid_devices",
PF_GOOD_DEVICE);
/* We don't gain anything by holding invalid devices */
/* _read_array(pf, cft, "persistent_filter_cache/invalid_devices",
PF_BAD_DEVICE); */
/* Did we find anything? */
if (dm_hash_get_num_entries(pf->devices)) {
/* We populated dev_cache ourselves */
dev_cache_scan(0);
if (!dev_cache_index_devs())
stack;
r = 1;
}
log_very_verbose("Loaded persistent filter cache from %s", pf->file);
out:
@@ -274,29 +289,61 @@ out:
static int _lookup_p(struct dev_filter *f, struct device *dev)
{
struct pfilter *pf = (struct pfilter *) f->private;
void *l = dm_hash_lookup(pf->devices, dev_name(dev));
void *l;
struct dm_str_list *sl;
int pass = 1;
/* Cached BAD? */
if (l == PF_BAD_DEVICE) {
log_debug_devs("%s: Skipping (cached)", dev_name(dev));
if (dm_list_empty(&dev->aliases)) {
log_debug_devs("%d:%d: filter cache skipping (no name)",
(int)MAJOR(dev->dev), (int)MINOR(dev->dev));
return 0;
}
/* Test dm devices every time, so cache them as GOOD. */
if (MAJOR(dev->dev) == pf->dt->device_mapper_major) {
if (!l)
dm_list_iterate_items(sl, &dev->aliases)
if (!dm_hash_insert(pf->devices, sl->str, PF_GOOD_DEVICE)) {
log_error("Failed to hash device to filter.");
return 0;
}
return pf->real->passes_filter(pf->real, dev);
l = dm_hash_lookup(pf->devices, dev_name(dev));
/* Cached bad, skip dev */
if (l == PF_BAD_DEVICE) {
log_debug_devs("%s: filter cache skipping (cached bad)", dev_name(dev));
return 0;
}
/* Uncached */
/* Cached good, use dev */
if (l == PF_GOOD_DEVICE) {
log_debug_devs("%s: filter cache using (cached good)", dev_name(dev));
return 1;
}
/* Uncached, check filters and cache the result */
if (!l) {
l = pf->real->passes_filter(pf->real, dev) ? PF_GOOD_DEVICE : PF_BAD_DEVICE;
dev->flags &= ~DEV_FILTER_AFTER_SCAN;
pass = pf->real->passes_filter(pf->real, dev);
if (!pass) {
/*
* A device that does not pass one filter is excluded
* even if the result of another filter is deferred,
* because the deferred result won't change the exclude.
*/
l = PF_BAD_DEVICE;
} else if ((pass == -EAGAIN) || (dev->flags & DEV_FILTER_AFTER_SCAN)) {
/*
* When the filter result is deferred, we let the device
* pass for now, but do not cache the result. We need to
* rerun the filters later. At that point the final result
* will be cached.
*/
log_debug_devs("filter cache deferred %s", dev_name(dev));
dev->flags |= DEV_FILTER_AFTER_SCAN;
pass = 1;
goto out;
} else if (pass) {
l = PF_GOOD_DEVICE;
}
log_debug_devs("filter caching %s %s", pass ? "good" : "bad", dev_name(dev));
dm_list_iterate_items(sl, &dev->aliases)
if (!dm_hash_insert(pf->devices, sl->str, l)) {
@@ -304,8 +351,8 @@ static int _lookup_p(struct dev_filter *f, struct device *dev)
return 0;
}
}
return (l == PF_BAD_DEVICE) ? 0 : 1;
out:
return pass;
}
static void _persistent_destroy(struct dev_filter *f)

View File

@@ -0,0 +1,96 @@
/*
* Copyright (C) 2004 Luca Berra
* Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "lib.h"
#include "filter.h"
#ifdef __linux__
#define BUFSIZE 4096
static int _ignore_signature(struct dev_filter *f __attribute__((unused)),
struct device *dev)
{
char buf[BUFSIZE];
int ret = 0;
if (!scan_bcache) {
/* let pass, call again after scan */
log_debug_devs("filter signature deferred %s", dev_name(dev));
dev->flags |= DEV_FILTER_AFTER_SCAN;
return 1;
}
memset(buf, 0, BUFSIZE);
if (!dev_read_bytes(dev, 0, BUFSIZE, buf)) {
log_debug_devs("%s: Skipping: error in signature detection",
dev_name(dev));
ret = 0;
goto out;
}
if (dev_is_lvm1(dev, buf, BUFSIZE)) {
log_debug_devs("%s: Skipping lvm1 device", dev_name(dev));
ret = 0;
goto out;
}
if (dev_is_pool(dev, buf, BUFSIZE)) {
log_debug_devs("%s: Skipping gfs-pool device", dev_name(dev));
ret = 0;
goto out;
}
ret = 1;
out:
return ret;
}
static void _destroy(struct dev_filter *f)
{
if (f->use_count)
log_error(INTERNAL_ERROR "Destroying signature filter while in use %u times.", f->use_count);
dm_free(f);
}
struct dev_filter *signature_filter_create(struct dev_types *dt)
{
struct dev_filter *f;
if (!(f = dm_zalloc(sizeof(*f)))) {
log_error("md filter allocation failed");
return NULL;
}
f->passes_filter = _ignore_signature;
f->destroy = _destroy;
f->use_count = 0;
f->private = dt;
log_debug_devs("signature filter initialised.");
return f;
}
#else
struct dev_filter *signature_filter_create(struct dev_types *dt)
{
return NULL;
}
#endif

View File

@@ -27,12 +27,6 @@ static int _native_check_pv_min_size(struct device *dev)
uint64_t size;
int ret = 0;
/* Check it's accessible */
if (!dev_open_readonly_quiet(dev)) {
log_debug_devs("%s: Skipping: open failed", dev_name(dev));
return 0;
}
/* Check it's not too small */
if (!dev_get_size(dev, &size)) {
log_debug_devs("%s: Skipping: dev_get_size failed", dev_name(dev));
@@ -47,9 +41,6 @@ static int _native_check_pv_min_size(struct device *dev)
ret = 1;
out:
if (!dev_close(dev))
stack;
return ret;
}

View File

@@ -23,7 +23,7 @@
struct dev_filter *composite_filter_create(int n, int use_dev_ext_info, struct dev_filter **filters);
struct dev_filter *lvm_type_filter_create(struct dev_types *dt);
struct dev_filter *md_filter_create(struct dev_types *dt);
struct dev_filter *md_filter_create(struct cmd_context *cmd, struct dev_types *dt);
struct dev_filter *fwraid_filter_create(struct dev_types *dt);
struct dev_filter *mpath_filter_create(struct dev_types *dt);
struct dev_filter *partitioned_filter_create(struct dev_types *dt);
@@ -31,6 +31,7 @@ struct dev_filter *persistent_filter_create(struct dev_types *dt,
struct dev_filter *f,
const char *file);
struct dev_filter *sysfs_filter_create(void);
struct dev_filter *signature_filter_create(struct dev_types *dt);
struct dev_filter *internal_filter_create(void);
int internal_filter_allow(struct dm_pool *mem, struct device *dev);

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