1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-11-16 04:23:50 +03:00

Compare commits

...

439 Commits

Author SHA1 Message Date
Marian Csontos
ec4fa75cee build: make generate 2019-06-14 12:14:41 +02:00
David Teigland
a4dbbefaff WHATS_NEW for recent changes 2019-06-13 17:44:14 -05:00
David Teigland
208a09745d tests: aux have_writecache
function was never defined, causing writecache.sh to be skipped
2019-06-13 11:36:18 -05:00
David Teigland
7eaa3adedf vgchange: change debug message level
A debug message was mistakely left visible.
2019-06-11 16:14:07 -05:00
David Teigland
4bb7d3da0e lvmcache: remove wrapper around lvmcache_get_vgnameids
This was left over from when there was an lvmetad
version of the function.
2019-06-11 14:10:14 -05:00
David Teigland
0f350ba890 remove unused trustcache option 2019-06-11 11:42:49 -05:00
Zdenek Kabelac
c9203a6106 tests: correct checked target name
So when the target name happened to be a suffix of another one,
the grep was filtering incorrect line
(i.e. dm-cache && dm-writecache) - so do a line head matching.
2019-06-11 16:43:14 +02:00
David Teigland
e225bf59ff fix command definition for pvchange -a
The -a was being included in the set of "one or more"
options instead of an actual required option.  Even
though the cmd def was not implementing the restrictions
correctly, the command internally was.

Adjust the cmd def code which did not support a command
with some real required options and a set of "one or more"
options.
2019-06-10 13:43:20 -05:00
David Teigland
b7850faba7 locking: fix repeated convert to ex
Some uncommon commands like pvchange -a -u may
call convert to ex multiple times.
2019-06-10 13:37:03 -05:00
David Teigland
49b8846567 lvmcache: remove unused function
Drop lvmcache_fmt_from_vgname(), the way it was called made
it identical to the existing lvmcache_vginfo_from_vgname().
2019-06-10 10:38:32 -05:00
David Teigland
550536474f vgsplit: simplify vg creation
The way that this command now uses the global lock
followed by a label scan, it can simply check if the
new VG name exists, and if not lock it and create it.
2019-06-10 10:38:32 -05:00
David Teigland
5036244ce8 lvmcache: remove unused code 2019-06-10 10:38:32 -05:00
David Teigland
a07cc8dbef reset cmd wipe_outdated_pvs
at the start of a command, which is needed in case the cmd
struct is reused.
2019-06-10 10:34:58 -05:00
David Teigland
36cbc6db24 locking: reset global_ex flag at end of cmd
These two flags may be not reset at the end of
the command when the unlock is implicit, which
is a problem if the cmd struct is reused.
Clear the flags in the general fin_locking.
2019-06-10 10:34:58 -05:00
Marian Csontos
4c020b4d4a Merge remote-tracking branch 'origin/master'
* origin/master: (22 commits)
  tests: add metadata-bad-mdaheader.sh
  tests: add metadata-bad-text.sh
  tests: add outdated-pv.sh
  tests: add metadata-old.sh
  tests: add missing-pv missing-pv-unused
  metadata.c: removed unused code
  improve reading and repairing vg metadata
  add a warning message when updating old metadata
  vgcfgbackup add error messages
  vgck --updatemetadata is a new command
  move pv header repairs to vg_write
  process_each_pv handle outdated pvs
  move wipe_outdated_pvs to vg_write
  create separate lvmcache update functions for read and write
  fix vg_commit return value
  change args for text label read function
  add mda arg to add_mda
  keep track of which mdas have old metadata in lvmcache
  ability to keep track of outdated pvs in lvmcache
  ability to keep track of bad mdas in lvmcache
  ...
2019-06-10 17:05:04 +02:00
Marian Csontos
dbc5543cbb post-release 2019-06-10 17:04:30 +02:00
Marian Csontos
f1b4aeba66 pre-release 2019-06-10 16:59:49 +02:00
David Teigland
d7c1168c6a tests: add metadata-bad-mdaheader.sh
needs xxd command
2019-06-07 15:54:04 -05:00
David Teigland
878741502a tests: add metadata-bad-text.sh 2019-06-07 15:54:04 -05:00
David Teigland
4fa1638301 tests: add outdated-pv.sh 2019-06-07 15:54:04 -05:00
David Teigland
9156640b60 tests: add metadata-old.sh 2019-06-07 15:54:04 -05:00
David Teigland
d3636ff832 tests: add missing-pv missing-pv-unused 2019-06-07 15:54:04 -05:00
David Teigland
a3a676e0e7 metadata.c: removed unused code
if 0 was placed around old vg_read code by
the previous commit.
2019-06-07 15:54:04 -05:00
David Teigland
ba7ff96faf improve reading and repairing vg metadata
The fact that vg repair is implemented as a part of vg read
has led to a messy and complicated implementation of vg_read,
and limited and uncontrolled repair capability.  This splits
read and repair apart.

Summary
-------

- take all kinds of various repairs out of vg_read
- vg_read no longer writes anything
- vg_read now simply reads and returns vg metadata
- vg_read ignores bad or old copies of metadata
- vg_read proceeds with a single good copy of metadata
- improve error checks and handling when reading
- keep track of bad (corrupt) copies of metadata in lvmcache
- keep track of old (seqno) copies of metadata in lvmcache
- keep track of outdated PVs in lvmcache
- vg_write will do basic repairs
- new command vgck --updatemetdata will do all repairs

Details
-------

- In scan, do not delete dev from lvmcache if reading/processing fails;
  the dev is still present, and removing it makes it look like the dev
  is not there.  Records are now kept about the problems with each PV
  so they be fixed/repaired in the appropriate places.

- In scan, record a bad mda on failure, and delete the mda from
  mda in use list so it will not be used by vg_read or vg_write,
  only by repair.

- In scan, succeed if any good mda on a device is found, instead of
  failing if any is bad.  The bad/old copies of metadata should not
  interfere with normal usage while good copies can be used.

- In scan, add a record of old mdas in lvmcache for later, do not repair
  them while reading, and do not let them prevent us from finding and
  using a good copy of metadata from elsewhere.  One result is that
  "inconsistent metadata" is no longer a read error, but instead a
  record in lvmcache that can be addressed separate from the read.

- Treat a dev with no good mdas like a dev with no mdas, which is an
  existing case we already handle.

- Don't use a fake vg "handle" for returning an error from vg_read,
  or the vg_read_error function for getting that error number;
  just return null if the vg cannot be read or used, and an error_flags
  arg with flags set for the specific kind of error (which can be used
  later for determining the kind of repair.)

- Saving an original copy of the vg metadata, for purposes of reverting
  a write, is now done explicitly in vg_read instead of being hidden in
  the vg_make_handle function.

- When a vg is not accessible due to "access restrictions" but is
  otherwise fine, return the vg through the new error_vg arg so that
  process_each_pv can skip the PVs in the VG while processing.
  (This is a temporary accomodation for the way process_each_pv
  tracks which devs have been looked at, and can be dropped later
  when process_each_pv implementation dev tracking is changed.)

- vg_read does not try to fix or recover a vg, but now just reads the
  metadata, checks access restrictions and returns it.
  (Checking access restrictions might be better done outside of vg_read,
   but this is a later improvement.)

- _vg_read now simply makes one attempt to read metadata from
  each mda, and uses the most recent copy to return to the caller
  in the form of a 'vg' struct.
  (bad mdas were excluded during the scan and are not retried)
  (old mdas were not excluded during scan and are retried here)

- vg_read uses _vg_read to get the latest copy of metadata from mdas,
  and then makes various checks against it to produce warnings,
  and to check if VG access is allowed (access restrictions include:
  writable, foreign, shared, clustered, missing pvs).

- Things that were previously silently/automatically written by vg_read
  that are now done by vg_write, based on the records made in lvmcache
  during the scan and read:
  . clearing the missing flag
  . updating old copies of metadata
  . clearing outdated pvs
  . updating pv header flags

- Bad/corrupt metadata are now repaired; they were not before.

Test changes
------------

- A read command no longer writes the VG to repair it, so add a write
  command to do a repair.
  (inconsistent-metadata, unlost-pv)

- When a missing PV is removed from a VG, and then the device is
  enabled again, vgck --updatemetadata is needed to clear the
  outdated PV before it can be used again, where it wasn't before.
  (lvconvert-repair-policy, lvconvert-repair-raid, lvconvert-repair,
   mirror-vgreduce-removemissing, pv-ext-flags, unlost-pv)

Reading bad/old metadata
------------------------

- "bad metadata": the mda_header or metadata text has invalid fields
  or can't be parsed by lvm.  This is a form of corruption that would
  not be caused by known failure scenarios.  A checksum error is
  typically included among the errors reported.

- "old metadata": a valid copy of the metadata that has a smaller seqno
  than other copies of the metadata.  This can happen if the device
  failed, or io failed, or lvm failed while commiting new metadata
  to all the metadata areas.  Old metadata on a PV that has been
  removed from the VG is the "outdated" case below.

When a VG has some PVs with bad/old metadata, lvm can simply ignore
the bad/old copies, and use a good copy.  This is why there are
multiple copies of the metadata -- so it's available even when some
of the copies cannot be used.  The bad/old copies do not have to be
repaired before the VG can be used (the repair can happen later.)

A PV with no good copies of the metadata simply falls back to being
treated like a PV with no mdas; a common and harmless configuration.

When bad/old metadata exists, lvm warns the user about it, and
suggests repairing it using a new metadata repair command.
Bad metadata in particular is something that users will want to
investigate and repair themselves, since it should not happen and
may indicate some other problem that needs to be fixed.

PVs with bad/old metadata are not the same as missing devices.
Missing devices will block various kinds of VG modification or
activation, but bad/old metadata will not.

Previously, lvm would attempt to repair bad/old metadata whenever
it was read.  This was unnecessary since lvm does not require every
copy of the metadata to be used.  It would also hide potential
problems that should be investigated by the user.  It was also
dangerous in cases where the VG was on shared storage.  The user
is now allowed to investigate potential problems and decide how
and when to repair them.

Repairing bad/old metadata
--------------------------

When label scan sees bad metadata in an mda, that mda is removed
from the lvmcache info->mdas list.  This means that vg_read will
skip it, and not attempt to read/process it again.  If it was
the only in-use mda on a PV, that PV is treated like a PV with
no mdas.  It also means that vg_write will also skip the bad mda,
and not attempt to write new metadata to it.  The only way to
repair bad metadata is with the metadata repair command.

When label scan sees old metadata in an mda, that mda is kept
in the lvmcache info->mdas list.  This means that vg_read will
read/process it again, and likely see the same mismatch with
the other copies of the metadata.  Like the label_scan, the
vg_read will simply ignore the old copy of the metadata and
use the latest copy.  If the command is modifying the vg
(e.g. lvcreate), then vg_write, which writes new metadata to
every mda on info->mdas, will write the new metadata to the
mda that had the old version.  If successful, this will resolve
the old metadata problem (without needing to run a metadata
repair command.)

Outdated PVs
------------

An outdated PV is a PV that has an old copy of VG metadata
that shows it is a member of the VG, but the latest copy of
the VG metadata does not include this PV.  This happens if
the PV is disconnected, vgreduce --removemissing is run to
remove the PV from the VG, then the PV is reconnected.
In this case, the outdated PV needs have its outdated metadata
removed and the PV used flag needs to be cleared.  This repair
will be done by the subsequent repair command.  It is also done
if vgremove is run on the VG.

MISSING PVs
-----------

When a device is missing, most commands will refuse to modify
the VG.  This is the simple case.  More complicated is when
a command is allowed to modify the VG while it is missing a
device.

When a VG is written while a device is missing for one of it's PVs,
the VG metadata is written to disk with the MISSING flag on the PV
with the missing device.  When the VG is next used, it is treated
as if the PV with the MISSING flag still has a missing device, even
if that device has reappeared.

If all LVs that were using a PV with the MISSING flag are removed
or repaired so that the MISSING PV is no longer used, then the
next time the VG metadata is written, the MISSING flag will be
dropped.

Alternative methods of clearing the MISSING flag are:

vgreduce --removemissing will remove PVs with missing devices,
or PVs with the MISSING flag where the device has reappeared.

vgextend --restoremissing will clear the MISSING flag on PVs
where the device has reappeared, allowing the VG to be used
normally.  This must be done with caution since the reappeared
device may have old data that is inconsistent with data on other PVs.

Bad mda repair
--------------

The new command:
vgck --updatemetadata VG

first uses vg_write to repair old metadata, and other basic
issues mentioned above (old metadata, outdated PVs, pv_header
flags, MISSING_PV flags).  It will also go further and repair
bad metadata:

. text metadata that has a bad checksum
. text metadata that is not parsable
. corrupt mda_header checksum and version fields

(To keep a clean diff, #if 0 is added around functions that
are replaced by new code.  These commented functions are
removed by the following commit.)
2019-06-07 15:54:04 -05:00
David Teigland
015b906069 add a warning message when updating old metadata
in an mda that had previously not been updated
2019-06-07 15:54:04 -05:00
David Teigland
5dd32680b0 vgcfgbackup add error messages 2019-06-07 15:54:04 -05:00
David Teigland
47effdc025 vgck --updatemetadata is a new command
uses vg_write to correct more common or less severe issues,
and also adds the ability to repair some metadata corruption
that couldn't be handled previously.
2019-06-07 15:54:04 -05:00
David Teigland
de3d3b11f4 move pv header repairs to vg_write
Correct PV header in-use or version fields
from vg_write instead of vg_read.
2019-06-07 15:54:04 -05:00
David Teigland
89914a541f process_each_pv handle outdated pvs
process_each_pv should account for outdated pvs
in the list of all devices it is processing.
2019-06-07 15:54:04 -05:00
David Teigland
ab61a6d85d move wipe_outdated_pvs to vg_write
and implement it based on a device, not based
on a pv struct (which is not available when the
device is not a part of the vg.)

currently only the vgremove command wipes outdated
pvs until more advanced recovery is added in a
subsequent commit
2019-06-07 15:54:04 -05:00
David Teigland
45b164f62c create separate lvmcache update functions for read and write
The vg read and vg write cases need to update lvmcache
differently, so create separate functions for them.

The read case now handles checking for outdated mdas
and moves them aside into a new list to be repaired in
a subsequent commit.
2019-06-07 15:54:04 -05:00
David Teigland
027e0e92e6 fix vg_commit return value
The existing comment was desribing the correct behavior,
but the code didn't match.  The commit is successful if
one mda was committed.  Making it depend on the result of
the internal lvmcache update was wrong.
2019-06-07 15:54:04 -05:00
David Teigland
86d831b916 change args for text label read function
Have the caller pass the label_sector to the read
function so the read function can set the sector
field in the label struct, instead of having the
read function return a pointer to the label for
the caller to set the sector field.

Also have the read function return a flag indicating
to the caller that the scanned device was identified
as a duplicate pv.
2019-06-07 15:54:04 -05:00
David Teigland
889b5d3183 add mda arg to add_mda
Allow the caller of lvmcache_add_mda() to have the
new mda returned.
2019-06-07 15:54:04 -05:00
David Teigland
b2447e3538 keep track of which mdas have old metadata in lvmcache
This will be used for more advanced repair in a
subsequent commit.
2019-06-07 15:54:04 -05:00
David Teigland
0b18c25d93 ability to keep track of outdated pvs in lvmcache
Outdated PVs hold metadata for VG from which they
have been removed.  Add the ability to keep track
of these in lvmcache.
This will be used for more advanced repair in a
subsequent commit.
2019-06-07 15:54:04 -05:00
David Teigland
650524b955 ability to keep track of bad mdas in lvmcache
mda's that cannot be processed by lvm because of
some corruption can be kept on a separate list.
These will be used for more advanced repair in a
subsequent commit.
2019-06-07 15:54:04 -05:00
David Teigland
aeafdc1f45 add flags to keep track of bad metadata
When reading metadata headers and text, use a new set
of flags to identify specific errors that are seen.
These will be used for more advanced repair in a
subsequent commit.
2019-06-07 15:54:04 -05:00
David Teigland
db98a6e362 Additional MD component checking
If udev info is missing for a device, (which would indicate
if it's an MD component), then do an end-of-device read to
check if a PV is an MD component.  (This is skipped when
using hints since we already know devs in hints are good.)

A new config setting md_component_checks can be used to
disable the additional end-of-device MD checks, or to
always enable end-of-device MD checks.

When both hints and udev info are disabled/unavailable,
the end of PVs will now be scanned by default.  If md
devices with end-of-device superblocks are not being
used, the extra I/O overhead can be avoided by setting
md_component_checks="start".
2019-06-07 13:27:16 -05:00
Marian Csontos
a2c309a5c5 build: make generate 2019-06-07 17:59:43 +02:00
Marian Csontos
07d41de74c build: autoreconf 2019-06-07 17:56:56 +02:00
Marian Csontos
24bd35b4ce Merge remote-tracking branch 'origin/master'
* origin/master:
  lvmcache: remove unused_duplicate_devs list from cmd
2019-06-07 17:29:45 +02:00
Marian Csontos
4d11bf8d50 post-release 2019-06-07 17:24:51 +02:00
Marian Csontos
cb6277aa8a pre-release 2019-06-07 17:24:51 +02:00
David Teigland
2bcd43c683 lvmcache: remove unused_duplicate_devs list from cmd
Save the previous duplicate PVs in a global list instead
of a list on the cmd struct.  dmeventd reuses the cmd struct
for multiple commands, and the list entries between commands
were being freed (apparently), causing a segfault in dmeventd
when it tried to use items in cmd->unused_duplicate_devs
that had been saved there by the previous command.
2019-06-07 10:14:33 -05:00
David Teigland
c315112a3b tests: pvscan-autoactivate check for machine-id 2019-06-06 15:32:42 -05:00
David Teigland
2b241eb1f6 pvck: use new dump routines for old output
Use the recently added dump routines to produce the
old/traditional pvck output, and remove the code that
had been used for that.

The validation/checking done by the new routines means
that new lines prefixed with CHECK are printed for
incorrect values.
2019-06-05 16:28:52 -05:00
David Teigland
356ea897cc tests: pvck-dump 2019-06-05 13:58:26 -05:00
David Teigland
bada89a224 pvck: dump metadata_all
This searches the entire metadata area for any
copy of the metadata and dumps it to file.
2019-06-05 12:25:34 -05:00
Zdenek Kabelac
4d9f41b119 tests: check no_discard_passdown
Check reporting works
2019-06-05 15:48:44 +02:00
Zdenek Kabelac
ddd68fbead tests: automatically set scan_lvs when using extend_filter
When using 'aux extend_filter' we always want to use LV as PV.
2019-06-05 15:48:44 +02:00
Zdenek Kabelac
e3c4ab0cc7 cache: support no_discard_passdown
Recent kernel version from kernel commit:
de7180ff908b2bc0342e832dbdaa9a5f1ecaa33a
started to report in cache status line new flag:
no_discard_passdown

Whenever lvm spots unknown status it reports:
Unknown feature in status:

So add reconginzing this feature flag and also report this with

'lvs -o+kernel_discards'

When no_discard_passdown is found in status 'nopassdown' gets reported
for this field  (roughly matching what we report for thin-pools).
2019-06-05 15:48:41 +02:00
David Teigland
d18e491f68 pvck: dump headers and metadata
Add 'pvck --dump headers' to print all the
lvm ondisk structs.  Also checks the values
and prints any problems.

The previous dump metadata is also converted to
use these same routines, which do not depend on lvm
fully scanning/reading/processing the headers and
metadata on disk.  This makes it useful to get data in
cases where there is corruption that would otherwise
prevent the normal functions from working.
2019-06-03 15:13:32 -05:00
Marian Csontos
669a834981 test: Increase latency in pvmove-resume-multiseg
The test was failing consistently on some VMs (F25), and inconsistently
on Rawhide.

With increased latency these failures are no longer reproducible.

Reproducer:

    make check_lvmpolld T=pvmove-resume-multiseg.sh
2019-06-03 16:57:49 +02:00
Marian Csontos
a9907bef99 test: Restore testing of D-Bus API 2019-05-31 08:58:30 +02:00
David Teigland
eebb5e9fff tests: add debug to pvscan-cache deactivation 2019-05-23 15:32:46 -05:00
David Teigland
e055b89d28 tests: pvscan-cache more attempts to fix 2019-05-23 14:55:57 -05:00
David Teigland
645dd27604 separate code for setting devices from metadata parsing
Pull the code that sets devs for PVs out of the metadata
parsing code and call it separately.
2019-05-23 11:57:38 -05:00
David Teigland
ef2d61fea8 WHATS_NEW: pvck --dump 2019-05-23 11:50:16 -05:00
David Teigland
52586b1039 pvck: new dump option to extract metadata
The new command 'pvck --dump metadata PV' will extract
the current version of VG metadata from a PV for testing
and debugging.  --dump metadata_area extracts the entire
text metadata area.
2019-05-23 11:49:06 -05:00
David Teigland
1022b88a66 tests: change mkfs usage in lvconvert raid tests
The "echo y | mkfs" was failing at times from echo y.
Remove echo y and replace with wipefs -a prior to mkfs.
2019-05-23 11:45:26 -05:00
David Teigland
6169c0a51b tests: fix error detection in lvconvert-raid-takeover.sh 2019-05-23 10:29:52 -05:00
David Teigland
2036608423 tests: pvscan-cache try to fix teardown problems
teardown after the test was failing, probably because
of uncoordinated udev actions running on the test
system.  Try to avoid this by doing some work before
teardown.
2019-05-22 11:55:48 -05:00
David Teigland
78afe75b08 tests: fsadm-crypt.sh update mkfs parameter
mkfs.xfs was rejecting previously working value
2019-05-21 14:46:01 -05:00
David Teigland
cf3f463929 tests: pvscan-autoactivate.sh switch system_id_source
to machineid instead of uname which would break if
the test system had no proper uname set.
2019-05-21 14:37:55 -05:00
David Teigland
99ca06ca46 tests: hints check if strace exists
avoid test failure if test system does not
have strace
2019-05-21 14:24:57 -05:00
David Teigland
dc1e12dcd4 scan: expand and update label scan comments 2019-05-21 12:02:40 -05:00
David Teigland
60bf9c9f33 hints: exclude md components
In some cases md components could be included in
the hints, so add a check to hint creation to make
sure they are excluded.
2019-05-21 11:58:01 -05:00
David Teigland
6422b9ddc5 move the setting of use_full_md_check flag
from each command to one location in command init.
No functional change.
2019-05-21 11:51:58 -05:00
David Teigland
19ef399ea7 devs: rename dev_is_md dev_is_md_component
The naming was confusing and misleading since
it it's testing if a device is an md component,
not an md device.
2019-05-21 11:44:39 -05:00
Zdenek Kabelac
0c26aa13ca tests: check accepting out-of-range creation_time 2019-05-10 15:00:21 +02:00
Zdenek Kabelac
85dbcda150 metadata: allow reading metadata with invalid creation_time
lvm2 till version 2.02.169 (commit 78d004efa8)
was printing invalid creation_time argument into metadata on 32bit arch.

However with commit ba9820b142 we started
to properly validate all input numbers and thus we refused to accept
invalid metadata with 'garbage' string - but this results in the
situation where metadata produced on older lvm2 on 32 bit architecture
will become unreadable after upgrade.

To fix this case - extend libdm parser in a way, that whenever we
find error integer value, we also check if the parsed value is not for
creation_time node and in this case we let the metadata pass through
with made-up date 2018-05-24 (release date of 2.02.169).
2019-05-10 14:40:11 +02:00
Zdenek Kabelac
1f7c9da554 tests: split args
Here we want args to be splited into individual strings.
2019-05-06 13:02:45 +02:00
Zdenek Kabelac
4ff472b907 tests: drop call of wipefs
wipefs might not be present on test system.
Devices are also already zeroed by cleanup_md_dev
(which 'fakes' missing wipefs eventually)
2019-05-04 19:11:00 +02:00
David Teigland
9f561f2206 pvscan: fix segfault in recent commit
commit aa75b31db5
  "pvscan: handle case of scanning PV without metadata last"

failed to recognize that an arg may be null in the case of
'pvscan --cache' (without -aay) which does not keep track
of complete VGs because it does not need to activate them.
2019-05-03 16:51:34 -05:00
David Teigland
3405ead1e0 pvs: remove unnecessary label scan
The scanning rework missed removing this instance of label scan.
It's no longer needed because of the way that label scan is always
run once from the start of the command.  This unnecessary scan
would be triggered by running 'pvs @tag'.
2019-05-03 16:16:29 -05:00
David Teigland
6ff1583c1b tests: expand lvm-on-md
test both md raid0 and raid1
2019-05-03 14:39:42 -05:00
David Teigland
1e9e21a171 pvscan: don't record PV online after error reading metadata 2019-05-03 14:39:42 -05:00
David Teigland
6078585381 add md component check in vg_read based on size
If an md component is not excluded by other means and
vg_read is used to read metadata from it, then this new
check compares the device size with the PV size, and runs
a full md check on the device if the sizes don't match.
2019-05-03 14:39:42 -05:00
Zdenek Kabelac
ac627fd1ce tests: use luks1 for test
Since we do not need anywhere luks2 - pick older format
which does not require password for resize to keep
the rest of test unmodified.
2019-05-03 13:17:22 +02:00
Zdenek Kabelac
8c56e31134 tests: update resize value
Since we now properly extend also _pmspare - there was not enough free
space to add 8extents to both volumes.
2019-05-03 13:17:22 +02:00
Zdenek Kabelac
d60d59a5f3 cleanup: use unsigned type 2019-05-03 13:17:22 +02:00
Zdenek Kabelac
7a5ea681fb build: fix compilation without lvmlockd 2019-05-03 13:17:22 +02:00
Zdenek Kabelac
a520b3002c locking: validate locking mode
Ensure 'ret' is always defined and validate 'mode'.
2019-05-03 13:17:22 +02:00
Zdenek Kabelac
3c70ae1803 clean: avoid cleaning iterator on error path
Return error dirrectly instead of using 'out' code path.
2019-05-03 13:17:22 +02:00
David Teigland
99de816a1b scan: remove comments about lvmetad 2019-05-02 13:32:30 -05:00
David Teigland
81735b46d9 lvmlockd: fix snprintf warnings 2019-05-02 12:59:55 -05:00
David Teigland
0046c4e7a7 use memcpy for constant ondisk strings
Use memcpy/memcmp for on disk strings which are not
null terminated: FMTT_MAGIC, LVM2_LABEL and LABEL_ID.
Quiets compile warnings.
2019-05-02 12:59:50 -05:00
David Teigland
adfb9bf20c remove unused string writecache 2019-05-01 16:50:14 -05:00
David Teigland
90b94ead12 lvmcache: remove unused flag
The new label scan design is never called recursively,
so we don't need a flag to check for that.
2019-04-30 14:59:27 -05:00
David Teigland
d7054cd28a vgcreate: remove the lvmcache locking workaround
Recent cleanups and simplifications to lvmcache and locking
mean that the odd locking to workaround other issues is now
unnecessary.
2019-04-30 14:26:16 -05:00
David Teigland
366c1ac15b pvcreate: call label scan prior to pvcreate_each_device
and don't call it from inside pvcreate_each_device.
This avoids having to repeat it for users of
pvcreate_each_device (pvcreate/pvremove/vgcreate/vgextend.)
2019-04-30 14:10:27 -05:00
David Teigland
6d0f09f478 pvscan: remove fixme comment that is fixed
Remove the fixme comment describing the case that was
fixed by aa75b31db5
  "pvscan: handle case of scanning PV without metadata last"
2019-04-29 15:44:57 -05:00
David Teigland
c3e385c108 hints: skip hint flock if nolocking option is set 2019-04-29 13:01:15 -05:00
David Teigland
a519be8d4b remove retry for missed PVs in process_each_pv
This is no longer needed with the change to orphan
and global locks.
2019-04-29 13:01:15 -05:00
David Teigland
8c87dda195 locking: unify global lock for flock and lockd
There have been two file locks used to protect lvm
"global state": "ORPHANS" and "GLOBAL".

Commands that used the ORPHAN flock in exclusive mode:
  pvcreate, pvremove, vgcreate, vgextend, vgremove,
  vgcfgrestore

Commands that used the ORPHAN flock in shared mode:
  vgimportclone, pvs, pvscan, pvresize, pvmove,
  pvdisplay, pvchange, fullreport

Commands that used the GLOBAL flock in exclusive mode:
  pvchange, pvscan, vgimportclone, vgscan

Commands that used the GLOBAL flock in shared mode:
  pvscan --cache, pvs

The ORPHAN lock covers the important cases of serializing
the use of orphan PVs.  It also partially covers the
reporting of orphan PVs (although not correctly as
explained below.)

The GLOBAL lock doesn't seem to have a clear purpose
(it may have eroded over time.)

Neither lock correctly protects the VG namespace, or
orphan PV properties.

To simplify and correct these issues, the two separate
flocks are combined into the one GLOBAL flock, and this flock
is used from the locking sites that are in place for the
lvmlockd global lock.

The logic behind the lvmlockd (distributed) global lock is
that any command that changes "global state" needs to take
the global lock in ex mode.  Global state in lvm is: the list
of VG names, the set of orphan PVs, and any properties of
orphan PVs.  Reading this global state can use the global lock
in sh mode to ensure it doesn't change while being reported.

The locking of global state now looks like:

lockd_global()
  previously named lockd_gl(), acquires the distributed
  global lock through lvmlockd.  This is unchanged.
  It serializes distributed lvm commands that are changing
  global state.  This is a no-op when lvmlockd is not in use.

lockf_global()
  acquires an flock on a local file.  It serializes local lvm
  commands that are changing global state.

lock_global()
  first calls lockf_global() to acquire the local flock for
  global state, and if this succeeds, it calls lockd_global()
  to acquire the distributed lock for global state.

Replace instances of lockd_gl() with lock_global(), so that the
existing sites for lvmlockd global state locking are now also
used for local file locking of global state.  Remove the previous
file locking calls lock_vol(GLOBAL) and lock_vol(ORPHAN).

The following commands which change global state are now
serialized with the exclusive global flock:

pvchange (of orphan), pvresize (of orphan), pvcreate, pvremove,
vgcreate, vgextend, vgremove, vgreduce, vgrename,
vgcfgrestore, vgimportclone, vgmerge, vgsplit

Commands that use a shared flock to read global state (and will
be serialized against the prior list) are those that use
process_each functions that are based on processing a list of
all VG names, or all PVs.  The list of all VGs or all PVs is
global state and the shared lock prevents those lists from
changing while the command is processing them.

The ORPHAN lock previously attempted to produce an accurate
listing of orphan PVs, but it was only acquired at the end of
the command during the fake vg_read of the fake orphan vg.
This is not when orphan PVs were determined; they were
determined by elimination beforehand by processing all real
VGs, and subtracting the PVs in the real VGs from the list
of all PVs that had been identified during the initial scan.
This is fixed by holding the single global lock in shared mode
while processing all VGs to determine the list of orphan PVs.
2019-04-29 13:01:05 -05:00
David Teigland
ccd1386070 wipe_lv: initially open LV in writable mode
wipe_lv knows it's going to write the device, so it
can open rw from the start.  It was opening readonly,
and then dev_write needed to reopen it readwrite.
2019-04-26 14:49:27 -05:00
Zdenek Kabelac
8fbaa6d9a5 cleanup: missed string specifier 2019-04-17 11:35:44 +02:00
Zdenek Kabelac
44cfa55843 libdaemon: use pselect to avoid condition checking race
To avoid tiny race on checking arrival of signal and entering select
(that can latter remain stuck as signal was already delivered) switch
to use  pselect().

If it would needed, we can eventually add extra code for older systems
without pselect(), but there are probably no such ancient systems in
use.
2019-04-16 12:18:34 +02:00
Zdenek Kabelac
116bd314cb configure: check for pselect 2019-04-16 12:14:31 +02:00
David Teigland
aa75b31db5 pvscan: handle case of scanning PV without metadata last
Handle the case where pvscan --cache -aay (with no dev args)
gets to the final PV, completing the VG, but that final PV does not
have VG metadata.  In this case, we need to use VG metadata from a
previously scanned PV in the same VG, which we saved for this
possibility.  Using this saved metadata, we can find which VG
this PVID belongs to, and then check if that VG is now complete,
and if so add the VG name to the list of complete VGs to be
autoactivated.
2019-04-15 11:27:49 -05:00
David Teigland
41ba2b568b tests: disable unworking pvscan case
and add corresponding fixme in the code
2019-04-12 15:40:38 -05:00
David Teigland
d0b869e46a hints: fix non-empty hints list when not using hints
When hints are invalid and ignored, the list of hints
could be non-empty (from additions before an invalid
hint was found).  This confused the calling code which
was checking for an empty list to see if hints were used.
Ensure the list is empty when hints are not used.
2019-04-11 11:58:51 -05:00
David Teigland
0cc80ccfd5 hints: fix case of error getting device size
When checking hints, if there's an error getting
the device size, that should be equivalent to
seeing zero size.
2019-04-11 10:32:28 -05:00
Peter Rajnoha
25f231cf06 systemd: put back DefaultDependencies=no for lvmpolld socket unit
Previous commit 0cab341e1d removed this
by mistake - we have to keep the DefaultDependencies=no - the
sockets.target is after sysinit.target.
2019-04-11 12:18:02 +02:00
Peter Rajnoha
0cab341e1d systemd: add missing Before=shutdown.target to LVM2 services to fix shutdown ordering
We already used Conflicts=shutdown target to stop LVM2 services on shutdown.
But we still missed the ordering - the shutdown.target should be reached
only after all the services are really stopped.

Reported here: https://github.com/lvmteam/lvm2/issues/17
2019-04-09 12:24:37 +02:00
David Teigland
344a9e9afd WHATS_NEW: add several recent changes 2019-04-08 10:56:43 -05:00
David Teigland
7836e7aa1c pvscan: ignore device with incorrect size
If a device looks like a PV, but its size does not
match the PV size in the metadata, then skip it for
purposes of autoactivation.  It's probably not wrong
device for the PV.
2019-04-05 16:44:00 -05:00
David Teigland
6f18186bfd pvscan: print more reasons for ignoring devices 2019-04-05 15:48:12 -05:00
David Teigland
48e9f116ae tests: update pvscan-autoactivate for init change 2019-04-05 14:04:42 -05:00
David Teigland
f58a70c168 pvscan: don't print warning about lvmlockd not running
pvscan --cache ignores shared VGs, so it doesn't need to
consider lvmlockd, and shouldn't include a warning about it.
2019-04-05 14:04:42 -05:00
David Teigland
0ba316f102 pvscan: remove initialization case
In the past, the first 'pvscan --cache -aay dev' command
to run on the system would initialize the pvs_online dir
by scanning all devs and creating online files for all pvs
it found, and then autoactivating the VG (if complete) for
the named dev.  The idea was that the system may not have
been able to run pvscan commands for early devices, so the
first pvscan to run would need to "make up" for any devices
that had appeared previously, which the system was unable to
scan.  The problem or idea of making up for missed scans is
historical and should no longer be needed, so remove this
special init case.
2019-04-05 14:04:02 -05:00
David Teigland
6b89c0d4b7 pvscan: for init only autoactivate vg for named dev
When pvscan is run for the initialization case (the first
pvscan run on the system), it scans all devs and creates
online files for all PVs it finds.  Previously it would
then autoactivate every complete VG, but change this to
only autoactive the (complete) VG corresponding to the
named device arg(s).
2019-04-05 12:46:39 -05:00
David Teigland
417724efe2 pvscan: reorganize code
to simplify and prepare for subsequent change.
Should be no change in behavior.
2019-04-05 12:46:39 -05:00
David Teigland
6f408f68d2 man: updates to lvmlockd
- remove reference to locking_type which is no longer used
- remove references to adopting locks which has been disabled
- move some sanlock-specific info out of a general section
- remove info about doing automatic lockstart by the system
  since this was never used (the resource agent does it)
- replace info about lvextend and manual refresh under gfs2
  with a description about the automatic remote refresh
2019-04-04 14:36:28 -05:00
David Teigland
c33770c02d lvmlockd: do not allow mirror LV to be activated shared
This reverts 518a8e8cfb
  "lvmlockd: activate mirror LVs in shared mode with cmirrord"

because while activating a mirror LV with cmirrord worked,
changes to the active cmirror did not work.
2019-04-04 13:21:38 -05:00
David Teigland
50800e33d5 lvextend: refresh shared LV without using select
Using select instead of normal args did not end
up being a help, so remove it.
2019-04-04 13:19:08 -05:00
Zdenek Kabelac
5d6fe796bd tests: check auto-growth of thin-pool meta 2019-04-03 13:28:56 +02:00
Zdenek Kabelac
fcec6691f0 thin: fix maintenance of _pmspare
When metadata grows lvm2 may need to extend also _pmspare volume.
2019-04-03 13:28:54 +02:00
Zdenek Kabelac
e27d027155 thin: resize metadata with data
When data are growing, adapt also size of metadata.
As we get way too many reports from users doing huge growths of
data portion while keep metadata small and avoiding using monitoring.

So to enhance the user-experience in case user requests grown of
thin-pool (without passing PV list for growth) - lvm2 will automaticaly
grown also the metadata part of thin-pool (if possible).
2019-04-03 13:28:22 +02:00
Zdenek Kabelac
7c3de2fd93 thin: introduce estimate_thin_pool_metadata_size
Add function for estimation of thin-pool metadata size for given size of
data. Function is using already existing internal API so it can
be reused for resize of thin-pool data.
2019-04-03 13:27:17 +02:00
Zdenek Kabelac
bca0a4df9a filter: fix mpath test
Fix bug which leaked into commit
dc6dea4033,
where the testing code got mistakenly commited.
2019-04-03 13:27:17 +02:00
David Teigland
2f471f0184 lvresize: fix when compiled without lvmlockd
The no-op result of lockd_lv_resize should be success.
2019-04-02 10:51:38 -05:00
David Teigland
27cfeb1d39 lvextend: refresh shared LV with vgname as arg
Update the previous commit to leave the vgname as
an arg instead of moving it into the select option,
(the compound select option rule is confusing the
dlm arg processing.)
2019-03-22 15:01:29 -05:00
David Teigland
86b96ede2a lvextend: refresh shared LV using select option
Using --select 'lvname=LV && vgname=VG' avoids the problem
of the lvchange exit code not distinguishing an actual error
result vs the VG or LV not existing.  (This is in case there
is an odd dlm/gfs2 setup where some nodes are running the dlm
but do not have access to the VG.)
2019-03-22 14:35:02 -05:00
David Teigland
85e68a8333 lvextend: refresh shared LV remotely using dlm/corosync
When lvextend extends an LV that is active with a shared
lock, use this as a signal that other hosts may also have
the LV active, with gfs2 mounted, and should have the LV
refreshed to reflect the new size.  Use the libdlmcontrol
run api, which uses dlm_controld/corosync to run an
lvchange --refresh command on other cluster nodes.
2019-03-21 12:38:20 -05:00
David Teigland
d369de8399 lvextend: allow on LV active with a shared lock
Detect when a shared lock exists, don't require the
normal exclusive lock, and allow the lvextend.
2019-03-21 12:38:20 -05:00
David Teigland
9b4926aaff warn about changes to an active lv with shared lock
When an LV is active with a shared lock, a command can be
run to change the LV with --lockopt skiplv (to override the
exclusive lock the command ordinarily requires which is not
compatible with the outstanding shared lock.)

In this case, other commands may have the LV active and may
need to refresh the LV, so print warning stating this.
2019-03-21 12:38:20 -05:00
Zdenek Kabelac
7f757ab616 tests: vdo caching tests 2019-03-20 14:39:11 +01:00
Zdenek Kabelac
5139e5f1b3 tests: vdo dmevent autoresize 2019-03-20 14:39:11 +01:00
Zdenek Kabelac
1117f1d46f man: dmeventd vdo plugin 2019-03-20 14:39:11 +01:00
Zdenek Kabelac
597113646d man: basic vdo stacking support
Document some basic lvconvert stacking posibilities.
2019-03-20 14:39:11 +01:00
Zdenek Kabelac
4411fe2ba8 activation: synchronize before removing devices
Udev is running udev-rule action upon 'resume'.

However lvm2 in special case is doing replacement of
'soon-to-be-removed' device with 'error' target for resuming
and then follows actual removal - the sequence is usually quick,
so when udev start action - it can result in 'strange' error
message in kernel log like:

Process '/usr/sbin/dmsetup info -j 253 -m 17 -c --nameprefixes --noheadings --rows -o name,uuid,suspended' failed with exit code 1.

To avoid this - we need to ensure there is synchronization wait for udev
between 'resume'  and 'remove' part of this process.

However existing code put strict requirement to avoid synchronizing with
udev inside critical section - but this originally came from requirement
to not do anything special while there could be devices in
suspend-state. Now we are able to see differnce between critical section
with or without suspended devices.  For udev synchronization only
suspended devices are prohibited to be there - so slightly relax
condition and allow calling and using 'fs_sync()' even inside critical
section - but there must not be any suspended device.
2019-03-20 14:39:09 +01:00
Zdenek Kabelac
677aa84be3 vdo: enable caching for vdopool LV and vdo LV
Allow using caching with VDO.
User can either cache a single vdopool or
a vdo LV - difference when the caching is put-in depends on a use-case
and it's upto user to decide which kind of speed is expected.
2019-03-20 14:38:31 +01:00
Zdenek Kabelac
0db22c5f81 lv_manip: insert remove layer skips pools
Fixing renaming of subLVs when removing and inserting layers - this
got visible when using stacked VDO pools.
2019-03-20 14:38:05 +01:00
Zdenek Kabelac
ac31bfd6fd tests: check vgsplit works with cache 2019-03-20 14:38:05 +01:00
Zdenek Kabelac
030c39073e cache: support vgsplit
Enable vgsplit to work with VG containing cached LVs.
2019-03-20 14:38:02 +01:00
Zdenek Kabelac
1cc690e911 thin: max thin 2019-03-20 14:37:44 +01:00
Zdenek Kabelac
74b5f22838 debug: use log_warn
This reports are not causing command failure, so report them as
warning.
2019-03-20 14:37:44 +01:00
Zdenek Kabelac
dc6dea4033 filter: enhance mpath detection
Internal detection of SCSI device being in-use by DM mpath has been
performed several times for each component device - this could be
eventually racy - so instead when we do remember  1st. checked result
for device being mpath and use it consistenly over the filter runtime.
2019-03-20 14:37:42 +01:00
Zdenek Kabelac
1eeb2fa3f6 dev_manager: add dev_manager_remove_dm_major_minor
Move DM usage into dev_manager.c source file.
Also convert STATUS to INFO ioctl - as that's enough
to obtain UUID - this also avoid issuing unwanted flush on checked DM
device for being mpath.
2019-03-20 14:37:10 +01:00
Zdenek Kabelac
da31541bd8 gitignore: update 2019-03-20 14:35:09 +01:00
David Teigland
d84134c75b pvscan: fix ignoring foreign PVs
Fix to previous commit
  "pvscan: ignore online for shared and foreign PVs"

which was incorrectly considering a PV foreign if its
VG had no system ID when the host did have a system ID.
2019-03-13 16:03:02 -05:00
David Teigland
9b2b0fef9c config: improve scan_lvs description 2019-03-06 13:33:07 -06:00
David Teigland
98b7a3a42d tests: check that pvscan --cache ignores certain PVs 2019-03-06 12:17:47 -06:00
David Teigland
4e20ebd6a1 pvscan: ignore online for shared and foreign PVs
Activation would not be allowed anyway, but we can
check for these cases early and avoid wasted time in
pvscan managing online files an attempting activation.
2019-03-05 15:19:05 -06:00
David Teigland
a0c848d4e4 pvscan: ignore online for unused PV
If an unused PV comes online, ignore it from
pvscan --cache.
2019-03-04 14:25:53 -06:00
David Teigland
07483cc165 WHATS_NEW: io_memory_size 2019-03-04 12:22:49 -06:00
David Teigland
7edbf8a441 io: increase the default io memory from 4 to 8 MiB
This is the default bcache size that is created at the
start of the command.  It needs to be large enough to
hold a single copy of metadata for a given VG, or the
VG cannot be read or written (since the entire VG would
not fit into available memory.)

Increasing the default reduces the chances of anyone
needing to increase the default to use their VG.

The size can be set in lvm.conf global/io_memory_size;
the lower limit is 4 MiB and the upper limit is 128 MiB.
2019-03-04 12:14:06 -06:00
David Teigland
3584e0c0d5 io: warn when metadata size approaches io memory size
When a single copy of metadata gets within 1MB of the
current io_memory_size value, begin printing a warning
that the io_memory_size should be increased.
2019-03-04 12:13:09 -06:00
David Teigland
dd8d083795 config: add new setting io_memory_size
which defines the amount of memory that lvm will allocate
for bcache.  Increasing this setting is required if it is
smaller than a single copy of VG metadata.
2019-03-04 11:36:21 -06:00
David Teigland
3ed9256985 remove unused io functions 2019-02-28 10:58:00 -06:00
David Teigland
fb83719d7f logging: remove unused code
Incomplete bits of original code that's unused.
2019-02-28 10:30:54 -06:00
David Teigland
ce79b62bc2 pvscan service: use StartLimitIntervalSec
systemd changed the name
2019-02-28 08:50:37 -06:00
David Teigland
a9eaab6beb Use "cachevol" to refer to cache on a single LV
and "cachepool" to refer to a cache on a cache pool object.

The problem was that the --cachepool option was being used
to refer to both a cache pool object, and to a standard LV
used for caching.  This could be somewhat confusing, and it
made it less clear when each kind would be used.  By
separating them, it's clear when a cachepool or a cachevol
should be used.

Previously:

- lvm would use the cache pool approach when the user passed
  a cache-pool LV to the --cachepool option.

- lvm would use the cache vol approach when the user passed
  a standard LV in the --cachepool option.

Now:

- lvm will always use the cache pool approach when the user
  uses the --cachepool option.

- lvm will always use the cache vol approach when the user
  uses the --cachevol option.
2019-02-27 08:52:34 -06:00
David Teigland
c8fc18e8bf config: make hints setting commented 2019-02-26 15:54:30 -06:00
David Teigland
90149c303e logging: new config settings to specify debug fields
For users who do not want all of the fields included
in debug lines, let them specify in lvm.conf which
fields to include.  timestamp, command[pid], and
file:line fields can all be disabled.
2019-02-26 14:42:16 -06:00
David Teigland
74460f70ef pvscan: fix hint recreation
Restore part of the fix from f0089472e7 that was lost
in the process of backporting 74a388cca1.
2019-02-26 10:30:11 -06:00
David Teigland
9aea6ae956 logging: add command[pid] and timestamp to file and verbose output
Without this, the output from different commands in a single
log file could not be separated.

Change the default "indent" setting to 0 so that the default
debug output does not include variable spaces in the middle
of debug lines.
2019-02-26 10:03:44 -06:00
Alasdair G Kergon
ccfbd505fe dmsetup: Fix multi-line concise table parsing
Use the correct loop variable within the loop, instead of reusing the
initial value.  Table lines after the first don't get terminated in
the right place.

Signed-off-by: Kurt Garloff <kurt@garloff.de>
2019-02-25 13:41:51 +00:00
David Teigland
eff33684f7 WHATS_NEW: concurrent pvscan autoactivation 2019-02-21 15:31:23 -06:00
David Teigland
74a388cca1 pvscan: autoactivate a VG once
When a VG has multiple PVs, and all those PVs come online
at the same time, concurrent pvscans for each PV will all
create the individual pvid files, and all will often see
the VG is now complete.  This causes each of the pvscan
commands to think it should activate the VG, so there
are multiple activations of the same VG.  The vg lock
serializes them, and only the first pvscan actually does
the activation, but there is still a lot of extra overhead
and time used by the other pvscans that attempt to
activate the already active VG.  This can lead to a backlog
of pvscans and timeouts.

To fix this, this adds a new /run/lvm/vgs_online/ dir that
works like the existing /run/lvm/pvs_online/ dir.  Each pvscan
that wants to activate a VG will first try to exlusively create
the file vgs_online/<vgname>.  Only the first pvscan will
succeed, and that one will do the VG activation. The other
pvscans will find the vgname file exists and will not do the
activation step.

When a PV goes offline, the vgs_online file for the corresponding
VG is removed.  This allows the VG to be autoactivated again
when the PV comes online again.  This requires that the vgname be
stored in the pvid files.
2019-02-21 15:17:41 -06:00
David Teigland
f0089472e7 pvscan: fix autoactivation from concurrent pvscans
Use a file lock to ensure that only one pvscan will do
initialization of pvs_online, otherwise multiple concurrent
pvscans may all see an empty pvs_online directory and
do initialization.

The pvscan that is doing initialization should also only
attempt to activate complete VGs.
2019-02-20 16:33:59 -06:00
David Teigland
71a302effe WHATS_NEW: scan_lvs default change 2019-02-20 14:04:49 -06:00
David Teigland
fedeab28c3 tests: set scan_lvs=1 in tests that stack PVs on LVs 2019-02-20 13:52:35 -06:00
David Teigland
7be6791e70 config: change scan_lvs default to 0
so that lvm does not scan LVs for PVs by default.
2019-02-20 13:30:46 -06:00
David Teigland
0aa51a2f61 hints: fix recreating hints from pvscan
When aay was included in the pvscan --cache command,
the activation part was complaining about the unusual
state of the hint file since it had been recreated
just prior.
2019-02-13 15:23:43 -06:00
David Teigland
3ebce8dbd2 apply obtain_device_list_from_udev to all libudev usage
udev_dev_is_md_component and udev_dev_is_mpath_component
are not used for obtaining the device list, but they still
use libudev for device info.  When there are problems with
udev, these functions can get stuck. So, use the existing
obtain_device_list_from_udev config setting to also control
whether these "is component" functions are used, which gives
us a way to avoid using libudev entirely when it's causing
problems.
2019-02-05 10:15:40 -06:00
Zdenek Kabelac
d19e372795 cleanup: indent 2019-01-28 22:39:10 +01:00
Zdenek Kabelac
5cf8888976 man: lvmvdo component activation description
Describe component activation for VDO Data LV.
2019-01-28 22:39:10 +01:00
Zdenek Kabelac
d04520c321 man: vdo regenerated
Correcting order of appearance of VDO description in lvcreate.
2019-01-28 22:39:10 +01:00
Zdenek Kabelac
cb90606c83 vdo: add some basic example 2019-01-28 22:39:10 +01:00
Zdenek Kabelac
59b87cf7d6 vdo: document types vdo and vdo-pool 2019-01-28 22:39:10 +01:00
Zdenek Kabelac
87864f09f6 vdo: complete matching with thin syntax
Just like we support for thin-pool syntax:

lvcreate --thinpool new_tpoolname -L Size vg

add same support logic with for vdo-poo:

lvcreate --vdopool new_vpoolname -L Size vg

Also move description of syntax bellow thin-pool, so it's
correctly ordered in generated man page.
2019-01-28 22:18:17 +01:00
Zdenek Kabelac
b64021ee5f lvconvert: pass force and yes options for vdo conversion 2019-01-28 22:17:27 +01:00
Zdenek Kabelac
ab1fd0cb37 tests: rounding for pools changed to power of 2
Even with 64K chunk support, lvm2 will target power-of-2 chunks.
2019-01-28 22:17:27 +01:00
Zdenek Kabelac
78dd9d820d thin: select chunk size as power of 2
Whenever thin-pool chunk size is unspecified and left for lvm calculation
try to select the size as nearest highest power-of-2 instead of
just being a multiple of 64KiB.
2019-01-28 22:17:25 +01:00
Zdenek Kabelac
58ad831c72 cache: select chunk size as power of 2
When cache chunk size is not configured, and left for lvm deduction,
select the value which is power-of-2.
2019-01-28 22:17:14 +01:00
David Teigland
cbf62b9262 tests: use pvscan after enable_dev in process-each-duplicate-vgnames
instead of vgscan, so that new dev is recognized with hints
2019-01-28 11:38:05 -06:00
David Teigland
30ad845f3d vgscan: drop 'take a while' message
every command does this
2019-01-28 11:22:42 -06:00
Zdenek Kabelac
2a45ef0300 rpm: package lvmvdo man page 2019-01-22 14:35:47 +01:00
Zdenek Kabelac
2264399b0d vdo: some formating updates 2019-01-22 14:35:47 +01:00
Zdenek Kabelac
105a8edea1 lv_manip: better work with PERCENT_VG modifier with lvresize
Fixing recent commit 022ebb0cfe
Resize already has size that needs to be counted with,
otherwise upsizing operation could turn into size reduction one.
2019-01-21 15:39:24 +01:00
Zdenek Kabelac
e689bfb5d5 vdo: minor API cleanup
Since the parse_vdo_pool_status() become vdo_manip API part,
and there will be no 'dm' matching status parser,
the API can be simplified and closely match thin API here.
2019-01-21 12:53:16 +01:00
Zdenek Kabelac
fc02343eff tests: vdo dmeventd resize 2019-01-21 12:53:16 +01:00
Zdenek Kabelac
f3c52a515b vdo: enable dmeventd resize 2019-01-21 12:53:16 +01:00
Zdenek Kabelac
3d367f3348 vdo: add simple wrapper for getting pool percentage
Just like with i.e. thins provide simple function for
getting percentage of VDO Pool usage (uses existing
status function).
2019-01-21 12:53:16 +01:00
Zdenek Kabelac
cbadf3d370 tests: initial test for vdo resize 2019-01-21 12:53:16 +01:00
Zdenek Kabelac
246b0c444b tests: aux fix testing for kvdo 2019-01-21 12:53:16 +01:00
Zdenek Kabelac
2cac4bfc15 tests: update cache test
Since migration_threshold is now protected to not be smaller
then 8*chunk_size - update tests to count with this modification.
2019-01-21 12:53:16 +01:00
Zdenek Kabelac
01cbdc4e67 vdo: man documenting resize 2019-01-21 12:53:16 +01:00
Zdenek Kabelac
a16d914d34 cleanup: better naming 2019-01-21 12:53:16 +01:00
Zdenek Kabelac
08cabe9b83 vdo: allow resize of VDO and VDO pool volumes
Now with newer VDO kvdo target we can start to use standard mechanism
to enable resize of VDO volumes.

VDO pool can be grown.

Virtual volume grows on top of VDO pool when is not big enough.
Reduced VDOLV is calling discard for reduced areas - this can
take long time!

TODO: implement some pollable mechanism for out-of-lock TRIM.
2019-01-21 12:53:16 +01:00
Zdenek Kabelac
bd6709cec6 vdo: size reduction requires VDO to be active
To be able to send discard to reduced areas - the VDO LV needs to
be active.
2019-01-21 12:53:16 +01:00
Zdenek Kabelac
f1ad4b0679 vdo: discard reduced area
Implement sending discard to reduced LV area.
2019-01-21 12:53:16 +01:00
Zdenek Kabelac
ca72d19691 vdo: estimate virtual size after resize 2019-01-21 12:53:16 +01:00
Zdenek Kabelac
ab031d673d vdo: introduce function for estimation of virtual size 2019-01-21 12:53:16 +01:00
Zdenek Kabelac
022ebb0cfe lv_manip: better work with PERCENT_VG modifier
When using 'lvcreate -l100%VG' and there is big disproportion between
real available space and requested setting - automatically fallback
to 100%FREE.

Difference can be seen when VG is big and already most space was
allocated, so the requestion 100%VG can end (and by spec for % modifier
it's correct) as LV with size of 1%VG.  Usually this is not a big
problem - buit in some cases - like cache-pool allocation, this
can result a big difference for chunksize selection.

With this patch it's more closely match common-sense logic without
the need of reitteration of too big changes in lvm2 core ATM.

TODO: in the future there should be allocator solving all allocations
in a single call.
2019-01-21 12:53:15 +01:00
Zdenek Kabelac
74ae1c5bc1 dm: migration_threshold for old linked tools
Just like with precending  lvm2 device_mapper patch, ensure
that old users of libdm will also get fixed migration threshold
for caches.
2019-01-21 12:52:16 +01:00
Zdenek Kabelac
30a3dda9d6 dm: ensure migration_threshold is big enough
When using caches with BIG pool size (>TB) there is required
to use relatively huge chunk size.  Once the chunksize has
got over 1MiB - kernel cache target stopped writing such chunks
back on this if the migration_threshold remained on default 1MiB
(2048 sectors) size.

This patch ensure, DM layer will not let pass table line which
has not big enough migration threshold that can let pass
at least 8 chunks (independently of lvm2 metadata).
2019-01-21 12:48:50 +01:00
Zdenek Kabelac
9a0535e354 man: document dD attrs for VDO lvs
New attrs v(d)o pool and v(D) pool data.
2019-01-21 12:39:23 +01:00
Zdenek Kabelac
21742c3f3d man: initial man page for VDO support
Basic lvm2 command support for VDO.
2019-01-21 12:39:23 +01:00
Zdenek Kabelac
e8ea3c9a61 man: missed --zero option for thin-pool creation
During man page rewrite this info got lost and remained
only for lvconvert. So restore it back for lvcreate.
2019-01-21 12:38:47 +01:00
Zdenek Kabelac
28f3125aaa vdo: update vdo profile 2019-01-21 12:38:00 +01:00
Zdenek Kabelac
f87dd7b127 vdo: fix archived metadata comment
lvm uses 'minimum_io_size' name to exactly match  VDO naming here,
however in all common cases  _size  is using 'sector/512b' unit.
But in this case the value is in bytes and can have only 2 values:
either 512 or 4096.

It's probably not worth to rename it internaly, so we can just
drop comment - instead of using 1 or 8.

Thought let's think about it....
2019-01-21 12:37:52 +01:00
Tony Asleson
0d142f6514 lvmdbusd: Use UUID instead of name for VG rename
Use the UUID to specify the VG to rename instead of the name as this
approach works when we have duplicate VG names.
2019-01-16 16:29:05 -06:00
Tony Asleson
f43b7bb461 lvmdbusd: Handle duplicate VG names
Lvm can at times have duplicate names.  When this happens the daemon will
internally use vg_name:vg_uuid as the name for lookups, but display just
the vg_name externally.  If an API user uses the Manager.LookUpByLvmId and
queries the vg name they will only get returned one result as the API
can only accommodate returning 1.  The one returned is the first instance
found when sorting the volume groups by UUID.

Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1583510
2019-01-16 16:29:05 -06:00
Tony Asleson
b4c3382990 lvmdbusd: Correct object manager lookups
When we have two logical volumes which switch their names at the
same time we are left with incorrect lookups.  Anytime we find
an entry by doing a lookup by UUID or by name we will ensure
that the lookups are indeed correct.

Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1642176
2019-01-16 16:29:05 -06:00
Tony Asleson
1ed4b3f23b lvmdbusd: Spelling correction 2019-01-16 16:29:05 -06:00
Tony Asleson
4c1fd82774 lvmdbusd: LookUpByLvmId: Add doc for cb, cbe 2019-01-16 16:29:05 -06:00
Tony Asleson
b6d26245fb lvmdbusd: Ensure all paths return value 2019-01-16 16:29:05 -06:00
David Teigland
5f102b3421 hints: invalidate when pvscan --cache sees a new PV
An idea from Zdenek for better ensuring valid hints by invalidating
them when pvscan --cache <device> sees a new PV, which is a case
where we know that hints should be invalidated.  This is triggered
from systemd/udev logic, and there may be some cases where it would
invalidate hints that the existing methods wouldn't detect.
2019-01-16 15:34:20 -06:00
David Teigland
facd520931 lvmlockd: fix make lockstart wait
when building without lvmlockd
2019-01-16 13:24:29 -06:00
David Teigland
ebaaff3590 move init_use_aio
it doesn't make sense to call from init_logging
2019-01-16 11:45:53 -06:00
David Teigland
e158835a05 lvmlockd: make lockstart wait for existing start
If there are two independent scripts doing:
  vgchange --lockstart vg
  lvchange -ay vg/lv

The first vgchange to do the lockstart will wait for
the lockstart to complete before returning.
The second vgchange to do the lockstart will see that
the start is already in progress (from the first) and
will do nothing.  This means the second does not wait
for any lockstart to complete, and moves on to the
lvchange which may find the lockspace still starting
and fail.

To fix this, make the vgchange lockstart command
wait for any lockstart's in progress to complete.
2019-01-16 10:49:04 -06:00
David Teigland
7b5abc3fb1 hints: fix hint flock when using lvm shell
also cmd->use_hints needs to be set for each shell command
2019-01-15 12:23:16 -06:00
David Teigland
3cf7668e34 WHATS_NEW: device hints 2019-01-15 10:33:25 -06:00
David Teigland
6620dc9475 add device hints to reduce scanning
Save the list of PVs in /run/lvm/hints.  These hints
are used to reduce scanning in a number of commands
to only the PVs on the system, or only the PVs in a
requested VG (rather than all devices on the system.)
2019-01-15 10:23:47 -06:00
Zdenek Kabelac
81b3b71dae raid: man regenerated 2019-01-08 13:13:57 +01:00
Zdenek Kabelac
c0c202e606 mirror: regenerate config
Drop extra line in source file - since this line is auto-generated
and would appear twice in resuling .in file with 'make generate'.
2019-01-08 13:13:57 +01:00
Zdenek Kabelac
54a569be40 vdo: regenerate config 2019-01-08 13:13:57 +01:00
Zdenek Kabelac
61e378c4e7 config: drop extra spaces 2019-01-08 13:13:57 +01:00
Zdenek Kabelac
fdd612b824 generators: avoid contacting syslog with generators
The systemd generators are executed very early during the switch
from initramfs to system partition and the syslog is not yet fully
operational - it may cause blocking, if some debug logging is enabled
at the same time in /etc/lvm/lvm.conf log{} section.

To avoid timeouting and killing this generator - rather enhance lvm
code to suppress any syslog communication when LVM_SUPPRESS_SYSLOG
envvar is set.

Use of this envvar is needed since the parsing of i.e. cmdline options
that could eventually override lvm.conf setting happens in this case
way too late and number of lines could have been already streamed to
syslog.
2019-01-08 13:13:54 +01:00
Peter Rajnoha
6298eaeca5 scripts: lvm2-activation-generator fix lvmconfig call
Fix a scenario where global/event_activation setting is not found. In
this case we need to take default value just like lvm tools do when
executed. So use "lvmconfig --type full".

Also, if we fail to execute lvmconfig for whatever reason, fallback to
generating the activation units as failsafe action.

Reported by: Bastian Blank <waldi debian org>
2019-01-08 13:11:46 +01:00
David Teigland
bc40391b7d writecache: use wipe_lv to warn about specific signatures
When initializing an LV to hold the writecache, use wipe_lv()
which looks for specific signatures on the LV.

Wiping signatures is not necessary, but printing a warning
that names a specific signature (in addition to the existing
generic warning/confirmation) may help if a user accidentally
specifies the wrong LV which contains something important.
2019-01-03 10:47:35 -06:00
David Teigland
938b6b8253 writecache: prompt before using an LV to hold cache 2019-01-02 11:44:03 -06:00
David Teigland
89c61f2018 Revert "lvconvert: use standard wiping code"
This reverts commit fb85d5d024.

Adding a confirmation prompt in the following commit so the
wiping confirmation won't be needed.
2019-01-02 11:21:45 -06:00
Zdenek Kabelac
ee9d623d38 tests: indent 2018-12-23 01:07:27 +01:00
Zdenek Kabelac
6d8356d208 tests: fix unit test
Use more universal  /usr/bin/env bash
(as older systems do only have /bin/sh)
Uncommment disabled event_activation testing.
2018-12-23 01:07:27 +01:00
Zdenek Kabelac
1dee4b4ffc tests: testing mirrorred mirror log
Enable mirrorlog creation for test.
2018-12-23 01:07:05 +01:00
Zdenek Kabelac
88faf5a53b debug: drop some unneeded backtraces 2018-12-22 23:55:48 +01:00
Zdenek Kabelac
44aeb6d6b8 cleanup: use zalloc
Some places forget to use zalloc().
2018-12-22 23:55:48 +01:00
Zdenek Kabelac
fc479b2b07 cov: fix memleak on error path
Do not leak lvs pointer on error path.
2018-12-22 23:55:48 +01:00
Zdenek Kabelac
83c6f7e7e6 stats: initilize regions to NULL
Commit 3750b0cff5 used bad: error
path in more occasions thus it now needs regions defined as NULL.
2018-12-21 22:42:36 +01:00
Zdenek Kabelac
1fc5d8c428 Revert "lvmlockd: Fix arguments when built without sanlock"
This reverts commit b068f21f6a.

This revert was incorrect.
2018-12-21 22:41:00 +01:00
Zdenek Kabelac
26ead4bf45 cov: extent_size cannot be 0
Make this obvious to coverity.
2018-12-21 21:45:08 +01:00
Zdenek Kabelac
9dfb1a11b7 cov: drop unneeded header file
MAX macro no longer needed in pe_align.
2018-12-21 21:45:08 +01:00
Zdenek Kabelac
a355aeb17a cov: looks like cut&paste error
Fua and nofua code path should have different compares.
2018-12-21 21:45:08 +01:00
Zdenek Kabelac
8db2527c6e cov: ensure lock_type is not NULL 2018-12-21 21:45:08 +01:00
Zdenek Kabelac
e2c017fdac mangenerator: check strdup was successfull
Check for strdup != NULL
and drop unneeded zeroing when buffer is overwritten.
2018-12-21 21:45:08 +01:00
Zdenek Kabelac
2724a09e58 debug: tracing close errors 2018-12-21 21:45:08 +01:00
Zdenek Kabelac
095c9791ca debug: drop some extra backtraces
Unneeded tracking after log_*.
2018-12-21 21:45:08 +01:00
Zdenek Kabelac
82f66834ef bcache: fix memory leak on error path
Coverity noticed missing free of io struct on error path.
2018-12-21 21:45:03 +01:00
Zdenek Kabelac
a13fa75d8e dmeventd: unlock lvm2 lock on error path
New code missed to unlock locked lvm2 on error path when
command is not configured.
2018-12-21 21:43:36 +01:00
Zdenek Kabelac
65cb8efd16 lvconvert: writecache fix return code
Detach function return 0 for error and 1 for success.
Add missing log errors from failing deactivation.
Add missing log error from failing synchronization.
2018-12-21 21:42:30 +01:00
Zdenek Kabelac
fb85d5d024 lvconvert: use standard wiping code 2018-12-21 21:42:30 +01:00
Zdenek Kabelac
9830aa207c cleanup: missing copyright header 2018-12-21 21:42:30 +01:00
Zdenek Kabelac
3750b0cff5 stats: fix error path when region is NULL
We should not call _stats_cleanup_region_ids() when regions
are NULL.
Also add backtracing for  goto.
2018-12-21 21:42:30 +01:00
Zdenek Kabelac
0161ebe484 scripts: simplify including for generator
Uses included .c file as primary header includer.
2018-12-21 21:42:30 +01:00
Zdenek Kabelac
a4577c427a scripts: avoid voiding write result
Gcc doesn't want to ignore write() return code.
2018-12-21 21:42:30 +01:00
Zdenek Kabelac
a3fe619552 lvmlockd: drop superfluous defines
These defines are automatically granted with _GNU_SOURCE
which is use for whole compilation via configure.h.
2018-12-21 21:42:30 +01:00
Zdenek Kabelac
71af650760 lvmlockd: use commonly used define NOTIFYDBUS_SUPPORT
Build with configured NOTIFYDBUS_SUPPORT, SYSTEMD_LIBS, SYSTEMD_CFLAGS.
Also add proper build dependencies on internal libraries.
2018-12-21 21:42:30 +01:00
Zdenek Kabelac
7832d35668 lvmlockd: fix error return code for _init_vg_sanlock
In few cases error paths from initialization were returned as
'success == 1'.

Also assing num_mb with single compare checking valid sector_size.

For dumb compiler make num_mb always defined.
2018-12-21 21:42:30 +01:00
Zdenek Kabelac
98924e4703 lvmpolld: improve makefile deps
Add correct build dependencies on internal libraries.
2018-12-21 21:42:23 +01:00
Zdenek Kabelac
18aa541ca2 configure: avoid repeative inclusion of configure.h
Since configure.h is a generated header and it's missing traditional
ifdefs preambule - it can be included & parsed multiple times.
Normally compiler is fine when defines have same value and there is
no warning - yet we don't need to parse this several times
and by adding -include  directive we can ensure every file
in the package is rightly compile with configure.h as the
first header file.
2018-12-21 19:19:50 +01:00
Tony Asleson
a7034fa420 tests/dbus: Re-enable nesting and pvcreate via symlink
If we are running the test where the device is /dev/* we will will
run the unit tests 'test_nesting' and 'test_pv_symlinks'.  Otherwise
we will skip them.
2018-12-20 10:27:30 -06:00
Tony Asleson
5bdcafff47 lvmdbusd: Handle exported VG(s)
When a VG is exported, the 'fullreport' returns an exit code of 5, but
otherwise returns the data we are wanting.

Signed-off-by: Tony Asleson <tasleson@redhat.com>
2018-12-20 10:27:30 -06:00
Tony Asleson
ab1f1a306b lvmdbusd: Exit daemon when unable to retrieve state
In some cases we get stuck where we are unable to retrieve the current
state of lvm as we are encountering an error.  When the error is
persistent we will log and exit the daemon instead of consuming vast
amounts of resources.

Signed-off-by: Tony Asleson <tasleson@redhat.com>
2018-12-20 10:27:30 -06:00
Zdenek Kabelac
3320ab8334 lib: move towards v2 version of VDO format
Drop very old original format of VDO target and focus on V2 version.
So some variables were renamed or replaced.
There is no compatibility preserved (with assumption so far this is
experimental feature and there is no real user).

Note - version currently VDO calls this version 6.2.
2018-12-20 13:26:55 +01:00
Zdenek Kabelac
9785e40b8d dmeventd: resolve compilation of vdo status parsing
A bit of chicken & egg problem - dmeventd needs to use old libdm library.
VDO is only part of new device_mapper internal library.

So include directly source file for parsing status - this fixes usability
problem of VDO plugin introduced with previous Makefile reshaping
patchset.

NOTE: source file needs to be keep then compilable in both environments.

Also add missing copyright header.
2018-12-20 13:26:55 +01:00
Marian Csontos
f05104af76 cov: Close a FD on error 2018-12-19 16:29:31 +01:00
Marian Csontos
b068f21f6a lvmlockd: Fix arguments when built without sanlock
(cherry picked from commit 24254ca866)
2018-12-18 17:42:22 +01:00
Marian Csontos
93c7bca08f Revert "tests: Remove unsupported mirrored mirrorlog"
Incorrect cherry pick from another branch.

This reverts commit 07fc4866f0.
2018-12-18 10:55:35 +01:00
Marian Csontos
88153c7c0a build: Remove badly placed @ 2018-12-18 09:54:47 +01:00
Marian Csontos
e0c2d374ae build: Remove reference to undefined @BUILD_LVMETAD@ 2018-12-18 09:54:45 +01:00
Marian Csontos
07fc4866f0 tests: Remove unsupported mirrored mirrorlog 2018-12-18 09:54:42 +01:00
Heinz Mauelshagen
e82303fd6a lvcreate/lvconvert: optionally reenable mirrored mirror log for testing purposes only
This is a followup patch to commit edb72cb70c
to support related lvm2 test suite tests.

A 'global/support_mirrored_mirror_log' bool configuration variable gets
introduced allowing the creation of, or conversion to mirrored 'mirror'
logs if set.  The capability to create these in turn allows the rest of
the tests to perform activation of such existing LVs and their conversions
to disk/core 'mirror' logs.

Display a disclaimer warning if enabled that this is not for regular use.

Add definition of the enabled config option to respective test scripts.

Related: rhbz1643562
2018-12-17 19:28:54 +01:00
David Teigland
1f1d36f6a2 unit test: use_lvmetad replaced by event_activation 2018-12-17 10:04:44 -06:00
Zdenek Kabelac
2076dda0b8 makefiles: also fix build of unit test 2018-12-17 11:51:38 +01:00
Zdenek Kabelac
5db56b36f1 makefile: fixes build for older system
With older gcc - we need to resolve symbols linked with devmapper-event
that is now using -ldevmapper.

Also add forgotten systemd library needed for dbus notification.
2018-12-17 11:41:38 +01:00
Zdenek Kabelac
94237354dd makefiles: correcting login of makefile
Fixing some ordering issue with inclusion of common make.tmpl.
Correcting dependency calculation
Simplifying inclusive makefile
2018-12-17 10:55:20 +01:00
Zdenek Kabelac
0dc7abe013 makefiles: dm-tools improve Makefile 2018-12-17 10:55:20 +01:00
Zdenek Kabelac
b5366b1d8d makefiles: allow to set LIBS in Makefiles
Avoid doing hard set of LIBS var,
so if the LIBS is set before 'include make.tmpl' it's not lost.
This gives better control over order of linked libraries.
2018-12-17 10:55:19 +01:00
Zdenek Kabelac
143c8dcd7f makefiles: no longer used define
Not used anymore -D_BUILDING_LVM
2018-12-17 10:51:01 +01:00
Zdenek Kabelac
a665206453 makefiles: missing cleaning 2018-12-17 10:36:52 +01:00
Zdenek Kabelac
f619cac598 makefiles: quite install 2018-12-17 10:36:52 +01:00
Zdenek Kabelac
a63015442e makefiles: drop unneeded LIBS add 2018-12-17 10:36:52 +01:00
Zdenek Kabelac
d76b4afb8e makefiles: sort 2018-12-17 10:36:52 +01:00
Zdenek Kabelac
a8cdd9e16a cmirror: link with libdm
Since there is very little change there will be any new devel going
to happing with cmirror - avoid eating extra disk space and link
with already installed libdm which implements all use basic
function of dm list
2018-12-17 10:36:52 +01:00
Zdenek Kabelac
701ecff0ff lvm: drop usage of dl library
Since lvm no longer supports any dlopen-able plugins
(which in practice was never really usable) drop linking
with -ldl.
2018-12-17 10:36:52 +01:00
Zdenek Kabelac
8bf445b2de dmeventd: do not link internal libraries to plugins
Avoid linking internal device-mapper and link dynamically libdevmapper.
This considerably reduced size of installed binaries.
2018-12-17 10:36:52 +01:00
Zdenek Kabelac
035a7b9a4b dmeventd: fix linking with libdevmapper
Since dmeventd is 'libdm' based project, it needs to link
libdm library instead of its internal version

An external users may provide plugins loadeable by dmeventd.
So external user of libdevmapper-event library has no other option
then to link with released libdevmapper library.

The complexity comes with lvm2 plugins.
The lvm2 plugin itself uses internal version of device_mapper,
but libdevmapper-event usage is libdm based - so there needs to be avoided
any breakage on compatibility of internal i.e. dm_task_run structures.

TODO: most likely dmeventd itself should be moved into libdm/dm-tools dir,
and only lvm2 plugins should be created as part of lvm project,
but those still need to link with libdevmapper.
2018-12-14 22:33:22 +01:00
Zdenek Kabelac
c666e8d25e dmfilemapd: avoid linking with DL_LIBS
Dmfilemapd is not using dlopen so doesn't need to be linked with
DL_LIBS.
2018-12-14 22:27:33 +01:00
Zdenek Kabelac
f514e37978 lvconvert: ensure proper init of pv_list 2018-12-14 22:27:33 +01:00
Tony Asleson
2e01af0f78 lvmdbusd: Update table lookup for state lv_attr 2018-12-14 08:28:03 -06:00
Tony Asleson
a6cba2d0a0 lvmdbusd: Update table lookup for health lv_attr 2018-12-14 08:28:02 -06:00
Tony Asleson
51f08efaa7 lvmdbusd: Handle missing lv_attr table lookups
If we don't know the meaning we will return the key with default text
instead of raising an exception and taking the daemon out in the
process.

Resolves: rhbz1657950
2018-12-14 08:28:02 -06:00
Tony Asleson
f1684bf8e8 lvmdbusd: Dump blackbox newest first
When we get bug reports we may not get the entire log, so lets
dump the fight recorder from newest to oldest as the one we
are interested in was likely to be the last command run.
2018-12-14 08:28:02 -06:00
Ming-Hung Tsai
859feb81e5 lvmanip: uninitialized members in struct pv_list (#10)
Scenario: Given an existed LV `lvol0`, I want to create another LV
on the PVs used by `lvol0`.

I use `build_parallel_areas_from_lv()` to obtain the `pv_list` of each segments.
However, the returned `pv_list` is not properly initialized, which causes
segfault in subsequent operations.
2018-12-14 15:23:18 +01:00
Zdenek Kabelac
db6d9e04af debug: drop extra tracing
Stack tracing after log_error() is not needed.
2018-12-14 15:14:48 +01:00
Zdenek Kabelac
cc5cfb88d7 cleanup: some local headers first 2018-12-14 15:14:48 +01:00
Zdenek Kabelac
73bef5e3dd makefiles: some leftovers from lvmetad 2018-12-14 15:14:48 +01:00
Zdenek Kabelac
4801919b01 makefiles: local headers first 2018-12-14 15:14:48 +01:00
Zdenek Kabelac
454024f957 makefiles: drop unneeded include path 2018-12-14 15:14:48 +01:00
Zdenek Kabelac
0f5bdd4d31 makefiles: correct libdm dependency
Correcting dependency tracking for libdm internal files.
2018-12-14 15:14:32 +01:00
Zdenek Kabelac
63b0f0dab8 headers: use full path header instead of -I directive
Replace Makefile -I  with full path to headers like we use now
everywhere else.
2018-12-14 15:13:38 +01:00
Zdenek Kabelac
0b19387dae headers: use configure.h as 1st. header
Ensure configure.h is always 1st. included header.
Maybe we could eventually introduce gcc -include option, but for now
this better uses dependency tracking.

Also move _REENTRANT and _GNU_SOURCE into configure.h so it
doesn't need to be present in various source files.
This ensures consistent compilation of headers like stdio.h since
it may produce different declaration.
2018-12-14 15:09:13 +01:00
Zdenek Kabelac
3c37764333 libdm: use libdm header
User libdm header file.
2018-12-14 15:08:34 +01:00
Marian Csontos
46a8d2e898 dmeventd: Fix libdevmapper-event linking 2018-12-12 15:43:03 +01:00
Heinz Mauelshagen
627f0e2bd8 man: document 's' RAID attribute bit 2018-12-11 16:54:17 +01:00
Heinz Mauelshagen
dd5716ddf2 raid: fix (de)activation of RaidLVs with visible SubLVs
There's a small window during creation of a new RaidLV when
rmeta SubLVs are made visible to wipe them in order to prevent
erroneous discovery of stale RAID metadata.  In case a crash
prevents the SubLVs from being committed hidden after such
wiping, the RaidLV can still be activated with the SubLVs visible.
During deactivation though, a deadlock occurs because the visible
SubLVs are deactivated before the RaidLV.

The patch adds _check_raid_sublvs to the raid validation in merge.c,
an activation check to activate.c (paranoid, because the merge.c check
will prevent activation in case of visible SubLVs) and shares the
existing wiping function _clear_lvs in raid_manip.c moved to lv_manip.c
and renamed to activate_and_wipe_lvlist to remove code duplication.
Whilst on it, introduce activate_and_wipe_lv to share with
(lvconvert|lvchange).c.

Resolves: rhbz1633167
2018-12-11 16:35:34 +01:00
Heinz Mauelshagen
b2d1facd96 WHATS_NEW 2018-12-10 14:49:33 +01:00
Heinz Mauelshagen
edb72cb70c lvcreate/lvconvert: prohibit creation of/conversion to mirrored mirror logs
In RHEL7 we marked mirrored mirror logs as deprecated and
added a related message.  This patch prohibits creating new
'mirror' LVs with that log type or converting existing LVs
to have one.

Existing LVs with mirrored mirror log can be activated
and converted to disk/core logs.

Avoid double deprecation message when running lvconvert.

Resolves: rhbz1643562
2018-12-08 02:52:50 +01:00
David Teigland
a4b8377488 lvmlockd: fix missing LV lock for lvconvert repair
Add missing lvmlockd LV lock for lvconvert repair
on mirror and thin/cache pools.
2018-12-07 13:11:31 -06:00
Marian Csontos
21784e94d6 udev: 69-dm-lvm-metad.rules is still needed 2018-12-06 10:50:42 +01:00
Marian Csontos
92b0d014aa build: Upse PYTHON_CONFIG env.variable when set
This adds up to Commit 6462e8dffc.
2018-12-06 09:02:47 +01:00
David Teigland
73687b7b75 tests: lvm-on-md udev issues 2018-12-05 12:14:17 -06:00
David Teigland
752b1e95f4 man lvmlockd: lvextend with gfs2 2018-12-05 11:31:58 -06:00
David Teigland
3d2fd95af7 remove unused full filter
it's the same as cmd->filter
2018-12-04 14:06:46 -06:00
David Teigland
89c11a2b49 remove unused lvmetad filter 2018-12-04 12:44:43 -06:00
David Teigland
c1b2de936c pvscan: use correct dev filters
pvscan was still using lvmetad_filter which has been
null since lvmetad was removed.  Switch it to use the
full_filter.
2018-12-03 12:58:46 -06:00
David Teigland
a063d2d123 devs: use udev info to improve md component detection
Use udev info to supplement native md component detection.
2018-12-03 12:58:28 -06:00
Zdenek Kabelac
5a5e3bcf15 gcc: ensure sector is initilized
Some older gcc errnously report the variable can be used uninitlized.
Quite warning by explicit initalization.
2018-12-01 01:07:01 +01:00
Zdenek Kabelac
d8ad73e937 gcc: avoid shadowing use_aio
Function use_aio() is already declared, avoid its shadowing.
lvm-globals.h:59: warning: shadowed declaration is here
2018-12-01 01:07:01 +01:00
Zdenek Kabelac
0d61a17152 gcc: avoid shadowing activate_lv
Function activate_lv() is already declared, avoid its shadowing.
activate.h:133: warning: shadowed declaration is here
2018-12-01 01:06:57 +01:00
Zdenek Kabelac
1aac59f82a gcc: avoid shadowing index
Some older headers were declaring 'index' so avoid its usage.
/usr/include/string.h:489: warning: shadowed declaration is here
2018-12-01 01:06:51 +01:00
Zdenek Kabelac
250e05a965 makefiles: ensure test dir can run unit-test 2018-12-01 01:05:53 +01:00
Zdenek Kabelac
a1e5b8832b makefiles: avoid clustering out
When ctags package is not installed, avoid cluttering output
from failing 'which' command.
2018-12-01 01:05:53 +01:00
Zdenek Kabelac
38c7ba315d device_mapper: move internal header to front 2018-12-01 01:04:27 +01:00
Zdenek Kabelac
65eb29503b libdm: optimize dm_pool_strndup 2018-12-01 01:04:27 +01:00
Zdenek Kabelac
93dfb5dd3e device_mapper: optimize dm_pool_strndup 2018-12-01 01:04:27 +01:00
Zdenek Kabelac
c61c4271a4 device_mapper: fix incorrect dm_strncpy usage
Patch 668c9d0762 introduced regression,
since the code here would actually always return failing result.
Replace it with more simple call to strndup().
2018-12-01 01:04:27 +01:00
Zdenek Kabelac
6a4a6a7cd7 rpm: install lvm2-pvscan again
Let's repeat history once more 13d5c78a8d.
2018-11-30 13:10:00 +01:00
Zdenek Kabelac
c0c318e4f2 tests: extend sleep 2018-11-30 13:03:09 +01:00
Zdenek Kabelac
8b87ffaa8a makefiles: clean unit-test 2018-11-30 13:03:09 +01:00
Zdenek Kabelac
7fb280ceac makefiles: ignore missing files 2018-11-30 13:03:09 +01:00
Zdenek Kabelac
46f946145c configure: update 2018-11-30 13:03:09 +01:00
Zdenek Kabelac
41afe8c5cc tests: drop use_lvmetad from unit test 2018-11-29 23:10:09 +01:00
Zdenek Kabelac
e940293c33 tests: reduce memory footprint 2018-11-29 23:10:09 +01:00
Zdenek Kabelac
7da75f41ed tests: updates 2018-11-29 23:10:09 +01:00
Zdenek Kabelac
217d647a46 tests: requires at least 2 iterations 2018-11-29 23:10:09 +01:00
Zdenek Kabelac
5f87ba68d4 tests: use select with dmsetup
Use 'dmsetup -S' to greatly simplify such loops.
2018-11-29 23:10:09 +01:00
Zdenek Kabelac
74731a5277 tests: add mising udev_wait
mdadm does not handle udev waiting so it may exit earlier,
while devices are still 'running'.
2018-11-29 23:10:08 +01:00
Zdenek Kabelac
e3a22cdc31 make: generate man update 2018-11-29 23:10:08 +01:00
Zdenek Kabelac
fc482406ec make: generate config update 2018-11-29 23:10:08 +01:00
Zdenek Kabelac
4ddd756d6f makefiles: add missing srcdir 2018-11-29 23:05:43 +01:00
Zdenek Kabelac
98c21e98b2 makefiles: improving cleaning rules 2018-11-29 23:05:43 +01:00
Zdenek Kabelac
f54ead831f makefiles: avoid dependency calcs for base dir
For some targets we do not want to generate dependencies.
Also add note about usage of such Makefile - it might be
possibly better to rename it to different filename to avoid
any confusion.
2018-11-29 23:05:43 +01:00
Zdenek Kabelac
ceb2f0ad3b makefiles: updates for less verbosity 2018-11-29 23:05:43 +01:00
Zdenek Kabelac
483ed8f767 makefiles: improve lcov generator
Simplify generation of lcov report.
2018-11-29 23:05:43 +01:00
Zdenek Kabelac
8bb5dd5430 base: use calloc
Make zalloc a wrapper over calloc
2018-11-29 23:05:43 +01:00
Peter Rajnoha
cb04b84c79 scan: md metadata version 0.90 is at the end of disk
commit de28637
  scan: use full md filter when md 1.0 devices are present

missed the fact that md superblock version 0.90 also puts
metadata at the end of the device, so the full md filter
needs to be used when either 0.90 or 1.0 is present.
2018-11-29 12:35:54 -06:00
David Teigland
cd0fb0846d config settings: fix version 3.0.0
version 3.0.0 was changed in the end to 2.3.0,
but config settings had previously been encoded
with version 3.0.0.
2018-11-28 12:16:50 -06:00
David Teigland
ea9b2c2122 lvmlockd: vgchange locktype with yes option
for auto response to yes/no prompt.
2018-11-27 14:40:24 -06:00
David Teigland
d8284beb23 lvmlockctl: wait by default when stopping
lvmlockctl --stop-lockspaces was by default not waiting
for all the lockspaces to be gone.
2018-11-27 13:41:33 -06:00
David Teigland
904e1e3d26 Place the first PE at 1 MiB for all defaults
. When using default settings, this commit should change
  nothing.  The first PE continues to be placed at 1 MiB
  resulting in a metadata area size of 1020 KiB (for
  4K page sizes; slightly smaller for larger page sizes.)

. When default_data_alignment is disabled in lvm.conf,
  align pe_start at 1 MiB, based on a default metadata area
  size that adapts to the page size.  Previously, disabling
  this option would result in mda_size that was too small
  for common use, and produced a 64 KiB aligned pe_start.

. Customized pe_start and mda_size values continue to be
  set as before in lvm.conf and command line.

. Remove the configure option for setting default_data_alignment
  at build time.

. Improve alignment related option descriptions.

. Add section about alignment to pvcreate man page.

Previously, DEFAULT_PVMETADATASIZE was 255 sectors.
However, the fact that the config setting named
"default_data_alignment" has a default value of 1 (MiB)
meant that DEFAULT_PVMETADATASIZE was having no effect.

The metadata area size is the space between the start of
the metadata area (page size offset from the start of the
device) and the first PE (1 MiB by default due to
default_data_alignment 1.)  The result is a 1020 KiB metadata
area on machines with 4KiB page size (1024 KiB - 4 KiB),
and smaller on machines with larger page size.

If default_data_alignment was set to 0 (disabled), then
DEFAULT_PVMETADATASIZE 255 would take effect, and produce a
metadata area that was 188 KiB and pe_start of 192 KiB.
This was too small for common use.

This is fixed by making the default metadata area size a
computed value that matches the value produced by
default_data_alignment.
2018-11-26 16:36:50 -06:00
David Teigland
2d1152103f blk_availability service drop lvmetad 2018-11-26 14:51:32 -06:00
David Teigland
4b5d6de86b pvscan systemd service for event based activation
The pvscan systemd service for autoactivation was
mistakenly dropped along with the lvmetad related
services.

The activation generator program now looks at the new
lvm.conf setting "event_activation" (default 1) to
switch between event activation and direct activation.

Previously, the old use_lvmetad setting was used to
switch between event and direct activation.
2018-11-26 14:33:31 -06:00
David Teigland
229e63b638 writecache: set block_size using --cachesettings
instead of a separate --writecacheblocksize option.
writecache block_size is not technically a setting,
but it can borrow the option as a special case.
2018-11-21 15:16:23 -06:00
David Teigland
9deb134014 WHATS_NEW: sync io 2018-11-20 09:20:28 -06:00
David Teigland
7e721ca048 bcache: sync io fixes
fix lseek error check
fix read/write error checks
handle zero return from read and write
don't return an error for short io
fix partial read/write loop
2018-11-20 09:19:18 -06:00
David Teigland
ca66d52032 io: use sync io if aio fails
io_setup() for aio may fail if a system has reached the
aio request limit.  In this case, fall back to using
sync io.  Also, lvm use of aio can be disabled entirely
with config setting global/use_aio=0.

The system limit for aio requests can be seen from
  /proc/sys/fs/aio-max-nr

The current usage of aio requests can be seen from
  /proc/sys/fs/aio-nr

The system limit for aio requests can be increased by
setting fs.aio-max-nr using sysctl.

Also add last-byte limit to the sync io code.
2018-11-20 09:13:20 -06:00
Zdenek Kabelac
b1e9fe9505 tests: update required raid target
For embeded reshaping operation require higher driver version.
(otherwise we get:

Converting vg/LV1 from raid6 (same as raid6_zr) is directly possible to the following layouts:
 raid6_nc
 raid6_nr
 raid6_la_6
 raid6_ls_6
 raid6_ra_6
 raid6_rs_6
 raid6_n_6
2018-11-19 18:08:54 +01:00
Zdenek Kabelac
cb15373ad7 tests: missing copyright 2018-11-19 17:58:09 +01:00
Zdenek Kabelac
b968c73d21 sanlock: update headers 2018-11-19 16:55:11 +01:00
Zdenek Kabelac
b2261b5d81 tests: generate slightly less volumes 2018-11-19 13:42:23 +01:00
Zdenek Kabelac
54de0d829b tests: speed-up testing full of lvm2 metadata
Generate faster full metadata condition.

FIXME: vgremove is extremaly slow with larger set of LVs.
2018-11-19 13:16:03 +01:00
Zdenek Kabelac
a53024cafc tests: update parm for new kernel 2018-11-18 22:21:24 +01:00
Zdenek Kabelac
6d2609a232 tests: skip part of test
On kernel 4.8 this test piece oopses machine (fc23).
2018-11-18 22:03:50 +01:00
Zdenek Kabelac
0747a6d0de tests: create whole path with mkdir
Create also 'lvm' upper this if such one is missing in /run dir
and use '-p' with mkdir.
2018-11-18 22:03:50 +01:00
Zdenek Kabelac
f7adcb5f6d tests: skip portion of test for lvmpolld
lvmpolld ATM is not desingned to preserve interval checking
in the same way the 'lvconvert' tool is doing - so the passed
'-i 40' is not respected and lvmpolld autonomously checks
state of conversion and updates lvm2 metadata and dm tables
when needed.

So skip portion of test that relayed on this and preserve this logic
only for command line invocation and forking of polling process
where the interval of checking is under full control.
2018-11-18 22:03:50 +01:00
Zdenek Kabelac
14f24c2175 tests: skip when gcore from gdb package is missing
gcore is needed for gathering all userspace mappings.
2018-11-18 22:03:50 +01:00
Zdenek Kabelac
4021e88a31 tests: prefer internal header
Although we primarily want to check externally used libdevmapper
library,   out internal  all.h is still keeping all symbols
as the original library has - so for simpler compilation keep
using this private copy for defining needed symbols.
2018-11-17 01:40:29 +01:00
Zdenek Kabelac
188bedf8de tests: correcting header file enclosure
Use "" for internal header file.
2018-11-17 01:12:06 +01:00
Zdenek Kabelac
ea001426af tests: still more libs needs 2018-11-17 01:01:48 +01:00
Zdenek Kabelac
2d89192935 tests: makefile fixes
New tests needs more options and libs.
2018-11-17 00:52:59 +01:00
Zdenek Kabelac
a23ed35f6c tests: drop unwanted backup 2018-11-17 00:30:50 +01:00
Zdenek Kabelac
97a95f9648 tests: raise minsize of xfs
mkfs.xfs now needs at least ~1600...
2018-11-17 00:30:50 +01:00
Zdenek Kabelac
fd8001a9fc tests: extend 2018-11-17 00:30:50 +01:00
Zdenek Kabelac
83d9ea7348 tests: secure data erase 2018-11-17 00:30:50 +01:00
Zdenek Kabelac
55a8d6c86b libdm: add memory barrier
Just for case ensure compiler is not able to optimize
memset() away for resources that are released.

This idea of using memory barrier is taken from openssl.

Other options would be to check for 'explicit_bzero' function.
2018-11-17 00:30:50 +01:00
Zdenek Kabelac
43f8da7699 libdm: print params only for ioctls using them
When preparing ioctl buffer and flatting all parameters,
add table parameters only to ioctl that do process them.

Note: list of ioctl should be kept in sync with kernel code.
2018-11-17 00:30:50 +01:00
Zdenek Kabelac
1ae5bf2b83 libdm: add DM_DEVICE_ARM_POLL
Expose DM_DEVICE_ARM_POLL via standard API enum.
2018-11-17 00:30:50 +01:00
Zdenek Kabelac
10e191fd12 libdm: do not add params for resume and remove
DM_DEVICE_CREATE with table is doing several ioctl operations,
however only some of then takes parameters.
Since _create_and_load_v4() reused already existing dm task from
DM_DEVICE_RELOAD it has also kept passing its table parameters
to DM_DEVICE_RESUME ioctl - but this ioctl is supposed to not take
any argument and thus there is no wiping of passed data - and
since kernel returns buffer and shortens dmi->data_size accordingly,
anything past returned data size remained uncleared in zfree()
function.

This has problem if the user used dm_task_secure_data (i.e. cryptsetup),
as in this case binary expact secured data are erased from main memory
after use, but they may have been left in place.

This patch is also closing the possible hole for error path,
which also reuse same dm task structure for DM_DEVICE_REMOVE.
2018-11-17 00:30:50 +01:00
David Teigland
d44bfe90f1 scripts: remove lvmetad from makefile 2018-11-15 09:25:55 -06:00
David Teigland
df2fa88e63 lvm2-monitoring service shouldn't refer to lvmetad 2018-11-15 09:20:47 -06:00
David Teigland
16fed9ef0c man: remove some clvmd references 2018-11-14 10:00:23 -06:00
David Teigland
e6be10ffd2 man: remove scattered lvmetad references 2018-11-14 09:57:57 -06:00
David Teigland
3ca8ed66a7 remove unused backgroundfork option 2018-11-14 09:34:49 -06:00
David Teigland
814cff0c20 man: pvscan updates 2018-11-14 09:34:30 -06:00
David Teigland
819b469880 pvscan: background option is not used
Move this into the list of ignored options so
it doesn't appear in the man page.
2018-11-13 17:27:53 -06:00
David Teigland
cbee4d3d88 man pvscan: replace lvmetad text 2018-11-13 17:23:32 -06:00
David Teigland
1c0b02e367 man: remove lvmetad 2018-11-13 16:22:34 -06:00
David Teigland
8aec65c054 man lvmdump: remove clvm reference 2018-11-13 16:20:02 -06:00
David Teigland
c203ce7f86 man: remove clvmd man page 2018-11-13 16:17:17 -06:00
David Teigland
970f49dcab man: remove cluster references 2018-11-13 16:15:41 -06:00
Zdenek Kabelac
517332e78d tests: add wait loop
Add a little wait loop - since lvconvert started background process
and we need to wait till this bg task initiate its work -
adding ~1s loop should give reasonable enough time to start mirroring.
2018-11-12 15:30:40 +01:00
Zdenek Kabelac
836dc9876b devicemapper: retry mirror leg deactivation
This could be seen as continuation of
6cee8f1b06.
Some test maching with old udev system shows problem,
where udev 'jumps on' leg device after mirror target
releases its legs -  since udev does not (in this old case) skips
such device from scanning - it opens device - and this prevent
leg device to be deactivated - effectively such device stays
'leaked' in DM table invisibly to lvm2 command.

So to 'combat' this issue - if the device has '_mimage' in its name,
the retry of deactivation is automatically assumed.

NOTE: wider impact is unexpected - as it's touching only old mirror
target which is nowadays replaced with 'raid'.

In case there will be some problem identified - probably both patches
should be reverted.
2018-11-12 15:30:40 +01:00
David Teigland
38770db19b man: lvmcache update
for cache changes including writecache
2018-11-08 15:48:36 -06:00
David Teigland
2f02e8d33a tests: specify m1 for raid1 in cache-single-types 2018-11-08 14:12:42 -06:00
Zdenek Kabelac
73132bc254 tests: futher test tunning 2018-11-08 17:19:39 +01:00
David Teigland
025332edc2 tests: add lvchange cachemode passthrough in cache-single-options 2018-11-08 10:08:38 -06:00
David Teigland
8794fb71db tests: enable cachepolicy cleaner in cache-single-options 2018-11-08 09:43:23 -06:00
David Teigland
e1e33e75e7 tests: enable writeback in cache-single-options 2018-11-08 09:40:41 -06:00
David Teigland
8c5fbd5fac tests: fix dd option in cache-single-options 2018-11-08 09:33:09 -06:00
Zdenek Kabelac
d4de3cfa4d tests: updates 2018-11-08 12:22:18 +01:00
Zdenek Kabelac
f86f01a3a1 tests: keep results configurable 2018-11-08 12:22:18 +01:00
Zdenek Kabelac
3a557dcfbf configure: update 2018-11-08 12:22:07 +01:00
Zdenek Kabelac
6cee8f1b06 devicemapper: retry remove even for subLVs
With older systems and udevs we don't have control over scanning of lvm2
internal devices - so far we set retry-removal only for top-level LVs,
but in occasional cases udev can be 'fast enough' to open device for
scanning and prevent removal of such device from DM table.

So to combat this case - try to pass 'retry' flag also for removal of
internal device so see how many races can go away with this simple
patch.

Note: patch is applied only to internal version of libdm so the external
API remains working in the old way for now.
2018-11-08 12:20:57 +01:00
Zdenek Kabelac
c1703845c3 activation: trimming string is expected
Commit 813347cf84 added extra validation,
however in this particular we do want to trim suffix out so rather ignore
resulting error code here intentionaly.
2018-11-08 12:20:57 +01:00
David Teigland
1dc5603f73 devices: reuse bcache fd when getting block size
This avoids an unnecessary open() on the device.
2018-11-06 16:36:18 -06:00
David Teigland
3ae5569570 Add dm-writecache support
dm-writecache is used like dm-cache with a standard LV
as the cache.

$ lvcreate -n main -L 128M -an foo /dev/loop0

$ lvcreate -n fast -L 32M -an foo /dev/pmem0

$ lvconvert --type writecache --cachepool fast foo/main

$ lvs -a foo -o+devices
  LV            VG  Attr       LSize   Origin        Devices
  [fast]        foo -wi-------  32.00m               /dev/pmem0(0)
  main          foo Cwi------- 128.00m [main_wcorig] main_wcorig(0)
  [main_wcorig] foo -wi------- 128.00m               /dev/loop0(0)

$ lvchange -ay foo/main

$ dmsetup table
foo-main_wcorig: 0 262144 linear 7:0 2048
foo-main: 0 262144 writecache p 253:4 253:3 4096 0
foo-fast: 0 65536 linear 259:0 2048

$ lvchange -an foo/main

$ lvconvert --splitcache foo/main

$ lvs -a foo -o+devices
  LV   VG  Attr       LSize   Devices
  fast foo -wi-------  32.00m /dev/pmem0(0)
  main foo -wi------- 128.00m /dev/loop0(0)
2018-11-06 14:18:41 -06:00
David Teigland
cac4a9743a Allow dm-cache cache device to be standard LV
If a single, standard LV is specified as the cache, use
it directly instead of converting it into a cache-pool
object with two separate LVs (for data and metadata).

With a single LV as the cache, lvm will use blocks at the
beginning for metadata, and the rest for data.  Separate
dm linear devices are set up to point at the metadata and
data areas of the LV.  These dm devs are given to the
dm-cache target to use.

The single LV cache cannot be resized without recreating it.

If the --poolmetadata option is used to specify an LV for
metadata, then a cache pool will be created (with separate
LVs for data and metadata.)

Usage:

$ lvcreate -n main -L 128M vg /dev/loop0

$ lvcreate -n fast -L 64M vg /dev/loop1

$ lvs -a vg
  LV   VG Attr       LSize   Type   Devices
  main vg -wi-a----- 128.00m linear /dev/loop0(0)
  fast vg -wi-a-----  64.00m linear /dev/loop1(0)

$ lvconvert --type cache --cachepool fast vg/main

$ lvs -a vg
  LV           VG Attr       LSize   Origin       Pool  Type   Devices
  [fast]       vg Cwi---C---  64.00m                     linear /dev/loop1(0)
  main         vg Cwi---C--- 128.00m [main_corig] [fast] cache  main_corig(0)
  [main_corig] vg owi---C--- 128.00m                     linear /dev/loop0(0)

$ lvchange -ay vg/main

$ dmsetup ls
vg-fast_cdata   (253:4)
vg-fast_cmeta   (253:5)
vg-main_corig   (253:6)
vg-main (253:24)
vg-fast (253:3)

$ dmsetup table
vg-fast_cdata: 0 98304 linear 253:3 32768
vg-fast_cmeta: 0 32768 linear 253:3 0
vg-main_corig: 0 262144 linear 7:0 2048
vg-main: 0 262144 cache 253:5 253:4 253:6 128 2 metadata2 writethrough mq 0
vg-fast: 0 131072 linear 7:1 2048

$ lvchange -an vg/min

$ lvconvert --splitcache vg/main

$ lvs -a vg
  LV   VG Attr       LSize   Type   Devices
  fast vg -wi-------  64.00m linear /dev/loop1(0)
  main vg -wi------- 128.00m linear /dev/loop0(0)
2018-11-06 13:44:54 -06:00
David Teigland
8c9d9a7446 cache: factor lvchange_cache
to prepare for future addition
2018-11-06 11:36:34 -06:00
David Teigland
e548e7c29d cache: factor report functions
to prepare for future addition
2018-11-06 11:36:29 -06:00
David Teigland
a686391eca cache: reorganize cache_set_policy
to prepare for future addition
2018-11-06 11:36:29 -06:00
David Teigland
23948e99b3 cache: improve error message about flush 2018-11-06 11:36:29 -06:00
David Teigland
3e547fa952 cache: improve warning message about cached thin data 2018-11-06 11:36:28 -06:00
David Teigland
5ee1727f80 cache: rename variable in _cache_add_target_line
so it is not specific to lv/seg type
2018-11-06 11:36:28 -06:00
David Teigland
7541e002b2 cache: rename variable in _cache_display
so it is not specific to lv/seg type
2018-11-06 11:36:28 -06:00
David Teigland
85b4b2f924 cache: clean up segment line creation 2018-11-06 11:36:28 -06:00
David Teigland
e26dacf30a cache: factor getting cache mode
so part can be called separately
2018-11-06 11:36:28 -06:00
David Teigland
f3f3d6066b cache: factor settings text import export
Pull out the export/import of settings text so
it can be used later from elsewhere.
2018-11-06 11:36:28 -06:00
David Teigland
8d7075528f cache: add cache_mode_num_to_str
Requires only string and number, no specific lv/seg type.
2018-11-06 11:36:28 -06:00
Zdenek Kabelac
a427a93549 tests: fix shell quoting 2018-11-06 17:26:15 +01:00
Zdenek Kabelac
ad0268e239 tests: add wait for udev
Since the test is currently directly working with live directory,
which can be getting updates from system's udev - add wait
for settling so removal of all known PVs happens after that.
But still this has major influce on behavior of running system,
so the test should never be executed on a user used box.
2018-11-06 15:05:44 +01:00
Zdenek Kabelac
a1b1b3dbb6 pvscan: add error checking for write of online files
When there is any write failure during writting file,
report this upward as error and fail command instead
of continuing futher.
2018-11-06 15:05:44 +01:00
Zdenek Kabelac
9a6f0e64f9 debug: missing backtrace 2018-11-05 17:25:11 +01:00
Zdenek Kabelac
9d9979963f debug: tracing fclose failure
Using log_debug (not returning error code) to trace possible
failure of fclose().
2018-11-05 17:25:11 +01:00
Zdenek Kabelac
aa8b2d6a0f cleanup: move cast to det_t into MKDEV macro 2018-11-05 17:25:11 +01:00
Zdenek Kabelac
d3ebb18f40 cov: avoid unsing unchecked label_scan_open
Drop extra call too label_scan_open() without checking return value,
and let code go through next call bellow.
2018-11-05 17:25:11 +01:00
Zdenek Kabelac
70e3d0a613 cov: remove unused assigns 2018-11-05 17:25:11 +01:00
Zdenek Kabelac
a91ac41b93 cov: hide intentionaly ptr arithmetic report
Only single region count is ever replaced with on-stack uint64_t.
2018-11-03 16:10:32 +01:00
Zdenek Kabelac
9238b972c5 cov: mark warning as expected one 2018-11-03 16:10:32 +01:00
Zdenek Kabelac
0d934e730e cov: trace failing pthread_kill 2018-11-03 16:10:32 +01:00
Zdenek Kabelac
813347cf84 cov: add missing check for dm_strncpy 2018-11-03 16:10:32 +01:00
Zdenek Kabelac
c7789daec0 cov: overflow before widen
Evaluate as 64bit arithmetic (instead of doing 32bit mults which can
in this case purely teoretically overflow).
2018-11-03 16:10:31 +01:00
Zdenek Kabelac
bc1976011a cov: explicit ignore if failures
Here we can't do anything better than just ignore syscall failures
(with silence as there is no loging mechanism)
2018-11-03 16:09:36 +01:00
Zdenek Kabelac
79879bd201 cov: split check for type assignment
Check that type is always defined, if not make it explicit internal
error (although logged as debug - so catched only with proper lvm.conf
setting).
This ensures later type being NULL can't be dereferenced with coredump.
2018-11-03 16:09:36 +01:00
Zdenek Kabelac
6235861e64 cov: remove uneeded code
Since clvmd was dropped this code become useless.
2018-11-03 16:09:36 +01:00
Zdenek Kabelac
1951e0db0f label: add stack trace for failing dev_set_last_byte
Temporarily add check for failure, but whole function
needs to be likely traced for error result.

FIXME
2018-11-03 16:09:36 +01:00
David Teigland
5d747f724e lvmlockd: use standard major minor functions 2018-11-02 15:58:47 -05:00
David Teigland
e7a56d5cd3 lvmlockd: fix handling of sanlock release error
When sanlock_release returns an error because of an i/o
timeout releasing the lease on disk, lvmlockd should just
consider the lock released.  sanlock will continue trying
to release the lease on disk after the original request
times out.
2018-11-02 12:11:09 -05:00
David Teigland
f6a54a50a0 lvmlockd: deactivate lvmlock LV in vgchange
When changing a VG to lock_type sanlock, the internal
lvmlock LV was left active at the end of vgchange.
It shouldn't be active until lockstart.
2018-11-01 13:25:21 -05:00
David Teigland
7a170873aa lvmlockd: fix size/resizing of internal lvmlock LV for sanlock
The lvmlock LV size was not adjusted correctly for 512 vs 4K
sector sizes which influence the lease size used by sanlock.

When lvmlock was automatically extended, the zeroing through
bcache wasn't working.
2018-11-01 13:25:21 -05:00
David Teigland
0b01e3f5d7 lvmlockd: use new sanlock sector/align interface
The choice about sector size and lease align size is
now made by the sanlock user, in this case lvmlockd.
This will allow lvmlockd to use other lease sizes in
the future.  This also prevents breakage if hosts
report different sector sizes, or the sector size
reported by a device changes.
2018-11-01 13:25:21 -05:00
Bryn M. Reeves
925aaf0b87 dmsetup: fix stats report command output
Since the stats handle is neither bound nor listed before the
attempt to call dm_stats_get_nr_regions(), it will always return
zero: this prevents reporting of any dmstats regions on any
device.

Remove the dm_stats_get_nr_regions() check and instead rely on
the correct return status from dm_stats_populate() which only
returns 0 in the case that there are regions to inspect (and
which logs a specific error for all other cases).

Reported-by: Bryan Gurney <bgurney@redhat.com>
2018-11-01 17:00:06 +00:00
Bryn M. Reeves
19f2105b87 libdm-stats: move no regions warning after dm_stats_list()
It doesn't make sense to test or warn about the region count until
the stats handle has been listed: at this point it may or may not
contain valid information (but is guaranteed to be correct after
the list).
2018-11-01 16:59:56 +00:00
Marian Csontos
420af27f08 post-release 2018-10-31 15:56:41 +01:00
400 changed files with 17879 additions and 11323 deletions

9
.gitignore vendored
View File

@@ -25,17 +25,25 @@ make.tmpl
/autom4te.cache/
/autoscan.log
/build/
/config.cache
/config.log
/config.status
/configure.scan
/cscope.out
/html/
/reports/
/tags
/tmp/
coverity/coverity_model.xml
tools/man-generator
tools/man-generator.c
test/.lib-dir-stamp
test/.tests-stamp
test/lib/dmsecuretest
test/lib/lvchange
test/lib/lvconvert
test/lib/lvcreate
@@ -60,6 +68,7 @@ test/lib/pvremove
test/lib/pvresize
test/lib/pvs
test/lib/pvscan
test/lib/securetest
test/lib/vgcfgbackup
test/lib/vgcfgrestore
test/lib/vgchange

View File

@@ -43,16 +43,22 @@ DISTCLEAN_TARGETS += config.cache config.log config.status make.tmpl
include make.tmpl
include $(top_srcdir)/base/Makefile
include $(top_srcdir)/device_mapper/Makefile
include $(top_srcdir)/test/unit/Makefile
libdm: include
libdaemon: include
lib: libdm libdaemon
lib: libdaemon $(BASE_TARGET) $(DEVICE_MAPPER_TARGET)
daemons: lib libdaemon tools
tools: lib libdaemon device-mapper
scripts: lib
tools: lib libdaemon
po: tools daemons
man: tools
all_man: tools
scripts: libdm
test: tools daemons
unit-test run-unit-test: test
lib.device-mapper: include.device-mapper
libdm.device-mapper: include.device-mapper
@@ -148,18 +154,8 @@ install_all_man:
install_tmpfiles_configuration:
$(MAKE) -C scripts install_tmpfiles_configuration
LCOV_TRACES = libdm.info lib.info tools.info \
libdaemon/client.info libdaemon/server.info \
test/unit.info \
daemons/clvmd.info \
daemons/dmeventd.info \
daemons/lvmlockd.info \
daemons/lvmpolld.info
CLEAN_TARGETS += $(LCOV_TRACES)
ifneq ("$(LCOV)", "")
.PHONY: lcov-reset lcov lcov-dated $(LCOV_TRACES)
.PHONY: lcov-reset lcov lcov-dated
ifeq ($(MAKECMDGOALS),lcov-dated)
LCOV_REPORTS_DIR := lcov_reports-$(shell date +%Y%m%d%k%M%S)
@@ -169,35 +165,22 @@ LCOV_REPORTS_DIR := lcov_reports
endif
lcov-reset:
$(LCOV) --zerocounters $(addprefix -d , $(basename $(LCOV_TRACES)))
# maybe use subdirs processing to create tracefiles...
$(LCOV_TRACES):
$(LCOV) -b $(basename $@) -d $(basename $@) \
--ignore-errors source -c -o - | $(SED) \
-e "s/\(dmeventd_lvm.[ch]\)/plugins\/lvm2\/\1/" \
-e "s/dmeventd_\(mirror\|snapshot\|thin\|raid\)\.c/plugins\/\1\/dmeventd_\1\.c/" \
>$@
$(LCOV) --zerocounters --directory $(top_builddir)
ifneq ("$(GENHTML)", "")
lcov: $(LCOV_TRACES)
$(RM) -r $(LCOV_REPORTS_DIR)
lcov:
$(RM) -rf $(LCOV_REPORTS_DIR)
$(MKDIR_P) $(LCOV_REPORTS_DIR)
for i in $(LCOV_TRACES); do \
test -s $$i -a $$(wc -w <$$i) -ge 100 && lc="$$lc $$i"; \
done; \
test -z "$$lc" || $(GENHTML) -p @abs_top_builddir@ \
-o $(LCOV_REPORTS_DIR) $$lc
$(LCOV) --capture --directory $(top_builddir) --ignore-errors source \
--output-file $(LCOV_REPORTS_DIR)/out.info
-test ! -s $(LCOV_REPORTS_DIR)/out.info || \
$(GENHTML) -o $(LCOV_REPORTS_DIR) --ignore-errors source \
$(LCOV_REPORTS_DIR)/out.info
endif
endif
# FIXME: Drop once top-level make is resolved
-include test/unit/Makefile
include $(top_srcdir)/device_mapper/Makefile
include $(top_srcdir)/base/Makefile
ifneq ($(shell which ctags),)
ifneq ($(shell which ctags 2>/dev/null),)
.PHONY: tags
tags:
test -z "$(shell find $(top_srcdir) -type f -name '*.[ch]' -newer tags 2>/dev/null | head -1)" || $(RM) tags

View File

@@ -1 +1 @@
2.03.01(2) (2018-10-31)
2.03.05(2)-git (2019-06-10)

View File

@@ -1 +1 @@
1.02.153 (2018-10-31)
1.02.163-git (2019-06-10)

View File

@@ -1,3 +1,63 @@
Version 2.03.05 -
================================
Fix command definition for pvchange -a.
Add vgck --updatemetadata command that will repair metadata problems.
Improve VG reading to work if one good copy of metadata is found.
Report/display/scan commands that read VGs will no longer write/repair.
Move metadata repairs from VG reading to VG writing.
Add config setting md_component_checks to control MD component checks.
Add end of device MD component checks when dev has no udev info.
Version 2.03.04 - 10th June 2019
================================
Remove unused_duplicate_devs from cmd causing segfault in dmeventd.
Version 2.03.03 - 07th June 2019
================================
Report no_discard_passdown for cache LVs with lvs -o+kernel_discards.
Add pvck --dump option to extract metadata.
Fix signal delivery checking race in libdaemon (lvmetad).
Add missing Before=shutdown.target to LVM2 services to fix shutdown ordering.
Skip autoactivation for a PV when PV size does not match device size.
Remove first-pvscan-initialization which should no longer be needed.
Add remote refresh through lvmlockd/dlm for shared LVs after lvextend.
Ignore foreign and shared PVs for pvscan online files.
Add config setting to control fields in debug file and verbose output.
Add command[pid] and timestamp to debug file and verbose output.
Fix missing growth of _pmsmare volume when extending _tmeta volume.
Automatically grow thin metadata, when thin data gets too big.
Add synchronization with udev before removing cached devices.
Add support for caching VDO LVs and VDOPOOL LVs.
Add support for vgsplit with cached devices.
Query mpath device only once per command for its state.
Use device INFO instead of STATUS when checking for mpath device uuid.
Change default io_memory_size from 4 to 8 MiB.
Add config setting io_memory_size to set bcache size.
Fix pvscan autoactivation for concurrent pvscans.
Change scan_lvs default to 0 so LVs are not scanned for PVs.
Thin-pool selects power-of-2 chunk size by default.
Cache selects power-of-2 chunk size by default.
Support reszing for VDOPoolLV and VDOLV.
Improve -lXXX%VG modifier which improves cache segment estimation.
Ensure migration_threshold for cache is at least 8 chunks.
Restore missing man info lvcreate --zero for thin-pools.
Drop misleadning comment for metadata minimum_io_size for VDO segment.
Add device hints to reduce scanning.
Introduce LVM_SUPPRESS_SYSLOG to suppress syslog usage by generator.
Fix generator quering lvmconfig unpresent config option.
Fix memleak on bcache error path code.
Fix missing unlock on lvm2 dmeventd plugin error path initialization.
Improve Makefile dependency tracking.
Move VDO support towards V2 target (6.2) support.
Version 2.03.02 - 18th December 2018
====================================
Fix missing proper initialization of pv_list struct when adding pv.
Fix (de)activation of RaidLVs with visible SubLVs.
Prohibit mirrored 'mirror' log via lvcreate and lvconvert.
Use sync io if async io_setup fails, or use_aio=0 is set in config.
Fix more issues reported by coverity scan.
Version 2.03.01 - 31st October 2018
===================================

View File

@@ -1,3 +1,22 @@
Version 1.02.163 -
=================================
Version 1.02.161 - 10th June 2019
=================================
Version 1.02.159 - 07th June 2019
=================================
Parsing of cache status understand no_discard_passdown.
Ensure migration_threshold for cache is at least 8 chunks.
Version 1.02.155 - 18th December 2018
=====================================
Include correct internal header inside libdm list.c.
Enhance ioctl flattening and add parameters only when needed.
Add DM_DEVICE_ARM_POLL for API completness matching kernel.
Do not add parameters for RESUME with DM_DEVICE_CREATE dm task.
Fix dmstats report printing no output.
Version 1.02.153 - 31st October 2018
====================================

View File

@@ -14,22 +14,27 @@
# Comment to build the advanced radix tree.
#base/data-struct/radix-tree.o: CFLAGS += -DSIMPLE_RADIX_TREE
# NOTE: this Makefile only works as 'include' for toplevel Makefile
# which defined all top_* variables
BASE_SOURCE=\
base/data-struct/radix-tree.c \
base/data-struct/hash.c \
base/data-struct/list.c
base/data-struct/list.c \
base/data-struct/radix-tree.c
BASE_DEPENDS=$(addprefix $(top_builddir)/,$(subst .c,.d,$(BASE_SOURCE)))
BASE_OBJECTS=$(addprefix $(top_builddir)/,$(subst .c,.o,$(BASE_SOURCE)))
CLEAN_TARGETS+=$(BASE_DEPENDS) $(BASE_OBJECTS)
BASE_TARGET = base/libbase.a
BASE_DEPENDS = $(BASE_SOURCE:%.c=%.d)
BASE_OBJECTS = $(BASE_SOURCE:%.c=%.o)
CLEAN_TARGETS += $(BASE_DEPENDS) $(BASE_OBJECTS) \
$(BASE_SOURCE:%.c=%.gcda) \
$(BASE_SOURCE:%.c=%.gcno) \
$(BASE_TARGET)
-include $(BASE_DEPENDS)
$(BASE_OBJECTS): INCLUDES+=-I$(top_srcdir)/base/
$(top_builddir)/base/libbase.a: $(BASE_OBJECTS)
$(BASE_TARGET): $(BASE_OBJECTS)
@echo " [AR] $@"
$(Q) $(RM) $@
$(Q) $(AR) rsv $@ $(BASE_OBJECTS) > /dev/null
CLEAN_TARGETS+=$(top_builddir)/base/libbase.a
ifeq ("$(DEPENDS)","yes")
-include $(BASE_DEPENDS)
endif

View File

@@ -18,6 +18,7 @@
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
//----------------------------------------------------------------
@@ -354,6 +355,7 @@ static bool _insert_node16(struct radix_tree *rt, struct value *v, uint8_t *kb,
return false;
n48->nr_entries = 17;
/* coverity[bad_memset] intentional use of '0' */
memset(n48->keys, 48, sizeof(n48->keys));
for (i = 0; i < 16; i++) {
@@ -623,15 +625,15 @@ static void _degrade_to_n48(struct node256 *n256, struct value *result)
}
// Removes an entry in an array by sliding the values above it down.
static void _erase_elt(void *array, unsigned obj_size, unsigned count, unsigned index)
static void _erase_elt(void *array, size_t obj_size, unsigned count, unsigned idx)
{
if (index == (count - 1))
if (idx == (count - 1))
// The simple case
return;
memmove(((uint8_t *) array) + (obj_size * index),
((uint8_t *) array) + (obj_size * (index + 1)),
obj_size * (count - index - 1));
memmove(((uint8_t *) array) + (obj_size * idx),
((uint8_t *) array) + (obj_size * (idx + 1)),
obj_size * (count - idx - 1));
// Zero the now unused last elt (set's v.type to UNSET)
memset(((uint8_t *) array) + (count - 1) * obj_size, 0, obj_size);

View File

@@ -14,16 +14,12 @@
#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;
return calloc(1, len);
}
//----------------------------------------------------------------

View File

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

View File

@@ -88,6 +88,22 @@ devices {
#
external_device_info_source = "none"
# Configuration option devices/hints.
# Use a local file to remember which devices have PVs on them.
# Some commands will use this as an optimization to reduce device
# scanning, and will only scan the listed PVs. Removing the hint file
# will cause lvm to generate a new one. Disable hints if PVs will
# be copied onto devices using non-lvm commands, like dd.
#
# Accepted values:
# all
# Use all hints.
# none
# Use no hints.
#
# This configuration option has an automatic default value.
# hints = "all"
# Configuration option devices/preferred_names.
# Select which path name to display for a block device.
# If multiple path names exist for a block device, and LVM needs to
@@ -149,18 +165,6 @@ devices {
# This configuration option has an automatic default value.
# global_filter = [ "a|.*/|" ]
# Configuration option devices/cache_dir.
# This setting is no longer used.
cache_dir = "@DEFAULT_SYS_DIR@/@DEFAULT_CACHE_SUBDIR@"
# Configuration option devices/cache_file_prefix.
# This setting is no longer used.
cache_file_prefix = ""
# Configuration option devices/write_cache_state.
# This setting is no longer used.
write_cache_state = 1
# Configuration option devices/types.
# List of additional acceptable block device types.
# These are of device type names from /proc/devices, followed by the
@@ -179,17 +183,52 @@ devices {
sysfs_scan = 1
# Configuration option devices/scan_lvs.
# Scan LVM LVs for layered PVs.
scan_lvs = 1
# Scan LVM LVs for layered PVs, allowing LVs to be used as PVs.
# When 1, LVM will detect PVs layered on LVs, and caution must be
# taken to avoid a host accessing a layered VG that may not belong
# to it, e.g. from a guest image. This generally requires excluding
# the LVs with device filters. Also, when this setting is enabled,
# every LVM command will scan every active LV on the system (unless
# filtered), which can cause performance problems on systems with
# many active LVs. When this setting is 0, LVM will not detect or
# use PVs that exist on LVs, and will not allow a PV to be created on
# an LV. The LVs are ignored using a built in device filter that
# identifies and excludes LVs.
scan_lvs = 0
# Configuration option devices/multipath_component_detection.
# Ignore devices that are components of DM multipath devices.
multipath_component_detection = 1
# Configuration option devices/md_component_detection.
# Ignore devices that are components of software RAID (md) devices.
# Enable detection and exclusion of MD component devices.
# An MD component device is a block device that MD uses as part
# of a software RAID virtual device. When an LVM PV is created
# on an MD device, LVM must only use the top level MD device as
# the PV, and should ignore the underlying component devices.
# In cases where the MD superblock is located at the end of the
# component devices, it is more difficult for LVM to consistently
# identify an MD component, see the md_component_checks setting.
md_component_detection = 1
# Configuration option devices/md_component_checks.
# The checks LVM should use to detect MD component devices.
# MD component devices are block devices used by MD software RAID.
#
# Accepted values:
# auto
# LVM will skip scanning the end of devices when it has other
# indications that the device is not an MD component.
# start
# LVM will only scan the start of devices for MD superblocks.
# This does not incur extra I/O by LVM.
# full
# LVM will scan the start and end of devices for MD superblocks.
# This requires an extra read at the end of devices.
#
# This configuration option has an automatic default value.
# md_component_checks = "auto"
# Configuration option devices/fw_raid_component_detection.
# Ignore devices that are components of firmware RAID devices.
# LVM must use an external_device_info_source other than none for this
@@ -197,19 +236,24 @@ devices {
fw_raid_component_detection = 0
# Configuration option devices/md_chunk_alignment.
# Align PV data blocks with md device's stripe-width.
# Align the start of a PV data area with md device's stripe-width.
# This applies if a PV is placed directly on an md device.
# default_data_alignment will be overriden if it is not aligned
# with the value detected for this setting.
# This setting is overriden by data_alignment_detection,
# data_alignment, and the --dataalignment option.
md_chunk_alignment = 1
# Configuration option devices/default_data_alignment.
# Default alignment of the start of a PV data area in MB.
# If set to 0, a value of 64KiB will be used.
# Set to 1 for 1MiB, 2 for 2MiB, etc.
# Align the start of a PV data area with this number of MiB.
# Set to 1 for 1MiB, 2 for 2MiB, etc. Set to 0 to disable.
# This setting is overriden by data_alignment and the --dataalignment
# option.
# This configuration option has an automatic default value.
# default_data_alignment = 1
# Configuration option devices/data_alignment_detection.
# Detect PV data alignment based on sysfs device information.
# Align the start of a PV data area with sysfs io properties.
# The start of a PV data area will be a multiple of minimum_io_size or
# optimal_io_size exposed in sysfs. minimum_io_size is the smallest
# request the device can perform without incurring a read-modify-write
@@ -217,27 +261,29 @@ devices {
# preferred unit of receiving I/O, e.g. MD stripe width.
# minimum_io_size is used if optimal_io_size is undefined (0).
# If md_chunk_alignment is enabled, that detects the optimal_io_size.
# This setting takes precedence over md_chunk_alignment.
# default_data_alignment and md_chunk_alignment will be overriden
# if they are not aligned with the value detected for this setting.
# This setting is overriden by data_alignment and the --dataalignment
# option.
data_alignment_detection = 1
# Configuration option devices/data_alignment.
# Alignment of the start of a PV data area in KiB.
# If a PV is placed directly on an md device and md_chunk_alignment or
# data_alignment_detection are enabled, then this setting is ignored.
# Otherwise, md_chunk_alignment and data_alignment_detection are
# disabled if this is set. Set to 0 to use the default alignment or the
# page size, if larger.
# Align the start of a PV data area with this number of KiB.
# When non-zero, this setting overrides default_data_alignment.
# Set to 0 to disable, in which case default_data_alignment
# is used to align the first PE in units of MiB.
# This setting is overriden by the --dataalignment option.
data_alignment = 0
# Configuration option devices/data_alignment_offset_detection.
# Detect PV data alignment offset based on sysfs device information.
# The start of a PV aligned data area will be shifted by the
# Shift the start of an aligned PV data area based on sysfs information.
# After a PV data area is aligned, it will be shifted by the
# alignment_offset exposed in sysfs. This offset is often 0, but may
# be non-zero. Certain 4KiB sector drives that compensate for windows
# partitioning will have an alignment_offset of 3584 bytes (sector 7
# is the lowest aligned logical block, the 4KiB sectors start at
# LBA -1, and consequently sector 63 is aligned on a 4KiB boundary).
# pvcreate --dataalignmentoffset will skip this detection.
# This setting is overriden by the --dataalignmentoffset option.
data_alignment_offset_detection = 1
# Configuration option devices/ignore_suspended_devices.
@@ -265,10 +311,6 @@ devices {
# different way, making them a better choice for VG stacking.
ignore_lvm_mirrors = 1
# Configuration option devices/disable_after_error_count.
# This setting is no longer used.
disable_after_error_count = 0
# Configuration option devices/require_restorefile_with_uuid.
# Allow use of pvcreate --uuid without requiring --restorefile.
require_restorefile_with_uuid = 1
@@ -506,10 +548,19 @@ allocation {
# This configuration option has an automatic default value.
# vdo_use_deduplication = 1
# Configuration option allocation/vdo_emulate_512_sectors.
# Specifies that the VDO volume is to emulate a 512 byte block device.
# Configuration option allocation/vdo_use_metadata_hints.
# Enables or disables whether VDO volume should tag its latency-critical
# writes with the REQ_SYNC flag. Some device mapper targets such as dm-raid5
# process writes with this flag at a higher priority.
# Default is enabled.
# This configuration option has an automatic default value.
# vdo_emulate_512_sectors = 0
# vdo_use_metadata_hints = 1
# Configuration option allocation/vdo_minimum_io_size.
# The minimum IO size for VDO volume to accept, in bytes.
# Valid values are 512 or 4096. The recommended and default value is 4096.
# This configuration option has an automatic default value.
# vdo_minimum_io_size = 4096
# Configuration option allocation/vdo_block_map_cache_size_mb.
# Specifies the amount of memory in MiB allocated for caching block map
@@ -520,10 +571,10 @@ allocation {
# vdo_block_map_cache_size_mb = 128
# Configuration option allocation/vdo_block_map_period.
# Tunes the quantity of block map updates that can accumulate
# before cache pages are flushed to disk. The value must be
# at least 1 and less then 16380.
# A lower value means shorter recovery time but lower performance.
# The speed with which the block map cache writes out modified block map pages.
# A smaller era length is likely to reduce the amount time spent rebuilding,
# at the cost of increased block map writes during normal operation.
# The maximum and recommended value is 16380; the minimum value is 1.
# This configuration option has an automatic default value.
# vdo_block_map_period = 16380
@@ -543,22 +594,6 @@ allocation {
# This configuration option has an automatic default value.
# vdo_index_memory_size_mb = 256
# Configuration option allocation/vdo_use_read_cache.
# Enables or disables the read cache within the VDO volume.
# The cache should be enabled if write workloads are expected
# to have high levels of deduplication, or for read intensive
# workloads of highly compressible data.
# This configuration option has an automatic default value.
# vdo_use_read_cache = 0
# Configuration option allocation/vdo_read_cache_size_mb.
# Specifies the extra VDO volume read cache size in MiB.
# This space is in addition to a system-defined minimum.
# The value must be less then 16TiB and 1.12 MiB of memory
# will be used per MiB of read cache specified, per bio thread.
# This configuration option has an automatic default value.
# vdo_read_cache_size_mb = 0
# Configuration option allocation/vdo_slab_size_mb.
# Specifies the size in MiB of the increment by which a VDO is grown.
# Using a smaller size constrains the total maximum physical size
@@ -634,6 +669,18 @@ allocation {
# Data which has not been flushed is not guaranteed to persist in this mode.
# This configuration option has an automatic default value.
# vdo_write_policy = "auto"
# Configuration option allocation/vdo_max_discard.
# Specified te maximum size of discard bio accepted, in 4096 byte blocks.
# I/O requests to a VDO volume are normally split into 4096-byte blocks,
# and processed up to 2048 at a time. However, discard requests to a VDO volume
# can be automatically split to a larger size, up to <max discard> 4096-byte blocks
# in a single bio, and are limited to 1500 at a time.
# Increasing this value may provide better overall performance, at the cost of
# increased latency for the individual discard requests.
# The default and minimum is 1. The maximum is UINT_MAX / 4096.
# This configuration option has an automatic default value.
# vdo_max_discard = 1
}
# Configuration section log.
@@ -724,7 +771,8 @@ log {
# Configuration option log/indent.
# Indent messages according to their severity.
indent = 1
# This configuration option has an automatic default value.
# indent = 0
# Configuration option log/command_names.
# Display the command name on each line of output.
@@ -750,6 +798,20 @@ log {
# available: memory, devices, io, activation, allocation,
# metadata, cache, locking, lvmpolld. Use "all" to see everything.
debug_classes = [ "memory", "devices", "io", "activation", "allocation", "metadata", "cache", "locking", "lvmpolld", "dbus" ]
# Configuration option log/debug_file_fields.
# The fields included in debug output written to log file.
# Use "all" to include everything (the default).
# This configuration option is advanced.
# This configuration option has an automatic default value.
# debug_file_fields = [ "time", "command", "fileline", "message" ]
# Configuration option log/debug_output_fields.
# The fields included in debug output written to stderr.
# Use "all" to include everything (the default).
# This configuration option is advanced.
# This configuration option has an automatic default value.
# debug_output_fields = [ "time", "command", "fileline", "message" ]
}
# Configuration section backup.
@@ -837,20 +899,6 @@ global {
# the error messages.
activation = 1
# Configuration option global/fallback_to_lvm1.
# This setting is no longer used.
# This configuration option has an automatic default value.
# fallback_to_lvm1 = 0
# Configuration option global/format.
# This setting is no longer used.
# This configuration option has an automatic default value.
# format = "lvm2"
# Configuration option global/format_libraries.
# This setting is no longer used.
# This configuration option does not have a default value defined.
# Configuration option global/segment_libraries.
# This configuration option does not have a default value defined.
@@ -863,22 +911,10 @@ global {
# Location of /etc system configuration directory.
etc = "@CONFDIR@"
# Configuration option global/locking_type.
# This setting is no longer used.
locking_type = 1
# Configuration option global/wait_for_locks.
# When disabled, fail if a lock request would block.
wait_for_locks = 1
# Configuration option global/fallback_to_clustered_locking.
# This setting is no longer used.
fallback_to_clustered_locking = 1
# Configuration option global/fallback_to_local_locking.
# This setting is no longer used.
fallback_to_local_locking = 1
# Configuration option global/locking_dir.
# Directory to use for LVM command file locks.
# Local non-LV directory that holds file-based locks while commands are
@@ -899,11 +935,6 @@ global {
# Search this directory first for shared libraries.
# This configuration option does not have a default value defined.
# Configuration option global/locking_library.
# This setting is no longer used.
# This configuration option has an automatic default value.
# locking_library = "liblvm2clusterlock.so"
# Configuration option global/abort_on_internal_errors.
# Abort a command that encounters an internal error.
# Treat any internal errors as fatal errors, aborting the process that
@@ -944,6 +975,16 @@ global {
#
mirror_segtype_default = "@DEFAULT_MIRROR_SEGTYPE@"
# Configuration option global/support_mirrored_mirror_log.
# Enable mirrored 'mirror' log type for testing.
#
# This type is deprecated to create or convert to but can
# be enabled to test that activation of existing mirrored
# logs and conversion to disk/core works.
#
# Not supported for regular operation!
support_mirrored_mirror_log = 0
# Configuration option global/raid10_segtype_default.
# The segment type used by the -i -m combination.
# The --type raid10|mirror option overrides this setting.
@@ -992,14 +1033,20 @@ global {
# This configuration option has an automatic default value.
# lvdisplay_shows_full_device_path = 0
# Configuration option global/use_lvmetad.
# This setting is no longer used.
use_lvmetad = 0
# Configuration option global/event_activation.
# Activate LVs based on system-generated device events.
# When a device appears on the system, a system-generated event runs
# the pvscan command to activate LVs if the new PV completes the VG.
# Use auto_activation_volume_list to select which LVs should be
# activated from these events (the default is all.)
# When event_activation is disabled, the system will generally run
# a direct activation command to activate LVs in complete VGs.
event_activation = 1
# Configuration option global/lvmetad_update_wait_time.
# This setting is no longer used.
# Configuration option global/use_aio.
# Use async I/O when reading and writing devices.
# This configuration option has an automatic default value.
# lvmetad_update_wait_time = 0
# use_aio = 1
# Configuration option global/use_lvmlockd.
# Use lvmlockd for locking among hosts using LVM on shared storage.
@@ -1193,6 +1240,16 @@ global {
# When enabled, an LVM command that changes PVs, changes VG metadata,
# or changes the activation state of an LV will send a notification.
notify_dbus = 1
# Configuration option global/io_memory_size.
# The amount of memory in KiB that LVM allocates to perform disk io.
# LVM performance may benefit from more io memory when there are many
# disks or VG metadata is large. Increasing this size may be necessary
# when a single copy of VG metadata is larger than the current setting.
# This value should usually not be decreased from the default; setting
# it too low can result in lvm failing to read VGs.
# This configuration option has an automatic default value.
# io_memory_size = 8192
}
# Configuration section activation.
@@ -1681,13 +1738,20 @@ activation {
# vgmetadatacopies = 0
# Configuration option metadata/pvmetadatasize.
# Approximate number of sectors to use for each metadata copy.
# VGs with large numbers of PVs or LVs, or VGs containing complex LV
# structures, may need additional space for VG metadata. The metadata
# areas are treated as circular buffers, so unused space becomes filled
# with an archive of the most recent previous versions of the metadata.
# The default size of the metadata area in units of 512 byte sectors.
# The metadata area begins at an offset of the page size from the start
# of the device. The first PE is by default at 1 MiB from the start of
# the device. The space between these is the default metadata area size.
# The actual size of the metadata area may be larger than what is set
# here due to default_data_alignment making the first PE a MiB multiple.
# The metadata area begins with a 512 byte header and is followed by a
# circular buffer used for VG metadata text. The maximum size of the VG
# metadata is about half the size of the metadata buffer. VGs with large
# numbers of PVs or LVs, or VGs containing complex LV structures, may need
# additional space for VG metadata. The --metadatasize option overrides
# this setting.
# This configuration option does not have a default value defined.
# This configuration option has an automatic default value.
# pvmetadatasize = 255
# Configuration option metadata/pvmetadataignore.
# Ignore metadata areas on a new PV.
@@ -1702,11 +1766,6 @@ activation {
# This configuration option is advanced.
# This configuration option has an automatic default value.
# stripesize = 64
# Configuration option metadata/dirs.
# This setting is no longer used.
# This configuration option is advanced.
# This configuration option does not have a default value defined.
# }
# Configuration section report.

View File

@@ -1,25 +1,24 @@
# Demo configuration for 'VDO' using less memory.
#
# ~lvmconfig --type full | grep vdo
allocation {
vdo_use_compression = 1
vdo_use_deduplication = 1
vdo_emulate_512_sectors = 0
vdo_block_map_cache_size_mb = 128
vdo_block_map_period = 16380
vdo_check_point_frequency = 0
vdo_use_sparse_index = 0
vdo_index_memory_size_mb = 256
vdo_use_read_cache = 0
vdo_read_cache_size_mb = 0
vdo_slab_size_mb = 2048
vdo_ack_threads = 1
vdo_bio_threads = 1
vdo_bio_rotation = 64
vdo_cpu_threads = 2
vdo_hash_zone_threads = 1
vdo_logical_threads = 1
vdo_physical_threads = 1
vdo_write_policy = "auto"
vdo_use_compression=1
vdo_use_deduplication=1
vdo_use_metadata_hints=1
vdo_minimum_io_size=4096
vdo_block_map_cache_size_mb=128
vdo_block_map_period=16380
vdo_check_point_frequency=0
vdo_use_sparse_index=0
vdo_index_memory_size_mb=256
vdo_slab_size_mb=2048
vdo_ack_threads=1
vdo_bio_threads=1
vdo_bio_rotation=64
vdo_cpu_threads=2
vdo_hash_zone_threads=1
vdo_logical_threads=1
vdo_physical_threads=1
vdo_write_policy="auto"
vdo_max_discard=1
}

165
configure vendored
View File

@@ -728,7 +728,6 @@ DEFAULT_PID_DIR
DEFAULT_MIRROR_SEGTYPE
DEFAULT_LOCK_DIR
DEFAULT_DM_RUN_DIR
DEFAULT_DATA_ALIGNMENT
DEFAULT_CACHE_SUBDIR
DEFAULT_BACKUP_SUBDIR
DEFAULT_ARCHIVE_SUBDIR
@@ -743,6 +742,7 @@ CLDNOWHOLEARCHIVE
CLDFLAGS
CACHE
BUILD_DMFILEMAPD
BUILD_LOCKDDLM_CONTROL
BUILD_LOCKDDLM
BUILD_LOCKDSANLOCK
BUILD_LVMLOCKD
@@ -772,6 +772,8 @@ BLKID_LIBS
BLKID_CFLAGS
NOTIFY_DBUS_LIBS
NOTIFY_DBUS_CFLAGS
LOCKD_DLM_CONTROL_LIBS
LOCKD_DLM_CONTROL_CFLAGS
LOCKD_DLM_LIBS
LOCKD_DLM_CFLAGS
LOCKD_SANLOCK_LIBS
@@ -915,6 +917,7 @@ with_cache_restore
enable_cache_check_needs_check
with_vdo
with_vdo_format
with_writecache
enable_readline
enable_realtime
enable_ocf
@@ -932,6 +935,7 @@ enable_devmapper
enable_lvmpolld
enable_lvmlockd_sanlock
enable_lvmlockd_dlm
enable_lvmlockd_dlmcontrol
enable_use_lvmlockd
with_lvmlockd_pidfile
enable_use_lvmpolld
@@ -973,7 +977,6 @@ with_default_archive_subdir
with_default_backup_subdir
with_default_cache_subdir
with_default_locking_dir
with_default_data_alignment
with_interface
'
ac_precious_vars='build_alias
@@ -1001,6 +1004,8 @@ LOCKD_SANLOCK_CFLAGS
LOCKD_SANLOCK_LIBS
LOCKD_DLM_CFLAGS
LOCKD_DLM_LIBS
LOCKD_DLM_CONTROL_CFLAGS
LOCKD_DLM_CONTROL_LIBS
NOTIFY_DBUS_CFLAGS
NOTIFY_DBUS_LIBS
BLKID_CFLAGS
@@ -1644,6 +1649,8 @@ Optional Features:
--enable-lvmlockd-sanlock
enable the LVM lock daemon using sanlock
--enable-lvmlockd-dlm enable the LVM lock daemon using dlm
--enable-lvmlockd-dlmcontrol
enable lvmlockd remote refresh using libdlmcontrol
--disable-use-lvmlockd disable usage of LVM lock daemon
--disable-use-lvmpolld disable usage of LVM Poll Daemon
--enable-dmfilemapd enable the dmstats filemap daemon
@@ -1708,6 +1715,7 @@ Optional Packages:
cache_restore tool: [autodetect]
--with-vdo=TYPE vdo support: internal/none [internal]
--with-vdo-format=PATH vdoformat tool: [autodetect]
--with-writecache=TYPE writecache support: internal/none [internal]
--with-ocfdir=DIR install OCF files in
[PREFIX/lib/ocf/resource.d/lvm2]
--with-default-pid-dir=PID_DIR
@@ -1752,8 +1760,6 @@ Optional Packages:
default metadata cache subdir [cache]
--with-default-locking-dir=DIR
default locking directory [autodetect_lock_dir/lvm]
--with-default-data-alignment=NUM
set the default data alignment in MiB [1]
--with-interface=IFACE choose kernel interface (ioctl) [ioctl]
Some influential environment variables:
@@ -1790,6 +1796,10 @@ Some influential environment variables:
C compiler flags for LOCKD_DLM, overriding pkg-config
LOCKD_DLM_LIBS
linker flags for LOCKD_DLM, overriding pkg-config
LOCKD_DLM_CONTROL_CFLAGS
C compiler flags for LOCKD_DLM_CONTROL, overriding pkg-config
LOCKD_DLM_CONTROL_LIBS
linker flags for LOCKD_DLM_CONTROL, overriding pkg-config
NOTIFY_DBUS_CFLAGS
C compiler flags for NOTIFY_DBUS, overriding pkg-config
NOTIFY_DBUS_LIBS
@@ -3079,6 +3089,7 @@ case "$host_os" in
BUILD_LVMPOLLD=no
LOCKDSANLOCK=no
LOCKDDLM=no
LOCKDDLM_CONTROL=no
ODIRECT=yes
DM_IOCTLS=yes
SELINUX=yes
@@ -6625,9 +6636,18 @@ fi
$as_echo "#define _GNU_SOURCE 1" >>confdefs.h
$as_echo "#define _REENTRANT 1" >>confdefs.h
################################################################################
for ac_func in ftruncate gethostname getpagesize gettimeofday localtime_r \
memchr memset mkdir mkfifo munmap nl_langinfo realpath rmdir setenv \
memchr memset mkdir mkfifo munmap nl_langinfo pselect realpath rmdir setenv \
setlocale strcasecmp strchr strcspn strdup strerror strncasecmp strndup \
strrchr strspn strstr strtol strtoul uname
do :
@@ -9705,6 +9725,31 @@ _ACEOF
# VDO_LIB=$withval, VDO_LIB="/usr/lib")
#AC_MSG_RESULT($VDO_LIB)
################################################################################
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to include writecache" >&5
$as_echo_n "checking whether to include writecache... " >&6; }
# Check whether --with-writecache was given.
if test "${with_writecache+set}" = set; then :
withval=$with_writecache; WRITECACHE=$withval
else
WRITECACHE="none"
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $WRITECACHE" >&5
$as_echo "$WRITECACHE" >&6; }
case "$WRITECACHE" in
none) ;;
internal)
$as_echo "#define WRITECACHE_INTERNAL 1" >>confdefs.h
;;
*) as_fn_error $? "--with-writecache parameter invalid" "$LINENO" 5 ;;
esac
################################################################################
# Check whether --enable-readline was given.
if test "${enable_readline+set}" = set; then :
@@ -10926,6 +10971,97 @@ $as_echo "#define LOCKDDLM_SUPPORT 1" >>confdefs.h
BUILD_LVMLOCKD=yes
fi
################################################################################
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build lvmlockddlmcontrol" >&5
$as_echo_n "checking whether to build lvmlockddlmcontrol... " >&6; }
# Check whether --enable-lvmlockd-dlmcontrol was given.
if test "${enable_lvmlockd_dlmcontrol+set}" = set; then :
enableval=$enable_lvmlockd_dlmcontrol; LOCKDDLM_CONTROL=$enableval
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $LOCKDDLM_CONTROL" >&5
$as_echo "$LOCKDDLM_CONTROL" >&6; }
BUILD_LOCKDDLM_CONTROL=$LOCKDDLM_CONTROL
if test "$BUILD_LOCKDDLM_CONTROL" = yes; then
pkg_failed=no
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LOCKD_DLM_CONTROL" >&5
$as_echo_n "checking for LOCKD_DLM_CONTROL... " >&6; }
if test -n "$LOCKD_DLM_CONTROL_CFLAGS"; then
pkg_cv_LOCKD_DLM_CONTROL_CFLAGS="$LOCKD_DLM_CONTROL_CFLAGS"
elif test -n "$PKG_CONFIG"; then
if test -n "$PKG_CONFIG" && \
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libdlmcontrol >= 3.2\""; } >&5
($PKG_CONFIG --exists --print-errors "libdlmcontrol >= 3.2") 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
pkg_cv_LOCKD_DLM_CONTROL_CFLAGS=`$PKG_CONFIG --cflags "libdlmcontrol >= 3.2" 2>/dev/null`
test "x$?" != "x0" && pkg_failed=yes
else
pkg_failed=yes
fi
else
pkg_failed=untried
fi
if test -n "$LOCKD_DLM_CONTROL_LIBS"; then
pkg_cv_LOCKD_DLM_CONTROL_LIBS="$LOCKD_DLM_CONTROL_LIBS"
elif test -n "$PKG_CONFIG"; then
if test -n "$PKG_CONFIG" && \
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libdlmcontrol >= 3.2\""; } >&5
($PKG_CONFIG --exists --print-errors "libdlmcontrol >= 3.2") 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
pkg_cv_LOCKD_DLM_CONTROL_LIBS=`$PKG_CONFIG --libs "libdlmcontrol >= 3.2" 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
LOCKD_DLM_CONTROL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libdlmcontrol >= 3.2" 2>&1`
else
LOCKD_DLM_CONTROL_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libdlmcontrol >= 3.2" 2>&1`
fi
# Put the nasty error message in config.log where it belongs
echo "$LOCKD_DLM_CONTROL_PKG_ERRORS" >&5
$bailout
elif test $pkg_failed = untried; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
$bailout
else
LOCKD_DLM_CONTROL_CFLAGS=$pkg_cv_LOCKD_DLM_CONTROL_CFLAGS
LOCKD_DLM_CONTROL_LIBS=$pkg_cv_LOCKD_DLM_CONTROL_LIBS
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
HAVE_LOCKD_DLM_CONTROL=yes
fi
$as_echo "#define LOCKDDLM_CONTROL_SUPPORT 1" >>confdefs.h
BUILD_LVMLOCKD=yes
fi
################################################################################
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build lvmlockd" >&5
$as_echo_n "checking whether to build lvmlockd... " >&6; }
@@ -11641,7 +11777,6 @@ fi
################################################################################
if test "$BUILD_LVMDBUSD" = yes; then
unset PYTHON_CONFIG
unset am_cv_pathless_PYTHON ac_cv_path_PYTHON am_cv_python_platform
unset am_cv_python_pythondir am_cv_python_version am_cv_python_pyexecdir
unset ac_cv_path_PYTHON_CONFIG ac_cv_path_ac_pt_PYTHON_CONFIG
@@ -13563,21 +13698,6 @@ cat >>confdefs.h <<_ACEOF
_ACEOF
################################################################################
# Check whether --with-default-data-alignment was given.
if test "${with_default_data_alignment+set}" = set; then :
withval=$with_default_data_alignment; DEFAULT_DATA_ALIGNMENT=$withval
else
DEFAULT_DATA_ALIGNMENT=1
fi
cat >>confdefs.h <<_ACEOF
#define DEFAULT_DATA_ALIGNMENT $DEFAULT_DATA_ALIGNMENT
_ACEOF
################################################################################
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for kernel interface choice" >&5
$as_echo_n "checking for kernel interface choice... " >&6; }
@@ -13772,7 +13892,7 @@ _ACEOF
################################################################################
ac_config_files="$ac_config_files Makefile make.tmpl libdm/make.tmpl daemons/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/dmeventd/plugins/vdo/Makefile daemons/lvmdbusd/Makefile daemons/lvmdbusd/lvmdbusd daemons/lvmdbusd/lvmdb.py daemons/lvmdbusd/lvm_shell_proxy.py daemons/lvmdbusd/path.py 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/Makefile lib/Makefile include/lvm-version.h libdaemon/Makefile libdaemon/client/Makefile libdaemon/server/Makefile libdm/Makefile libdm/dm-tools/Makefile libdm/libdevmapper.pc man/Makefile po/Makefile scripts/blkdeactivate.sh scripts/blk_availability_init_red_hat scripts/blk_availability_systemd_red_hat.service 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_cmirrord_systemd_red_hat.service scripts/lvm2_lvmdbusd_systemd_red_hat.service scripts/lvm2_lvmpolld_init_red_hat scripts/lvm2_lvmpolld_systemd_red_hat.service scripts/lvm2_lvmpolld_systemd_red_hat.socket scripts/lvmlockd.service scripts/lvmlocks.service scripts/lvm2_monitoring_init_red_hat scripts/lvm2_monitoring_systemd_red_hat.service scripts/lvm2_tmpfiles_red_hat.conf scripts/lvmdump.sh scripts/Makefile test/Makefile tools/Makefile udev/Makefile"
ac_config_files="$ac_config_files Makefile make.tmpl libdm/make.tmpl daemons/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/dmeventd/plugins/vdo/Makefile daemons/lvmdbusd/Makefile daemons/lvmdbusd/lvmdbusd daemons/lvmdbusd/lvmdb.py daemons/lvmdbusd/lvm_shell_proxy.py daemons/lvmdbusd/path.py 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/Makefile lib/Makefile include/lvm-version.h libdaemon/Makefile libdaemon/client/Makefile libdaemon/server/Makefile libdm/Makefile libdm/dm-tools/Makefile libdm/libdevmapper.pc man/Makefile po/Makefile scripts/lvm2-pvscan.service scripts/blkdeactivate.sh scripts/blk_availability_init_red_hat scripts/blk_availability_systemd_red_hat.service 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_cmirrord_systemd_red_hat.service scripts/lvm2_lvmdbusd_systemd_red_hat.service scripts/lvm2_lvmpolld_init_red_hat scripts/lvm2_lvmpolld_systemd_red_hat.service scripts/lvm2_lvmpolld_systemd_red_hat.socket scripts/lvmlockd.service scripts/lvmlocks.service scripts/lvm2_monitoring_init_red_hat scripts/lvm2_monitoring_systemd_red_hat.service scripts/lvm2_tmpfiles_red_hat.conf scripts/lvmdump.sh scripts/Makefile test/Makefile tools/Makefile udev/Makefile"
cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
@@ -14504,6 +14624,7 @@ do
"libdm/libdevmapper.pc") CONFIG_FILES="$CONFIG_FILES libdm/libdevmapper.pc" ;;
"man/Makefile") CONFIG_FILES="$CONFIG_FILES man/Makefile" ;;
"po/Makefile") CONFIG_FILES="$CONFIG_FILES po/Makefile" ;;
"scripts/lvm2-pvscan.service") CONFIG_FILES="$CONFIG_FILES scripts/lvm2-pvscan.service" ;;
"scripts/blkdeactivate.sh") CONFIG_FILES="$CONFIG_FILES scripts/blkdeactivate.sh" ;;
"scripts/blk_availability_init_red_hat") CONFIG_FILES="$CONFIG_FILES scripts/blk_availability_init_red_hat" ;;
"scripts/blk_availability_systemd_red_hat.service") CONFIG_FILES="$CONFIG_FILES scripts/blk_availability_systemd_red_hat.service" ;;

View File

@@ -42,6 +42,7 @@ case "$host_os" in
BUILD_LVMPOLLD=no
LOCKDSANLOCK=no
LOCKDDLM=no
LOCKDDLM_CONTROL=no
ODIRECT=yes
DM_IOCTLS=yes
SELINUX=yes
@@ -144,10 +145,15 @@ AC_TYPE_UINT64_T
AX_GCC_BUILTIN([__builtin_clz])
AX_GCC_BUILTIN([__builtin_clzll])
AC_DEFINE([_GNU_SOURCE], 1, [Define to get access to GNU/Linux extension])
AC_DEFINE([_REENTRANT], 1, [Define to use re-entrant thread safe versions])
################################################################################
dnl -- Check for functions
AC_CHECK_FUNCS([ftruncate gethostname getpagesize gettimeofday localtime_r \
memchr memset mkdir mkfifo munmap nl_langinfo realpath rmdir setenv \
memchr memset mkdir mkfifo munmap nl_langinfo pselect realpath rmdir setenv \
setlocale strcasecmp strchr strcspn strdup strerror strncasecmp strndup \
strrchr strspn strstr strtol strtoul uname], , [AC_MSG_ERROR(bailing out)])
AC_FUNC_ALLOCA
@@ -642,6 +648,24 @@ AC_DEFINE_UNQUOTED([VDO_FORMAT_CMD], ["$VDO_FORMAT_CMD"],
# VDO_LIB=$withval, VDO_LIB="/usr/lib")
#AC_MSG_RESULT($VDO_LIB)
################################################################################
dnl -- writecache inclusion type
AC_MSG_CHECKING(whether to include writecache)
AC_ARG_WITH(writecache,
AC_HELP_STRING([--with-writecache=TYPE],
[writecache support: internal/none [internal]]),
WRITECACHE=$withval, WRITECACHE="none")
AC_MSG_RESULT($WRITECACHE)
case "$WRITECACHE" in
none) ;;
internal)
AC_DEFINE([WRITECACHE_INTERNAL], 1, [Define to 1 to include built-in support for writecache.])
;;
*) AC_MSG_ERROR([--with-writecache parameter invalid]) ;;
esac
################################################################################
dnl -- Disable readline
AC_ARG_ENABLE([readline],
@@ -893,6 +917,24 @@ if test "$BUILD_LOCKDDLM" = yes; then
BUILD_LVMLOCKD=yes
fi
################################################################################
dnl -- Build lvmlockddlmcontrol
AC_MSG_CHECKING(whether to build lvmlockddlmcontrol)
AC_ARG_ENABLE(lvmlockd-dlmcontrol,
AC_HELP_STRING([--enable-lvmlockd-dlmcontrol],
[enable lvmlockd remote refresh using libdlmcontrol]),
LOCKDDLM_CONTROL=$enableval)
AC_MSG_RESULT($LOCKDDLM_CONTROL)
BUILD_LOCKDDLM_CONTROL=$LOCKDDLM_CONTROL
dnl -- Look for libdlmcontrol libraries
if test "$BUILD_LOCKDDLM_CONTROL" = yes; then
PKG_CHECK_MODULES(LOCKD_DLM_CONTROL, libdlmcontrol >= 3.2, [HAVE_LOCKD_DLM_CONTROL=yes], $bailout)
AC_DEFINE([LOCKDDLM_CONTROL_SUPPORT], 1, [Define to 1 to include code that uses lvmlockd dlm control option.])
BUILD_LVMLOCKD=yes
fi
################################################################################
dnl -- Build lvmlockd
AC_MSG_CHECKING(whether to build lvmlockd)
@@ -1154,7 +1196,6 @@ AS_IF([test "$NOTIFYDBUS_SUPPORT" = yes && test "BUILD_LVMDBUSD" = yes],
dnl -- Enable Python dbus library
if test "$BUILD_LVMDBUSD" = yes; then
unset PYTHON_CONFIG
unset am_cv_pathless_PYTHON ac_cv_path_PYTHON am_cv_python_platform
unset am_cv_python_pythondir am_cv_python_version am_cv_python_pyexecdir
unset ac_cv_path_PYTHON_CONFIG ac_cv_path_ac_pt_PYTHON_CONFIG
@@ -1580,15 +1621,6 @@ AC_ARG_WITH(default-locking-dir,
AC_DEFINE_UNQUOTED(DEFAULT_LOCK_DIR, ["$DEFAULT_LOCK_DIR"],
[Name of default locking directory.])
################################################################################
dnl -- Setup default data alignment
AC_ARG_WITH(default-data-alignment,
AC_HELP_STRING([--with-default-data-alignment=NUM],
[set the default data alignment in MiB [1]]),
DEFAULT_DATA_ALIGNMENT=$withval, DEFAULT_DATA_ALIGNMENT=1)
AC_DEFINE_UNQUOTED(DEFAULT_DATA_ALIGNMENT, [$DEFAULT_DATA_ALIGNMENT],
[Default data alignment.])
################################################################################
dnl -- which kernel interface to use (ioctl only)
AC_MSG_CHECKING(for kernel interface choice)
@@ -1629,6 +1661,7 @@ AC_SUBST(BUILD_LVMPOLLD)
AC_SUBST(BUILD_LVMLOCKD)
AC_SUBST(BUILD_LOCKDSANLOCK)
AC_SUBST(BUILD_LOCKDDLM)
AC_SUBST(BUILD_LOCKDDLM_CONTROL)
AC_SUBST(BUILD_DMFILEMAPD)
AC_SUBST(CACHE)
AC_SUBST(CFLAGS)
@@ -1649,7 +1682,6 @@ AC_SUBST(DEBUG)
AC_SUBST(DEFAULT_ARCHIVE_SUBDIR)
AC_SUBST(DEFAULT_BACKUP_SUBDIR)
AC_SUBST(DEFAULT_CACHE_SUBDIR)
AC_SUBST(DEFAULT_DATA_ALIGNMENT)
AC_SUBST(DEFAULT_DM_RUN_DIR)
AC_SUBST(DEFAULT_LOCK_DIR)
AC_SUBST(DEFAULT_MIRROR_SEGTYPE)
@@ -1810,6 +1842,7 @@ libdm/dm-tools/Makefile
libdm/libdevmapper.pc
man/Makefile
po/Makefile
scripts/lvm2-pvscan.service
scripts/blkdeactivate.sh
scripts/blk_availability_init_red_hat
scripts/blk_availability_systemd_red_hat.service

View File

@@ -28,9 +28,11 @@ LMLIBS += $(CPG_LIBS)
CFLAGS += $(CPG_CFLAGS) $(EXTRA_EXEC_CFLAGS)
LDFLAGS += $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS)
cmirrord: $(OBJECTS) $(top_builddir)/lib/liblvm-internal.a
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJECTS) \
$(LVMLIBS) $(LMLIBS) $(INTERNAL_LIBS) $(LIBS)
cmirrord: $(OBJECTS)
@echo " [CC] $@"
$(Q) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJECTS) \
$(LMLIBS) -L$(top_builddir)/libdm -ldevmapper $(LIBS)
install: $(TARGETS)
$(INSTALL_PROGRAM) -D cmirrord $(usrsbindir)/cmirrord
@echo " [INSTALL] $<"
$(Q) $(INSTALL_PROGRAM) -D cmirrord $(usrsbindir)/cmirrord

View File

@@ -17,6 +17,7 @@
#include "link_mon.h"
#include "local.h"
#include "lib/mm/xlate.h"
#include "base/memory/zalloc.h"
/* FIXME: remove this and the code */
#define CMIRROR_HAS_CHECKPOINT 0
@@ -402,13 +403,12 @@ static struct checkpoint_data *prepare_checkpoint(struct clog_cpg *entry,
return NULL;
}
new = malloc(sizeof(*new));
new = zalloc(sizeof(*new));
if (!new) {
LOG_ERROR("Unable to create checkpoint data for %u",
cp_requester);
return NULL;
}
memset(new, 0, sizeof(*new));
new->requester = cp_requester;
strncpy(new->uuid, entry->name.value, entry->name.length);
@@ -643,13 +643,12 @@ static int export_checkpoint(struct checkpoint_data *cp)
rq_size += RECOVERING_REGION_SECTION_SIZE;
rq_size += cp->bitmap_size * 2; /* clean|sync_bits */
rq = malloc(rq_size);
rq = zalloc(rq_size);
if (!rq) {
LOG_ERROR("export_checkpoint: "
"Unable to allocate transfer structs");
return -ENOMEM;
}
memset(rq, 0, rq_size);
dm_list_init(&rq->u.list);
rq->u_rq.request_type = DM_ULOG_CHECKPOINT_READY;
@@ -1621,12 +1620,11 @@ int create_cluster_cpg(char *uuid, uint64_t luid)
return -EEXIST;
}
new = malloc(sizeof(*new));
new = zalloc(sizeof(*new));
if (!new) {
LOG_ERROR("Unable to allocate memory for clog_cpg");
return -ENOMEM;
}
memset(new, 0, sizeof(*new));
dm_list_init(&new->list);
new->lowest_id = 0xDEAD;
dm_list_init(&new->startup_list);

View File

@@ -12,8 +12,8 @@
#ifndef _LVM_CLOG_CLUSTER_H
#define _LVM_CLOG_CLUSTER_H
#include "device_mapper/misc/dm-log-userspace.h"
#include "device_mapper/all.h"
#include "libdm/misc/dm-log-userspace.h"
#include "libdm/libdevmapper.h"
#define DM_ULOG_RESPONSE 0x1000U /* in last byte of 32-bit value */
#define DM_ULOG_CHECKPOINT_READY 21

View File

@@ -13,9 +13,6 @@
#ifndef _LVM_CLOG_LOGGING_H
#define _LVM_CLOG_LOGGING_H
#define _GNU_SOURCE
#include "configure.h"
#include <stdio.h>
#include <stdint.h>
#include <syslog.h>

View File

@@ -57,14 +57,16 @@ all: device-mapper
device-mapper: $(TARGETS)
CFLAGS_dmeventd.o += $(EXTRA_EXEC_CFLAGS)
LIBS += $(PTHREAD_LIBS)
LIBS += $(PTHREAD_LIBS) -L$(top_builddir)/libdm -ldevmapper
dmeventd: $(LIB_SHARED) dmeventd.o
$(CC) $(CFLAGS) -L. $(LDFLAGS) $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS) dmeventd.o \
-o $@ $(DL_LIBS) $(DMEVENT_LIBS) $(INTERNAL_LIBS) $(LIBS) -lm
@echo " [CC] $@"
$(Q) $(CC) $(CFLAGS) -L. $(LDFLAGS) $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS) dmeventd.o \
-o $@ $(DL_LIBS) $(DMEVENT_LIBS) $(LIBS) -lm
dmeventd.static: $(LIB_STATIC) dmeventd.o
$(CC) $(CFLAGS) $(LDFLAGS) -static -L. -L$(interfacebuilddir) dmeventd.o \
@echo " [CC] $@"
$(Q) $(CC) $(CFLAGS) $(LDFLAGS) -static -L. -L$(interfacebuilddir) dmeventd.o \
-o $@ $(DL_LIBS) $(DMEVENT_LIBS) $(LIBS) $(STATIC_LIBS)
ifeq ("@PKGCONFIG@", "yes")
@@ -80,23 +82,28 @@ CFLOW_SOURCES = $(addprefix $(srcdir)/, $(SOURCES))
endif
install_include: $(srcdir)/libdevmapper-event.h
$(INSTALL_DATA) -D $< $(includedir)/$(<F)
@echo " [INSTALL] $<"
$(Q) $(INSTALL_DATA) -D $< $(includedir)/$(<F)
install_pkgconfig: libdevmapper-event.pc
$(INSTALL_DATA) -D $< $(pkgconfigdir)/devmapper-event.pc
@echo " [INSTALL] $<"
$(Q) $(INSTALL_DATA) -D $< $(pkgconfigdir)/devmapper-event.pc
install_lib_dynamic: install_lib_shared
install_lib_static: $(LIB_STATIC)
$(INSTALL_DATA) -D $< $(usrlibdir)/$(<F)
@echo " [INSTALL] $<"
$(Q) $(INSTALL_DATA) -D $< $(usrlibdir)/$(<F)
install_lib: $(INSTALL_LIB_TARGETS)
install_dmeventd_dynamic: dmeventd
$(INSTALL_PROGRAM) -D $< $(sbindir)/$(<F)
@echo " [INSTALL] $<"
$(Q) $(INSTALL_PROGRAM) -D $< $(sbindir)/$(<F)
install_dmeventd_static: dmeventd.static
$(INSTALL_PROGRAM) -D $< $(staticdir)/$(<F)
@echo " [INSTALL] $<"
$(Q) $(INSTALL_PROGRAM) -D $< $(staticdir)/$(<F)
install_dmeventd: $(INSTALL_DMEVENTD_TARGETS)

View File

@@ -16,14 +16,12 @@
* dmeventd - dm event daemon to monitor active mapped devices
*/
#include "device_mapper/misc/dmlib.h"
#include "base/memory/zalloc.h"
#include "device_mapper/misc/dm-logging.h"
#include "daemons/dmeventd/libdevmapper-event.h"
#include "libdevmapper-event.h"
#include "dmeventd.h"
#include "tools/tool.h"
#include "libdm/misc/dm-logging.h"
#include "base/memory/zalloc.h"
#include <dlfcn.h>
#include <pthread.h>
@@ -35,6 +33,8 @@
#include <signal.h>
#include <arpa/inet.h> /* for htonl, ntohl */
#include <fcntl.h> /* for musl libc */
#include <unistd.h>
#include <syslog.h>
#ifdef __linux__
/*
@@ -62,8 +62,6 @@
#endif
#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 */

View File

@@ -12,11 +12,11 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "device_mapper/misc/dmlib.h"
#include "base/memory/zalloc.h"
#include "device_mapper/misc/dm-logging.h"
#include "daemons/dmeventd/libdevmapper-event.h"
#include "libdevmapper-event.h"
#include "dmeventd.h"
#include "libdm/misc/dm-logging.h"
#include "base/memory/zalloc.h"
#include "lib/misc/intl.h"
#include <fcntl.h>

View File

@@ -21,6 +21,7 @@
#ifndef LIB_DMEVENT_H
#define LIB_DMEVENT_H
#include <stdarg.h>
#include <stdint.h>
/*

View File

@@ -16,6 +16,7 @@ top_srcdir = @top_srcdir@
top_builddir = @top_builddir@
CLDFLAGS += -L$(top_builddir)/tools
LIBS += $(DMEVENT_LIBS) $(PTHREAD_LIBS) @LVM2CMD_LIB@
SOURCES = dmeventd_lvm.c
@@ -24,8 +25,6 @@ LIB_VERSION = $(LIB_VERSION_LVM)
include $(top_builddir)/make.tmpl
LIBS += @LVM2CMD_LIB@ $(INTERNAL_LIBS) $(PTHREAD_LIBS)
install_lvm2: install_lib_shared
install: install_lvm2

View File

@@ -159,6 +159,7 @@ int dmeventd_lvm2_command(struct dm_pool *mem, char *buffer, size_t size,
dmeventd_lvm2_lock();
if (!dmeventd_lvm2_run(cmd) ||
!(env = getenv(cmd))) {
dmeventd_lvm2_unlock();
log_error("Unable to find configured command.");
return 0;
}

View File

@@ -16,8 +16,8 @@ srcdir = @srcdir@
top_srcdir = @top_srcdir@
top_builddir = @top_builddir@
INCLUDES += -I$(top_srcdir)/daemons/dmeventd/plugins/lvm2
CLDFLAGS += -L$(top_builddir)/daemons/dmeventd/plugins/lvm2
LIBS += -ldevmapper-event-lvm2
SOURCES = dmeventd_mirror.c
@@ -30,8 +30,6 @@ CFLOW_LIST_TARGET = $(LIB_NAME).cflow
include $(top_builddir)/make.tmpl
LIBS += -ldevmapper-event-lvm2 $(INTERNAL_LIBS)
install_lvm2: install_dm_plugin
install: install_lvm2

View File

@@ -13,8 +13,8 @@
*/
#include "lib/misc/lib.h"
#include "daemons/dmeventd/plugins/lvm2/dmeventd_lvm.h"
#include "daemons/dmeventd/libdevmapper-event.h"
#include "dmeventd_lvm.h"
#include "lib/activate/activate.h"
/* FIXME Reformat to 80 char lines. */

View File

@@ -15,8 +15,8 @@ srcdir = @srcdir@
top_srcdir = @top_srcdir@
top_builddir = @top_builddir@
INCLUDES += -I$(top_srcdir)/daemons/dmeventd/plugins/lvm2
CLDFLAGS += -L$(top_builddir)/daemons/dmeventd/plugins/lvm2
LIBS += -ldevmapper-event-lvm2
SOURCES = dmeventd_raid.c
@@ -29,8 +29,6 @@ CFLOW_LIST_TARGET = $(LIB_NAME).cflow
include $(top_builddir)/make.tmpl
LIBS += -ldevmapper-event-lvm2 $(INTERNAL_LIBS)
install_lvm2: install_dm_plugin
install: install_lvm2

View File

@@ -13,9 +13,9 @@
*/
#include "lib/misc/lib.h"
#include "lib/config/defaults.h"
#include "dmeventd_lvm.h"
#include "daemons/dmeventd/plugins/lvm2/dmeventd_lvm.h"
#include "daemons/dmeventd/libdevmapper-event.h"
#include "lib/config/defaults.h"
/* Hold enough elements for the mximum number of RAID images */
#define RAID_DEVS_ELEMS ((DEFAULT_RAID_MAX_IMAGES + 63) / 64)

View File

@@ -16,8 +16,8 @@ srcdir = @srcdir@
top_srcdir = @top_srcdir@
top_builddir = @top_builddir@
INCLUDES += -I$(top_srcdir)/daemons/dmeventd/plugins/lvm2
CLDFLAGS += -L$(top_builddir)/daemons/dmeventd/plugins/lvm2
LIBS += -ldevmapper-event-lvm2
SOURCES = dmeventd_snapshot.c
@@ -26,8 +26,6 @@ LIB_VERSION = $(LIB_VERSION_LVM)
include $(top_builddir)/make.tmpl
LIBS += -ldevmapper-event-lvm2 $(INTERNAL_LIBS)
install_lvm2: install_dm_plugin
install: install_lvm2

View File

@@ -13,7 +13,7 @@
*/
#include "lib/misc/lib.h"
#include "dmeventd_lvm.h"
#include "daemons/dmeventd/plugins/lvm2/dmeventd_lvm.h"
#include "daemons/dmeventd/libdevmapper-event.h"
#include <sys/sysmacros.h>
@@ -175,6 +175,7 @@ void process_event(struct dm_task *dmt,
const char *device = dm_task_get_name(dmt);
int percent;
struct dm_info info;
int ret;
/* No longer monitoring, waiting for remove */
if (!state->percent_check)
@@ -205,7 +206,8 @@ void process_event(struct dm_task *dmt,
/* Maybe configurable ? */
_remove(dm_task_get_uuid(dmt));
#endif
pthread_kill(pthread_self(), SIGALRM);
if ((ret = pthread_kill(pthread_self(), SIGALRM)) && (ret != ESRCH))
log_sys_error("pthread_kill", "self");
goto out;
}
@@ -213,7 +215,8 @@ void process_event(struct dm_task *dmt,
/* TODO eventually recognize earlier when room is enough */
log_info("Dropping monitoring of fully provisioned snapshot %s.",
device);
pthread_kill(pthread_self(), SIGALRM);
if ((ret = pthread_kill(pthread_self(), SIGALRM)) && (ret != ESRCH))
log_sys_error("pthread_kill", "self");
goto out;
}

View File

@@ -15,8 +15,8 @@ srcdir = @srcdir@
top_srcdir = @top_srcdir@
top_builddir = @top_builddir@
INCLUDES += -I$(top_srcdir)/daemons/dmeventd/plugins/lvm2
CLDFLAGS += -L$(top_builddir)/daemons/dmeventd/plugins/lvm2
LIBS += -ldevmapper-event-lvm2
SOURCES = dmeventd_thin.c
@@ -29,8 +29,6 @@ CFLOW_LIST_TARGET = $(LIB_NAME).cflow
include $(top_builddir)/make.tmpl
LIBS += -ldevmapper-event-lvm2 $(INTERNAL_LIBS)
install_lvm2: install_dm_plugin
install: install_lvm2

View File

@@ -13,7 +13,7 @@
*/
#include "lib/misc/lib.h"
#include "dmeventd_lvm.h"
#include "daemons/dmeventd/plugins/lvm2/dmeventd_lvm.h"
#include "daemons/dmeventd/libdevmapper-event.h"
#include <sys/wait.h>

View File

@@ -15,8 +15,8 @@ srcdir = @srcdir@
top_srcdir = @top_srcdir@
top_builddir = @top_builddir@
INCLUDES += -I$(top_srcdir)/daemons/dmeventd/plugins/lvm2
CLDFLAGS += -L$(top_builddir)/daemons/dmeventd/plugins/lvm2
LIBS += -ldevmapper-event-lvm2
SOURCES = dmeventd_vdo.c
@@ -29,8 +29,6 @@ CFLOW_LIST_TARGET = $(LIB_NAME).cflow
include $(top_builddir)/make.tmpl
LIBS += -ldevmapper-event-lvm2 $(INTERNAL_LIBS)
install_lvm2: install_dm_plugin
install: install_lvm2

View File

@@ -13,9 +13,11 @@
*/
#include "lib/misc/lib.h"
#include "dmeventd_lvm.h"
#include "daemons/dmeventd/plugins/lvm2/dmeventd_lvm.h"
#include "daemons/dmeventd/libdevmapper-event.h"
#include "device_mapper/vdo/target.h"
/* Use parser from new device_mapper library */
#include "device_mapper/vdo/status.c"
#include <sys/wait.h>
#include <stdarg.h>
@@ -253,8 +255,7 @@ void process_event(struct dm_task *dmt,
} else
state->max_fails = 1; /* Reset on success */
/* FIXME: ATM nothing can be done, drop 0, once it becomes useful */
if (0 && needs_policy)
if (needs_policy)
_use_policy(dmt, state);
out:
if (vdop.status)

View File

@@ -23,11 +23,10 @@ LVMDBUS_SRCDIR_FILES = \
cfg.py \
cmdhandler.py \
fetch.py \
__init__.py \
job.py \
loader.py \
main.py \
lv.py \
main.py \
manager.py \
objectmanager.py \
pv.py \
@@ -35,7 +34,8 @@ LVMDBUS_SRCDIR_FILES = \
state.py \
udevwatch.py \
utils.py \
vg.py
vg.py \
__init__.py
LVMDBUS_BUILDDIR_FILES = \
lvmdb.py \
@@ -51,17 +51,18 @@ include $(top_builddir)/make.tmpl
.PHONY: install_lvmdbusd
all:
test -x $(LVMDBUSD) || chmod 755 $(LVMDBUSD)
$(Q) test -x $(LVMDBUSD) || chmod 755 $(LVMDBUSD)
install_lvmdbusd:
$(INSTALL_DIR) $(sbindir)
$(INSTALL_SCRIPT) $(LVMDBUSD) $(sbindir)
$(INSTALL_DIR) $(DESTDIR)$(lvmdbusdir)
(cd $(srcdir); $(INSTALL_DATA) $(LVMDBUS_SRCDIR_FILES) $(DESTDIR)$(lvmdbusdir))
$(INSTALL_DATA) $(LVMDBUS_BUILDDIR_FILES) $(DESTDIR)$(lvmdbusdir)
PYTHON=$(PYTHON3) $(PYCOMPILE) --destdir "$(DESTDIR)" --basedir "$(lvmdbusdir)" $(LVMDBUS_SRCDIR_FILES) $(LVMDBUS_BUILDDIR_FILES)
$(CHMOD) 755 $(DESTDIR)$(lvmdbusdir)/__pycache__
$(CHMOD) 444 $(DESTDIR)$(lvmdbusdir)/__pycache__/*.py[co]
@echo " [INSTALL] $<"
$(Q) $(INSTALL_DIR) $(sbindir)
$(Q) $(INSTALL_SCRIPT) $(LVMDBUSD) $(sbindir)
$(Q) $(INSTALL_DIR) $(DESTDIR)$(lvmdbusdir)
$(Q) (cd $(srcdir); $(INSTALL_DATA) $(LVMDBUS_SRCDIR_FILES) $(DESTDIR)$(lvmdbusdir))
$(Q) $(INSTALL_DATA) $(LVMDBUS_BUILDDIR_FILES) $(DESTDIR)$(lvmdbusdir)
$(Q) PYTHON=$(PYTHON3) $(PYCOMPILE) --destdir "$(DESTDIR)" --basedir "$(lvmdbusdir)" $(LVMDBUS_SRCDIR_FILES) $(LVMDBUS_BUILDDIR_FILES)
$(Q) $(CHMOD) 755 $(DESTDIR)$(lvmdbusdir)/__pycache__
$(Q) $(CHMOD) 444 $(DESTDIR)$(lvmdbusdir)/__pycache__/*.py[co]
install_lvm2: install_lvmdbusd

View File

@@ -155,7 +155,7 @@ class AutomatedProperties(dbus.service.Object):
# through all dbus objects as some don't have a search method, like
# 'Manager' object.
if not self._ap_search_method:
return
return 0
search = self.lvm_id
if search_key:

View File

@@ -87,3 +87,13 @@ blackbox = None
# RequestEntry ctor
create_request_entry = None
def exit_daemon():
"""
Exit the daemon cleanly
:return:
"""
if run and loop:
run.value = 0
loop.quit()

View File

@@ -67,7 +67,7 @@ class LvmFlightRecorder(object):
with cmd_lock:
if len(self.queue):
log_error("LVM dbus flight recorder START")
for c in self.queue:
for c in reversed(self.queue):
log_error(str(c))
log_error("LVM dbus flight recorder END")
@@ -263,10 +263,10 @@ def lv_tag(lv_name, add, rm, tag_options):
return _tag('lvchange', lv_name, add, rm, tag_options)
def vg_rename(vg, new_name, rename_options):
def vg_rename(vg_uuid, new_name, rename_options):
cmd = ['vgrename']
cmd.extend(options_to_cli_args(rename_options))
cmd.extend([vg, new_name])
cmd.extend([vg_uuid, new_name])
return call(cmd)
@@ -497,7 +497,8 @@ def lvm_full_report_json():
])
rc, out, err = call(cmd)
if rc == 0:
# When we have an exported vg the exit code of lvs or fullreport will be 5
if rc == 0 or rc == 5:
# With the current implementation, if we are using the shell then we
# are using JSON and JSON is returned back to us as it was parsed to
# figure out if we completed OK or not

View File

@@ -14,6 +14,7 @@ from . import cfg
from .utils import MThreadRunner, log_debug, log_error
import threading
import queue
import time
import traceback
@@ -82,6 +83,8 @@ class StateUpdate(object):
@staticmethod
def update_thread(obj):
exception_count = 0
queued_requests = []
while cfg.run.value != 0:
# noinspection PyBroadException
@@ -136,12 +139,26 @@ class StateUpdate(object):
# wake up if we get an exception
queued_requests = []
# We retrieved OK, clear exception count
exception_count = 0
except queue.Empty:
pass
except Exception:
except Exception as e:
st = traceback.format_exc()
log_error("update_thread exception: \n%s" % st)
cfg.blackbox.dump()
exception_count += 1
if exception_count >= 5:
for i in queued_requests:
i.set_result(e)
log_error("Too many errors in update_thread, exiting daemon")
cfg.exit_daemon()
else:
# Slow things down when encountering errors
time.sleep(1)
def __init__(self):
self.lock = threading.RLock()

View File

@@ -10,7 +10,7 @@
from .automatedproperties import AutomatedProperties
from . import utils
from .utils import vg_obj_path_generate
from .utils import vg_obj_path_generate, log_error
import dbus
from . import cmdhandler
from . import cfg
@@ -24,6 +24,8 @@ from . import background
from .utils import round_size, mt_remove_dbus_objects
from .job import JobState
import traceback
# Try and build a key for a LV, so that we sort the LVs with least dependencies
# first. This may be error prone because of the flexibility LVM
@@ -291,6 +293,22 @@ class LvCommon(AutomatedProperties):
(lv_uuid, lv_name))
return dbo
def attr_struct(self, index, type_map, default='undisclosed'):
try:
if self.state.Attr[index] not in type_map:
log_error("LV %s %s with lv_attr %s, lv_attr[%d] = "
"'%s' is not known" %
(self.Uuid, self.Name, self.Attr, index,
self.state.Attr[index]))
return dbus.Struct((self.state.Attr[index],
type_map.get(self.state.Attr[index], default)),
signature="(ss)")
except BaseException:
st = traceback.format_exc()
log_error("attr_struct: \n%s" % st)
return dbus.Struct(('?', 'Unavailable'), signature="(ss)")
@property
def VolumeType(self):
type_map = {'C': 'Cache', 'm': 'mirrored',
@@ -304,16 +322,14 @@ class LvCommon(AutomatedProperties):
'V': 'thin Volume', 't': 'thin pool', 'T': 'Thin pool data',
'e': 'raid or pool metadata or pool metadata spare',
'-': 'Unspecified'}
return dbus.Struct((self.state.Attr[0], type_map[self.state.Attr[0]]),
signature="as")
return self.attr_struct(0, type_map)
@property
def Permissions(self):
type_map = {'w': 'writable', 'r': 'read-only',
'R': 'Read-only activation of non-read-only volume',
'-': 'Unspecified'}
return dbus.Struct((self.state.Attr[1], type_map[self.state.Attr[1]]),
signature="(ss)")
return self.attr_struct(1, type_map)
@property
def AllocationPolicy(self):
@@ -322,8 +338,7 @@ class LvCommon(AutomatedProperties):
'i': 'inherited', 'I': 'inherited locked',
'l': 'cling', 'L': 'cling locked',
'n': 'normal', 'N': 'normal locked', '-': 'Unspecified'}
return dbus.Struct((self.state.Attr[2], type_map[self.state.Attr[2]]),
signature="(ss)")
return self.attr_struct(2, type_map)
@property
def FixedMinor(self):
@@ -331,15 +346,20 @@ class LvCommon(AutomatedProperties):
@property
def State(self):
type_map = {'a': 'active', 's': 'suspended', 'I': 'Invalid snapshot',
type_map = {'a': 'active',
's': 'suspended',
'I': 'Invalid snapshot',
'S': 'invalid Suspended snapshot',
'm': 'snapshot merge failed',
'M': 'suspended snapshot (M)erge failed',
'd': 'mapped device present without tables',
'i': 'mapped device present with inactive table',
'X': 'unknown', '-': 'Unspecified'}
return dbus.Struct((self.state.Attr[4], type_map[self.state.Attr[4]]),
signature="(ss)")
'h': 'historical',
'c': 'check needed suspended thin-pool',
'C': 'check needed',
'X': 'unknown',
'-': 'Unspecified'}
return self.attr_struct(4, type_map)
@property
def TargetType(self):
@@ -355,11 +375,18 @@ class LvCommon(AutomatedProperties):
@property
def Health(self):
type_map = {'p': 'partial', 'r': 'refresh',
'm': 'mismatches', 'w': 'writemostly',
'X': 'X unknown', '-': 'Unspecified'}
return dbus.Struct((self.state.Attr[8], type_map[self.state.Attr[8]]),
signature="(ss)")
type_map = {'p': 'partial',
'r': 'refresh needed',
'm': 'mismatches',
'w': 'writemostly',
'X': 'unknown',
'-': 'unspecified',
's': 'reshaping',
'F': 'failed',
'D': 'Data space',
'R': 'Remove',
'M': 'Metadata'}
return self.attr_struct(8, type_map)
@property
def SkipActivation(self):

View File

@@ -220,7 +220,10 @@ class LVMShellProxy(object):
# Parse the report to see what happened
if 'log' in report_json:
if report_json['log'][-1:][0]['log_ret_code'] == '1':
ret_code = int(report_json['log'][-1:][0]['log_ret_code'])
# If we have an exported vg we get a log_ret_code == 5 when
# we do a 'fullreport'
if (ret_code == 1) or (ret_code == 5 and argv[0] == 'fullreport'):
rc = 0
else:
error_msg = self.get_error_msg()

View File

@@ -141,13 +141,22 @@ class DataStore(object):
@staticmethod
def _parse_vgs(_vgs):
vgs = sorted(_vgs, key=lambda vk: vk['vg_name'])
vgs = sorted(_vgs, key=lambda vk: vk['vg_uuid'])
c_vgs = OrderedDict()
c_lookup = {}
for i in vgs:
c_lookup[i['vg_name']] = i['vg_uuid']
vg_name = i['vg_name']
# Lvm allows duplicate vg names. When this occurs, each subsequent
# matching VG name will be called vg_name:vg_uuid. Note: ':' is an
# invalid character for lvm VG names
if vg_name in c_lookup:
vg_name = "%s:%s" % (vg_name, i['vg_uuid'])
i['vg_name'] = vg_name
c_lookup[vg_name] = i['vg_uuid']
DataStore._insert_record(c_vgs, i['vg_uuid'], i, [])
return c_vgs, c_lookup
@@ -162,13 +171,22 @@ class DataStore(object):
tmp_vg.extend(r['vg'])
# Sort for consistent output, however this is optional
vgs = sorted(tmp_vg, key=lambda vk: vk['vg_name'])
vgs = sorted(tmp_vg, key=lambda vk: vk['vg_uuid'])
c_vgs = OrderedDict()
c_lookup = {}
for i in vgs:
c_lookup[i['vg_name']] = i['vg_uuid']
vg_name = i['vg_name']
# Lvm allows duplicate vg names. When this occurs, each subsequent
# matching VG name will be called vg_name:vg_uuid. Note: ':' is an
# invalid character for lvm VG names
if vg_name in c_lookup:
vg_name = "%s:%s" % (vg_name, i['vg_uuid'])
i['vg_name'] = vg_name
c_lookup[vg_name] = i['vg_uuid']
c_vgs[i['vg_uuid']] = i
return c_vgs, c_lookup
@@ -521,6 +539,10 @@ if __name__ == "__main__":
for v in ds.vgs.values():
pp.pprint(v)
print("VG name to UUID")
for k, v in ds.vg_name_to_uuid.items():
print("%s: %s" % (k, v))
print("LVS")
for v in ds.lvs.values():
pp.pprint(v)

View File

@@ -164,6 +164,8 @@ class Manager(AutomatedProperties):
return the object path in O(1) time.
:param key: The lookup value
:param cb: dbus python call back parameter, not client visible
:param cbe: dbus python error call back parameter, not client visible
:return: Return the object path. If object not found you will get '/'
"""
r = RequestEntry(-1, Manager._lookup_by_lvm_id, (key,), cb, cbe, False)

View File

@@ -189,8 +189,8 @@ class ObjectManager(AutomatedProperties):
path = dbus_object.dbus_object_path()
interfaces = dbus_object.interface()
# print 'UN-Registering object path %s for %s' % \
# (path, dbus_object.lvm_id)
# print('UN-Registering object path %s for %s' %
# (path, dbus_object.lvm_id))
self._lookup_remove(path)
@@ -240,39 +240,19 @@ class ObjectManager(AutomatedProperties):
return lookup_rc
return '/'
def _uuid_verify(self, path, uuid, lvm_id):
def _id_verify(self, path, uuid, lvm_id):
"""
Ensure uuid is present for a successful lvm_id lookup
Ensure our lookups are correct
NOTE: Internal call, assumes under object manager lock
:param path: Path to object we looked up
:param uuid: lvm uuid to verify
:param lvm_id: lvm_id used to find object
:param uuid: uuid lookup
:param lvm_id: lvm_id lookup
:return: None
"""
# This gets called when we found an object based on lvm_id, ensure
# uuid is correct too, as they can change. There is no durable
# non-changeable name in lvm
# There is no durable non-changeable name in lvm
if lvm_id != uuid:
if uuid and uuid not in self._id_to_object_path:
obj = self.get_object_by_path(path)
self._lookup_add(obj, path, lvm_id, uuid)
def _lvm_id_verify(self, path, uuid, lvm_id):
"""
Ensure lvm_id is present for a successful uuid lookup
NOTE: Internal call, assumes under object manager lock
:param path: Path to object we looked up
:param uuid: uuid used to find object
:param lvm_id: lvm_id to verify
:return: None
"""
# This gets called when we found an object based on uuid, ensure
# lvm_id is correct too, as they can change. There is no durable
# non-changeable name in lvm
if lvm_id != uuid:
if lvm_id and lvm_id not in self._id_to_object_path:
obj = self.get_object_by_path(path)
self._lookup_add(obj, path, lvm_id, uuid)
obj = self.get_object_by_path(path)
self._lookup_add(obj, path, lvm_id, uuid)
def _id_lookup(self, the_id):
path = None
@@ -339,22 +319,22 @@ class ObjectManager(AutomatedProperties):
# Lets check for the uuid first
path = self._id_lookup(uuid)
if path:
# Verify the lvm_id is sane
self._lvm_id_verify(path, uuid, lvm_id)
# Ensure table lookups are correct
self._id_verify(path, uuid, lvm_id)
else:
# Unable to find by UUID, lets lookup by lvm_id
path = self._id_lookup(lvm_id)
if path:
# Verify the uuid is sane
self._uuid_verify(path, uuid, lvm_id)
# Ensure table lookups are correct
self._id_verify(path, uuid, lvm_id)
else:
# We have exhausted all lookups, let's create if we can
if path_create:
path = path_create()
self._lookup_add(None, path, lvm_id, uuid)
# print('get_object_path_by_lvm_id(%s, %s, %s, %s: return %s' %
# (uuid, lvm_id, str(path_create), str(gen_new), path))
# print('get_object_path_by_lvm_id(%s, %s, %s): return %s' %
# (uuid, lvm_id, str(path_create), path))
return path

View File

@@ -52,18 +52,23 @@ def load_vgs(vg_specific=None, object_path=None, refresh=False,
# noinspection PyPep8Naming,PyUnresolvedReferences,PyUnusedLocal
class VgState(State):
@property
def lvm_id(self):
def internal_name(self):
return self.Name
@property
def lvm_id(self):
return self.internal_name
def identifiers(self):
return (self.Uuid, self.Name)
return (self.Uuid, self.internal_name)
def _lv_paths_build(self):
rc = []
for lv in cfg.db.lvs_in_vg(self.Uuid):
(lv_name, meta, lv_uuid) = lv
full_name = "%s/%s" % (self.Name, lv_name)
full_name = "%s/%s" % (self.internal_name, lv_name)
gen = utils.lv_object_path_method(lv_name, meta)
@@ -92,7 +97,7 @@ class VgState(State):
def create_dbus_object(self, path):
if not path:
path = cfg.om.get_object_path_by_uuid_lvm_id(
self.Uuid, self.Name, vg_obj_path_generate)
self.Uuid, self.internal_name, vg_obj_path_generate)
return Vg(path, self)
# noinspection PyMethodMayBeStatic
@@ -102,7 +107,6 @@ class VgState(State):
# noinspection PyPep8Naming
@utils.dbus_property(VG_INTERFACE, 'Uuid', 's')
@utils.dbus_property(VG_INTERFACE, 'Name', 's')
@utils.dbus_property(VG_INTERFACE, 'Fmt', 's')
@utils.dbus_property(VG_INTERFACE, 'SizeBytes', 't', 0)
@utils.dbus_property(VG_INTERFACE, 'FreeBytes', 't', 0)
@@ -135,6 +139,7 @@ class Vg(AutomatedProperties):
_AllocNormal_meta = ('b', VG_INTERFACE)
_AllocAnywhere_meta = ('b', VG_INTERFACE)
_Clustered_meta = ('b', VG_INTERFACE)
_Name_meta = ('s', VG_INTERFACE)
# noinspection PyUnusedLocal,PyPep8Naming
def __init__(self, object_path, object_state):
@@ -172,7 +177,7 @@ class Vg(AutomatedProperties):
# Make sure we have a dbus object representing it
Vg.validate_dbus_object(uuid, vg_name)
rc, out, err = cmdhandler.vg_rename(
vg_name, new_name, rename_options)
uuid, new_name, rename_options)
Vg.handle_execute(rc, out, err)
return '/'
@@ -216,7 +221,7 @@ class Vg(AutomatedProperties):
# TODO: This should be broken into a number of different methods
# instead of having one method that takes a hash for parameters. Some of
# the changes that vgchange does works on entire system, not just a
# specfic vg, thus that should be in the Manager interface.
# specific vg, thus that should be in the Manager interface.
@dbus.service.method(
dbus_interface=VG_INTERFACE,
in_signature='ia{sv}',
@@ -729,6 +734,12 @@ class Vg(AutomatedProperties):
cb, cbe, return_tuple=False)
cfg.worker_q.put(r)
@property
def Name(self):
if ':' in self.state.Name:
return self.state.Name.split(':')[0]
return self.state.Name
@property
def Tags(self):
return utils.parse_tags(self.state.tags)

View File

@@ -27,6 +27,7 @@ endif
ifeq ("@BUILD_LOCKDDLM@", "yes")
SOURCES += lvmlockd-dlm.c
LOCK_LIBS += -ldlm_lt
LOCK_LIBS += -ldlmcontrol
endif
SOURCES2 = lvmlockctl.c
@@ -37,29 +38,26 @@ TARGETS = lvmlockd lvmlockctl
include $(top_builddir)/make.tmpl
CFLAGS += $(EXTRA_EXEC_CFLAGS)
CFLAGS += $(EXTRA_EXEC_CFLAGS) $(SYSTEMD_CFLAGS)
INCLUDES += -I$(top_srcdir)/libdaemon/server
LDFLAGS += -L$(top_builddir)/libdaemon/server $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS)
LIBS += $(RT_LIBS) $(DAEMON_LIBS) $(PTHREAD_LIBS)
LDFLAGS += $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS)
LIBS += $(PTHREAD_LIBS) $(SYSTEMD_LIBS)
lvmlockd: $(OBJECTS) $(top_builddir)/libdaemon/server/libdaemonserver.a $(INTERNAL_LIBS)
@echo " [CC] $@"
$(Q) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $+ $(LOCK_LIBS) $(LIBS)
ifeq ($(USE_SD_NOTIFY),yes)
CFLAGS += $(shell pkg-config --cflags libsystemd) -DUSE_SD_NOTIFY
LIBS += $(shell pkg-config --libs libsystemd)
endif
lvmlockd: $(OBJECTS) $(top_builddir)/libdaemon/client/libdaemonclient.a \
$(top_builddir)/libdaemon/server/libdaemonserver.a
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJECTS) $(LOCK_LIBS) -ldaemonserver $(INTERNAL_LIBS) $(LIBS)
lvmlockctl: lvmlockctl.o $(top_builddir)/libdaemon/client/libdaemonclient.a
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ lvmlockctl.o $(INTERNAL_LIBS) $(LIBS)
lvmlockctl: lvmlockctl.o $(INTERNAL_LIBS)
@echo " [CC] $@"
$(Q) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $+ $(LIBS)
install_lvmlockd: lvmlockd
$(INSTALL_PROGRAM) -D $< $(sbindir)/$(<F)
@echo " [INSTALL] $<"
$(Q) $(INSTALL_PROGRAM) -D $< $(sbindir)/$(<F)
install_lvmlockctl: lvmlockctl
$(INSTALL_PROGRAM) -D $< $(sbindir)/$(<F)
@echo " [INSTALL] $<"
$(Q) $(INSTALL_PROGRAM) -D $< $(sbindir)/$(<F)
install_lvm2: install_lvmlockd install_lvmlockctl

View File

@@ -24,7 +24,7 @@
static int quit = 0;
static int info = 0;
static int dump = 0;
static int wait_opt = 0;
static int wait_opt = 1;
static int force_opt = 0;
static int kill_vg = 0;
static int drop_vg = 0;

View File

@@ -8,10 +8,6 @@
* of the GNU Lesser General Public License v.2.1.
*/
#define _XOPEN_SOURCE 500 /* pthread */
#define _ISOC99_SOURCE
#define _REENTRANT
#include "tools/tool.h"
#include "libdaemon/client/daemon-io.h"
@@ -35,7 +31,7 @@
#include <sys/utsname.h>
#include <sys/un.h>
#ifdef USE_SD_NOTIFY
#ifdef NOTIFYDBUS_SUPPORT
#include <systemd/sd-daemon.h>
#endif
@@ -409,12 +405,11 @@ struct lockspace *alloc_lockspace(void)
{
struct lockspace *ls;
if (!(ls = malloc(sizeof(struct lockspace)))) {
if (!(ls = zalloc(sizeof(struct lockspace)))) {
log_error("out of memory for lockspace");
return NULL;
}
memset(ls, 0, sizeof(struct lockspace));
INIT_LIST_HEAD(&ls->actions);
INIT_LIST_HEAD(&ls->resources);
pthread_mutex_init(&ls->mutex, NULL);
@@ -507,6 +502,10 @@ static struct lock *alloc_lock(void)
static void free_action(struct action *act)
{
if (act->path) {
free(act->path);
act->path = NULL;
}
pthread_mutex_lock(&unused_struct_mutex);
if (unused_action_count >= MAX_UNUSED_ACTION) {
free(act);
@@ -730,6 +729,8 @@ static const char *op_str(int x)
return "rename_final";
case LD_OP_RUNNING_LM:
return "running_lm";
case LD_OP_QUERY_LOCK:
return "query_lock";
case LD_OP_FIND_FREE_LOCK:
return "find_free_lock";
case LD_OP_KILL_VG:
@@ -742,6 +743,8 @@ static const char *op_str(int x)
return "dump_info";
case LD_OP_BUSY:
return "busy";
case LD_OP_REFRESH_LV:
return "refresh_lv";
default:
return "op_unknown";
};
@@ -929,12 +932,12 @@ static void lm_rem_resource(struct lockspace *ls, struct resource *r)
lm_rem_resource_sanlock(ls, r);
}
static int lm_find_free_lock(struct lockspace *ls, uint64_t *free_offset)
static int lm_find_free_lock(struct lockspace *ls, uint64_t *free_offset, int *sector_size, int *align_size)
{
if (ls->lm_type == LD_LM_DLM)
return 0;
else if (ls->lm_type == LD_LM_SANLOCK)
return lm_find_free_lock_sanlock(ls, free_offset);
return lm_find_free_lock_sanlock(ls, free_offset, sector_size, align_size);
return -1;
}
@@ -1819,9 +1822,9 @@ static void res_process(struct lockspace *ls, struct resource *r,
add_client_result(act);
} else {
/* persistent lock is sh, transient request is ex */
/* FIXME: can we remove this case? do a convert here? */
log_debug("res_process %s existing persistent lock new transient", r->name);
r->last_client_id = act->client_id;
act->flags |= LD_AF_SH_EXISTS;
act->result = -EEXIST;
list_del(&act->list);
add_client_result(act);
@@ -2201,6 +2204,7 @@ static int process_op_during_kill(struct action *act)
case LD_OP_UPDATE:
case LD_OP_RENAME_BEFORE:
case LD_OP_RENAME_FINAL:
case LD_OP_QUERY_LOCK:
case LD_OP_FIND_FREE_LOCK:
return 0;
};
@@ -2226,7 +2230,7 @@ static void *lockspace_thread_main(void *arg_in)
struct action *act_op_free = NULL;
struct list_head tmp_act;
struct list_head act_close;
char tmp_name[MAX_NAME+1];
char tmp_name[MAX_NAME+5];
int free_vg = 0;
int drop_vg = 0;
int error = 0;
@@ -2425,13 +2429,31 @@ static void *lockspace_thread_main(void *arg_in)
break;
}
if (act->op == LD_OP_QUERY_LOCK) {
r = find_resource_act(ls, act, 0);
if (!r)
act->result = -ENOENT;
else {
act->result = 0;
act->mode = r->mode;
}
list_del(&act->list);
add_client_result(act);
continue;
}
if (act->op == LD_OP_FIND_FREE_LOCK && act->rt == LD_RT_VG) {
uint64_t free_offset = 0;
int sector_size = 0;
int align_size = 0;
log_debug("S %s find free lock", ls->name);
rv = lm_find_free_lock(ls, &free_offset);
log_debug("S %s find free lock %d offset %llu",
ls->name, rv, (unsigned long long)free_offset);
rv = lm_find_free_lock(ls, &free_offset, &sector_size, &align_size);
log_debug("S %s find free lock %d offset %llu sector_size %d align_size %d",
ls->name, rv, (unsigned long long)free_offset, sector_size, align_size);
ls->free_lock_offset = free_offset;
ls->free_lock_sector_size = sector_size;
ls->free_lock_align_size = align_size;
list_del(&act->list);
act->result = rv;
add_client_result(act);
@@ -2602,8 +2624,10 @@ out_act:
* 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);
memset(tmp_name, 0, sizeof(tmp_name));
memcpy(tmp_name, "REM:", 4);
strncpy(tmp_name+4, ls->name, sizeof(tmp_name)-4);
memcpy(ls->name, tmp_name, sizeof(ls->name));
pthread_mutex_unlock(&lockspaces_mutex);
/* worker_thread will join this thread, and free the ls */
@@ -2743,6 +2767,9 @@ static int add_lockspace_thread(const char *ls_name,
if (ls2->thread_stop) {
log_debug("add_lockspace_thread %s exists and stopping", ls->name);
rv = -EAGAIN;
} else if (!ls2->create_fail && !ls2->create_done) {
log_debug("add_lockspace_thread %s exists and starting", ls->name);
rv = -ESTARTING;
} else {
log_debug("add_lockspace_thread %s exists", ls->name);
rv = -EEXIST;
@@ -2984,7 +3011,7 @@ static int count_lockspace_starting(uint32_t client_id)
pthread_mutex_lock(&lockspaces_mutex);
list_for_each_entry(ls, &lockspaces, list) {
if (ls->start_client_id != client_id)
if (client_id && (ls->start_client_id != client_id))
continue;
if (!ls->create_done && !ls->create_fail) {
@@ -3237,6 +3264,8 @@ static int work_init_lv(struct action *act)
char vg_args[MAX_ARGS+1];
char lv_args[MAX_ARGS+1];
uint64_t free_offset = 0;
int sector_size = 0;
int align_size = 0;
int lm_type = 0;
int rv = 0;
@@ -3252,6 +3281,8 @@ static int work_init_lv(struct action *act)
lm_type = ls->lm_type;
memcpy(vg_args, ls->vg_args, MAX_ARGS);
free_offset = ls->free_lock_offset;
sector_size = ls->free_lock_sector_size;
align_size = ls->free_lock_align_size;
}
pthread_mutex_unlock(&lockspaces_mutex);
@@ -3268,7 +3299,7 @@ static int work_init_lv(struct action *act)
if (lm_type == LD_LM_SANLOCK) {
rv = lm_init_lv_sanlock(ls_name, act->vg_name, act->lv_uuid,
vg_args, lv_args, free_offset);
vg_args, lv_args, sector_size, align_size, free_offset);
memcpy(act->lv_args, lv_args, MAX_ARGS);
return rv;
@@ -3385,7 +3416,7 @@ static void *worker_thread_main(void *arg_in)
add_client_result(act);
} else if (act->op == LD_OP_START_WAIT) {
act->result = count_lockspace_starting(act->client_id);
act->result = count_lockspace_starting(0);
if (!act->result)
add_client_result(act);
else
@@ -3398,6 +3429,15 @@ static void *worker_thread_main(void *arg_in)
else
list_add(&act->list, &delayed_list);
} else if (act->op == LD_OP_REFRESH_LV) {
log_debug("work refresh_lv %s %s", act->lv_uuid, act->path);
rv = lm_refresh_lv_start_dlm(act);
if (rv < 0) {
act->result = rv;
add_client_result(act);
} else
list_add(&act->list, &delayed_list);
} else {
log_error("work unknown op %d", act->op);
act->result = -EINVAL;
@@ -3419,7 +3459,7 @@ static void *worker_thread_main(void *arg_in)
list_for_each_entry_safe(act, safe, &delayed_list, list) {
if (act->op == LD_OP_START_WAIT) {
log_debug("work delayed start_wait for client %u", act->client_id);
act->result = count_lockspace_starting(act->client_id);
act->result = count_lockspace_starting(0);
if (!act->result) {
list_del(&act->list);
add_client_result(act);
@@ -3433,6 +3473,19 @@ static void *worker_thread_main(void *arg_in)
act->result = 0;
add_client_result(act);
}
} else if (act->op == LD_OP_REFRESH_LV) {
log_debug("work delayed refresh_lv");
rv = lm_refresh_lv_check_dlm(act);
if (!rv) {
list_del(&act->list);
act->result = 0;
add_client_result(act);
} else if ((rv < 0) && (rv != -EAGAIN)) {
list_del(&act->list);
act->result = rv;
add_client_result(act);
}
}
}
@@ -3638,6 +3691,9 @@ static int client_send_result(struct client *cl, struct action *act)
if ((act->flags & LD_AF_WARN_GL_REMOVED) || gl_vg_removed)
strcat(result_flags, "WARN_GL_REMOVED,");
if (act->flags & LD_AF_SH_EXISTS)
strcat(result_flags, "SH_EXISTS,");
if (act->op == LD_OP_INIT) {
/*
* init is a special case where lock args need
@@ -3666,6 +3722,20 @@ static int client_send_result(struct client *cl, struct action *act)
"result_flags = %s", result_flags[0] ? result_flags : "none",
NULL);
} else if (act->op == LD_OP_QUERY_LOCK) {
log_debug("send %s[%d] cl %u %s %s rv %d mode %d",
cl->name[0] ? cl->name : "client", cl->pid, cl->id,
op_str(act->op), rt_str(act->rt),
act->result, act->mode);
res = daemon_reply_simple("OK",
"op = " FMTd64, (int64_t)act->op,
"op_result = " FMTd64, (int64_t) act->result,
"lock_type = %s", lm_str(act->lm_type),
"mode = %s", mode_str(act->mode),
NULL);
} else if (act->op == LD_OP_DUMP_LOG || act->op == LD_OP_DUMP_INFO) {
/*
* lvmlockctl creates the unix socket then asks us to write to it.
@@ -3996,6 +4066,16 @@ static int str_to_op_rt(const char *req_name, int *op, int *rt)
*rt = 0;
return 0;
}
if (!strcmp(req_name, "query_lock_vg")) {
*op = LD_OP_QUERY_LOCK;
*rt = LD_RT_VG;
return 0;
}
if (!strcmp(req_name, "query_lock_lv")) {
*op = LD_OP_QUERY_LOCK;
*rt = LD_RT_LV;
return 0;
}
if (!strcmp(req_name, "find_free_lock")) {
*op = LD_OP_FIND_FREE_LOCK;
*rt = LD_RT_VG;
@@ -4011,6 +4091,11 @@ static int str_to_op_rt(const char *req_name, int *op, int *rt)
*rt = LD_RT_VG;
return 0;
}
if (!strcmp(req_name, "refresh_lv")) {
*op = LD_OP_REFRESH_LV;
*rt = 0;
return 0;
}
out:
return -1;
}
@@ -4372,6 +4457,7 @@ static void client_recv_action(struct client *cl)
const char *vg_name;
const char *vg_uuid;
const char *vg_sysid;
const char *path;
const char *str;
int64_t val;
uint32_t opts = 0;
@@ -4458,6 +4544,7 @@ static void client_recv_action(struct client *cl)
opts = str_to_opts(str);
str = daemon_request_str(req, "vg_lock_type", NULL);
lm = str_to_lm(str);
path = daemon_request_str(req, "path", NULL);
if (cl_pid && cl_pid != cl->pid)
log_error("client recv bad message pid %d client %d", cl_pid, cl->pid);
@@ -4490,6 +4577,9 @@ static void client_recv_action(struct client *cl)
act->flags = opts;
act->lm_type = lm;
if (path)
act->path = strdup(path);
if (vg_name && strcmp(vg_name, "none"))
strncpy(act->vg_name, vg_name, MAX_NAME);
@@ -4566,6 +4656,7 @@ static void client_recv_action(struct client *cl)
case LD_OP_STOP_ALL:
case LD_OP_RENAME_FINAL:
case LD_OP_RUNNING_LM:
case LD_OP_REFRESH_LV:
add_work_action(act);
rv = 0;
break;
@@ -4575,6 +4666,7 @@ static void client_recv_action(struct client *cl)
case LD_OP_DISABLE:
case LD_OP_FREE:
case LD_OP_RENAME_BEFORE:
case LD_OP_QUERY_LOCK:
case LD_OP_FIND_FREE_LOCK:
case LD_OP_KILL_VG:
case LD_OP_DROP_VG:

View File

@@ -24,6 +24,7 @@
* link with non-threaded version of library, libdlm_lt.
*/
#include "libdlm.h"
#include "libdlmcontrol.h"
#include <stddef.h>
#include <poll.h>
@@ -127,16 +128,18 @@ static int read_cluster_name(char *clustername)
return 0;
}
#define MAX_VERSION 16
int lm_init_vg_dlm(char *ls_name, char *vg_name, uint32_t flags, char *vg_args)
{
char clustername[MAX_ARGS+1];
char lock_args_version[MAX_ARGS+1];
char lock_args_version[MAX_VERSION+1];
int rv;
memset(clustername, 0, sizeof(clustername));
memset(lock_args_version, 0, sizeof(lock_args_version));
snprintf(lock_args_version, MAX_ARGS, "%u.%u.%u",
snprintf(lock_args_version, MAX_VERSION, "%u.%u.%u",
VG_LOCK_ARGS_MAJOR, VG_LOCK_ARGS_MINOR, VG_LOCK_ARGS_PATCH);
rv = read_cluster_name(clustername);
@@ -148,7 +151,9 @@ int lm_init_vg_dlm(char *ls_name, char *vg_name, uint32_t flags, char *vg_args)
return -EARGS;
}
snprintf(vg_args, MAX_ARGS, "%s:%s", lock_args_version, clustername);
rv = snprintf(vg_args, MAX_ARGS, "%s:%s", lock_args_version, clustername);
if (rv >= MAX_ARGS)
log_debug("init_vg_dlm vg_args may be too long %d %s", rv, vg_args);
rv = 0;
log_debug("init_vg_dlm done %s vg_args %s", ls_name, vg_args);
@@ -272,10 +277,9 @@ static int lm_add_resource_dlm(struct lockspace *ls, struct resource *r, int wit
int rv;
if (r->type == LD_RT_GL || r->type == LD_RT_VG) {
buf = malloc(sizeof(struct val_blk) + DLM_LVB_LEN);
buf = zalloc(sizeof(struct val_blk) + DLM_LVB_LEN);
if (!buf)
return -ENOMEM;
memset(buf, 0, sizeof(struct val_blk) + DLM_LVB_LEN);
rdd->vb = (struct val_blk *)buf;
rdd->lksb.sb_lvbptr = buf + sizeof(struct val_blk);
@@ -777,3 +781,107 @@ int lm_is_running_dlm(void)
return 1;
}
#ifdef LOCKDDLM_CONTROL_SUPPORT
int lm_refresh_lv_start_dlm(struct action *act)
{
char path[PATH_MAX];
char command[DLMC_RUN_COMMAND_LEN];
char run_uuid[DLMC_RUN_UUID_LEN];
char *p, *vgname, *lvname;
int rv;
/* split /dev/vgname/lvname into vgname and lvname strings */
strncpy(path, act->path, strlen(act->path));
/* skip past dev */
p = strchr(path + 1, '/');
/* skip past slashes */
while (*p == '/')
p++;
/* start of vgname */
vgname = p;
/* skip past vgname */
while (*p != '/')
p++;
/* terminate vgname */
*p = '\0';
p++;
/* skip past slashes */
while (*p == '/')
p++;
lvname = p;
memset(command, 0, sizeof(command));
memset(run_uuid, 0, sizeof(run_uuid));
/* todo: add --readonly */
snprintf(command, DLMC_RUN_COMMAND_LEN,
"lvm lvchange --refresh --partial --nolocking %s/%s",
vgname, lvname);
rv = dlmc_run_start(command, strlen(command), 0,
DLMC_FLAG_RUN_START_NODE_NONE,
run_uuid);
if (rv < 0) {
log_debug("refresh_lv run_start error %d", rv);
return rv;
}
log_debug("refresh_lv run_start %s", run_uuid);
/* Bit of a hack here, we don't need path once started,
but we do need to save the run_uuid somewhere, so just
replace the path with the uuid. */
free(act->path);
act->path = strdup(run_uuid);
return 0;
}
int lm_refresh_lv_check_dlm(struct action *act)
{
uint32_t check_status = 0;
int rv;
/* NB act->path was replaced with run_uuid */
rv = dlmc_run_check(act->path, strlen(act->path), 0,
DLMC_FLAG_RUN_CHECK_CLEAR,
&check_status);
if (rv < 0) {
log_debug("refresh_lv check error %d", rv);
return rv;
}
log_debug("refresh_lv check %s status %x", act->path, check_status);
if (!(check_status & DLMC_RUN_STATUS_DONE))
return -EAGAIN;
if (check_status & DLMC_RUN_STATUS_FAILED)
return -1;
return 0;
}
#else /* LOCKDDLM_CONTROL_SUPPORT */
int lm_refresh_lv_start_dlm(struct action *act)
{
return 0;
}
int lm_refresh_lv_check_dlm(struct action *act)
{
return 0;
}
#endif /* LOCKDDLM_CONTROL_SUPPORT */

View File

@@ -53,6 +53,8 @@ enum {
LD_OP_KILL_VG,
LD_OP_DROP_VG,
LD_OP_BUSY,
LD_OP_QUERY_LOCK,
LD_OP_REFRESH_LV,
};
/* resource types */
@@ -105,6 +107,7 @@ struct client {
#define LD_AF_WARN_GL_REMOVED 0x00020000
#define LD_AF_LV_LOCK 0x00040000
#define LD_AF_LV_UNLOCK 0x00080000
#define LD_AF_SH_EXISTS 0x00100000
/*
* Number of times to repeat a lock request after
@@ -127,6 +130,7 @@ struct action {
int max_retries;
int result;
int lm_rv; /* return value from lm_ function */
char *path;
char vg_uuid[64];
char vg_name[MAX_NAME+1];
char lv_name[MAX_NAME+1];
@@ -174,7 +178,9 @@ struct lockspace {
int8_t lm_type; /* lock manager: LM_DLM, LM_SANLOCK */
void *lm_data;
uint64_t host_id;
uint64_t free_lock_offset; /* start search for free lock here */
uint64_t free_lock_offset; /* for sanlock, start search for free lock here */
int free_lock_sector_size; /* for sanlock */
int free_lock_align_size; /* for sanlock */
uint32_t start_client_id; /* client_id that started the lockspace */
pthread_t thread; /* makes synchronous lock requests */
@@ -387,6 +393,8 @@ int lm_get_lockspaces_dlm(struct list_head *ls_rejoin);
int lm_data_size_dlm(void);
int lm_is_running_dlm(void);
int lm_hosts_dlm(struct lockspace *ls, int notify);
int lm_refresh_lv_start_dlm(struct action *act);
int lm_refresh_lv_check_dlm(struct action *act);
static inline int lm_support_dlm(void)
{
@@ -463,12 +471,22 @@ static inline int lm_hosts_dlm(struct lockspace *ls, int notify)
return 0;
}
static inline int lm_refresh_lv_start_dlm(struct action *act)
{
return 0;
}
static inline int lm_refresh_lv_check_dlm(struct action *act)
{
return 0;
}
#endif /* dlm support */
#ifdef LOCKDSANLOCK_SUPPORT
int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_args);
int lm_init_lv_sanlock(char *ls_name, char *vg_name, char *lv_name, char *vg_args, char *lv_args, uint64_t free_offset);
int lm_init_lv_sanlock(char *ls_name, char *vg_name, char *lv_name, char *vg_args, char *lv_args, int sector_size, int align_size, uint64_t free_offset);
int lm_free_lv_sanlock(struct lockspace *ls, struct resource *r);
int lm_rename_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_args);
int lm_prepare_lockspace_sanlock(struct lockspace *ls);
@@ -488,7 +506,7 @@ int lm_gl_is_enabled(struct lockspace *ls);
int lm_get_lockspaces_sanlock(struct list_head *ls_rejoin);
int lm_data_size_sanlock(void);
int lm_is_running_sanlock(void);
int lm_find_free_lock_sanlock(struct lockspace *ls, uint64_t *free_offset);
int lm_find_free_lock_sanlock(struct lockspace *ls, uint64_t *free_offset, int *sector_size, int *align_size);
static inline int lm_support_sanlock(void)
{
@@ -502,7 +520,7 @@ static inline int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flag
return -1;
}
static inline int lm_init_lv_sanlock(char *ls_name, char *vg_name, char *lv_name, char *vg_args, char *lv_args, uint64_t free_offset)
static inline int lm_init_lv_sanlock(char *ls_name, char *vg_name, char *lv_name, char *vg_args, char *lv_args, int sector_size, int align_size, uint64_t free_offset)
{
return -1;
}
@@ -590,7 +608,7 @@ static inline int lm_is_running_sanlock(void)
return 0;
}
static inline int lm_find_free_lock_sanlock(struct lockspace *ls, uint64_t *free_offset)
static inline int lm_find_free_lock_sanlock(struct lockspace *ls, uint64_t *free_offset, int *sector_size, int *align_size)
{
return -1;
}

View File

@@ -24,10 +24,29 @@
#include "sanlock_admin.h"
#include "sanlock_resource.h"
/* FIXME: these are copied from sanlock.h only until
an updated version of sanlock is available with them. */
#define SANLK_RES_ALIGN1M 0x00000010
#define SANLK_RES_ALIGN2M 0x00000020
#define SANLK_RES_ALIGN4M 0x00000040
#define SANLK_RES_ALIGN8M 0x00000080
#define SANLK_RES_SECTOR512 0x00000100
#define SANLK_RES_SECTOR4K 0x00000200
#define SANLK_LSF_ALIGN1M 0x00000010
#define SANLK_LSF_ALIGN2M 0x00000020
#define SANLK_LSF_ALIGN4M 0x00000040
#define SANLK_LSF_ALIGN8M 0x00000080
#define SANLK_LSF_SECTOR512 0x00000100
#define SANLK_LSF_SECTOR4K 0x00000200
#include <stddef.h>
#include <poll.h>
#include <errno.h>
#include <syslog.h>
#include <blkid/blkid.h>
#include <sys/sysmacros.h>
#define ONE_MB 1048576
/*
-------------------------------------------------------------------------------
@@ -139,6 +158,7 @@ release all the leases for the VG.
struct lm_sanlock {
struct sanlk_lockspace ss;
int sector_size;
int align_size;
int sock; /* sanlock daemon connection */
};
@@ -201,7 +221,6 @@ int lm_data_size_sanlock(void)
* ...
*/
#define LS_BEGIN 0
#define GL_LOCK_BEGIN UINT64_C(65)
#define VG_LOCK_BEGIN UINT64_C(66)
#define LV_LOCK_BEGIN UINT64_C(67)
@@ -288,7 +307,8 @@ static int read_host_id_file(void)
}
}
if (fclose(file))
log_error("failed to close host id file %s", daemon_host_id_file);
log_debug("Failed to fclose host id file %s (%s).",
daemon_host_id_file, strerror(errno));
out:
log_debug("host_id %d from %s", host_id, daemon_host_id_file);
return host_id;
@@ -324,6 +344,154 @@ fail:
return rv;
}
static void _read_sysfs_size(dev_t devno, const char *name, unsigned int *val)
{
char path[PATH_MAX];
char buf[32];
FILE *fp;
size_t len;
snprintf(path, sizeof(path), "/sys/dev/block/%d:%d/queue/%s",
(int)major(devno), (int)minor(devno), name);
if (!(fp = fopen(path, "r")))
return;
if (!fgets(buf, sizeof(buf), fp))
goto out;
if ((len = strlen(buf)) && buf[len - 1] == '\n')
buf[--len] = '\0';
if (strlen(buf))
*val = atoi(buf);
out:
if (fclose(fp))
log_debug("Failed to fclose host id file %s (%s).", path, strerror(errno));
}
/* Select sector/align size for a new VG based on what the device reports for
sector size of the lvmlock LV. */
static int get_sizes_device(char *path, int *sector_size, int *align_size)
{
unsigned int physical_block_size = 0;
unsigned int logical_block_size = 0;
struct stat st;
int rv;
rv = stat(path, &st);
if (rv < 0) {
log_error("Failed to stat device to get block size %s %d", path, errno);
return -1;
}
_read_sysfs_size(st.st_rdev, "physical_block_size", &physical_block_size);
_read_sysfs_size(st.st_rdev, "logical_block_size", &logical_block_size);
if ((physical_block_size == 512) && (logical_block_size == 512)) {
*sector_size = 512;
*align_size = ONE_MB;
return 0;
}
if ((physical_block_size == 4096) && (logical_block_size == 4096)) {
*sector_size = 4096;
*align_size = 8 * ONE_MB;
return 0;
}
if (physical_block_size && (physical_block_size != 512) && (physical_block_size != 4096)) {
log_warn("WARNING: invalid block sizes physical %u logical %u for %s",
physical_block_size, logical_block_size, path);
physical_block_size = 0;
}
if (logical_block_size && (logical_block_size != 512) && (logical_block_size != 4096)) {
log_warn("WARNING: invalid block sizes physical %u logical %u for %s",
physical_block_size, logical_block_size, path);
logical_block_size = 0;
}
if (!physical_block_size && !logical_block_size) {
log_error("Failed to get a block size for %s", path);
return -1;
}
if (!physical_block_size || !logical_block_size) {
log_warn("WARNING: incomplete block size information physical %u logical %u for %s",
physical_block_size, logical_block_size, path);
if (!physical_block_size)
physical_block_size = logical_block_size;
if (!logical_block_size)
logical_block_size = physical_block_size;
}
if ((logical_block_size == 4096) && (physical_block_size == 512)) {
log_warn("WARNING: mixed block sizes physical %u logical %u (using 4096) for %s",
physical_block_size, logical_block_size, path);
*sector_size = 4096;
*align_size = 8 * ONE_MB;
return 0;
}
if ((physical_block_size == 4096) && (logical_block_size == 512)) {
log_warn("WARNING: mixed block sizes physical %u logical %u (using 4096) for %s",
physical_block_size, logical_block_size, path);
*sector_size = 4096;
*align_size = 8 * ONE_MB;
return 0;
}
if (physical_block_size == 512) {
*sector_size = 512;
*align_size = ONE_MB;
return 0;
}
if (physical_block_size == 4096) {
*sector_size = 4096;
*align_size = 8 * ONE_MB;
return 0;
}
log_error("Failed to get a block size for %s", path);
return -1;
}
/* Get the sector/align sizes that were used to create an existing VG.
sanlock encoded this in the lockspace/resource structs on disk. */
static int get_sizes_lockspace(char *path, int *sector_size, int *align_size)
{
struct sanlk_lockspace ss;
uint32_t io_timeout = 0;
int rv;
memset(&ss, 0, sizeof(ss));
memcpy(ss.host_id_disk.path, path, SANLK_PATH_LEN);
ss.host_id_disk.offset = 0;
rv = sanlock_read_lockspace(&ss, 0, &io_timeout);
if (rv < 0) {
log_error("get_sizes_lockspace %s error %d", path, rv);
return rv;
}
if ((ss.flags & SANLK_LSF_SECTOR4K) && (ss.flags & SANLK_LSF_ALIGN8M)) {
*sector_size = 4096;
*align_size = 8 * ONE_MB;
} else if ((ss.flags & SANLK_LSF_SECTOR512) && (ss.flags & SANLK_LSF_ALIGN1M)) {
*sector_size = 512;
*align_size = ONE_MB;
}
log_debug("get_sizes_lockspace found %d %d", *sector_size, *align_size);
return 0;
}
/*
* vgcreate
*
@@ -332,18 +500,21 @@ fail:
* version and lv name, and returns the real lock_args in vg_args.
*/
#define MAX_VERSION 16
int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_args)
{
struct sanlk_lockspace ss;
struct sanlk_resourced rd;
struct sanlk_disk disk;
char lock_lv_name[MAX_ARGS+1];
char lock_args_version[MAX_ARGS+1];
char lock_args_version[MAX_VERSION+1];
const char *gl_name = NULL;
uint32_t daemon_version;
uint32_t daemon_proto;
uint64_t offset;
int align_size;
int sector_size = 0;
int align_size = 0;
int i, rv;
memset(&ss, 0, sizeof(ss));
@@ -357,7 +528,7 @@ int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_ar
return -EARGS;
}
snprintf(lock_args_version, MAX_ARGS, "%u.%u.%u",
snprintf(lock_args_version, MAX_VERSION, "%u.%u.%u",
VG_LOCK_ARGS_MAJOR, VG_LOCK_ARGS_MINOR, VG_LOCK_ARGS_PATCH);
/* see comment above about input vg_args being only lock_lv_name */
@@ -374,7 +545,9 @@ int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_ar
if (daemon_test) {
if (!gl_lsname_sanlock[0])
strncpy(gl_lsname_sanlock, ls_name, MAX_NAME);
snprintf(vg_args, MAX_ARGS, "%s:%s", lock_args_version, lock_lv_name);
rv = snprintf(vg_args, MAX_ARGS, "%s:%s", lock_args_version, lock_lv_name);
if (rv >= MAX_ARGS)
log_debug("init_vg_san vg_args may be too long %d %s", rv, vg_args);
return 0;
}
@@ -387,23 +560,25 @@ 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);
rv = sanlock_align(&disk);
if (rv <= 0) {
/* Nothing formatted on disk yet, use what the device reports. */
rv = get_sizes_device(disk.path, &sector_size, &align_size);
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",
log_error("S %s init_vg_san sanlock error %d trying to get sector/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);
ss.host_id_disk.offset = LS_BEGIN * align_size;
ss.host_id_disk.offset = 0;
ss.flags = (sector_size == 4096) ? (SANLK_LSF_SECTOR4K | SANLK_LSF_ALIGN8M) :
(SANLK_LSF_SECTOR512 | SANLK_LSF_ALIGN1M);
rv = sanlock_write_lockspace(&ss, 0, 0, sanlock_io_timeout);
if (rv < 0) {
@@ -436,6 +611,8 @@ int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_ar
memcpy(rd.rs.disks[0].path, disk.path, SANLK_PATH_LEN);
rd.rs.disks[0].offset = align_size * GL_LOCK_BEGIN;
rd.rs.num_disks = 1;
rd.rs.flags = (sector_size == 4096) ? (SANLK_RES_SECTOR4K | SANLK_RES_ALIGN8M) :
(SANLK_RES_SECTOR512 | SANLK_RES_ALIGN1M);
rv = sanlock_write_resource(&rd.rs, 0, 0, 0);
if (rv < 0) {
@@ -449,6 +626,8 @@ int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_ar
memcpy(rd.rs.disks[0].path, disk.path, SANLK_PATH_LEN);
rd.rs.disks[0].offset = align_size * VG_LOCK_BEGIN;
rd.rs.num_disks = 1;
rd.rs.flags = (sector_size == 4096) ? (SANLK_RES_SECTOR4K | SANLK_RES_ALIGN8M) :
(SANLK_RES_SECTOR512 | SANLK_RES_ALIGN1M);
rv = sanlock_write_resource(&rd.rs, 0, 0, 0);
if (rv < 0) {
@@ -460,7 +639,9 @@ int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_ar
if (!strcmp(gl_name, R_NAME_GL))
strncpy(gl_lsname_sanlock, ls_name, MAX_NAME);
snprintf(vg_args, MAX_ARGS, "%s:%s", lock_args_version, lock_lv_name);
rv = snprintf(vg_args, MAX_ARGS, "%s:%s", lock_args_version, lock_lv_name);
if (rv >= MAX_ARGS)
log_debug("init_vg_san vg_args may be too long %d %s", rv, vg_args);
log_debug("S %s init_vg_san done vg_args %s", ls_name, vg_args);
@@ -472,6 +653,8 @@ int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_ar
memset(&rd, 0, sizeof(rd));
rd.rs.num_disks = 1;
rd.rs.flags = (sector_size == 4096) ? (SANLK_RES_SECTOR4K | SANLK_RES_ALIGN8M) :
(SANLK_RES_SECTOR512 | SANLK_RES_ALIGN1M);
memcpy(rd.rs.disks[0].path, disk.path, SANLK_PATH_LEN);
strncpy(rd.rs.lockspace_name, ls_name, SANLK_NAME_LEN);
strcpy(rd.rs.name, "#unused");
@@ -510,13 +693,13 @@ int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_ar
*/
int lm_init_lv_sanlock(char *ls_name, char *vg_name, char *lv_name,
char *vg_args, char *lv_args, uint64_t free_offset)
char *vg_args, char *lv_args,
int sector_size, int align_size, uint64_t free_offset)
{
struct sanlk_resourced rd;
char lock_lv_name[MAX_ARGS+1];
char lock_args_version[MAX_ARGS+1];
char lock_args_version[MAX_VERSION+1];
uint64_t offset;
int align_size;
int rv;
memset(&rd, 0, sizeof(rd));
@@ -530,11 +713,11 @@ int lm_init_lv_sanlock(char *ls_name, char *vg_name, char *lv_name,
return rv;
}
snprintf(lock_args_version, MAX_ARGS, "%u.%u.%u",
snprintf(lock_args_version, MAX_VERSION, "%u.%u.%u",
LV_LOCK_ARGS_MAJOR, LV_LOCK_ARGS_MINOR, LV_LOCK_ARGS_PATCH);
if (daemon_test) {
align_size = 1048576;
align_size = ONE_MB;
snprintf(lv_args, MAX_ARGS, "%s:%llu",
lock_args_version,
(unsigned long long)((align_size * LV_LOCK_BEGIN) + (align_size * daemon_test_lv_count)));
@@ -547,12 +730,35 @@ int lm_init_lv_sanlock(char *ls_name, char *vg_name, char *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) {
log_error("S %s init_lv_san align error %d", ls_name, align_size);
return -EINVAL;
/*
* These should not usually be zero, maybe only the first time this function is called?
* We need to use the same sector/align sizes that are already being used.
*/
if (!sector_size || !align_size) {
rv = get_sizes_lockspace(rd.rs.disks[0].path, &sector_size, &align_size);
if (rv < 0) {
log_error("S %s init_lv_san read_lockspace error %d %s",
ls_name, rv, rd.rs.disks[0].path);
return rv;
}
if (sector_size)
log_debug("S %s init_lv_san found ls sector_size %d align_size %d", ls_name, sector_size, align_size);
else {
/* use the old method */
align_size = sanlock_align(&rd.rs.disks[0]);
if (align_size <= 0) {
log_error("S %s init_lv_san align error %d", ls_name, align_size);
return -EINVAL;
}
sector_size = (align_size == ONE_MB) ? 512 : 4096;
log_debug("S %s init_lv_san found old sector_size %d align_size %d", ls_name, sector_size, align_size);
}
}
rd.rs.flags = (sector_size == 4096) ? (SANLK_RES_SECTOR4K | SANLK_RES_ALIGN8M) :
(SANLK_RES_SECTOR512 | SANLK_RES_ALIGN1M);
if (free_offset)
offset = free_offset;
else
@@ -595,6 +801,8 @@ int lm_init_lv_sanlock(char *ls_name, char *vg_name, char *lv_name,
ls_name, lv_name, (unsigned long long)offset);
strncpy(rd.rs.name, lv_name, SANLK_NAME_LEN);
rd.rs.flags = (sector_size == 4096) ? (SANLK_RES_SECTOR4K | SANLK_RES_ALIGN8M) :
(SANLK_RES_SECTOR512 | SANLK_RES_ALIGN1M);
rv = sanlock_write_resource(&rd.rs, 0, 0, 0);
if (!rv) {
@@ -626,7 +834,8 @@ int lm_rename_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_
char lock_lv_name[MAX_ARGS+1];
uint64_t offset;
uint32_t io_timeout;
int align_size;
int sector_size = 0;
int align_size = 0;
int i, rv;
memset(&disk, 0, sizeof(disk));
@@ -655,20 +864,13 @@ int lm_rename_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_
/* FIXME: device is not always ready for us here */
sleep(1);
align_size = sanlock_align(&disk);
if (align_size <= 0) {
log_error("S %s rename_vg_san bad align size %d %s",
ls_name, align_size, disk.path);
return -EINVAL;
}
/*
* Lockspace
*/
memset(&ss, 0, sizeof(ss));
memcpy(ss.host_id_disk.path, disk.path, SANLK_PATH_LEN);
ss.host_id_disk.offset = LS_BEGIN * align_size;
ss.host_id_disk.offset = 0;
rv = sanlock_read_lockspace(&ss, 0, &io_timeout);
if (rv < 0) {
@@ -677,6 +879,26 @@ int lm_rename_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_
return rv;
}
if ((ss.flags & SANLK_LSF_SECTOR4K) && (ss.flags & SANLK_LSF_ALIGN8M)) {
sector_size = 4096;
align_size = 8 * ONE_MB;
} else if ((ss.flags & SANLK_LSF_SECTOR512) && (ss.flags & SANLK_LSF_ALIGN1M)) {
sector_size = 512;
align_size = ONE_MB;
} else {
/* use the old method */
align_size = sanlock_align(&ss.host_id_disk);
if (align_size <= 0) {
log_error("S %s rename_vg_san unknown sector/align size for %s",
ls_name, ss.host_id_disk.path);
return -1;
}
sector_size = (align_size == ONE_MB) ? 512 : 4096;
}
if (!sector_size || !align_size)
return -1;
strncpy(ss.name, ls_name, SANLK_NAME_LEN);
rv = sanlock_write_lockspace(&ss, 0, 0, sanlock_io_timeout);
@@ -830,6 +1052,11 @@ int lm_ex_disable_gl_sanlock(struct lockspace *ls)
rd1.rs.num_disks = 1;
strncpy(rd1.rs.disks[0].path, lms->ss.host_id_disk.path, SANLK_PATH_LEN-1);
rd1.rs.disks[0].offset = lms->align_size * GL_LOCK_BEGIN;
rd1.rs.flags = (lms->sector_size == 4096) ? (SANLK_RES_SECTOR4K | SANLK_RES_ALIGN8M) :
(SANLK_RES_SECTOR512 | SANLK_RES_ALIGN1M);
rd2.rs.flags = (lms->sector_size == 4096) ? (SANLK_RES_SECTOR4K | SANLK_RES_ALIGN8M) :
(SANLK_RES_SECTOR512 | SANLK_RES_ALIGN1M);
rv = sanlock_acquire(lms->sock, -1, 0, 1, &rs1, NULL);
if (rv < 0) {
@@ -891,6 +1118,8 @@ int lm_able_gl_sanlock(struct lockspace *ls, int enable)
rd.rs.num_disks = 1;
strncpy(rd.rs.disks[0].path, lms->ss.host_id_disk.path, SANLK_PATH_LEN-1);
rd.rs.disks[0].offset = lms->align_size * GL_LOCK_BEGIN;
rd.rs.flags = (lms->sector_size == 4096) ? (SANLK_RES_SECTOR4K | SANLK_RES_ALIGN8M) :
(SANLK_RES_SECTOR512 | SANLK_RES_ALIGN1M);
rv = sanlock_write_resource(&rd.rs, 0, 0, 0);
if (rv < 0) {
@@ -936,7 +1165,8 @@ static int gl_is_enabled(struct lockspace *ls, struct lm_sanlock *lms)
rv = sanlock_read_resource(&rd.rs, 0);
if (rv < 0) {
log_error("gl_is_enabled read_resource error %d", rv);
log_error("gl_is_enabled read_resource align_size %d offset %llu error %d",
lms->align_size, (unsigned long long)offset, rv);
return rv;
}
@@ -973,7 +1203,7 @@ int lm_gl_is_enabled(struct lockspace *ls)
* been disabled.)
*/
int lm_find_free_lock_sanlock(struct lockspace *ls, uint64_t *free_offset)
int lm_find_free_lock_sanlock(struct lockspace *ls, uint64_t *free_offset, int *sector_size, int *align_size)
{
struct lm_sanlock *lms = (struct lm_sanlock *)ls->lm_data;
struct sanlk_resourced rd;
@@ -983,15 +1213,22 @@ int lm_find_free_lock_sanlock(struct lockspace *ls, uint64_t *free_offset)
int round = 0;
if (daemon_test) {
*free_offset = (1048576 * LV_LOCK_BEGIN) + (1048576 * (daemon_test_lv_count + 1));
*free_offset = (ONE_MB * LV_LOCK_BEGIN) + (ONE_MB * (daemon_test_lv_count + 1));
*sector_size = 512;
*align_size = ONE_MB;
return 0;
}
*sector_size = lms->sector_size;
*align_size = lms->align_size;
memset(&rd, 0, sizeof(rd));
strncpy(rd.rs.lockspace_name, ls->name, SANLK_NAME_LEN);
rd.rs.num_disks = 1;
strncpy(rd.rs.disks[0].path, lms->ss.host_id_disk.path, SANLK_PATH_LEN-1);
rd.rs.flags = (lms->sector_size == 4096) ? (SANLK_RES_SECTOR4K | SANLK_RES_ALIGN8M) :
(SANLK_RES_SECTOR512 | SANLK_RES_ALIGN1M);
if (ls->free_lock_offset)
offset = ls->free_lock_offset;
@@ -1091,6 +1328,8 @@ int lm_prepare_lockspace_sanlock(struct lockspace *ls)
char disk_path[SANLK_PATH_LEN];
char killpath[SANLK_PATH_LEN];
char killargs[SANLK_PATH_LEN];
int sector_size = 0;
int align_size = 0;
int gl_found;
int ret, rv;
@@ -1160,7 +1399,7 @@ int lm_prepare_lockspace_sanlock(struct lockspace *ls)
goto fail;
}
lms = malloc(sizeof(struct lm_sanlock));
lms = zalloc(sizeof(struct lm_sanlock));
if (!lms) {
ret = -ENOMEM;
goto fail;
@@ -1169,7 +1408,6 @@ int lm_prepare_lockspace_sanlock(struct lockspace *ls)
memset(lsname, 0, sizeof(lsname));
strncpy(lsname, ls->name, SANLK_NAME_LEN);
memset(lms, 0, sizeof(struct lm_sanlock));
memcpy(lms->ss.name, lsname, SANLK_NAME_LEN);
lms->ss.host_id_disk.offset = 0;
lms->ss.host_id = ls->host_id;
@@ -1207,13 +1445,34 @@ int lm_prepare_lockspace_sanlock(struct lockspace *ls)
goto fail;
}
lms->align_size = sanlock_align(&lms->ss.host_id_disk);
if (lms->align_size <= 0) {
log_error("S %s prepare_lockspace_san align error %d", lsname, lms->align_size);
rv = get_sizes_lockspace(disk_path, &sector_size, &align_size);
if (rv < 0) {
log_error("S %s prepare_lockspace_san cannot get sector/align sizes %d", lsname, rv);
ret = -EMANAGER;
goto fail;
}
if (!sector_size) {
log_debug("S %s prepare_lockspace_san using old size method", lsname);
/* use the old method */
align_size = sanlock_align(&lms->ss.host_id_disk);
if (align_size <= 0) {
log_error("S %s prepare_lockspace_san align error %d", lsname, align_size);
ret = -EINVAL;
goto fail;
}
sector_size = (align_size == ONE_MB) ? 512 : 4096;
log_debug("S %s prepare_lockspace_san found old sector_size %d align_size %d", lsname, sector_size, align_size);
}
log_debug("S %s prepare_lockspace_san sizes %d %d", lsname, sector_size, align_size);
lms->align_size = align_size;
lms->sector_size = sector_size;
lms->ss.flags = (sector_size == 4096) ? (SANLK_LSF_SECTOR4K | SANLK_LSF_ALIGN8M) :
(SANLK_LSF_SECTOR512 | SANLK_LSF_ALIGN1M);
gl_found = gl_is_enabled(ls, lms);
if (gl_found < 0) {
log_error("S %s prepare_lockspace_san gl_enabled error %d", lsname, gl_found);
@@ -1351,6 +1610,7 @@ static int lm_add_resource_sanlock(struct lockspace *ls, struct resource *r)
strncpy(rds->rs.name, r->name, SANLK_NAME_LEN);
rds->rs.num_disks = 1;
memcpy(rds->rs.disks[0].path, lms->ss.host_id_disk.path, SANLK_PATH_LEN);
rds->rs.flags = (lms->sector_size == 4096) ? (SANLK_RES_SECTOR4K | SANLK_RES_ALIGN8M) : (SANLK_RES_SECTOR512 | SANLK_RES_ALIGN1M);
if (r->type == LD_RT_GL)
rds->rs.disks[0].offset = GL_LOCK_BEGIN * lms->align_size;
@@ -1360,10 +1620,9 @@ static int lm_add_resource_sanlock(struct lockspace *ls, struct resource *r)
/* LD_RT_LV offset is set in each lm_lock call from lv_args. */
if (r->type == LD_RT_GL || r->type == LD_RT_VG) {
rds->vb = malloc(sizeof(struct val_blk));
rds->vb = zalloc(sizeof(struct val_blk));
if (!rds->vb)
return -ENOMEM;
memset(rds->vb, 0, sizeof(struct val_blk));
}
return 0;
@@ -1860,12 +2119,20 @@ int lm_unlock_sanlock(struct lockspace *ls, struct resource *r,
if (rv < 0)
log_error("S %s R %s unlock_san release error %d", ls->name, r->name, rv);
if (rv == -EIO)
rv = -ELOCKIO;
else if (rv < 0)
rv = -ELMERR;
/*
* sanlock may return an error here if it fails to release the lease on
* disk because of an io timeout. But, sanlock will continue trying to
* release the lease after this call returns. We shouldn't return an
* error here which would result in lvmlockd-core keeping the lock
* around. By releasing the lock in lvmlockd-core at this point,
* lvmlockd may send another acquire request to lvmlockd. If sanlock
* has not been able to release the previous instance of the lock yet,
* then it will return an error for the new request. But, acquiring a
* new lock is able o fail gracefully, until sanlock is finally able to
* release the old lock.
*/
return rv;
return 0;
}
int lm_hosts_sanlock(struct lockspace *ls, int notify)

View File

@@ -29,15 +29,16 @@ include $(top_builddir)/make.tmpl
CFLAGS += $(EXTRA_EXEC_CFLAGS)
INCLUDES += -I$(top_srcdir)/libdaemon/server
LDFLAGS += -L$(top_builddir)/libdaemon/server $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS)
LIBS += $(DAEMON_LIBS) -ldaemonserver $(PTHREAD_LIBS)
LDFLAGS += $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS)
LIBS += $(DAEMON_LIBS) $(PTHREAD_LIBS)
lvmpolld: $(OBJECTS) $(top_builddir)/libdaemon/client/libdaemonclient.a \
$(top_builddir)/libdaemon/server/libdaemonserver.a
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJECTS) $(INTERNAL_LIBS) $(LIBS)
lvmpolld: $(OBJECTS) $(top_builddir)/libdaemon/server/libdaemonserver.a $(INTERNAL_LIBS)
@echo " [CC] $@"
$(Q) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $+ $(LIBS)
install_lvmpolld: lvmpolld
$(INSTALL_PROGRAM) -D $< $(sbindir)/$(<F)
@echo " [INSTALL] $<"
$(Q) $(INSTALL_PROGRAM) -D $< $(sbindir)/$(<F)
install_lvm2: install_lvmpolld

View File

@@ -18,8 +18,6 @@
#ifndef _LVM_LVMPOLLD_COMMON_H
#define _LVM_LVMPOLLD_COMMON_H
#define _REENTRANT
#include "tools/tool.h"
#include "lvmpolld-cmd-utils.h"

View File

@@ -915,7 +915,7 @@ int main(int argc, char *argv[])
int option_index = 0;
int client = 0, server = 0;
unsigned action = ACTION_MAX;
struct timeval timeout;
struct timespec timeout;
daemon_idle di = { .ptimeout = &timeout };
struct lvmpolld_state ls = { .log_config = "" };
daemon_state s = {

View File

@@ -10,8 +10,12 @@
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
# NOTE: this Makefile only works as 'include' for toplevel Makefile
# which defined all top_* variables
DEVICE_MAPPER_SOURCE=\
device_mapper/datastruct/bitset.c \
device_mapper/ioctl/libdm-iface.c \
device_mapper/libdm-common.c \
device_mapper/libdm-config.c \
device_mapper/libdm-deptree.c \
@@ -24,29 +28,25 @@ DEVICE_MAPPER_SOURCE=\
device_mapper/regex/matcher.c \
device_mapper/regex/parse_rx.c \
device_mapper/regex/ttree.c \
device_mapper/ioctl/libdm-iface.c \
device_mapper/vdo/vdo_target.c \
device_mapper/vdo/status.c
device_mapper/vdo/status.c \
device_mapper/vdo/vdo_target.c
DEVICE_MAPPER_DEPENDS=$(addprefix $(top_builddir)/,$(subst .c,.d,$(DEVICE_MAPPER_SOURCE)))
DEVICE_MAPPER_OBJECTS=$(addprefix $(top_builddir)/,$(subst .c,.o,$(DEVICE_MAPPER_SOURCE)))
CLEAN_TARGETS+=$(DEVICE_MAPPER_DEPENDS) $(DEVICE_MAPPER_OBJECTS)
DEVICE_MAPPER_TARGET = device_mapper/libdevice-mapper.a
DEVICE_MAPPER_DEPENDS = $(DEVICE_MAPPER_SOURCE:%.c=%.d)
DEVICE_MAPPER_OBJECTS = $(DEVICE_MAPPER_SOURCE:%.c=%.o)
CLEAN_TARGETS += $(DEVICE_MAPPER_DEPENDS) $(DEVICE_MAPPER_OBJECTS) \
$(DEVICE_MAPPER_SOURCE:%.c=%.gcda) \
$(DEVICE_MAPPER_SOURCE:%.c=%.gcno) \
$(DEVICE_MAPPER_TARGET)
#$(DEVICE_MAPPER_DEPENDS): INCLUDES+=$(VDO_INCLUDES)
#$(DEVICE_MAPPER_OBJECTS): INCLUDES+=$(VDO_INCLUDES)
ifeq ("$(USE_TRACKING)","yes")
ifeq (,$(findstring $(MAKECMDGOALS),cscope.out cflow clean distclean lcov \
help check check_local check_cluster check_lvmetad check_lvmpolld))
-include $(DEVICE_MAPPER_DEPENDS)
endif
endif
$(DEVICE_MAPPER_OBJECTS): INCLUDES+=-I$(top_srcdir)/device_mapper/
$(top_builddir)/device_mapper/libdevice-mapper.a: $(DEVICE_MAPPER_OBJECTS)
$(DEVICE_MAPPER_TARGET): $(DEVICE_MAPPER_OBJECTS)
@echo " [AR] $@"
$(Q) $(RM) $@
$(Q) $(AR) rsv $@ $(DEVICE_MAPPER_OBJECTS) > /dev/null
CLEAN_TARGETS+=$(top_builddir)/device_mapper/libdevice-mapper.a
ifeq ("$(DEPENDS)","yes")
-include $(DEVICE_MAPPER_DEPENDS)
endif

View File

@@ -116,10 +116,12 @@ enum {
DM_DEVICE_MKNODES,
DM_DEVICE_LIST_VERSIONS,
DM_DEVICE_TARGET_MSG,
DM_DEVICE_SET_GEOMETRY
DM_DEVICE_SET_GEOMETRY,
DM_DEVICE_ARM_POLL
};
/*
@@ -378,6 +380,16 @@ struct dm_status_cache {
int dm_get_status_cache(struct dm_pool *mem, const char *params,
struct dm_status_cache **status);
struct dm_status_writecache {
uint32_t error;
uint64_t total_blocks;
uint64_t free_blocks;
uint64_t writeback_blocks;
};
int dm_get_status_writecache(struct dm_pool *mem, const char *params,
struct dm_status_writecache **status);
/*
* Parse params from STATUS call for snapshot target
*
@@ -891,6 +903,7 @@ int dm_tree_node_add_raid_target_with_params_v2(struct dm_tree_node *node,
#define DM_CACHE_FEATURE_WRITETHROUGH 0x00000002
#define DM_CACHE_FEATURE_PASSTHROUGH 0x00000004
#define DM_CACHE_FEATURE_METADATA2 0x00000008 /* cache v1.10 */
#define DM_CACHE_FEATURE_NO_DISCARD_PASSDOWN 0x00000010
struct dm_config_node;
/*
@@ -912,14 +925,57 @@ int dm_tree_node_add_cache_target(struct dm_tree_node *node,
const char *origin_uuid,
const char *policy_name,
const struct dm_config_node *policy_settings,
uint64_t metadata_start,
uint64_t metadata_len,
uint64_t data_start,
uint64_t data_len,
uint32_t data_block_size);
struct writecache_settings {
uint64_t high_watermark;
uint64_t low_watermark;
uint64_t writeback_jobs;
uint64_t autocommit_blocks;
uint64_t autocommit_time; /* in milliseconds */
uint32_t fua;
uint32_t nofua;
/*
* Allow an unrecognized key and its val to be passed to the kernel for
* cases where a new kernel setting is added but lvm doesn't know about
* it yet.
*/
char *new_key;
char *new_val;
/*
* Flag is 1 if a value has been set.
*/
unsigned high_watermark_set:1;
unsigned low_watermark_set:1;
unsigned writeback_jobs_set:1;
unsigned autocommit_blocks_set:1;
unsigned autocommit_time_set:1;
unsigned fua_set:1;
unsigned nofua_set:1;
};
int dm_tree_node_add_writecache_target(struct dm_tree_node *node,
uint64_t size,
const char *origin_uuid,
const char *cache_uuid,
int pmem,
uint32_t writecache_block_size,
struct writecache_settings *settings);
/*
* VDO target
*/
int dm_tree_node_add_vdo_target(struct dm_tree_node *node,
uint64_t size,
const char *data_uuid,
uint64_t data_size,
const struct dm_vdo_target_params *param);
/*

View File

@@ -15,6 +15,7 @@
#include "base/memory/zalloc.h"
#include "device_mapper/misc/dmlib.h"
#include "device_mapper/misc/dm-ioctl.h"
#include "device_mapper/ioctl/libdm-targets.h"
#include "device_mapper/libdm-common.h"
@@ -32,11 +33,9 @@
#else
# define MAJOR(x) major((x))
# define MINOR(x) minor((x))
# define MKDEV(x,y) makedev((x),(y))
# define MKDEV(x,y) makedev(((dev_t)x),((dev_t)y))
#endif
#include "device_mapper/misc/dm-ioctl.h"
/*
* Ensure build compatibility.
* The hard-coded versions here are the highest present
@@ -117,6 +116,9 @@ static struct cmd_data _cmd_data_v4[] = {
#ifdef DM_DEV_SET_GEOMETRY
{"setgeometry", DM_DEV_SET_GEOMETRY, {4, 6, 0}},
#endif
#ifdef DM_DEV_ARM_POLL
{"armpoll", DM_DEV_ARM_POLL, {4, 36, 0}},
#endif
};
/* *INDENT-ON* */
@@ -261,7 +263,7 @@ static int _control_exists(const char *control, uint32_t major, uint32_t minor)
return -1;
}
if (major && buf.st_rdev != MKDEV((dev_t)major, (dev_t)minor)) {
if (major && buf.st_rdev != MKDEV(major, minor)) {
log_verbose("%s: Wrong device number: (%u, %u) instead of "
"(%u, %u)", control,
MAJOR(buf.st_mode), MINOR(buf.st_mode),
@@ -304,7 +306,7 @@ static int _create_control(const char *control, uint32_t major, uint32_t minor)
(void) dm_prepare_selinux_context(control, S_IFCHR);
old_umask = umask(DM_CONTROL_NODE_UMASK);
if (mknod(control, S_IFCHR | S_IRUSR | S_IWUSR,
MKDEV((dev_t)major, (dev_t)minor)) < 0) {
MKDEV(major, minor)) < 0) {
log_sys_error("mknod", control);
ret = 0;
}
@@ -468,6 +470,7 @@ static void _dm_zfree_string(char *string)
{
if (string) {
memset(string, 0, strlen(string));
asm volatile ("" ::: "memory"); /* Compiler barrier. */
free(string);
}
}
@@ -476,6 +479,7 @@ static void _dm_zfree_dmi(struct dm_ioctl *dmi)
{
if (dmi) {
memset(dmi, 0, dmi->data_size);
asm volatile ("" ::: "memory"); /* Compiler barrier. */
free(dmi);
}
}
@@ -1082,6 +1086,22 @@ static int _lookup_dev_name(uint64_t dev, char *buf, size_t len)
return r;
}
static int _add_params(int type)
{
switch (type) {
case DM_DEVICE_REMOVE_ALL:
case DM_DEVICE_CREATE:
case DM_DEVICE_REMOVE:
case DM_DEVICE_SUSPEND:
case DM_DEVICE_STATUS:
case DM_DEVICE_CLEAR:
case DM_DEVICE_ARM_POLL:
return 0; /* IOCTL_FLAGS_NO_PARAMS in drivers/md/dm-ioctl.c */
default:
return 1;
}
}
static struct dm_ioctl *_flatten(struct dm_task *dmt, unsigned repeat_count)
{
const size_t min_size = 16 * 1024;
@@ -1094,11 +1114,15 @@ static struct dm_ioctl *_flatten(struct dm_task *dmt, unsigned repeat_count)
char *b, *e;
int count = 0;
for (t = dmt->head; t; t = t->next) {
len += sizeof(struct dm_target_spec);
len += strlen(t->params) + 1 + ALIGNMENT;
count++;
}
if (_add_params(dmt->type))
for (t = dmt->head; t; t = t->next) {
len += sizeof(struct dm_target_spec);
len += strlen(t->params) + 1 + ALIGNMENT;
count++;
}
else if (dmt->head)
log_debug_activation(INTERNAL_ERROR "dm '%s' ioctl should not define parameters.",
_cmd_data_v4[dmt->type].name);
if (count && (dmt->sector || dmt->message)) {
log_error("targets and message are incompatible");
@@ -1182,7 +1206,7 @@ static struct dm_ioctl *_flatten(struct dm_task *dmt, unsigned repeat_count)
}
dmi->flags |= DM_PERSISTENT_DEV_FLAG;
dmi->dev = MKDEV((dev_t)dmt->major, (dev_t)dmt->minor);
dmi->dev = MKDEV(dmt->major, dmt->minor);
}
/* Does driver support device number referencing? */
@@ -1248,9 +1272,10 @@ static struct dm_ioctl *_flatten(struct dm_task *dmt, unsigned repeat_count)
b = (char *) (dmi + 1);
e = (char *) dmi + len;
for (t = dmt->head; t; t = t->next)
if (!(b = _add_target(t, b, e)))
goto_bad;
if (_add_params(dmt->type))
for (t = dmt->head; t; t = t->next)
if (!(b = _add_target(t, b, e)))
goto_bad;
if (dmt->newname)
strcpy(b, dmt->newname);
@@ -1454,6 +1479,7 @@ static int _create_and_load_v4(struct dm_task *dmt)
dmt->uuid = NULL;
free(dmt->mangled_uuid);
dmt->mangled_uuid = NULL;
_dm_task_free_targets(dmt);
if (dm_task_run(dmt))
return 1;
@@ -1464,6 +1490,7 @@ static int _create_and_load_v4(struct dm_task *dmt)
dmt->uuid = NULL;
free(dmt->mangled_uuid);
dmt->mangled_uuid = NULL;
_dm_task_free_targets(dmt);
/*
* Also udev-synchronize "remove" dm task that is a part of this revert!

View File

@@ -1042,7 +1042,7 @@ static int _add_dev_node(const char *dev_name, uint32_t major, uint32_t minor,
{
char path[PATH_MAX];
struct stat info;
dev_t dev = MKDEV((dev_t)major, (dev_t)minor);
dev_t dev = MKDEV(major, minor);
mode_t old_mask;
if (!_build_dev_path(path, sizeof(path), dev_name))

View File

@@ -51,6 +51,8 @@ struct parser {
struct dm_pool *mem;
int no_dup_node_check; /* whether to disable dup node checking */
const char *key; /* last obtained key */
unsigned ignored_creation_time;
};
struct config_output {
@@ -176,7 +178,7 @@ static int _do_dm_config_parse(struct dm_config_tree *cft, const char *start, co
/* TODO? if (start == end) return 1; */
struct parser *p;
if (!(p = dm_pool_alloc(cft->mem, sizeof(*p))))
if (!(p = dm_pool_zalloc(cft->mem, sizeof(*p))))
return_0;
p->mem = cft->mem;
@@ -615,6 +617,7 @@ static struct dm_config_node *_section(struct parser *p, struct dm_config_node *
match(TOK_SECTION_E);
} else {
match(TOK_EQ);
p->key = root->key;
if (!(value = _value(p)))
return_NULL;
if (root->v)
@@ -682,8 +685,17 @@ static struct dm_config_value *_type(struct parser *p)
errno = 0;
v->v.i = strtoll(p->tb, NULL, 0); /* FIXME: check error */
if (errno) {
log_error("Failed to read int token.");
return NULL;
if (errno == ERANGE && p->key &&
strcmp("creation_time", p->key) == 0) {
/* Due to a bug in some older 32bit builds (<2.02.169),
* lvm was able to produce invalid creation_time string */
v->v.i = 1527120000; /* Pick 2018-05-24 day instead */
if (!p->ignored_creation_time++)
log_warn("WARNING: Invalid creation_time found in metadata (repaired with next metadata update).");
} else {
log_error("Failed to read int token.");
return NULL;
}
}
match(TOK_INT);
break;

View File

@@ -37,6 +37,7 @@ enum {
SEG_SNAPSHOT_MERGE,
SEG_STRIPED,
SEG_ZERO,
SEG_WRITECACHE,
SEG_THIN_POOL,
SEG_THIN,
SEG_VDO,
@@ -76,6 +77,7 @@ static const struct {
{ SEG_SNAPSHOT_MERGE, "snapshot-merge" },
{ SEG_STRIPED, "striped" },
{ SEG_ZERO, "zero"},
{ SEG_WRITECACHE, "writecache"},
{ SEG_THIN_POOL, "thin-pool"},
{ SEG_THIN, "thin"},
{ SEG_VDO, "vdo" },
@@ -189,6 +191,11 @@ struct load_segment {
uint32_t min_recovery_rate; /* raid kB/sec/disk */
uint32_t data_copies; /* raid10 data_copies */
uint64_t metadata_start; /* Cache */
uint64_t metadata_len; /* Cache */
uint64_t data_start; /* Cache */
uint64_t data_len; /* Cache */
struct dm_tree_node *metadata; /* Thin_pool + Cache */
struct dm_tree_node *pool; /* Thin_pool, Thin */
struct dm_tree_node *external; /* Thin */
@@ -196,6 +203,7 @@ struct load_segment {
uint64_t transaction_id; /* Thin_pool */
uint64_t low_water_mark; /* Thin_pool */
uint32_t data_block_size; /* Thin_pool + cache */
uint32_t migration_threshold; /* Cache */
unsigned skip_block_zeroing; /* Thin_pool */
unsigned ignore_discard; /* Thin_pool target vsn 1.1 */
unsigned no_discard_passdown; /* Thin_pool target vsn 1.1 */
@@ -207,6 +215,12 @@ struct load_segment {
struct dm_tree_node *vdo_data; /* VDO */
struct dm_vdo_target_params vdo_params; /* VDO */
const char *vdo_name; /* VDO - device name is ALSO passed as table arg */
uint64_t vdo_data_size; /* VDO - size of data storage device */
struct dm_tree_node *writecache_node; /* writecache */
int writecache_pmem; /* writecache, 1 if pmem, 0 if ssd */
uint32_t writecache_block_size; /* writecache, in bytes */
struct writecache_settings writecache_settings; /* writecache */
};
/* Per-device properties */
@@ -531,7 +545,7 @@ static struct dm_tree_node *_create_dm_tree_node(struct dm_tree *dtree,
dm_list_init(&node->activated);
dm_list_init(&node->props.segs);
dev = MKDEV((dev_t)info->major, (dev_t)info->minor);
dev = MKDEV(info->major, info->minor);
if (!dm_hash_insert_binary(dtree->devs, (const char *) &dev,
sizeof(dev), node)) {
@@ -554,7 +568,7 @@ static struct dm_tree_node *_create_dm_tree_node(struct dm_tree *dtree,
static struct dm_tree_node *_find_dm_tree_node(struct dm_tree *dtree,
uint32_t major, uint32_t minor)
{
dev_t dev = MKDEV((dev_t)major, (dev_t)minor);
dev_t dev = MKDEV(major, minor);
return dm_hash_lookup_binary(dtree->devs, (const char *) &dev,
sizeof(dev));
@@ -1752,7 +1766,12 @@ static int _dm_tree_deactivate_children(struct dm_tree_node *dnode,
if (info.open_count) {
/* Skip internal non-toplevel opened nodes */
if (level)
/* On some old udev systems without corrrect udev rules
* this hack avoids 'leaking' active _mimageX legs after
* deactivation of mirror LV. Other suffixes are not added
* since it's expected newer systems with wider range of
* supported targets also use better udev */
if (level && !strstr(name, "_mimage"))
continue;
/* When retry is not allowed, error */
@@ -1792,7 +1811,7 @@ static int _dm_tree_deactivate_children(struct dm_tree_node *dnode,
if (!_deactivate_node(name, info.major, info.minor,
&child->dtree->cookie, child->udev_flags,
(level == 0) ? child->dtree->retry_remove : 0)) {
child->dtree->retry_remove)) {
log_error("Unable to deactivate %s (" FMTu32 ":"
FMTu32 ").", name, info.major, info.minor);
r = 0;
@@ -2544,7 +2563,7 @@ static int _cache_emit_segment_line(struct dm_task *dmt,
char *params, size_t paramsize)
{
int pos = 0;
/* unsigned feature_count; */
unsigned feature_count;
char data[DM_FORMAT_DEV_BUFSIZE];
char metadata[DM_FORMAT_DEV_BUFSIZE];
char origin[DM_FORMAT_DEV_BUFSIZE];
@@ -2569,29 +2588,119 @@ static int _cache_emit_segment_line(struct dm_task *dmt,
EMIT_PARAMS(pos, " %u", seg->data_block_size);
/* Features */
/* feature_count = hweight32(seg->flags); */
/* EMIT_PARAMS(pos, " %u", feature_count); */
feature_count = 1; /* One of passthrough|writeback|writethrough is always set. */
if (seg->flags & DM_CACHE_FEATURE_METADATA2)
EMIT_PARAMS(pos, " 2 metadata2 ");
else
EMIT_PARAMS(pos, " 1 ");
feature_count++;
EMIT_PARAMS(pos, " %u", feature_count);
if (seg->flags & DM_CACHE_FEATURE_METADATA2)
EMIT_PARAMS(pos, " metadata2");
if (seg->flags & DM_CACHE_FEATURE_PASSTHROUGH)
EMIT_PARAMS(pos, "passthrough");
EMIT_PARAMS(pos, " passthrough");
else if (seg->flags & DM_CACHE_FEATURE_WRITEBACK)
EMIT_PARAMS(pos, "writeback");
EMIT_PARAMS(pos, " writeback");
else
EMIT_PARAMS(pos, "writethrough");
EMIT_PARAMS(pos, " writethrough");
/* Cache Policy */
name = seg->policy_name ? : "default";
EMIT_PARAMS(pos, " %s", name);
EMIT_PARAMS(pos, " %u", seg->policy_argc * 2);
/* Do not pass migration_threshold 2048 which is default */
EMIT_PARAMS(pos, " %u", (seg->policy_argc + (seg->migration_threshold != 2048) ? 1 : 0) * 2);
if (seg->migration_threshold != 2048)
EMIT_PARAMS(pos, " migration_threshold %u", seg->migration_threshold);
if (seg->policy_settings)
for (cn = seg->policy_settings->child; cn; cn = cn->sib)
EMIT_PARAMS(pos, " %s %" PRIu64, cn->key, cn->v->v.i);
if (cn->v) /* Skip deleted entry */
EMIT_PARAMS(pos, " %s %" PRIu64, cn->key, cn->v->v.i);
return 1;
}
static int _writecache_emit_segment_line(struct dm_task *dmt,
struct load_segment *seg,
char *params, size_t paramsize)
{
int pos = 0;
int count = 0;
uint32_t block_size;
char origin_dev[DM_FORMAT_DEV_BUFSIZE];
char cache_dev[DM_FORMAT_DEV_BUFSIZE];
if (!_build_dev_string(origin_dev, sizeof(origin_dev), seg->origin))
return_0;
if (!_build_dev_string(cache_dev, sizeof(cache_dev), seg->writecache_node))
return_0;
if (seg->writecache_settings.high_watermark_set)
count += 2;
if (seg->writecache_settings.low_watermark_set)
count += 2;
if (seg->writecache_settings.writeback_jobs_set)
count += 2;
if (seg->writecache_settings.autocommit_blocks_set)
count += 2;
if (seg->writecache_settings.autocommit_time_set)
count += 2;
if (seg->writecache_settings.fua_set)
count += 1;
if (seg->writecache_settings.nofua_set)
count += 1;
if (seg->writecache_settings.new_key)
count += 2;
if (!(block_size = seg->writecache_block_size))
block_size = 4096;
EMIT_PARAMS(pos, "%s %s %s %u %d",
seg->writecache_pmem ? "p" : "s",
origin_dev, cache_dev, block_size, count);
if (seg->writecache_settings.high_watermark_set) {
EMIT_PARAMS(pos, " high_watermark %llu",
(unsigned long long)seg->writecache_settings.high_watermark);
}
if (seg->writecache_settings.low_watermark_set) {
EMIT_PARAMS(pos, " low_watermark %llu",
(unsigned long long)seg->writecache_settings.low_watermark);
}
if (seg->writecache_settings.writeback_jobs_set) {
EMIT_PARAMS(pos, " writeback_jobs %llu",
(unsigned long long)seg->writecache_settings.writeback_jobs);
}
if (seg->writecache_settings.autocommit_blocks_set) {
EMIT_PARAMS(pos, " autocommit_blocks %llu",
(unsigned long long)seg->writecache_settings.autocommit_blocks);
}
if (seg->writecache_settings.autocommit_time_set) {
EMIT_PARAMS(pos, " autocommit_time %llu",
(unsigned long long)seg->writecache_settings.autocommit_time);
}
if (seg->writecache_settings.fua_set) {
EMIT_PARAMS(pos, " fua");
}
if (seg->writecache_settings.nofua_set) {
EMIT_PARAMS(pos, " nofua");
}
if (seg->writecache_settings.new_key) {
EMIT_PARAMS(pos, " %s %s",
seg->writecache_settings.new_key,
seg->writecache_settings.new_val);
}
return 1;
}
@@ -2639,20 +2748,21 @@ static int _vdo_emit_segment_line(struct dm_task *dmt,
/* Unlike normal targets, current VDO requires device path */
if (dm_snprintf(data_dev, sizeof(data_dev), "/dev/dm-%u", seg->vdo_data->info.minor) < 0) {
log_error("Can create VDO data volume path for %s.", data);
return_0;
return 0;
}
EMIT_PARAMS(pos, "%s %u %s " FMTu64 " " FMTu64 " %u on %s %s "
"ack=%u,bio=%u,bioRotationInterval=%u,cpu=%u,hash=%u,logical=%u,physical=%u",
EMIT_PARAMS(pos, "V2 %s " FMTu64 " %u " FMTu64 " %u %s %s %s "
"maxDiscard %u ack %u bio %u bioRotationInterval %u cpu %u hash %u logical %u physical %u",
data_dev,
(seg->vdo_params.emulate_512_sectors == 0) ? 4096 : 512,
seg->vdo_params.use_read_cache ? "enabled" : "disabled",
seg->vdo_params.read_cache_size_mb * UINT64_C(256), // 1MiB -> 4KiB units
seg->vdo_data_size / 8, // this parameter is in 4K units
seg->vdo_params.minimum_io_size,
seg->vdo_params.block_map_cache_size_mb * UINT64_C(256), // 1MiB -> 4KiB units
seg->vdo_params.block_map_period,
seg->vdo_params.block_map_era_length,
seg->vdo_params.use_metadata_hints ? "on" : "off" ,
(seg->vdo_params.write_policy == DM_VDO_WRITE_POLICY_SYNC) ? "sync" :
(seg->vdo_params.write_policy == DM_VDO_WRITE_POLICY_ASYNC) ? "async" : "auto", // policy
seg->vdo_name,
seg->vdo_params.max_discard,
seg->vdo_params.ack_threads,
seg->vdo_params.bio_threads,
seg->vdo_params.bio_rotation,
@@ -2775,6 +2885,10 @@ static int _emit_segment_line(struct dm_task *dmt, uint32_t major,
if (!_cache_emit_segment_line(dmt, seg, params, paramsize))
return_0;
break;
case SEG_WRITECACHE:
if (!_writecache_emit_segment_line(dmt, seg, params, paramsize))
return_0;
break;
}
switch(seg->type) {
@@ -2786,6 +2900,7 @@ static int _emit_segment_line(struct dm_task *dmt, uint32_t major,
case SEG_THIN_POOL:
case SEG_THIN:
case SEG_CACHE:
case SEG_WRITECACHE:
break;
case SEG_CRYPT:
case SEG_LINEAR:
@@ -3469,6 +3584,10 @@ int dm_tree_node_add_cache_target(struct dm_tree_node *node,
const char *origin_uuid,
const char *policy_name,
const struct dm_config_node *policy_settings,
uint64_t metadata_start,
uint64_t metadata_len,
uint64_t data_start,
uint64_t data_len,
uint32_t data_block_size)
{
struct dm_config_node *cn;
@@ -3544,9 +3663,14 @@ int dm_tree_node_add_cache_target(struct dm_tree_node *node,
if (!_link_tree_nodes(node, seg->origin))
return_0;
seg->metadata_start = metadata_start;
seg->metadata_len = metadata_len;
seg->data_start = data_start;
seg->data_len = data_len;
seg->data_block_size = data_block_size;
seg->flags = feature_flags;
seg->policy_name = policy_name;
seg->migration_threshold = 2048; /* Default migration threshold 1MiB */
/* FIXME: better validation missing */
if (policy_settings) {
@@ -3559,10 +3683,58 @@ int dm_tree_node_add_cache_target(struct dm_tree_node *node,
log_error("Cache policy parameter %s is without integer value.", cn->key);
return 0;
}
seg->policy_argc++;
if (strcmp(cn->key, "migration_threshold") == 0) {
seg->migration_threshold = cn->v->v.i;
cn->v = NULL; /* skip this entry */
} else
seg->policy_argc++;
}
}
/* Always some throughput available for cache to proceed */
if (seg->migration_threshold < data_block_size * 8)
seg->migration_threshold = data_block_size * 8;
return 1;
}
int dm_tree_node_add_writecache_target(struct dm_tree_node *node,
uint64_t size,
const char *origin_uuid,
const char *cache_uuid,
int pmem,
uint32_t writecache_block_size,
struct writecache_settings *settings)
{
struct load_segment *seg;
if (!(seg = _add_segment(node, SEG_WRITECACHE, size)))
return_0;
seg->writecache_pmem = pmem;
seg->writecache_block_size = writecache_block_size;
if (!(seg->writecache_node = dm_tree_find_node_by_uuid(node->dtree, cache_uuid))) {
log_error("Missing writecache's cache uuid %s.", cache_uuid);
return 0;
}
if (!_link_tree_nodes(node, seg->writecache_node))
return_0;
if (!(seg->origin = dm_tree_find_node_by_uuid(node->dtree, origin_uuid))) {
log_error("Missing writecache's origin uuid %s.", origin_uuid);
return 0;
}
if (!_link_tree_nodes(node, seg->origin))
return_0;
memcpy(&seg->writecache_settings, settings, sizeof(struct writecache_settings));
if (settings->new_key && settings->new_val) {
seg->writecache_settings.new_key = dm_pool_strdup(node->dtree->mem, settings->new_key);
seg->writecache_settings.new_val = dm_pool_strdup(node->dtree->mem, settings->new_val);
}
return 1;
}
@@ -4022,13 +4194,14 @@ int dm_tree_node_add_cache_target_base(struct dm_tree_node *node,
return dm_tree_node_add_cache_target(node, size, feature_flags & _mask,
metadata_uuid, data_uuid, origin_uuid,
policy_name, policy_settings, data_block_size);
policy_name, policy_settings, 0, 0, 0, 0, data_block_size);
}
#endif
int dm_tree_node_add_vdo_target(struct dm_tree_node *node,
uint64_t size,
const char *data_uuid,
uint64_t data_size,
const struct dm_vdo_target_params *vtp)
{
struct load_segment *seg;
@@ -4049,6 +4222,7 @@ int dm_tree_node_add_vdo_target(struct dm_tree_node *node,
seg->vdo_params = *vtp;
seg->vdo_name = node->name;
seg->vdo_data_size = data_size;
node->props.send_messages = 2;

View File

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

View File

@@ -296,6 +296,8 @@ int dm_get_status_cache(struct dm_pool *mem, const char *params,
s->feature_flags |= DM_CACHE_FEATURE_PASSTHROUGH;
else if (!strncmp(p, "metadata2 ", 10))
s->feature_flags |= DM_CACHE_FEATURE_METADATA2;
else if (!strncmp(p, "no_discard_passdown ", 20))
s->feature_flags |= DM_CACHE_FEATURE_NO_DISCARD_PASSDOWN;
else
log_error("Unknown feature in status: %s", params);
@@ -346,6 +348,38 @@ bad:
return 0;
}
/*
* From linux/Documentation/device-mapper/writecache.txt
*
* Status:
* 1. error indicator - 0 if there was no error, otherwise error number
* 2. the number of blocks
* 3. the number of free blocks
* 4. the number of blocks under writeback
*/
int dm_get_status_writecache(struct dm_pool *mem, const char *params,
struct dm_status_writecache **status)
{
struct dm_status_writecache *s;
if (!(s = dm_pool_zalloc(mem, sizeof(struct dm_status_writecache))))
return_0;
if (sscanf(params, "%u %llu %llu %llu",
&s->error,
(unsigned long long *)&s->total_blocks,
(unsigned long long *)&s->free_blocks,
(unsigned long long *)&s->writeback_blocks) != 4) {
log_error("Failed to parse writecache params: %s.", params);
dm_pool_free(mem, s);
return 0;
}
*status = s;
return 1;
}
int parse_thin_pool_status(const char *params, struct dm_status_thin_pool *s)
{
int pos;

View File

@@ -21,11 +21,6 @@
// FIXME: get rid of this whole file
#include "configure.h"
#define _REENTRANT
#define _GNU_SOURCE
#include "device_mapper/all.h"
#include "lib/misc/util.h"
#include "dm-logging.h"

View File

@@ -17,6 +17,6 @@
#define MAJOR(dev) ((dev & 0xfff00) >> 8)
#define MINOR(dev) ((dev & 0xff) | ((dev >> 12) & 0xfff00))
#define MKDEV(ma,mi) ((mi & 0xff) | (ma << 8) | ((mi & ~0xff) << 12))
#define MKDEV(ma,mi) (((dev_t)mi & 0xff) | ((dev_t)ma << 8) | (((dev_t)mi & ~0xff) << 12))
#endif

View File

@@ -59,11 +59,13 @@ char *dm_pool_strdup(struct dm_pool *p, const char *str)
char *dm_pool_strndup(struct dm_pool *p, const char *str, size_t n)
{
size_t slen = strlen(str);
size_t len = (slen < n) ? slen : n;
char *ret = dm_pool_alloc(p, n + 1);
if (ret) {
strncpy(ret, str, n);
ret[n] = '\0';
ret[len] = '\0';
memcpy(ret, str, len);
}
return ret;

View File

@@ -1,8 +1,24 @@
#include "configure.h"
#include "target.h"
/*
* 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
*/
// For DM_ARRAY_SIZE!
/* Note: this object is also used by VDO dmeventd plugin for parsing status */
/* File could be included by VDO plugin and can use original libdm library */
#ifndef LIB_DMEVENT_H
#include "device_mapper/all.h"
#endif
#include "device_mapper/vdo/target.h"
#include "base/memory/zalloc.h"
#include <ctype.h>
@@ -203,16 +219,11 @@ bool dm_vdo_status_parse(struct dm_pool *mem, const char *input,
goto bad;
}
if (!(s->device = (!mem) ? malloc((e - b) + 1) : dm_pool_alloc(mem, (e - b) + 1))) {
if (!(s->device = (!mem) ? strndup(b, (te - b)) : dm_pool_alloc(mem, (te - b)))) {
_set_error(result, "out of memory");
goto bad;
}
if (!dm_strncpy(s->device, b, te - b + 1)) {
_set_error(result, "copy device");
goto bad;
}
b = _eat_space(te, e);
#define XX(p, f, fn) if (!_parse_field(&b, e, p, f, fn, result)) goto bad;

View File

@@ -74,16 +74,16 @@ enum dm_vdo_write_policy {
// FIXME: review whether we should use the createParams from the userlib
struct dm_vdo_target_params {
uint32_t minimum_io_size;
uint32_t block_map_cache_size_mb;
uint32_t block_map_period;
uint32_t block_map_era_length; // format period
uint32_t check_point_frequency;
uint32_t index_memory_size_mb;
uint32_t index_memory_size_mb; // format
uint32_t read_cache_size_mb;
uint32_t slab_size_mb;
uint32_t slab_size_mb; // format
uint32_t max_discard;
// threads
uint32_t ack_threads;
uint32_t bio_threads;
@@ -95,9 +95,8 @@ struct dm_vdo_target_params {
bool use_compression;
bool use_deduplication;
bool emulate_512_sectors;
bool use_sparse_index;
bool use_read_cache;
bool use_metadata_hints;
bool use_sparse_index; // format
// write policy
enum dm_vdo_write_policy write_policy;

View File

@@ -21,8 +21,8 @@
#define DM_VDO_BLOCK_MAP_CACHE_SIZE_MAXIMUM_MB (16 * 1024 * 1024 - 1) // 16TiB - 1
#define DM_VDO_BLOCK_MAP_CACHE_SIZE_MINIMUM_PER_LOGICAL_THREAD (4096 * DM_VDO_BLOCK_SIZE_KB)
#define DM_VDO_BLOCK_MAP_PERIOD_MINIMUM 1
#define DM_VDO_BLOCK_MAP_PERIOD_MAXIMUM (16380)
#define DM_VDO_BLOCK_MAP_ERA_LENGTH_MINIMUM (1)
#define DM_VDO_BLOCK_MAP_ERA_LENGTH_MAXIMUM (16380)
#define DM_VDO_INDEX_MEMORY_SIZE_MINIMUM_MB (256) // 0.25 GiB
#define DM_VDO_INDEX_MEMORY_SIZE_MAXIMUM_MB (1024 * 1024 * 1024) // 1TiB
@@ -57,4 +57,7 @@
//#define DM_VDO_PHYSICAL_THREADS_MINIMUM (0)
#define DM_VDO_PHYSICAL_THREADS_MAXIMUM (16)
#define DM_VDO_MAX_DISCARD_MINIMUM (1)
#define DM_VDO_MAX_DISCARD_MAXIMUM (UINT32_MAX / 4096)
#endif // DEVICE_MAPPER_VDO_LIMITS_H

View File

@@ -23,6 +23,13 @@ bool dm_vdo_validate_target_params(const struct dm_vdo_target_params *vtp,
{
bool valid = true;
if ((vtp->minimum_io_size != 512) &&
(vtp->minimum_io_size != 4096)) {
log_error("VDO minimum io size %u is unsupported.",
vtp->minimum_io_size);
valid = false;
}
if ((vtp->block_map_cache_size_mb < DM_VDO_BLOCK_MAP_CACHE_SIZE_MINIMUM_MB) ||
(vtp->block_map_cache_size_mb > DM_VDO_BLOCK_MAP_CACHE_SIZE_MAXIMUM_MB)) {
log_error("VDO block map cache size %u out of range.",
@@ -37,12 +44,6 @@ bool dm_vdo_validate_target_params(const struct dm_vdo_target_params *vtp,
valid = false;
}
if (vtp->read_cache_size_mb > DM_VDO_READ_CACHE_SIZE_MAXIMUM_MB) {
log_error("VDO read cache size %u out of range.",
vtp->read_cache_size_mb);
valid = false;
}
if ((vtp->slab_size_mb < DM_VDO_SLAB_SIZE_MINIMUM_MB) ||
(vtp->slab_size_mb > DM_VDO_SLAB_SIZE_MAXIMUM_MB)) {
log_error("VDO slab size %u out of range.",
@@ -50,6 +51,13 @@ bool dm_vdo_validate_target_params(const struct dm_vdo_target_params *vtp,
valid = false;
}
if ((vtp->max_discard < DM_VDO_MAX_DISCARD_MINIMUM) ||
(vtp->max_discard > DM_VDO_MAX_DISCARD_MAXIMUM)) {
log_error("VDO max discard %u out of range.",
vtp->max_discard);
valid = false;
}
if (vtp->ack_threads > DM_VDO_ACK_THREADS_MAXIMUM) {
log_error("VDO ack threads %u out of range.", vtp->ack_threads);
valid = false;

View File

@@ -18,7 +18,7 @@ top_builddir = @top_builddir@
include $(top_builddir)/make.tmpl
DISTCLEAN_TARGETS += .configure.h lvm-version.h
DISTCLEAN_TARGETS += configure.h lvm-version.h
CLEAN_TARGETS += \
.symlinks \
.symlinks_created \

View File

@@ -45,9 +45,6 @@
/* Name of default metadata cache subdirectory. */
#undef DEFAULT_CACHE_SUBDIR
/* Default data alignment. */
#undef DEFAULT_DATA_ALIGNMENT
/* Define default node creation behavior with dmsetup create */
#undef DEFAULT_DM_ADD_NODE
@@ -295,6 +292,9 @@
/* Define to 1 if you have the <paths.h> header file. */
#undef HAVE_PATHS_H
/* Define to 1 if you have the `pselect' function. */
#undef HAVE_PSELECT
/* Define to 1 if the system has the type `ptrdiff_t'. */
#undef HAVE_PTRDIFF_T
@@ -534,6 +534,9 @@
/* Locale-dependent data */
#undef LOCALEDIR
/* Define to 1 to include code that uses lvmlockd dlm control option. */
#undef LOCKDDLM_CONTROL_SUPPORT
/* Define to 1 to include code that uses lvmlockd dlm option. */
#undef LOCKDDLM_SUPPORT
@@ -669,6 +672,15 @@
/* Define to 1 to include built-in support for vdo. */
#undef VDO_INTERNAL
/* Define to 1 to include built-in support for writecache. */
#undef WRITECACHE_INTERNAL
/* Define to get access to GNU/Linux extension */
#undef _GNU_SOURCE
/* Define to use re-entrant thread safe versions */
#undef _REENTRANT
/* Define for Solaris 2.5.1 so the uint32_t typedef from <sys/synch.h>,
<pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
#define below would cause a syntax error. */

View File

@@ -19,6 +19,7 @@ top_builddir = @top_builddir@
SOURCES =\
activate/activate.c \
cache/lvmcache.c \
writecache/writecache.c \
cache_segtype/cache.c \
commands/toolcontext.c \
config/config.c \
@@ -60,6 +61,7 @@ SOURCES =\
format_text/text_label.c \
freeseg/freeseg.c \
label/label.c \
label/hints.c \
locking/file_locking.c \
locking/locking.c \
log/log.c \
@@ -90,6 +92,7 @@ SOURCES =\
misc/lvm-string.c \
misc/lvm-wrappers.c \
misc/lvm-percent.c \
misc/sharedlib.c \
mm/memlock.c \
notify/lvmnotify.c \
properties/prop_common.c \
@@ -108,10 +111,6 @@ ifeq ("@DEVMAPPER@", "yes")
activate/fs.c
endif
ifeq ("@HAVE_LIBDL@", "yes")
SOURCES += misc/sharedlib.c
endif
ifeq ("@BUILD_LVMPOLLD@", "yes")
SOURCES +=\
lvmpolld/lvmpolld-client.c
@@ -129,12 +128,6 @@ endif
LIB_NAME = liblvm-internal
LIB_STATIC = $(LIB_NAME).a
ifeq ($(MAKECMDGOALS),distclean)
SUBDIRS =\
notify \
locking
endif
CFLOW_LIST = $(SOURCES)
CFLOW_LIST_TARGET = $(LIB_NAME).cflow

View File

@@ -539,25 +539,7 @@ int target_version(const char *target_name, uint32_t *maj,
int lvm_dm_prefix_check(int major, int minor, const char *prefix)
{
struct dm_task *dmt;
const char *uuid;
int r;
if (!(dmt = dm_task_create(DM_DEVICE_STATUS)))
return_0;
if (!dm_task_set_minor(dmt, minor) ||
!dm_task_set_major(dmt, major) ||
!dm_task_run(dmt) ||
!(uuid = dm_task_get_uuid(dmt))) {
dm_task_destroy(dmt);
return 0;
}
r = strncasecmp(uuid, prefix, strlen(prefix));
dm_task_destroy(dmt);
return r ? 0 : 1;
return dev_manager_check_prefix_dm_major_minor(major, minor, prefix);
}
int module_present(struct cmd_context *cmd, const char *target_name)
@@ -1173,6 +1155,26 @@ out:
return r;
}
int lv_writecache_message(const struct logical_volume *lv, const char *msg)
{
int r = 0;
struct dev_manager *dm;
if (!lv_info(lv->vg->cmd, lv, 0, NULL, 0, 0)) {
log_error("Unable to send message to an inactive logical volume.");
return 0;
}
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1)))
return_0;
r = dev_manager_writecache_message(dm, lv, msg);
dev_manager_destroy(dm);
return r;
}
/*
* Return dm_status_cache for cache volume, accept also cache pool
*
@@ -1339,8 +1341,6 @@ int lv_vdo_pool_status(const struct logical_volume *lv, int flush,
{
int r = 0;
struct dev_manager *dm;
struct lv_status_vdo *status;
char *params;
if (!lv_info(lv->vg->cmd, lv, 0, NULL, 0, 0))
return 0;
@@ -1351,14 +1351,10 @@ int lv_vdo_pool_status(const struct logical_volume *lv, int flush,
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, !lv_is_pvmove(lv))))
return_0;
if (!dev_manager_vdo_pool_status(dm, lv, flush, &params, &status))
if (!dev_manager_vdo_pool_status(dm, lv, vdo_status, flush))
goto_out;
if (!parse_vdo_pool_status(status->mem, lv, params, status))
goto_out;
/* User is responsible to dm_pool_destroy memory pool! */
*vdo_status = status;
/* User has to call dm_pool_destroy(vdo_status->mem) */
r = 1;
out:
if (!r)
@@ -1367,6 +1363,19 @@ out:
return r;
}
int lv_vdo_pool_percent(const struct logical_volume *lv, dm_percent_t *percent)
{
struct lv_status_vdo *vdo_status;
if (!lv_vdo_pool_status(lv, 0, &vdo_status))
return_0;
*percent = vdo_status->usage;
dm_pool_destroy(vdo_status->mem);
return 1;
}
static int _lv_active(struct cmd_context *cmd, const struct logical_volume *lv)
{
struct lvinfo info;
@@ -2031,8 +2040,6 @@ static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
const struct logical_volume *lv, const struct logical_volume *lv_pre)
{
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, *lv_tmp;
struct seg_list *sl;
struct lv_segment *snap_seg;
@@ -2223,10 +2230,6 @@ static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
out:
if (mem)
dm_pool_destroy(mem);
if (lv_pre_to_free)
release_vg(lv_pre_to_free->vg);
if (lv_to_free)
release_vg(lv_to_free->vg);
return r;
}
@@ -2387,7 +2390,6 @@ static int _lv_has_open_snapshots(const struct logical_volume *lv)
int lv_deactivate(struct cmd_context *cmd, const char *lvid_s, const struct logical_volume *lv)
{
const struct logical_volume *lv_to_free = NULL;
struct lvinfo info;
static const struct lv_activate_opts laopts = { .skip_in_use = 1 };
struct dm_list *snh;
@@ -2457,27 +2459,25 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s, const struct logi
r = 0;
}
out:
if (lv_to_free)
release_vg(lv_to_free->vg);
return r;
}
/* Test if LV passes filter */
int lv_activation_filter(struct cmd_context *cmd, const char *lvid_s,
int *activate_lv, const struct logical_volume *lv)
int *activate, const struct logical_volume *lv)
{
if (!activation()) {
*activate_lv = 1;
*activate = 1;
return 1;
}
if (!_passes_activation_filter(cmd, lv)) {
log_verbose("Not activating %s since it does not pass "
"activation filter.", display_lvname(lv));
*activate_lv = 0;
*activate = 0;
} else
*activate_lv = 1;
*activate = 1;
return 1;
}
@@ -2521,6 +2521,12 @@ static int _lv_activate(struct cmd_context *cmd, const char *lvid_s,
goto out;
}
if (lv_raid_has_visible_sublvs(lv)) {
log_error("Refusing activation of RAID LV %s with "
"visible SubLVs.", display_lvname(lv));
goto out;
}
if (test_mode()) {
_skip("Activating %s.", display_lvname(lv));
r = 1;

View File

@@ -38,6 +38,7 @@ typedef enum {
SEG_STATUS_THIN,
SEG_STATUS_THIN_POOL,
SEG_STATUS_VDO_POOL,
SEG_STATUS_WRITECACHE,
SEG_STATUS_UNKNOWN
} lv_seg_status_type_t;
@@ -51,6 +52,7 @@ struct lv_seg_status {
struct dm_status_snapshot *snapshot;
struct dm_status_thin *thin;
struct dm_status_thin_pool *thin_pool;
struct dm_status_writecache *writecache;
struct lv_status_vdo vdo_pool;
};
};
@@ -160,10 +162,10 @@ int lv_info_with_seg_status(struct cmd_context *cmd,
int lv_check_not_in_use(const struct logical_volume *lv, int error_if_used);
/*
* Returns 1 if activate_lv has been set: 1 = activate; 0 = don't.
* Returns 1 if activate has been set: 1 = activate; 0 = don't.
*/
int lv_activation_filter(struct cmd_context *cmd, const char *lvid_s,
int *activate_lv, const struct logical_volume *lv);
int *activate, const struct logical_volume *lv);
/*
* Checks against the auto_activation_volume_list and
* returns 1 if the LV should be activated, 0 otherwise.
@@ -184,6 +186,7 @@ int lv_raid_dev_health(const struct logical_volume *lv, char **dev_health);
int lv_raid_mismatch_count(const struct logical_volume *lv, uint64_t *cnt);
int lv_raid_sync_action(const struct logical_volume *lv, char **sync_action);
int lv_raid_message(const struct logical_volume *lv, const char *msg);
int lv_writecache_message(const struct logical_volume *lv, const char *msg);
int lv_cache_status(const struct logical_volume *cache_lv,
struct lv_status_cache **status);
int lv_thin_pool_percent(const struct logical_volume *lv, int metadata,
@@ -195,6 +198,7 @@ int lv_thin_pool_transaction_id(const struct logical_volume *lv,
int lv_thin_device_id(const struct logical_volume *lv, uint32_t *device_id);
int lv_vdo_pool_status(const struct logical_volume *lv, int flush,
struct lv_status_vdo **status);
int lv_vdo_pool_percent(const struct logical_volume *lv, dm_percent_t *percent);
/*
* Return number of LVs in the VG that are active.
@@ -255,6 +259,7 @@ int device_is_usable(struct device *dev, struct dev_usable_check_params check);
void fs_unlock(void);
#define TARGET_NAME_CACHE "cache"
#define TARGET_NAME_WRITECACHE "writecache"
#define TARGET_NAME_ERROR "error"
#define TARGET_NAME_ERROR_OLD "erro" /* Truncated in older kernels */
#define TARGET_NAME_LINEAR "linear"
@@ -271,6 +276,7 @@ void fs_unlock(void);
#define MODULE_NAME_CLUSTERED_MIRROR "clog"
#define MODULE_NAME_CACHE TARGET_NAME_CACHE
#define MODULE_NAME_WRITECACHE TARGET_NAME_WRITECACHE
#define MODULE_NAME_ERROR TARGET_NAME_ERROR
#define MODULE_NAME_LOG_CLUSTERED "log-clustered"
#define MODULE_NAME_LOG_USERSPACE "log-userspace"

View File

@@ -213,6 +213,10 @@ static int _get_segment_status_from_target_params(const char *target_name,
if (!parse_vdo_pool_status(seg_status->mem, seg->lv, params, &seg_status->vdo_pool))
return_0;
seg_status->type = SEG_STATUS_VDO_POOL;
} else if (segtype_is_writecache(segtype)) {
if (!dm_get_status_writecache(seg_status->mem, params, &(seg_status->writecache)))
return_0;
seg_status->type = SEG_STATUS_WRITECACHE;
} else
/*
* TODO: Add support for other segment types too!
@@ -374,7 +378,7 @@ static int _ignore_blocked_mirror_devices(struct device *dev,
if (!(tmp_dev = dev_create_file(buf, NULL, NULL, 0)))
goto_out;
tmp_dev->dev = MKDEV((dev_t)sm->logs[0].major, (dev_t)sm->logs[0].minor);
tmp_dev->dev = MKDEV(sm->logs[0].major, sm->logs[0].minor);
if (device_is_usable(tmp_dev, (struct dev_usable_check_params)
{ .check_empty = 1,
.check_blocked = 1,
@@ -827,11 +831,135 @@ static int _info(struct cmd_context *cmd,
return 1;
}
/* FIXME: could we just use dev_manager_info instead of this? */
int get_cache_vol_meta_data(struct cmd_context *cmd,
struct logical_volume *lv,
struct logical_volume *pool_lv,
struct dm_info *info_meta, struct dm_info *info_data)
{
struct lv_segment *lvseg = first_seg(lv);
union lvid lvid_meta;
union lvid lvid_data;
char *name_meta;
char *name_data;
char *dlid_meta;
char *dlid_data;
memset(&lvid_meta, 0, sizeof(lvid_meta));
memset(&lvid_data, 0, sizeof(lvid_meta));
memcpy(&lvid_meta.id[0], &lv->vg->id, sizeof(struct id));
memcpy(&lvid_meta.id[1], &lvseg->metadata_id, sizeof(struct id));
memcpy(&lvid_data.id[0], &lv->vg->id, sizeof(struct id));
memcpy(&lvid_data.id[1], &lvseg->data_id, sizeof(struct id));
if (!(dlid_meta = dm_build_dm_uuid(cmd->mem, UUID_PREFIX, (const char *)&lvid_meta.s, NULL)))
return_0;
if (!(dlid_data = dm_build_dm_uuid(cmd->mem, UUID_PREFIX, (const char *)&lvid_data.s, NULL)))
return_0;
if (!(name_meta = dm_build_dm_name(cmd->mem, lv->vg->name, pool_lv->name, "_cmeta")))
return_0;
if (!(name_data = dm_build_dm_name(cmd->mem, lv->vg->name, pool_lv->name, "_cdata")))
return_0;
if (!_info(cmd, name_meta, dlid_meta, 1, 0, info_meta, NULL, NULL))
return_0;
if (!_info(cmd, name_data, dlid_data, 1, 0, info_data, NULL, NULL))
return_0;
return 1;
}
/*
* FIXME: isn't there a simpler, more direct way to just remove these two dm
* devs?
*/
int remove_cache_vol_meta_data(struct cmd_context *cmd,
struct dm_info *info_meta, struct dm_info *info_data)
{
struct dm_tree *dtree;
struct dm_tree_node *root;
struct dm_tree_node *child;
const char *uuid;
void *handle = NULL;
if (!(dtree = dm_tree_create()))
goto_out;
if (!dm_tree_add_dev(dtree, info_meta->major, info_meta->minor))
goto_out;
if (!dm_tree_add_dev(dtree, info_data->major, info_data->minor))
goto_out;
if (!(root = dm_tree_find_node(dtree, 0, 0)))
goto_out;
while ((child = dm_tree_next_child(&handle, root, 0))) {
if (!(uuid = dm_tree_node_get_uuid(child))) {
stack;
continue;
}
if (!dm_tree_deactivate_children(root, uuid, strlen(uuid))) {
stack;
continue;
}
}
dm_tree_free(dtree);
return 1;
out:
dm_tree_free(dtree);
return 0;
}
int dev_manager_remove_dm_major_minor(uint32_t major, uint32_t minor)
{
struct dm_task *dmt;
int r = 0;
log_verbose("Removing dm dev %u:%u", major, minor);
if (!(dmt = dm_task_create(DM_DEVICE_REMOVE)))
return_0;
if (!dm_task_set_major(dmt, major) || !dm_task_set_minor(dmt, minor)) {
log_error("Failed to set device number for remove %u:%u", major, minor);
goto out;
}
r = dm_task_run(dmt);
out:
dm_task_destroy(dmt);
return r;
}
static int _info_by_dev(uint32_t major, uint32_t minor, struct dm_info *info)
{
return _info_run(NULL, info, NULL, 0, 0, 0, major, minor);
}
int dev_manager_check_prefix_dm_major_minor(uint32_t major, uint32_t minor, const char *prefix)
{
struct dm_task *dmt;
const char *uuid;
int r = 1;
if (!(dmt = _setup_task_run(DM_DEVICE_INFO, NULL, NULL, NULL, 0, major, minor, 0, 0, 0)))
return_0;
if (!(uuid = dm_task_get_uuid(dmt)) || strncasecmp(uuid, prefix, strlen(prefix)))
r = 0;
dm_task_destroy(dmt);
return r;
}
int dev_manager_info(struct cmd_context *cmd,
const struct logical_volume *lv, const char *layer,
int with_open_count, int with_read_ahead,
@@ -1450,6 +1578,40 @@ out:
return r;
}
int dev_manager_writecache_message(struct dev_manager *dm,
const struct logical_volume *lv,
const char *msg)
{
int r = 0;
const char *dlid;
struct dm_task *dmt;
const char *layer = lv_layer(lv);
if (!lv_is_writecache(lv)) {
log_error(INTERNAL_ERROR "%s is not a writecache logical volume.",
display_lvname(lv));
return 0;
}
if (!(dlid = build_dm_uuid(dm->mem, lv, layer)))
return_0;
if (!(dmt = _setup_task_run(DM_DEVICE_TARGET_MSG, NULL, NULL, dlid, 0, 0, 0, 0, 1, 0)))
return_0;
if (!dm_task_set_message(dmt, msg))
goto_out;
if (!dm_task_run(dmt))
goto_out;
r = 1;
out:
dm_task_destroy(dmt);
return r;
}
int dev_manager_cache_status(struct dev_manager *dm,
const struct logical_volume *lv,
struct lv_status_cache **status)
@@ -1647,9 +1809,8 @@ out:
int dev_manager_vdo_pool_status(struct dev_manager *dm,
const struct logical_volume *lv,
int flush,
char **vdo_params,
struct lv_status_vdo **vdo_status)
struct lv_status_vdo **vdo_status,
int flush)
{
struct lv_status_vdo *status;
const char *dlid;
@@ -1660,7 +1821,6 @@ int dev_manager_vdo_pool_status(struct dev_manager *dm,
char *params = NULL;
int r = 0;
*vdo_params = NULL;
*vdo_status = NULL;
if (!(status = dm_pool_zalloc(dm->mem, sizeof(struct lv_status_vdo)))) {
@@ -1689,13 +1849,11 @@ int dev_manager_vdo_pool_status(struct dev_manager *dm,
goto out;
}
if (!(*vdo_params = dm_pool_strdup(dm->mem, params))) {
log_error("Cannot duplicate VDO status params.");
goto out;
}
if (!parse_vdo_pool_status(dm->mem, lv, params, status))
goto_out;
status->mem = dm->mem;
*vdo_status = status;
*vdo_status = status;
r = 1;
out:
@@ -1916,7 +2074,8 @@ static int _check_holder(struct dev_manager *dm, struct dm_tree *dtree,
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);
/* trims any UUID suffix (i.e. -cow) */
(void) 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))) {
@@ -2232,6 +2391,10 @@ static int _pool_register_callback(struct dev_manager *dm,
return 1;
#endif
/* Skip for single-device cache pool */
if (lv_is_cache(lv) && lv_is_cache_vol(first_seg(lv)->pool_lv))
return 1;
if (!(data = dm_pool_zalloc(dm->mem, sizeof(*data)))) {
log_error("Failed to allocated path for callback.");
return 0;
@@ -2299,6 +2462,53 @@ static int _add_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
/* Unused cache pool is activated as metadata */
}
if (lv_is_cache(lv) && lv_is_cache_vol(first_seg(lv)->pool_lv) && dm->activation) {
struct logical_volume *pool_lv = first_seg(lv)->pool_lv;
struct lv_segment *lvseg = first_seg(lv);
struct dm_info info_meta;
struct dm_info info_data;
union lvid lvid_meta;
union lvid lvid_data;
char *name_meta;
char *name_data;
char *dlid_meta;
char *dlid_data;
memset(&lvid_meta, 0, sizeof(lvid_meta));
memset(&lvid_data, 0, sizeof(lvid_meta));
memcpy(&lvid_meta.id[0], &lv->vg->id, sizeof(struct id));
memcpy(&lvid_meta.id[1], &lvseg->metadata_id, sizeof(struct id));
memcpy(&lvid_data.id[0], &lv->vg->id, sizeof(struct id));
memcpy(&lvid_data.id[1], &lvseg->data_id, sizeof(struct id));
if (!(dlid_meta = dm_build_dm_uuid(dm->mem, UUID_PREFIX, (const char *)&lvid_meta.s, NULL)))
return_0;
if (!(dlid_data = dm_build_dm_uuid(dm->mem, UUID_PREFIX, (const char *)&lvid_data.s, NULL)))
return_0;
if (!(name_meta = dm_build_dm_name(dm->mem, lv->vg->name, pool_lv->name, "_cmeta")))
return_0;
if (!(name_data = dm_build_dm_name(dm->mem, lv->vg->name, pool_lv->name, "_cdata")))
return_0;
if (!_info(dm->cmd, name_meta, dlid_meta, 1, 0, &info_meta, NULL, NULL))
return_0;
if (!_info(dm->cmd, name_data, dlid_data, 1, 0, &info_data, NULL, NULL))
return_0;
if (info_meta.exists &&
!dm_tree_add_dev_with_udev_flags(dtree, info_meta.major, info_meta.minor,
_get_udev_flags(dm, lv, NULL, 0, 0, 0))) {
log_error("Failed to add device (%" PRIu32 ":%" PRIu32") to dtree.", info_meta.major, info_meta.minor);
}
if (info_data.exists &&
!dm_tree_add_dev_with_udev_flags(dtree, info_data.major, info_data.minor,
_get_udev_flags(dm, lv, NULL, 0, 0, 0))) {
log_error("Failed to add device (%" PRIu32 ":%" PRIu32") to dtree.", info_data.major, info_data.minor);
}
}
if (!origin_only && !_add_dev_to_dtree(dm, dtree, lv, NULL))
return_0;
@@ -2439,8 +2649,12 @@ static int _add_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
if (seg->metadata_lv &&
!_add_lv_to_dtree(dm, dtree, seg->metadata_lv, 0))
return_0;
if (seg->writecache && seg_is_writecache(seg)) {
if (!_add_lv_to_dtree(dm, dtree, seg->writecache, dm->activation ? origin_only : 1))
return_0;
}
if (seg->pool_lv &&
(lv_is_cache_pool(seg->pool_lv) || dm->track_external_lv_deps) &&
(lv_is_cache_pool(seg->pool_lv) || lv_is_cache_vol(seg->pool_lv) || dm->track_external_lv_deps) &&
/* When activating and not origin_only detect linear 'overlay' over pool */
!_add_lv_to_dtree(dm, dtree, seg->pool_lv, dm->activation ? origin_only : 1))
return_0;
@@ -2891,6 +3105,11 @@ static int _add_segment_to_dtree(struct dev_manager *dm,
lv_layer(seg->pool_lv)))
return_0;
if (seg->writecache && !laopts->origin_only &&
!_add_new_lv_to_dtree(dm, dtree, seg->writecache, laopts,
lv_layer(seg->writecache)))
return_0;
/* Add any LVs used by this segment */
for (s = 0; s < seg->area_count; ++s) {
if ((seg_type(seg, s) == AREA_LV) &&
@@ -2937,6 +3156,14 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
int save_pending_delete = dm->track_pending_delete;
int merge_in_progress = 0;
if (!(lvlayer = dm_pool_alloc(dm->mem, sizeof(*lvlayer)))) {
log_error("_add_new_lv_to_dtree: pool alloc failed for %s %s.",
display_lvname(lv), layer);
return 0;
}
lvlayer->lv = lv;
lvlayer->visible_component = (laopts->component_lv == lv) ? 1 : 0;
log_debug_activation("Adding new LV %s%s%s to dtree", display_lvname(lv),
layer ? "-" : "", layer ? : "");
/* LV with pending delete is never put new into a table */
@@ -2953,6 +3180,99 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
return 1;
}
if (lv_is_cache(lv) && lv_is_cache_vol(first_seg(lv)->pool_lv)) {
struct logical_volume *pool_lv = first_seg(lv)->pool_lv;
struct lv_segment *lvseg = first_seg(lv);
struct volume_group *vg = lv->vg;
struct dm_tree_node *dnode_meta;
struct dm_tree_node *dnode_data;
union lvid lvid_meta;
union lvid lvid_data;
char *name_meta;
char *name_data;
char *dlid_meta;
char *dlid_data;
char *dlid_pool;
uint64_t meta_len = first_seg(lv)->metadata_len;
uint64_t data_len = first_seg(lv)->data_len;
uint16_t udev_flags = _get_udev_flags(dm, lv, layer,
laopts->noscan, laopts->temporary,
0);
log_debug("Add cache pool %s to dtree before cache %s", pool_lv->name, lv->name);
if (!_add_new_lv_to_dtree(dm, dtree, pool_lv, laopts, NULL)) {
log_error("Failed to add cachepool to dtree before cache");
return_0;
}
memset(&lvid_meta, 0, sizeof(lvid_meta));
memset(&lvid_data, 0, sizeof(lvid_meta));
memcpy(&lvid_meta.id[0], &vg->id, sizeof(struct id));
memcpy(&lvid_meta.id[1], &lvseg->metadata_id, sizeof(struct id));
memcpy(&lvid_data.id[0], &vg->id, sizeof(struct id));
memcpy(&lvid_data.id[1], &lvseg->data_id, sizeof(struct id));
if (!(dlid_meta = dm_build_dm_uuid(dm->mem, UUID_PREFIX, (const char *)&lvid_meta.s, NULL)))
return_0;
if (!(dlid_data = dm_build_dm_uuid(dm->mem, UUID_PREFIX, (const char *)&lvid_data.s, NULL)))
return_0;
if (!(name_meta = dm_build_dm_name(dm->mem, vg->name, pool_lv->name, "_cmeta")))
return_0;
if (!(name_data = dm_build_dm_name(dm->mem, vg->name, pool_lv->name, "_cdata")))
return_0;
if (!(dlid_pool = build_dm_uuid(dm->mem, pool_lv, NULL)))
return_0;
/* add meta dnode */
if (!(dnode_meta = dm_tree_add_new_dev_with_udev_flags(dtree,
name_meta,
dlid_meta,
-1, -1,
read_only_lv(lv, laopts, layer),
((lv->vg->status & PRECOMMITTED) | laopts->revert) ? 1 : 0,
lvlayer,
udev_flags)))
return_0;
/* add load_segment to meta dnode: linear, size of meta area */
if (!add_linear_area_to_dtree(dnode_meta,
meta_len,
lv->vg->extent_size,
lv->vg->cmd->use_linear_target,
lv->vg->name, lv->name))
return_0;
/* add seg_area to prev load_seg: offset 0 maps to cachepool lv offset 0 */
if (!dm_tree_node_add_target_area(dnode_meta, NULL, dlid_pool, 0))
return_0;
/* add data dnode */
if (!(dnode_data = dm_tree_add_new_dev_with_udev_flags(dtree,
name_data,
dlid_data,
-1, -1,
read_only_lv(lv, laopts, layer),
((lv->vg->status & PRECOMMITTED) | laopts->revert) ? 1 : 0,
lvlayer,
udev_flags)))
return_0;
/* add load_segment to data dnode: linear, size of data area */
if (!add_linear_area_to_dtree(dnode_data,
data_len,
lv->vg->extent_size,
lv->vg->cmd->use_linear_target,
lv->vg->name, lv->name))
return_0;
/* add seg_area to prev load_seg: offset 0 maps to cachepool lv after meta */
if (!dm_tree_node_add_target_area(dnode_data, NULL, dlid_pool, meta_len))
return_0;
}
/* FIXME Seek a simpler way to lay out the snapshot-merge tree. */
if (!layer && lv_is_merging_origin(lv)) {
@@ -3021,12 +3341,6 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
dm_tree_node_get_context(dnode))
return 1;
if (!(lvlayer = dm_pool_alloc(dm->mem, sizeof(*lvlayer)))) {
log_error("_add_new_lv_to_dtree: pool alloc failed for %s %s.",
display_lvname(lv), layer);
return 0;
}
lvlayer->lv = lv;
lvlayer->visible_component = (laopts->component_lv == lv) ? 1 : 0;
@@ -3117,7 +3431,7 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
!_pool_register_callback(dm, dnode, lv))
return_0;
if (lv_is_cache(lv) &&
if (lv_is_cache(lv) && !lv_is_cache_vol(first_seg(lv)->pool_lv) &&
/* Register callback only for layer activation or non-layered cache LV */
(layer || !lv_layer(lv)) &&
/* Register callback when metadata LV is NOT already active */
@@ -3402,6 +3716,19 @@ int dev_manager_activate(struct dev_manager *dm, const struct logical_volume *lv
if (!_tree_action(dm, lv, laopts, ACTIVATE))
return_0;
/*
* When lvm2 resumes a device and shortly after that it removes it,
* udevd rule will try to blindly call 'dmsetup info' on already removed
* device leaving the trace inside syslog about failing operation.
*
* TODO: It's not completely clear this call here is the best fix.
* Maybe there can be a better sequence, but ATM we do usually resume
* error device i.e. on cache deletion and remove it.
* TODO2: there could be more similar cases!
*/
if (!dm_list_empty(&dm->pending_delete))
fs_unlock();
if (!_tree_action(dm, lv, laopts, CLEAN))
return_0;

View File

@@ -63,6 +63,9 @@ int dev_manager_raid_status(struct dev_manager *dm,
int dev_manager_raid_message(struct dev_manager *dm,
const struct logical_volume *lv,
const char *msg);
int dev_manager_writecache_message(struct dev_manager *dm,
const struct logical_volume *lv,
const char *msg);
int dev_manager_cache_status(struct dev_manager *dm,
const struct logical_volume *lv,
struct lv_status_cache **status);
@@ -81,9 +84,8 @@ int dev_manager_thin_device_id(struct dev_manager *dm,
uint32_t *device_id);
int dev_manager_vdo_pool_status(struct dev_manager *dm,
const struct logical_volume *lv,
int flush,
char **vdo_params,
struct lv_status_vdo **vdo_status);
struct lv_status_vdo **vdo_status,
int flush);
int dev_manager_suspend(struct dev_manager *dm, const struct logical_volume *lv,
struct lv_activate_opts *laopts, int lockfs, int flush_required);
int dev_manager_activate(struct dev_manager *dm, const struct logical_volume *lv,
@@ -103,4 +105,16 @@ int dev_manager_execute(struct dev_manager *dm);
int dev_manager_device_uses_vg(struct device *dev,
struct volume_group *vg);
int dev_manager_remove_dm_major_minor(uint32_t major, uint32_t minor);
int dev_manager_check_prefix_dm_major_minor(uint32_t major, uint32_t minor, const char *prefix);
int get_cache_vol_meta_data(struct cmd_context *cmd,
struct logical_volume *lv,
struct logical_volume *pool_lv,
struct dm_info *info_meta, struct dm_info *info_data);
int remove_cache_vol_meta_data(struct cmd_context *cmd,
struct dm_info *info_meta, struct dm_info *info_data);
#endif

View File

@@ -487,7 +487,8 @@ int fs_rename_lv(const struct logical_volume *lv, const char *dev,
void fs_unlock(void)
{
if (!prioritized_section()) {
/* Do not allow syncing device name with suspended devices */
if (!dm_get_suspended_counter()) {
log_debug_activation("Syncing device names");
/* Wait for all processed udev devices */
if (!dm_udev_wait(_fs_cookie))

755
lib/cache/lvmcache.c vendored

File diff suppressed because it is too large Load Diff

87
lib/cache/lvmcache.h vendored
View File

@@ -57,10 +57,12 @@ struct lvmcache_vgsummary {
char *creation_host;
const char *system_id;
const char *lock_type;
uint32_t seqno;
uint32_t mda_checksum;
size_t mda_size;
int zero_offset;
int seqno;
int mda_num; /* 1 = summary from mda1, 2 = summary from mda2 */
unsigned mda_ignored:1;
unsigned zero_offset:1;
};
int lvmcache_init(struct cmd_context *cmd);
@@ -72,9 +74,9 @@ int lvmcache_label_rescan_vg(struct cmd_context *cmd, const char *vgname, const
/* Add/delete a device */
struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
struct device *dev,
const char *vgname, const char *vgid,
uint32_t vgstatus);
struct device *dev, uint64_t label_sector,
const char *vgname, const char *vgid,
uint32_t vgstatus, int *is_duplicate);
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);
@@ -82,18 +84,15 @@ void lvmcache_del_dev(struct device *dev);
/* Update things */
int lvmcache_update_vgname_and_id(struct lvmcache_info *info,
struct lvmcache_vgsummary *vgsummary);
int lvmcache_update_vg(struct volume_group *vg, unsigned precommitted);
int lvmcache_update_vg_from_read(struct volume_group *vg, unsigned precommitted);
int lvmcache_update_vg_from_write(struct volume_group *vg);
void lvmcache_lock_vgname(const char *vgname, int read_only);
void lvmcache_unlock_vgname(const char *vgname);
/* Queries */
const struct format_type *lvmcache_fmt_from_vgname(struct cmd_context *cmd, const char *vgname, const char *vgid, unsigned revalidate_labels);
int lvmcache_lookup_mda(struct lvmcache_vgsummary *vgsummary);
/* Decrement and test if there are still vg holders in vginfo. */
int lvmcache_vginfo_holders_dec_and_test_for_zero(struct lvmcache_vginfo *vginfo);
struct lvmcache_vginfo *lvmcache_vginfo_from_vgname(const char *vgname,
const char *vgid);
struct lvmcache_vginfo *lvmcache_vginfo_from_vgid(const char *vgid);
@@ -103,14 +102,11 @@ const char *lvmcache_vgid_from_vgname(struct cmd_context *cmd, const char *vgnam
struct device *lvmcache_device_from_pvid(struct cmd_context *cmd, const struct id *pvid, uint64_t *label_sector);
const char *lvmcache_vgname_from_info(struct lvmcache_info *info);
const struct format_type *lvmcache_fmt_from_info(struct lvmcache_info *info);
int lvmcache_vgs_locked(void);
int lvmcache_get_vgnameids(struct cmd_context *cmd, int include_internal,
struct dm_list *vgnameids);
/* Returns list of struct dm_str_list containing pool-allocated copy of pvids */
struct dm_list *lvmcache_get_pvids(struct cmd_context *cmd, const char *vgname,
const char *vgid);
int lvmcache_get_vgnameids(struct cmd_context *cmd,
struct dm_list *vgnameids,
const char *only_this_vgname,
int include_internal);
void lvmcache_drop_metadata(const char *vgname, int drop_precommitted);
void lvmcache_commit_metadata(const char *vgname);
@@ -127,7 +123,8 @@ void lvmcache_del_mdas(struct lvmcache_info *info);
void lvmcache_del_das(struct lvmcache_info *info);
void lvmcache_del_bas(struct lvmcache_info *info);
int lvmcache_add_mda(struct lvmcache_info *info, struct device *dev,
uint64_t start, uint64_t size, unsigned ignored);
uint64_t start, uint64_t size, unsigned ignored,
struct metadata_area **mda_new);
int lvmcache_add_da(struct lvmcache_info *info, uint64_t start, uint64_t size);
int lvmcache_add_ba(struct lvmcache_info *info, uint64_t start, uint64_t size);
@@ -163,14 +160,16 @@ 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);
int lvmcache_is_orphan(struct lvmcache_info *info);
unsigned lvmcache_mda_count(struct lvmcache_info *info);
int lvmcache_vgid_is_cached(const char *vgid);
uint64_t lvmcache_smallest_mda_size(struct lvmcache_info *info);
int lvmcache_found_duplicate_pvs(void);
struct metadata_area *lvmcache_get_mda(struct cmd_context *cmd,
const char *vgname,
struct device *dev,
int use_mda_num);
void lvmcache_pvscan_duplicate_check(struct cmd_context *cmd);
int lvmcache_found_duplicate_pvs(void);
int lvmcache_found_duplicate_vgnames(void);
int lvmcache_get_unused_duplicate_devs(struct cmd_context *cmd, struct dm_list *head);
@@ -183,30 +182,44 @@ void lvmcache_get_max_name_lengths(struct cmd_context *cmd,
int lvmcache_vg_is_foreign(struct cmd_context *cmd, const char *vgname, const char *vgid);
void lvmcache_lock_ordering(int enable);
int lvmcache_dev_is_unchosen_duplicate(struct device *dev);
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);
bool lvmcache_scan_mismatch(struct cmd_context *cmd, const char *vgname, const char *vgid);
int lvmcache_scan_mismatch(struct cmd_context *cmd, const char *vgname, const char *vgid);
int lvmcache_vginfo_has_pvid(struct lvmcache_vginfo *vginfo, char *pvid);
/*
* 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);
uint64_t lvmcache_max_metadata_size(void);
void lvmcache_save_metadata_size(uint64_t val);
int dev_in_device_list(struct device *dev, struct dm_list *head);
bool lvmcache_has_bad_metadata(struct device *dev);
bool lvmcache_has_old_metadata(struct cmd_context *cmd, const char *vgname, const char *vgid, struct device *dev);
void lvmcache_get_outdated_devs(struct cmd_context *cmd,
const char *vgname, const char *vgid,
struct dm_list *devs);
void lvmcache_get_outdated_mdas(struct cmd_context *cmd,
const char *vgname, const char *vgid,
struct device *dev,
struct dm_list **mdas);
bool lvmcache_is_outdated_dev(struct cmd_context *cmd,
const char *vgname, const char *vgid,
struct device *dev);
void lvmcache_del_outdated_devs(struct cmd_context *cmd,
const char *vgname, const char *vgid);
void lvmcache_save_bad_mda(struct lvmcache_info *info, struct metadata_area *mda);
void lvmcache_get_bad_mdas(struct cmd_context *cmd,
const char *vgname, const char *vgid,
struct dm_list *bad_mda_list);
#endif

View File

@@ -47,23 +47,33 @@ static int _cache_out_line(const char *line, void *_f)
static void _cache_display(const struct lv_segment *seg)
{
const struct dm_config_node *n;
const struct lv_segment *pool_seg =
seg_is_cache_pool(seg) ? seg : first_seg(seg->pool_lv);
const struct lv_segment *setting_seg = NULL;
if (seg_is_cache(seg) && lv_is_cache_vol(seg->pool_lv))
setting_seg = seg;
else if (seg_is_cache_pool(seg))
setting_seg = seg;
else if (seg_is_cache(seg))
setting_seg = first_seg(seg->pool_lv);
else
return;
log_print(" Chunk size\t\t%s",
display_size(seg->lv->vg->cmd, pool_seg->chunk_size));
display_size(seg->lv->vg->cmd, setting_seg->chunk_size));
if (pool_seg->cache_metadata_format != CACHE_METADATA_FORMAT_UNSELECTED)
log_print(" Metadata format\t%u", pool_seg->cache_metadata_format);
if (setting_seg->cache_metadata_format != CACHE_METADATA_FORMAT_UNSELECTED)
log_print(" Metadata format\t%u", setting_seg->cache_metadata_format);
if (pool_seg->cache_mode != CACHE_MODE_UNSELECTED)
log_print(" Mode\t\t%s", get_cache_mode_name(pool_seg));
if (setting_seg->cache_mode != CACHE_MODE_UNSELECTED)
log_print(" Mode\t\t%s", get_cache_mode_name(setting_seg));
if (pool_seg->policy_name)
log_print(" Policy\t\t%s", pool_seg->policy_name);
if (setting_seg->policy_name)
log_print(" Policy\t\t%s", setting_seg->policy_name);
if (pool_seg->policy_settings &&
(n = pool_seg->policy_settings->child))
if (setting_seg->policy_settings &&
(n = setting_seg->policy_settings->child))
dm_config_write_node(n, _cache_out_line, NULL);
log_print(" ");
@@ -99,32 +109,16 @@ static void _fix_missing_defaults(struct lv_segment *cpool_seg)
}
}
static int _cache_pool_text_import(struct lv_segment *seg,
const struct dm_config_node *sn,
struct dm_hash_table *pv_hash __attribute__((unused)))
static int _settings_text_import(struct lv_segment *seg,
const struct dm_config_node *sn)
{
struct logical_volume *data_lv, *meta_lv;
const char *str = NULL;
struct dm_pool *mem = seg->lv->vg->vgmem;
if (!dm_config_has_node(sn, "data"))
return SEG_LOG_ERROR("Cache data not specified in");
if (!(str = dm_config_find_str(sn, "data", NULL)))
return SEG_LOG_ERROR("Cache data must be a string in");
if (!(data_lv = find_lv(seg->lv->vg, str)))
return SEG_LOG_ERROR("Unknown logical volume %s specified for "
"cache data in", str);
if (!dm_config_has_node(sn, "metadata"))
return SEG_LOG_ERROR("Cache metadata not specified in");
if (!(str = dm_config_find_str(sn, "metadata", NULL)))
return SEG_LOG_ERROR("Cache metadata must be a string in");
if (!(meta_lv = find_lv(seg->lv->vg, str)))
return SEG_LOG_ERROR("Unknown logical volume %s specified for "
"cache metadata in", str);
if (!dm_config_get_uint32(sn, "chunk_size", &seg->chunk_size))
return SEG_LOG_ERROR("Couldn't read cache chunk_size in");
if (dm_config_has_node(sn, "chunk_size")) {
if (!dm_config_get_uint32(sn, "chunk_size", &seg->chunk_size))
return SEG_LOG_ERROR("Couldn't read cache chunk_size in");
}
/*
* Read in features:
@@ -146,16 +140,6 @@ static int _cache_pool_text_import(struct lv_segment *seg,
return SEG_LOG_ERROR("Failed to duplicate policy in");
}
if (dm_config_has_node(sn, "metadata_format")) {
if (!dm_config_get_uint32(sn, "metadata_format", &seg->cache_metadata_format) ||
((seg->cache_metadata_format != CACHE_METADATA_FORMAT_1) &&
(seg->cache_metadata_format != CACHE_METADATA_FORMAT_2)))
return SEG_LOG_ERROR("Unknown cache metadata format %u number in",
seg->cache_metadata_format);
if (seg->cache_metadata_format == CACHE_METADATA_FORMAT_2)
seg->lv->status |= LV_METADATA_FORMAT;
}
/*
* Read in policy args:
* policy_settings {
@@ -184,6 +168,75 @@ static int _cache_pool_text_import(struct lv_segment *seg,
return_0;
}
return 1;
}
static int _settings_text_export(const struct lv_segment *seg,
struct formatter *f)
{
if (seg->chunk_size)
outf(f, "chunk_size = %" PRIu32, seg->chunk_size);
if (seg->cache_mode != CACHE_MODE_UNSELECTED) {
const char *cache_mode;
if (!(cache_mode = cache_mode_num_to_str(seg->cache_mode)))
return_0;
outf(f, "cache_mode = \"%s\"", cache_mode);
}
if (seg->policy_name) {
outf(f, "policy = \"%s\"", seg->policy_name);
if (seg->policy_settings) {
if (strcmp(seg->policy_settings->key, "policy_settings")) {
log_error(INTERNAL_ERROR "Incorrect policy_settings tree, %s.",
seg->policy_settings->key);
return 0;
}
if (seg->policy_settings->child)
out_config_node(f, seg->policy_settings);
}
}
return 1;
}
static int _cache_pool_text_import(struct lv_segment *seg,
const struct dm_config_node *sn,
struct dm_hash_table *pv_hash __attribute__((unused)))
{
struct logical_volume *data_lv, *meta_lv;
const char *str = NULL;
if (!dm_config_has_node(sn, "data"))
return SEG_LOG_ERROR("Cache data not specified in");
if (!(str = dm_config_find_str(sn, "data", NULL)))
return SEG_LOG_ERROR("Cache data must be a string in");
if (!(data_lv = find_lv(seg->lv->vg, str)))
return SEG_LOG_ERROR("Unknown logical volume %s specified for "
"cache data in", str);
if (!dm_config_has_node(sn, "metadata"))
return SEG_LOG_ERROR("Cache metadata not specified in");
if (!(str = dm_config_find_str(sn, "metadata", NULL)))
return SEG_LOG_ERROR("Cache metadata must be a string in");
if (!(meta_lv = find_lv(seg->lv->vg, str)))
return SEG_LOG_ERROR("Unknown logical volume %s specified for "
"cache metadata in", str);
if (dm_config_has_node(sn, "metadata_format")) {
if (!dm_config_get_uint32(sn, "metadata_format", &seg->cache_metadata_format) ||
((seg->cache_metadata_format != CACHE_METADATA_FORMAT_1) &&
(seg->cache_metadata_format != CACHE_METADATA_FORMAT_2)))
return SEG_LOG_ERROR("Unknown cache metadata format %u number in",
seg->cache_metadata_format);
if (seg->cache_metadata_format == CACHE_METADATA_FORMAT_2)
seg->lv->status |= LV_METADATA_FORMAT;
}
if (!_settings_text_import(seg, sn))
return_0;
if (!attach_pool_data_lv(seg, data_lv))
return_0;
if (!attach_pool_metadata_lv(seg, meta_lv))
@@ -207,11 +260,8 @@ static int _cache_pool_text_import_area_count(const struct dm_config_node *sn,
static int _cache_pool_text_export(const struct lv_segment *seg,
struct formatter *f)
{
const char *cache_mode;
outf(f, "data = \"%s\"", seg_lv(seg, 0)->name);
outf(f, "metadata = \"%s\"", seg->metadata_lv->name);
outf(f, "chunk_size = %" PRIu32, seg->chunk_size);
switch (seg->cache_metadata_format) {
case CACHE_METADATA_FORMAT_UNSELECTED:
@@ -237,25 +287,9 @@ static int _cache_pool_text_export(const struct lv_segment *seg,
* but not worth to break backward compatibility, by shifting
* content to cache segment
*/
if (seg->cache_mode != CACHE_MODE_UNSELECTED) {
if (!(cache_mode = get_cache_mode_name(seg)))
return_0;
outf(f, "cache_mode = \"%s\"", cache_mode);
}
if (seg->policy_name) {
outf(f, "policy = \"%s\"", seg->policy_name);
if (seg->policy_settings) {
if (strcmp(seg->policy_settings->key, "policy_settings")) {
log_error(INTERNAL_ERROR "Incorrect policy_settings tree, %s.",
seg->policy_settings->key);
return 0;
}
if (seg->policy_settings->child)
out_config_node(f, seg->policy_settings);
}
}
if (!_settings_text_export(seg, f))
return_0;
return 1;
}
@@ -443,6 +477,7 @@ static int _cache_text_import(struct lv_segment *seg,
{
struct logical_volume *pool_lv, *origin_lv;
const char *name;
const char *uuid;
if (!dm_config_has_node(sn, "cache_pool"))
return SEG_LOG_ERROR("cache_pool not specified in");
@@ -472,9 +507,44 @@ static int _cache_text_import(struct lv_segment *seg,
if (!attach_pool_lv(seg, pool_lv, NULL, NULL, NULL))
return_0;
/* load order is unknown, could be cache origin or pool LV, so check for both */
if (!dm_list_empty(&pool_lv->segments))
_fix_missing_defaults(first_seg(pool_lv));
if (!_settings_text_import(seg, sn))
return_0;
if (dm_config_has_node(sn, "metadata_format")) {
if (!dm_config_get_uint32(sn, "metadata_format", &seg->cache_metadata_format))
return SEG_LOG_ERROR("Couldn't read cache metadata_format in");
if (seg->cache_metadata_format != CACHE_METADATA_FORMAT_2)
return SEG_LOG_ERROR("Unknown cache metadata format %u number in",
seg->cache_metadata_format);
}
if (dm_config_has_node(sn, "metadata_start")) {
if (!dm_config_get_uint64(sn, "metadata_start", &seg->metadata_start))
return SEG_LOG_ERROR("Couldn't read metadata_start in");
if (!dm_config_get_uint64(sn, "metadata_len", &seg->metadata_len))
return SEG_LOG_ERROR("Couldn't read metadata_len in");
if (!dm_config_get_uint64(sn, "data_start", &seg->data_start))
return SEG_LOG_ERROR("Couldn't read data_start in");
if (!dm_config_get_uint64(sn, "data_len", &seg->data_len))
return SEG_LOG_ERROR("Couldn't read data_len in");
if (!dm_config_get_str(sn, "metadata_id", &uuid))
return SEG_LOG_ERROR("Couldn't read metadata_id in");
if (!id_read_format(&seg->metadata_id, uuid))
return SEG_LOG_ERROR("Couldn't format metadata_id in");
if (!dm_config_get_str(sn, "data_id", &uuid))
return SEG_LOG_ERROR("Couldn't read data_id in");
if (!id_read_format(&seg->data_id, uuid))
return SEG_LOG_ERROR("Couldn't format data_id in");
} else {
/* Do not call this when LV is cache_vol. */
/* load order is unknown, could be cache origin or pool LV, so check for both */
if (!dm_list_empty(&pool_lv->segments))
_fix_missing_defaults(first_seg(pool_lv));
}
return 1;
}
@@ -489,6 +559,8 @@ static int _cache_text_import_area_count(const struct dm_config_node *sn,
static int _cache_text_export(const struct lv_segment *seg, struct formatter *f)
{
char buffer[40];
if (!seg_lv(seg, 0))
return_0;
@@ -498,6 +570,26 @@ static int _cache_text_export(const struct lv_segment *seg, struct formatter *f)
if (seg->cleaner_policy)
outf(f, "cleaner = 1");
if (lv_is_cache_vol(seg->pool_lv)) {
outf(f, "metadata_format = " FMTu32, seg->cache_metadata_format);
if (!_settings_text_export(seg, f))
return_0;
outf(f, "metadata_start = " FMTu64, seg->metadata_start);
outf(f, "metadata_len = " FMTu64, seg->metadata_len);
outf(f, "data_start = " FMTu64, seg->data_start);
outf(f, "data_len = " FMTu64, seg->data_len);
if (!id_write_format(&seg->metadata_id, buffer, sizeof(buffer)))
return_0;
outf(f, "metadata_id = \"%s\"", buffer);
if (!id_write_format(&seg->data_id, buffer, sizeof(buffer)))
return_0;
outf(f, "data_id = \"%s\"", buffer);
}
return 1;
}
@@ -512,6 +604,9 @@ static int _cache_add_target_line(struct dev_manager *dm,
uint32_t *pvmove_mirror_count __attribute__((unused)))
{
struct lv_segment *cache_pool_seg;
struct lv_segment *setting_seg;
union lvid metadata_lvid;
union lvid data_lvid;
char *metadata_uuid, *data_uuid, *origin_uuid;
uint64_t feature_flags = 0;
unsigned attr;
@@ -521,15 +616,23 @@ static int _cache_add_target_line(struct dev_manager *dm,
return 0;
}
log_debug("cache_add_target_line lv %s pool %s", seg->lv->name, seg->pool_lv->name);
cache_pool_seg = first_seg(seg->pool_lv);
if (lv_is_cache_vol(seg->pool_lv))
setting_seg = seg;
else
setting_seg = cache_pool_seg;
if (seg->cleaner_policy)
/* With cleaner policy always pass writethrough */
feature_flags |= DM_CACHE_FEATURE_WRITETHROUGH;
else
switch (cache_pool_seg->cache_mode) {
switch (setting_seg->cache_mode) {
default:
log_error(INTERNAL_ERROR "LV %s has unknown cache mode %d.",
display_lvname(seg->lv), cache_pool_seg->cache_mode);
display_lvname(seg->lv), setting_seg->cache_mode);
/* Fall through */
case CACHE_MODE_WRITETHROUGH:
feature_flags |= DM_CACHE_FEATURE_WRITETHROUGH;
@@ -542,7 +645,7 @@ static int _cache_add_target_line(struct dev_manager *dm,
break;
}
switch (cache_pool_seg->cache_metadata_format) {
switch (setting_seg->cache_metadata_format) {
case CACHE_METADATA_FORMAT_1: break;
case CACHE_METADATA_FORMAT_2:
if (!_target_present(cmd, NULL, &attr))
@@ -550,7 +653,7 @@ static int _cache_add_target_line(struct dev_manager *dm,
if (!(attr & CACHE_FEATURE_METADATA2)) {
log_error("LV %s has metadata format %u unsuported by kernel.",
display_lvname(seg->lv), cache_pool_seg->cache_metadata_format);
display_lvname(seg->lv), setting_seg->cache_metadata_format);
return 0;
}
feature_flags |= DM_CACHE_FEATURE_METADATA2;
@@ -558,19 +661,50 @@ static int _cache_add_target_line(struct dev_manager *dm,
break;
default:
log_error(INTERNAL_ERROR "LV %s has unknown metadata format %u.",
display_lvname(seg->lv), cache_pool_seg->cache_metadata_format);
display_lvname(seg->lv), setting_seg->cache_metadata_format);
return 0;
}
if (!(metadata_uuid = build_dm_uuid(mem, cache_pool_seg->metadata_lv, NULL)))
return_0;
if (!(data_uuid = build_dm_uuid(mem, seg_lv(cache_pool_seg, 0), NULL)))
return_0;
if (!(origin_uuid = build_dm_uuid(mem, seg_lv(seg, 0), NULL)))
return_0;
if (!lv_is_cache_vol(seg->pool_lv)) {
/* We don't use start/len when using separate data/meta devices. */
if (seg->metadata_len || seg->data_len) {
log_error(INTERNAL_ERROR "LV %s using unsupported ranges with cache pool.",
display_lvname(seg->lv));
return 0;
}
if (!(metadata_uuid = build_dm_uuid(mem, cache_pool_seg->metadata_lv, NULL)))
return_0;
if (!(data_uuid = build_dm_uuid(mem, seg_lv(cache_pool_seg, 0), NULL)))
return_0;
} else {
if (!seg->metadata_len || !seg->data_len || (seg->metadata_start == seg->data_start)) {
log_error(INTERNAL_ERROR "LV %s has invalid ranges metadata %llu %llu data %llu %llu.",
display_lvname(seg->lv),
(unsigned long long)seg->metadata_start,
(unsigned long long)seg->metadata_len,
(unsigned long long)seg->data_start,
(unsigned long long)seg->data_len);
return 0;
}
memset(&metadata_lvid, 0, sizeof(metadata_lvid));
memset(&data_lvid, 0, sizeof(data_lvid));
memcpy(&metadata_lvid.id[0], &seg->lv->vg->id, sizeof(struct id));
memcpy(&metadata_lvid.id[1], &seg->metadata_id, sizeof(struct id));
memcpy(&data_lvid.id[0], &seg->lv->vg->id, sizeof(struct id));
memcpy(&data_lvid.id[1], &seg->data_id, sizeof(struct id));
if (!(metadata_uuid = dm_build_dm_uuid(mem, UUID_PREFIX, (const char *)&metadata_lvid.s, NULL)))
return_0;
if (!(data_uuid = dm_build_dm_uuid(mem, UUID_PREFIX, (const char *)&data_lvid.s, NULL)))
return_0;
}
if (!dm_tree_node_add_cache_target(node, len,
feature_flags,
metadata_uuid,
@@ -579,8 +713,12 @@ static int _cache_add_target_line(struct dev_manager *dm,
seg->cleaner_policy ? "cleaner" :
/* undefined policy name -> likely an old "mq" */
cache_pool_seg->policy_name ? : "mq",
seg->cleaner_policy ? NULL : cache_pool_seg->policy_settings,
cache_pool_seg->chunk_size))
seg->cleaner_policy ? NULL : setting_seg->policy_settings,
seg->metadata_start,
seg->metadata_len,
seg->data_start,
seg->data_len,
setting_seg->chunk_size))
return_0;
return 1;

View File

@@ -22,6 +22,7 @@
#include "lib/activate/activate.h"
#include "lib/filters/filter.h"
#include "lib/label/label.h"
#include "lib/label/hints.h"
#include "lib/misc/lvm-file.h"
#include "lib/format_text/format-text.h"
#include "lib/display/display.h"
@@ -32,10 +33,6 @@
#include "lib/format_text/archiver.h"
#include "lib/lvmpolld/lvmpolld-client.h"
#ifdef HAVE_LIBDL
#include "lib/misc/sharedlib.h"
#endif
#include <locale.h>
#include <sys/stat.h>
#include <sys/syscall.h>
@@ -235,6 +232,45 @@ static void _get_sysfs_dir(struct cmd_context *cmd, char *buf, size_t buf_size)
strncpy(buf, sys_mnt, buf_size);
}
static uint32_t _parse_debug_fields(struct cmd_context *cmd, int cfg, const char *cfgname)
{
const struct dm_config_node *cn;
const struct dm_config_value *cv;
uint32_t debug_fields = 0;
if (!(cn = find_config_tree_array(cmd, cfg, NULL))) {
log_error(INTERNAL_ERROR "Unable to find configuration for log/%s.", cfgname);
return 0;
}
for (cv = cn->v; cv; cv = cv->next) {
if (cv->type != DM_CFG_STRING) {
log_verbose("log/%s contains a value which is not a string. Ignoring.", cfgname);
continue;
}
if (!strcasecmp(cv->v.str, "all"))
return 0;
if (!strcasecmp(cv->v.str, "time"))
debug_fields |= LOG_DEBUG_FIELD_TIME;
else if (!strcasecmp(cv->v.str, "command"))
debug_fields |= LOG_DEBUG_FIELD_COMMAND;
else if (!strcasecmp(cv->v.str, "fileline"))
debug_fields |= LOG_DEBUG_FIELD_FILELINE;
else if (!strcasecmp(cv->v.str, "message"))
debug_fields |= LOG_DEBUG_FIELD_MESSAGE;
else
log_verbose("Unrecognised value for log/%s: %s", cfgname, cv->v.str);
}
return debug_fields;
}
static int _parse_debug_classes(struct cmd_context *cmd)
{
const struct dm_config_node *cn;
@@ -323,8 +359,8 @@ static void _init_logging(struct cmd_context *cmd)
cmd->default_settings.msg_prefix = find_config_tree_str_allow_empty(cmd, log_prefix_CFG, NULL);
init_msg_prefix(cmd->default_settings.msg_prefix);
cmd->default_settings.cmd_name = find_config_tree_bool(cmd, log_command_names_CFG, NULL);
init_cmd_name(cmd->default_settings.cmd_name);
/* so that file and verbose output have a command prefix */
init_log_command(0, 0);
/* Test mode */
cmd->default_settings.test =
@@ -338,21 +374,19 @@ static void _init_logging(struct cmd_context *cmd)
log_file = find_config_tree_str(cmd, log_file_CFG, NULL);
if (log_file) {
release_log_memory();
fin_log();
init_log_file(log_file, append);
}
log_file = find_config_tree_str(cmd, log_activate_file_CFG, NULL);
if (log_file)
init_log_direct(log_file, append);
init_log_while_suspended(find_config_tree_bool(cmd, log_activation_CFG, NULL));
cmd->default_settings.debug_classes = _parse_debug_classes(cmd);
log_debug("Setting log debug classes to %d", cmd->default_settings.debug_classes);
init_debug_classes_logged(cmd->default_settings.debug_classes);
init_debug_file_fields(_parse_debug_fields(cmd, log_debug_file_fields_CFG, "debug_file_fields"));
init_debug_output_fields(_parse_debug_fields(cmd, log_debug_output_fields_CFG, "debug_output_fields"));
t = time(NULL);
ctime_r(&t, &timebuf[0]);
timebuf[24] = '\0';
@@ -681,6 +715,8 @@ static int _process_config(struct cmd_context *cmd)
if (!_init_system_id(cmd))
return_0;
init_io_memory_size(find_config_tree_int(cmd, global_io_memory_size_CFG, NULL));
return 1;
}
@@ -1032,7 +1068,7 @@ static int _init_dev_cache(struct cmd_context *cmd)
#define MAX_FILTERS 10
static struct dev_filter *_init_lvmetad_filter_chain(struct cmd_context *cmd)
static struct dev_filter *_init_filter_chain(struct cmd_context *cmd)
{
int nr_filt = 0;
const struct dm_config_node *cn;
@@ -1141,27 +1177,9 @@ bad:
}
/*
* The way the filtering is initialized depends on whether lvmetad is uesd or not.
*
* If lvmetad is used, there are three filter chains:
*
* - cmd->lvmetad_filter - the lvmetad filter chain used when scanning devs for lvmetad update:
* sysfs filter -> internal filter -> global regex filter -> type filter ->
* usable device filter(FILTER_MODE_PRE_LVMETAD) ->
* mpath component filter -> partitioned filter ->
* md component filter -> fw raid filter
*
* - cmd->filter - the filter chain used for lvmetad responses:
* persistent filter -> regex_filter -> usable device filter(FILTER_MODE_POST_LVMETAD)
*
* - cmd->full_filter - the filter chain used for all the remaining situations:
* cmd->lvmetad_filter -> cmd->filter
*
* If lvmetad is not used, there's just one filter chain:
*
* - cmd->filter == cmd->full_filter:
* persistent filter -> sysfs filter -> internal filter -> global regex filter ->
* regex_filter -> type filter -> usable device filter(FILTER_MODE_NO_LVMETAD) ->
* cmd->filter ==
* persistent(cache) filter -> sysfs filter -> internal filter -> global regex filter ->
* regex_filter -> type filter -> usable device filter ->
* mpath component filter -> partitioned filter -> md component filter -> fw raid filter
*
*/
@@ -1174,32 +1192,30 @@ int init_filters(struct cmd_context *cmd, unsigned load_persistent_cache)
return 0;
}
cmd->lvmetad_filter = _init_lvmetad_filter_chain(cmd);
if (!cmd->lvmetad_filter)
filter = _init_filter_chain(cmd);
if (!filter)
goto_bad;
init_ignore_suspended_devices(find_config_tree_bool(cmd, devices_ignore_suspended_devices_CFG, NULL));
init_ignore_lvm_mirrors(find_config_tree_bool(cmd, devices_ignore_lvm_mirrors_CFG, NULL));
/*
* If lvmetad is used, there's a separation between pre-lvmetad filter chain
* ("cmd->lvmetad_filter") applied only if scanning for lvmetad update and
* post-lvmetad filter chain ("filter") applied on each lvmetad response.
* However, if lvmetad is not used, these two chains are not separated
* and we use exactly one filter chain during device scanning ("filter"
* that includes also "cmd->lvmetad_filter" chain).
* persisent filter is a cache of the previous result real filter result.
* If a dev is found in persistent filter, the pass/fail result saved by
* the pfilter is used. If a dev does not existing in the persistent
* filter, the dev is passed on to the real filter, and when the result
* of the real filter is saved in the persistent filter.
*
* FIXME: we should apply the filter once at the start of the command,
* and not call the filters repeatedly. In that case we would not need
* the persistent/caching filter layer.
*/
filter = cmd->lvmetad_filter;
cmd->lvmetad_filter = NULL;
if (!(pfilter = persistent_filter_create(cmd->dev_types, filter))) {
log_verbose("Failed to create persistent device filter.");
goto bad;
}
cmd->filter = filter = pfilter;
cmd->full_filter = filter;
cmd->filter = pfilter;
cmd->initialized.filters = 1;
return 1;
@@ -1221,10 +1237,6 @@ bad:
filter->destroy(filter);
}
/* if lvmetad is used, the cmd->lvmetad_filter is separate */
if (cmd->lvmetad_filter)
cmd->lvmetad_filter->destroy(cmd->lvmetad_filter);
cmd->initialized.filters = 0;
return 0;
}
@@ -1298,24 +1310,6 @@ int lvm_register_segtype(struct segtype_library *seglib,
return 1;
}
static int _init_single_segtype(struct cmd_context *cmd,
struct segtype_library *seglib)
{
struct segment_type *(*init_segtype_fn) (struct cmd_context *);
struct segment_type *segtype;
if (!(init_segtype_fn = dlsym(seglib->lib, "init_segtype"))) {
log_error("Shared library %s does not contain segment type "
"functions", seglib->libname);
return 0;
}
if (!(segtype = init_segtype_fn(seglib->cmd)))
return_0;
return lvm_register_segtype(seglib, segtype);
}
static int _init_segtypes(struct cmd_context *cmd)
{
int i;
@@ -1336,10 +1330,6 @@ static int _init_segtypes(struct cmd_context *cmd)
NULL
};
#ifdef HAVE_LIBDL
const struct dm_config_node *cn;
#endif
for (i = 0; init_segtype_array[i]; i++) {
if (!(segtype = init_segtype_array[i](cmd)))
return 0;
@@ -1367,55 +1357,9 @@ static int _init_segtypes(struct cmd_context *cmd)
return_0;
#endif
#ifdef HAVE_LIBDL
/* Load any formats in shared libs unless static */
if (!is_static() &&
(cn = find_config_tree_array(cmd, global_segment_libraries_CFG, NULL))) {
const struct dm_config_value *cv;
int (*init_multiple_segtypes_fn) (struct cmd_context *,
struct segtype_library *);
for (cv = cn->v; cv; cv = cv->next) {
if (cv->type != DM_CFG_STRING) {
log_error("Invalid string in config file: "
"global/segment_libraries");
return 0;
}
seglib.libname = cv->v.str;
if (!(seglib.lib = load_shared_library(cmd,
seglib.libname,
"segment type", 0)))
return_0;
if ((init_multiple_segtypes_fn =
dlsym(seglib.lib, "init_multiple_segtypes"))) {
if (dlsym(seglib.lib, "init_segtype"))
log_warn("WARNING: Shared lib %s has "
"conflicting init fns. Using"
" init_multiple_segtypes().",
seglib.libname);
} else
init_multiple_segtypes_fn =
_init_single_segtype;
if (!init_multiple_segtypes_fn(cmd, &seglib)) {
struct dm_list *sgtl, *tmp;
log_error("init_multiple_segtypes() failed: "
"Unloading shared library %s",
seglib.libname);
dm_list_iterate_safe(sgtl, tmp, &cmd->segtypes) {
segtype = dm_list_item(sgtl, struct segment_type);
if (segtype->library == seglib.lib) {
dm_list_del(&segtype->list);
segtype->ops->destroy(segtype);
}
}
dlclose(seglib.lib);
return_0;
}
}
}
#ifdef WRITECACHE_INTERNAL
if (!init_writecache_segtypes(cmd, &seglib))
return 0;
#endif
return 1;
@@ -1578,6 +1522,7 @@ struct cmd_context *create_config_context(void)
dm_list_init(&cmd->config_files);
dm_list_init(&cmd->tags);
dm_list_init(&cmd->hints);
if (!_init_lvm_conf(cmd))
goto_out;
@@ -1753,6 +1698,8 @@ struct cmd_context *create_toolcontext(unsigned is_clvmd,
find_config_tree_array(cmd, devices_types_CFG, NULL))))
goto_out;
init_use_aio(find_config_tree_bool(cmd, global_use_aio_CFG, NULL));
if (!_init_dev_cache(cmd))
goto_out;
@@ -1768,8 +1715,6 @@ struct cmd_context *create_toolcontext(unsigned is_clvmd,
if (!init_lvmcache_orphans(cmd))
goto_out;
dm_list_init(&cmd->unused_duplicate_devs);
if (!_init_segtypes(cmd))
goto_out;
@@ -1814,27 +1759,11 @@ static void _destroy_segtypes(struct dm_list *segtypes)
{
struct dm_list *sgtl, *tmp;
struct segment_type *segtype;
void *lib;
dm_list_iterate_safe(sgtl, tmp, segtypes) {
segtype = dm_list_item(sgtl, struct segment_type);
dm_list_del(&segtype->list);
lib = segtype->library;
segtype->ops->destroy(segtype);
#ifdef HAVE_LIBDL
/*
* If no segtypes remain from this library, close it.
*/
if (lib) {
struct segment_type *segtype2;
dm_list_iterate_items(segtype2, segtypes)
if (segtype2->library == lib)
goto skip_dlclose;
dlclose(lib);
skip_dlclose:
;
}
#endif
}
}
@@ -1849,9 +1778,9 @@ static void _destroy_dev_types(struct cmd_context *cmd)
static void _destroy_filters(struct cmd_context *cmd)
{
if (cmd->full_filter) {
cmd->full_filter->destroy(cmd->full_filter);
cmd->lvmetad_filter = cmd->filter = cmd->full_filter = NULL;
if (cmd->filter) {
cmd->filter->destroy(cmd->filter);
cmd->filter = NULL;
}
cmd->initialized.filters = 0;
}
@@ -1890,6 +1819,7 @@ int refresh_toolcontext(struct cmd_context *cmd)
*/
activation_release();
hints_exit(cmd);
lvmcache_destroy(cmd, 0, 0);
label_scan_destroy(cmd);
label_exit();
@@ -2009,6 +1939,7 @@ void destroy_toolcontext(struct cmd_context *cmd)
archive_exit(cmd);
backup_exit(cmd);
hints_exit(cmd);
lvmcache_destroy(cmd, 0, 0);
label_scan_destroy(cmd);
label_exit();
@@ -2059,7 +1990,6 @@ void destroy_toolcontext(struct cmd_context *cmd)
lvmpolld_disconnect();
release_log_memory();
activation_exit();
reset_log_duplicated();
fin_log();

View File

@@ -44,7 +44,6 @@ struct config_info {
const char *fmt_name;
const char *dmeventd_executable;
uint64_t unit_factor;
int cmd_name; /* Show command name? */
mode_t umask;
char unit_type;
char _padding[1];
@@ -160,7 +159,10 @@ struct cmd_context {
unsigned lockd_gl_removed:1;
unsigned lockd_vg_default_sh:1;
unsigned lockd_vg_enforce_sh:1;
unsigned lockd_lv_sh:1;
unsigned lockd_lv_sh_for_ex:1;
unsigned lockd_global_ex:1; /* set while global lock held ex (lockd) */
unsigned lockf_global_ex:1; /* set while global lock held ex (flock) */
unsigned nolocking:1;
unsigned vg_notify:1;
unsigned lv_notify:1;
unsigned pv_notify:1;
@@ -170,15 +172,21 @@ struct cmd_context {
unsigned pvscan_cache_single:1;
unsigned can_use_one_scan:1;
unsigned is_clvmd:1;
unsigned md_component_detection:1;
unsigned use_full_md_check:1;
unsigned is_activating:1;
unsigned enable_hints:1; /* hints are enabled for cmds in general */
unsigned use_hints:1; /* if hints are enabled this cmd can use them */
unsigned pvscan_recreate_hints:1; /* enable special case hint handling for pvscan --cache */
unsigned scan_lvs:1;
unsigned wipe_outdated_pvs:1;
/*
* Filtering.
* Devices and filtering.
*/
struct dev_filter *lvmetad_filter; /* pre-lvmetad filter chain */
struct dev_filter *filter; /* post-lvmetad filter chain */
struct dev_filter *full_filter; /* lvmetad_filter + filter */
struct dev_filter *filter;
struct dm_list hints;
const char *md_component_checks;
/*
* Configuration.
@@ -229,7 +237,6 @@ struct cmd_context {
const char *report_list_item_separator;
const char *time_format;
unsigned rand_seed;
struct dm_list unused_duplicate_devs; /* save preferences between lvmcache instances */
};
/*

View File

@@ -24,6 +24,7 @@
#include "lib/misc/lvm-file.h"
#include "lib/mm/memlock.h"
#include "lib/label/label.h"
#include "lib/metadata/metadata.h"
#include <sys/stat.h>
#include <sys/mman.h>
@@ -2333,6 +2334,11 @@ int load_pending_profiles(struct cmd_context *cmd)
return r;
}
int get_default_metadata_pvmetadatasize_CFG(struct cmd_context *cmd, struct profile *profile)
{
return get_default_pvmetadatasize_sectors();
}
const char *get_default_devices_cache_dir_CFG(struct cmd_context *cmd, struct profile *profile)
{
static char buf[PATH_MAX];

View File

@@ -311,5 +311,7 @@ int get_default_allocation_cache_pool_chunk_size_CFG(struct cmd_context *cmd, st
const char *get_default_allocation_cache_policy_CFG(struct cmd_context *cmd, struct profile *profile);
#define get_default_unconfigured_allocation_cache_policy_CFG NULL
uint64_t get_default_allocation_cache_pool_max_chunks_CFG(struct cmd_context *cmd, struct profile *profile);
int get_default_metadata_pvmetadatasize_CFG(struct cmd_context *cmd, struct profile *profile);
#define get_default_unconfigured_metadata_pvmetadatasize_CFG NULL
#endif

View File

@@ -226,7 +226,7 @@ cfg(devices_dir_CFG, "dir", devices_CFG_SECTION, CFG_ADVANCED, CFG_TYPE_STRING,
cfg_array(devices_scan_CFG, "scan", devices_CFG_SECTION, CFG_ADVANCED, CFG_TYPE_STRING, "#S/dev", vsn(1, 0, 0), NULL, 0, NULL,
"Directories containing device nodes to use with LVM.\n")
cfg_array(devices_loopfiles_CFG, "loopfiles", devices_CFG_SECTION, CFG_DEFAULT_UNDEFINED | CFG_UNSUPPORTED, CFG_TYPE_STRING, NULL, vsn(1, 2, 0), NULL, vsn(3, 0, 0), NULL, NULL)
cfg_array(devices_loopfiles_CFG, "loopfiles", devices_CFG_SECTION, CFG_DEFAULT_UNDEFINED | CFG_UNSUPPORTED, CFG_TYPE_STRING, NULL, vsn(1, 2, 0), NULL, vsn(2, 3, 0), NULL, NULL)
cfg(devices_obtain_device_list_from_udev_CFG, "obtain_device_list_from_udev", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_OBTAIN_DEVICE_LIST_FROM_UDEV, vsn(2, 2, 85), NULL, 0, NULL,
"Obtain the list of available devices from udev.\n"
@@ -255,6 +255,20 @@ cfg(devices_external_device_info_source_CFG, "external_device_info_source", devi
" compiled with udev support.\n"
"#\n")
cfg(devices_hints_CFG, "hints", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_HINTS, vsn(2, 3, 2), NULL, 0, NULL,
"Use a local file to remember which devices have PVs on them.\n"
"Some commands will use this as an optimization to reduce device\n"
"scanning, and will only scan the listed PVs. Removing the hint file\n"
"will cause lvm to generate a new one. Disable hints if PVs will\n"
"be copied onto devices using non-lvm commands, like dd.\n"
"#\n"
"Accepted values:\n"
" all\n"
" Use all hints.\n"
" none\n"
" Use no hints.\n"
"#\n")
cfg_array(devices_preferred_names_CFG, "preferred_names", devices_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_UNDEFINED , CFG_TYPE_STRING, NULL, vsn(1, 2, 19), NULL, 0, NULL,
"Select which path name to display for a block device.\n"
"If multiple path names exist for a block device, and LVM needs to\n"
@@ -314,13 +328,13 @@ cfg_array(devices_global_filter_CFG, "global_filter", devices_CFG_SECTION, CFG_D
cfg_runtime(devices_cache_CFG, "cache", devices_CFG_SECTION, 0, CFG_TYPE_STRING, vsn(1, 0, 0), vsn(1, 2, 19), NULL,
"This setting is no longer used.\n")
cfg_runtime(devices_cache_dir_CFG, "cache_dir", devices_CFG_SECTION, 0, CFG_TYPE_STRING, vsn(1, 2, 19), vsn(3, 0, 0), NULL,
cfg_runtime(devices_cache_dir_CFG, "cache_dir", devices_CFG_SECTION, 0, CFG_TYPE_STRING, vsn(1, 2, 19), vsn(2, 3, 0), NULL,
"This setting is no longer used.\n")
cfg(devices_cache_file_prefix_CFG, "cache_file_prefix", devices_CFG_SECTION, CFG_ALLOW_EMPTY, CFG_TYPE_STRING, DEFAULT_CACHE_FILE_PREFIX, vsn(1, 2, 19), NULL, vsn(3, 0, 0), NULL,
cfg(devices_cache_file_prefix_CFG, "cache_file_prefix", devices_CFG_SECTION, CFG_ALLOW_EMPTY, CFG_TYPE_STRING, DEFAULT_CACHE_FILE_PREFIX, vsn(1, 2, 19), NULL, vsn(2, 3, 0), NULL,
"This setting is no longer used.\n")
cfg(devices_write_cache_state_CFG, "write_cache_state", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, 1, vsn(1, 0, 0), NULL, vsn(3, 0, 0), NULL,
cfg(devices_write_cache_state_CFG, "write_cache_state", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, 1, vsn(1, 0, 0), NULL, vsn(2, 3, 0), NULL,
"This setting is no longer used.\n")
cfg_array(devices_types_CFG, "types", devices_CFG_SECTION, CFG_DEFAULT_UNDEFINED | CFG_ADVANCED, CFG_TYPE_INT | CFG_TYPE_STRING, NULL, vsn(1, 0, 0), NULL, 0, NULL,
@@ -338,13 +352,46 @@ cfg(devices_sysfs_scan_CFG, "sysfs_scan", devices_CFG_SECTION, 0, CFG_TYPE_BOOL,
"present on the system. sysfs must be part of the kernel and mounted.)\n")
cfg(devices_scan_lvs_CFG, "scan_lvs", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_SCAN_LVS, vsn(2, 2, 182), NULL, 0, NULL,
"Scan LVM LVs for layered PVs.\n")
"Scan LVM LVs for layered PVs, allowing LVs to be used as PVs.\n"
"When 1, LVM will detect PVs layered on LVs, and caution must be\n"
"taken to avoid a host accessing a layered VG that may not belong\n"
"to it, e.g. from a guest image. This generally requires excluding\n"
"the LVs with device filters. Also, when this setting is enabled,\n"
"every LVM command will scan every active LV on the system (unless\n"
"filtered), which can cause performance problems on systems with\n"
"many active LVs. When this setting is 0, LVM will not detect or\n"
"use PVs that exist on LVs, and will not allow a PV to be created on\n"
"an LV. The LVs are ignored using a built in device filter that\n"
"identifies and excludes LVs.\n")
cfg(devices_multipath_component_detection_CFG, "multipath_component_detection", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_MULTIPATH_COMPONENT_DETECTION, vsn(2, 2, 89), NULL, 0, NULL,
"Ignore devices that are components of DM multipath devices.\n")
cfg(devices_md_component_detection_CFG, "md_component_detection", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_MD_COMPONENT_DETECTION, vsn(1, 0, 18), NULL, 0, NULL,
"Ignore devices that are components of software RAID (md) devices.\n")
"Enable detection and exclusion of MD component devices.\n"
"An MD component device is a block device that MD uses as part\n"
"of a software RAID virtual device. When an LVM PV is created\n"
"on an MD device, LVM must only use the top level MD device as\n"
"the PV, and should ignore the underlying component devices.\n"
"In cases where the MD superblock is located at the end of the\n"
"component devices, it is more difficult for LVM to consistently\n"
"identify an MD component, see the md_component_checks setting.\n")
cfg(devices_md_component_checks_CFG, "md_component_checks", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_MD_COMPONENT_CHECKS, vsn(2, 3, 2), NULL, 0, NULL,
"The checks LVM should use to detect MD component devices.\n"
"MD component devices are block devices used by MD software RAID.\n"
"#\n"
"Accepted values:\n"
" auto\n"
" LVM will skip scanning the end of devices when it has other\n"
" indications that the device is not an MD component.\n"
" start\n"
" LVM will only scan the start of devices for MD superblocks.\n"
" This does not incur extra I/O by LVM.\n"
" full\n"
" LVM will scan the start and end of devices for MD superblocks.\n"
" This requires an extra read at the end of devices.\n"
"#\n")
cfg(devices_fw_raid_component_detection_CFG, "fw_raid_component_detection", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_FW_RAID_COMPONENT_DETECTION, vsn(2, 2, 112), NULL, 0, NULL,
"Ignore devices that are components of firmware RAID devices.\n"
@@ -352,16 +399,21 @@ cfg(devices_fw_raid_component_detection_CFG, "fw_raid_component_detection", devi
"detection to execute.\n")
cfg(devices_md_chunk_alignment_CFG, "md_chunk_alignment", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_MD_CHUNK_ALIGNMENT, vsn(2, 2, 48), NULL, 0, NULL,
"Align PV data blocks with md device's stripe-width.\n"
"This applies if a PV is placed directly on an md device.\n")
"Align the start of a PV data area with md device's stripe-width.\n"
"This applies if a PV is placed directly on an md device.\n"
"default_data_alignment will be overriden if it is not aligned\n"
"with the value detected for this setting.\n"
"This setting is overriden by data_alignment_detection,\n"
"data_alignment, and the --dataalignment option.\n")
cfg(devices_default_data_alignment_CFG, "default_data_alignment", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_DATA_ALIGNMENT, vsn(2, 2, 75), NULL, 0, NULL,
"Default alignment of the start of a PV data area in MB.\n"
"If set to 0, a value of 64KiB will be used.\n"
"Set to 1 for 1MiB, 2 for 2MiB, etc.\n")
cfg(devices_default_data_alignment_CFG, "default_data_alignment", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, FIRST_PE_AT_ONE_MB_IN_MB, vsn(2, 2, 75), NULL, 0, NULL,
"Align the start of a PV data area with this number of MiB.\n"
"Set to 1 for 1MiB, 2 for 2MiB, etc. Set to 0 to disable.\n"
"This setting is overriden by data_alignment and the --dataalignment\n"
"option.\n")
cfg(devices_data_alignment_detection_CFG, "data_alignment_detection", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_DATA_ALIGNMENT_DETECTION, vsn(2, 2, 51), NULL, 0, NULL,
"Detect PV data alignment based on sysfs device information.\n"
"Align the start of a PV data area with sysfs io properties.\n"
"The start of a PV data area will be a multiple of minimum_io_size or\n"
"optimal_io_size exposed in sysfs. minimum_io_size is the smallest\n"
"request the device can perform without incurring a read-modify-write\n"
@@ -369,25 +421,27 @@ cfg(devices_data_alignment_detection_CFG, "data_alignment_detection", devices_CF
"preferred unit of receiving I/O, e.g. MD stripe width.\n"
"minimum_io_size is used if optimal_io_size is undefined (0).\n"
"If md_chunk_alignment is enabled, that detects the optimal_io_size.\n"
"This setting takes precedence over md_chunk_alignment.\n")
"default_data_alignment and md_chunk_alignment will be overriden\n"
"if they are not aligned with the value detected for this setting.\n"
"This setting is overriden by data_alignment and the --dataalignment\n"
"option.\n")
cfg(devices_data_alignment_CFG, "data_alignment", devices_CFG_SECTION, 0, CFG_TYPE_INT, 0, vsn(2, 2, 45), NULL, 0, NULL,
"Alignment of the start of a PV data area in KiB.\n"
"If a PV is placed directly on an md device and md_chunk_alignment or\n"
"data_alignment_detection are enabled, then this setting is ignored.\n"
"Otherwise, md_chunk_alignment and data_alignment_detection are\n"
"disabled if this is set. Set to 0 to use the default alignment or the\n"
"page size, if larger.\n")
"Align the start of a PV data area with this number of KiB.\n"
"When non-zero, this setting overrides default_data_alignment.\n"
"Set to 0 to disable, in which case default_data_alignment\n"
"is used to align the first PE in units of MiB.\n"
"This setting is overriden by the --dataalignment option.\n")
cfg(devices_data_alignment_offset_detection_CFG, "data_alignment_offset_detection", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_DATA_ALIGNMENT_OFFSET_DETECTION, vsn(2, 2, 50), NULL, 0, NULL,
"Detect PV data alignment offset based on sysfs device information.\n"
"The start of a PV aligned data area will be shifted by the\n"
"Shift the start of an aligned PV data area based on sysfs information.\n"
"After a PV data area is aligned, it will be shifted by the\n"
"alignment_offset exposed in sysfs. This offset is often 0, but may\n"
"be non-zero. Certain 4KiB sector drives that compensate for windows\n"
"partitioning will have an alignment_offset of 3584 bytes (sector 7\n"
"is the lowest aligned logical block, the 4KiB sectors start at\n"
"LBA -1, and consequently sector 63 is aligned on a 4KiB boundary).\n"
"pvcreate --dataalignmentoffset will skip this detection.\n")
"This setting is overriden by the --dataalignmentoffset option.\n")
cfg(devices_ignore_suspended_devices_CFG, "ignore_suspended_devices", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_IGNORE_SUSPENDED_DEVICES, vsn(1, 2, 19), NULL, 0, NULL,
"Ignore DM devices that have I/O suspended while scanning devices.\n"
@@ -412,7 +466,7 @@ cfg(devices_ignore_lvm_mirrors_CFG, "ignore_lvm_mirrors", devices_CFG_SECTION, 0
"apply to LVM RAID types like 'raid1' which handle failures in a\n"
"different way, making them a better choice for VG stacking.\n")
cfg(devices_disable_after_error_count_CFG, "disable_after_error_count", devices_CFG_SECTION, 0, CFG_TYPE_INT, 0, vsn(2, 2, 75), NULL, vsn(3, 0, 0), NULL,
cfg(devices_disable_after_error_count_CFG, "disable_after_error_count", devices_CFG_SECTION, 0, CFG_TYPE_INT, 0, vsn(2, 2, 75), NULL, vsn(2, 3, 0), NULL,
"This setting is no longer used.\n")
cfg(devices_require_restorefile_with_uuid_CFG, "require_restorefile_with_uuid", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_REQUIRE_RESTOREFILE_WITH_UUID, vsn(2, 2, 73), NULL, 0, NULL,
@@ -618,10 +672,17 @@ cfg(allocation_vdo_use_compression_CFG, "vdo_use_compression", allocation_CFG_SE
cfg(allocation_vdo_use_deduplication_CFG, "vdo_use_deduplication", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_VDO_USE_DEDUPLICATION, VDO_1ST_VSN, NULL, 0, NULL,
"Enables or disables deduplication when creating a VDO volume.\n"
"Deduplication may be disabled in instances where data is not expected\n"
"to have good deduplication rates but compression is still desired.")
"to have good deduplication rates but compression is still desired.\n")
cfg(allocation_vdo_emulate_512_sectors_CFG, "vdo_emulate_512_sectors", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_VDO_EMULATE_512_SECTORS, VDO_1ST_VSN, NULL, 0, NULL,
"Specifies that the VDO volume is to emulate a 512 byte block device.\n")
cfg(allocation_vdo_use_metadata_hints_CFG, "vdo_use_metadata_hints", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_VDO_USE_METADATA_HINTS, VDO_1ST_VSN, NULL, 0, NULL,
"Enables or disables whether VDO volume should tag its latency-critical\n"
"writes with the REQ_SYNC flag. Some device mapper targets such as dm-raid5\n"
"process writes with this flag at a higher priority.\n"
"Default is enabled.\n")
cfg(allocation_vdo_minimum_io_size_CFG, "vdo_minimum_io_size", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_VDO_MINIMUM_IO_SIZE, VDO_1ST_VSN, NULL, 0, NULL,
"The minimum IO size for VDO volume to accept, in bytes.\n"
"Valid values are 512 or 4096. The recommended and default value is 4096.\n")
cfg(allocation_vdo_block_map_cache_size_mb_CFG, "vdo_block_map_cache_size_mb", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_VDO_BLOCK_MAP_CACHE_SIZE_MB, VDO_1ST_VSN, NULL, 0, NULL,
"Specifies the amount of memory in MiB allocated for caching block map\n"
@@ -629,34 +690,25 @@ cfg(allocation_vdo_block_map_cache_size_mb_CFG, "vdo_block_map_cache_size_mb", a
"at least 128MiB and less than 16TiB. The cache must be at least 16MiB\n"
"per logical thread. Note that there is a memory overhead of 15%.\n")
cfg(allocation_vdo_block_map_period_CFG, "vdo_block_map_period", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_VDO_BLOCK_MAP_PERIOD, VDO_1ST_VSN, NULL, 0, NULL,
"Tunes the quantity of block map updates that can accumulate\n"
"before cache pages are flushed to disk. The value must be\n"
"at least 1 and less then 16380.\n"
"A lower value means shorter recovery time but lower performance.\n")
// vdo format --blockMapPeriod
cfg(allocation_vdo_block_map_era_length_CFG, "vdo_block_map_period", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_VDO_BLOCK_MAP_ERA_LENGTH, VDO_1ST_VSN, NULL, 0, NULL,
"The speed with which the block map cache writes out modified block map pages.\n"
"A smaller era length is likely to reduce the amount time spent rebuilding,\n"
"at the cost of increased block map writes during normal operation.\n"
"The maximum and recommended value is 16380; the minimum value is 1.\n")
cfg(allocation_vdo_check_point_frequency_CFG, "vdo_check_point_frequency", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_VDO_CHECK_POINT_FREQUENCY, VDO_1ST_VSN, NULL, 0, NULL,
"The default check point frequency for VDO volume.\n")
// vdo format
cfg(allocation_vdo_use_sparse_index_CFG, "vdo_use_sparse_index", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_VDO_USE_SPARSE_INDEX, VDO_1ST_VSN, NULL, 0, NULL,
"Enables sparse indexing for VDO volume.\n")
// vdo format
cfg(allocation_vdo_index_memory_size_mb_CFG, "vdo_index_memory_size_mb", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_VDO_INDEX_MEMORY_SIZE_MB, VDO_1ST_VSN, NULL, 0, NULL,
"Specifies the amount of index memory in MiB for VDO volume.\n"
"The value must be at least 256MiB and at most 1TiB.\n")
cfg(allocation_vdo_use_read_cache_CFG, "vdo_use_read_cache", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_VDO_USE_READ_CACHE, VDO_1ST_VSN, NULL, 0, NULL,
"Enables or disables the read cache within the VDO volume.\n"
"The cache should be enabled if write workloads are expected\n"
"to have high levels of deduplication, or for read intensive\n"
"workloads of highly compressible data.\n")
cfg(allocation_vdo_read_cache_size_mb_CFG, "vdo_read_cache_size_mb", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_VDO_READ_CACHE_SIZE_MB, VDO_1ST_VSN, NULL, 0, NULL,
"Specifies the extra VDO volume read cache size in MiB.\n"
"This space is in addition to a system-defined minimum.\n"
"The value must be less then 16TiB and 1.12 MiB of memory\n"
"will be used per MiB of read cache specified, per bio thread.\n")
cfg(allocation_vdo_slab_size_mb_CFG, "vdo_slab_size_mb", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_VDO_SLAB_SIZE_MB, VDO_1ST_VSN, NULL, 0, NULL,
"Specifies the size in MiB of the increment by which a VDO is grown.\n"
"Using a smaller size constrains the total maximum physical size\n"
@@ -687,7 +739,7 @@ cfg(allocation_vdo_hash_zone_threads_CFG, "vdo_hash_zone_threads", allocation_CF
"processing based on the hash value computed from the block data.\n"
"The value must be at in range [0..100].\n"
"vdo_hash_zone_threads, vdo_logical_threads and vdo_physical_threads must be\n"
"either all zero or all non-zero.")
"either all zero or all non-zero.\n")
cfg(allocation_vdo_logical_threads_CFG, "vdo_logical_threads", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_VDO_LOGICAL_THREADS, VDO_1ST_VSN, NULL, 0, NULL,
"Specifies the number of threads across which to subdivide parts of the VDO\n"
@@ -715,6 +767,16 @@ cfg(allocation_vdo_write_policy_CFG, "vdo_write_policy", allocation_CFG_SECTION,
"async - Writes are acknowledged after data has been cached for writing to stable storage.\n"
" Data which has not been flushed is not guaranteed to persist in this mode.\n")
cfg(allocation_vdo_max_discard_CFG, "vdo_max_discard", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_VDO_MAX_DISCARD, VDO_1ST_VSN, NULL, 0, NULL,
"Specified te maximum size of discard bio accepted, in 4096 byte blocks.\n"
"I/O requests to a VDO volume are normally split into 4096-byte blocks,\n"
"and processed up to 2048 at a time. However, discard requests to a VDO volume\n"
"can be automatically split to a larger size, up to <max discard> 4096-byte blocks\n"
"in a single bio, and are limited to 1500 at a time.\n"
"Increasing this value may provide better overall performance, at the cost of\n"
"increased latency for the individual discard requests.\n"
"The default and minimum is 1. The maximum is UINT_MAX / 4096.\n")
cfg(log_report_command_log_CFG, "report_command_log", log_CFG_SECTION, CFG_PROFILABLE | CFG_DEFAULT_COMMENTED | CFG_DISALLOW_INTERACTIVE, CFG_TYPE_BOOL, DEFAULT_COMMAND_LOG_REPORT, vsn(2, 2, 158), NULL, 0, NULL,
"Enable or disable LVM log reporting.\n"
"If enabled, LVM will collect a log of operations, messages,\n"
@@ -783,7 +845,7 @@ cfg(log_level_CFG, "level", log_CFG_SECTION, 0, CFG_TYPE_INT, DEFAULT_LOGLEVEL,
"There are 6 syslog-like log levels currently in use: 2 to 7 inclusive.\n"
"7 is the most verbose (LOG_DEBUG).\n")
cfg(log_indent_CFG, "indent", log_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_INDENT, vsn(1, 0, 0), NULL, 0, NULL,
cfg(log_indent_CFG, "indent", log_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_INDENT, vsn(1, 0, 0), NULL, 0, NULL,
"Indent messages according to their severity.\n")
cfg(log_command_names_CFG, "command_names", log_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_CMD_NAME, vsn(1, 0, 0), NULL, 0, NULL,
@@ -809,6 +871,14 @@ cfg_array(log_debug_classes_CFG, "debug_classes", log_CFG_SECTION, CFG_ALLOW_EMP
"available: memory, devices, io, activation, allocation,\n"
"metadata, cache, locking, lvmpolld. Use \"all\" to see everything.\n")
cfg_array(log_debug_file_fields_CFG, "debug_file_fields", log_CFG_SECTION, CFG_DEFAULT_COMMENTED | CFG_ADVANCED, CFG_TYPE_STRING, "#Stime#Scommand#Sfileline#Smessage", vsn(2, 3, 2), NULL, 0, NULL,
"The fields included in debug output written to log file.\n"
"Use \"all\" to include everything (the default).\n")
cfg_array(log_debug_output_fields_CFG, "debug_output_fields", log_CFG_SECTION, CFG_DEFAULT_COMMENTED | CFG_ADVANCED, CFG_TYPE_STRING, "#Stime#Scommand#Sfileline#Smessage", vsn(2, 3, 2), NULL, 0, NULL,
"The fields included in debug output written to stderr.\n"
"Use \"all\" to include everything (the default).\n")
cfg(backup_backup_CFG, "backup", backup_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_BACKUP_ENABLED, vsn(1, 0, 0), NULL, 0, NULL,
"Maintain a backup of the current metadata configuration.\n"
"Think very hard before turning this off!\n")
@@ -864,13 +934,13 @@ 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, 0, vsn(1, 0, 18), NULL, vsn(3, 0, 0), NULL,
cfg(global_fallback_to_lvm1_CFG, "fallback_to_lvm1", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, 0, vsn(1, 0, 18), NULL, vsn(2, 3, 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, vsn(3, 0, 0), NULL,
cfg(global_format_CFG, "format", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_FORMAT, vsn(1, 0, 0), NULL, vsn(2, 3, 0), NULL,
"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, vsn(3, 0, 0), NULL,
cfg_array(global_format_libraries_CFG, "format_libraries", global_CFG_SECTION, CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(1, 0, 0), NULL, vsn(2, 3, 0), NULL,
"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)
@@ -881,16 +951,16 @@ cfg(global_proc_CFG, "proc", global_CFG_SECTION, CFG_ADVANCED, CFG_TYPE_STRING,
cfg(global_etc_CFG, "etc", global_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_ETC_DIR, vsn(2, 2, 117), "@CONFDIR@", 0, NULL,
"Location of /etc system configuration directory.\n")
cfg(global_locking_type_CFG, "locking_type", global_CFG_SECTION, 0, CFG_TYPE_INT, 1, vsn(1, 0, 0), NULL, vsn(3, 0, 0), NULL,
cfg(global_locking_type_CFG, "locking_type", global_CFG_SECTION, 0, CFG_TYPE_INT, 1, vsn(1, 0, 0), NULL, vsn(2, 3, 0), NULL,
"This setting is no longer used.")
cfg(global_wait_for_locks_CFG, "wait_for_locks", global_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_WAIT_FOR_LOCKS, vsn(2, 2, 50), NULL, 0, NULL,
"When disabled, fail if a lock request would block.\n")
cfg(global_fallback_to_clustered_locking_CFG, "fallback_to_clustered_locking", global_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_FALLBACK_TO_CLUSTERED_LOCKING, vsn(2, 2, 42), NULL, vsn(3, 0, 0), NULL,
cfg(global_fallback_to_clustered_locking_CFG, "fallback_to_clustered_locking", global_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_FALLBACK_TO_CLUSTERED_LOCKING, vsn(2, 2, 42), NULL, vsn(2, 3, 0), NULL,
"This setting is no longer used.\n")
cfg(global_fallback_to_local_locking_CFG, "fallback_to_local_locking", global_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_FALLBACK_TO_LOCAL_LOCKING, vsn(2, 2, 42), NULL, vsn(3, 0, 0), NULL,
cfg(global_fallback_to_local_locking_CFG, "fallback_to_local_locking", global_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_FALLBACK_TO_LOCAL_LOCKING, vsn(2, 2, 42), NULL, vsn(2, 3, 0), NULL,
"This setting is no longer used.\n")
cfg(global_locking_dir_CFG, "locking_dir", global_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_LOCK_DIR, vsn(1, 0, 0), "@DEFAULT_LOCK_DIR@", 0, NULL,
@@ -910,7 +980,7 @@ cfg(global_prioritise_write_locks_CFG, "prioritise_write_locks", global_CFG_SECT
cfg(global_library_dir_CFG, "library_dir", global_CFG_SECTION, CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(1, 0, 0), NULL, 0, NULL,
"Search this directory first for shared libraries.\n")
cfg(global_locking_library_CFG, "locking_library", global_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_LOCKING_LIB, vsn(1, 0, 0), NULL, vsn(3, 0, 0), NULL,
cfg(global_locking_library_CFG, "locking_library", global_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_LOCKING_LIB, vsn(1, 0, 0), NULL, vsn(2, 3, 0), NULL,
"This setting is no longer used.\n")
cfg(global_abort_on_internal_errors_CFG, "abort_on_internal_errors", global_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_ABORT_ON_INTERNAL_ERRORS, vsn(2, 2, 57), NULL, 0, NULL,
@@ -953,6 +1023,16 @@ cfg(global_mirror_segtype_default_CFG, "mirror_segtype_default", global_CFG_SECT
" fashion in a cluster.\n"
"#\n")
cfg(global_support_mirrored_mirror_log_CFG, "support_mirrored_mirror_log", global_CFG_SECTION, 0, CFG_TYPE_BOOL, 0, vsn(2, 3, 2), NULL, 0, NULL,
"Enable mirrored 'mirror' log type for testing.\n"
"#\n"
"This type is deprecated to create or convert to but can\n"
"be enabled to test that activation of existing mirrored\n"
"logs and conversion to disk/core works.\n"
"#\n"
"Not supported for regular operation!\n"
"\n")
cfg(global_raid10_segtype_default_CFG, "raid10_segtype_default", global_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_RAID10_SEGTYPE, vsn(2, 2, 99), "@DEFAULT_RAID10_SEGTYPE@", 0, NULL,
"The segment type used by the -i -m combination.\n"
"The --type raid10|mirror option overrides this setting.\n"
@@ -997,12 +1077,24 @@ cfg(global_lvdisplay_shows_full_device_path_CFG, "lvdisplay_shows_full_device_pa
"Previously this was always shown as /dev/vgname/lvname even when that\n"
"was never a valid path in the /dev filesystem.\n")
cfg(global_use_lvmetad_CFG, "use_lvmetad", global_CFG_SECTION, 0, CFG_TYPE_BOOL, 0, vsn(2, 2, 93), 0, vsn(3, 0, 0), NULL,
cfg(global_event_activation_CFG, "event_activation", global_CFG_SECTION, 0, CFG_TYPE_BOOL, 1, vsn(2, 3, 1), 0, 0, NULL,
"Activate LVs based on system-generated device events.\n"
"When a device appears on the system, a system-generated event runs\n"
"the pvscan command to activate LVs if the new PV completes the VG.\n"
"Use auto_activation_volume_list to select which LVs should be\n"
"activated from these events (the default is all.)\n"
"When event_activation is disabled, the system will generally run\n"
"a direct activation command to activate LVs in complete VGs.\n")
cfg(global_use_lvmetad_CFG, "use_lvmetad", global_CFG_SECTION, 0, CFG_TYPE_BOOL, 0, vsn(2, 2, 93), 0, vsn(2, 3, 0), NULL,
"This setting is no longer used.\n")
cfg(global_lvmetad_update_wait_time_CFG, "lvmetad_update_wait_time", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, 0, vsn(2, 2, 151), NULL, vsn(3, 0, 0), NULL,
cfg(global_lvmetad_update_wait_time_CFG, "lvmetad_update_wait_time", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, 0, vsn(2, 2, 151), NULL, vsn(2, 3, 0), NULL,
"This setting is no longer used.\n")
cfg(global_use_aio_CFG, "use_aio", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_USE_AIO, vsn(2, 2, 183), NULL, 0, NULL,
"Use async I/O when reading and writing devices.\n")
cfg(global_use_lvmlockd_CFG, "use_lvmlockd", global_CFG_SECTION, 0, CFG_TYPE_BOOL, 0, vsn(2, 2, 124), NULL, 0, NULL,
"Use lvmlockd for locking among hosts using LVM on shared storage.\n"
"Applicable only if LVM is compiled with lockd support in which\n"
@@ -1165,6 +1257,14 @@ cfg(global_notify_dbus_CFG, "notify_dbus", global_CFG_SECTION, 0, CFG_TYPE_BOOL,
"When enabled, an LVM command that changes PVs, changes VG metadata,\n"
"or changes the activation state of an LV will send a notification.\n")
cfg(global_io_memory_size_CFG, "io_memory_size", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_IO_MEMORY_SIZE_KB, vsn(2, 3, 2), NULL, 0, NULL,
"The amount of memory in KiB that LVM allocates to perform disk io.\n"
"LVM performance may benefit from more io memory when there are many\n"
"disks or VG metadata is large. Increasing this size may be necessary\n"
"when a single copy of VG metadata is larger than the current setting.\n"
"This value should usually not be decreased from the default; setting\n"
"it too low can result in lvm failing to read VGs.\n")
cfg(activation_udev_sync_CFG, "udev_sync", activation_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_UDEV_SYNC, vsn(2, 2, 51), NULL, 0, NULL,
"Use udev notifications to synchronize udev and LVM.\n"
"The --nodevsync option overrides this setting.\n"
@@ -1594,12 +1694,19 @@ cfg(metadata_vgmetadatacopies_CFG, "vgmetadatacopies", metadata_CFG_SECTION, CFG
"and allows you to control which metadata areas are used at the\n"
"individual PV level using pvchange --metadataignore y|n.\n")
cfg(metadata_pvmetadatasize_CFG, "pvmetadatasize", metadata_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_PVMETADATASIZE, vsn(1, 0, 0), NULL, 0, NULL,
"Approximate number of sectors to use for each metadata copy.\n"
"VGs with large numbers of PVs or LVs, or VGs containing complex LV\n"
"structures, may need additional space for VG metadata. The metadata\n"
"areas are treated as circular buffers, so unused space becomes filled\n"
"with an archive of the most recent previous versions of the metadata.\n")
cfg_runtime(metadata_pvmetadatasize_CFG, "pvmetadatasize", metadata_CFG_SECTION, CFG_DEFAULT_COMMENTED | CFG_DEFAULT_UNDEFINED, CFG_TYPE_INT, vsn(1, 0, 0), 0, NULL,
"The default size of the metadata area in units of 512 byte sectors.\n"
"The metadata area begins at an offset of the page size from the start\n"
"of the device. The first PE is by default at 1 MiB from the start of\n"
"the device. The space between these is the default metadata area size.\n"
"The actual size of the metadata area may be larger than what is set\n"
"here due to default_data_alignment making the first PE a MiB multiple.\n"
"The metadata area begins with a 512 byte header and is followed by a\n"
"circular buffer used for VG metadata text. The maximum size of the VG\n"
"metadata is about half the size of the metadata buffer. VGs with large\n"
"numbers of PVs or LVs, or VGs containing complex LV structures, may need\n"
"additional space for VG metadata. The --metadatasize option overrides\n"
"this setting.\n")
cfg(metadata_pvmetadataignore_CFG, "pvmetadataignore", metadata_CFG_SECTION, CFG_ADVANCED | CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_PVMETADATAIGNORE, vsn(2, 2, 69), NULL, 0, NULL,
"Ignore metadata areas on a new PV.\n"
@@ -1609,14 +1716,14 @@ cfg(metadata_pvmetadataignore_CFG, "pvmetadataignore", metadata_CFG_SECTION, CFG
cfg(metadata_stripesize_CFG, "stripesize", metadata_CFG_SECTION, CFG_ADVANCED | CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_STRIPESIZE, vsn(1, 0, 0), NULL, 0, NULL, NULL)
cfg_array(metadata_dirs_CFG, "dirs", metadata_CFG_SECTION, CFG_ADVANCED | CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(1, 0, 0), NULL, vsn(3, 0, 0), NULL,
cfg_array(metadata_dirs_CFG, "dirs", metadata_CFG_SECTION, CFG_ADVANCED | CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(1, 0, 0), NULL, vsn(2, 3, 0), NULL,
"This setting is no longer used.\n")
cfg_section(metadata_disk_areas_CFG_SUBSECTION, "disk_areas", metadata_CFG_SECTION, CFG_UNSUPPORTED | CFG_DEFAULT_COMMENTED, vsn(1, 0, 0), vsn(3, 0, 0), NULL, NULL)
cfg_section(disk_area_CFG_SUBSECTION, "disk_area", metadata_disk_areas_CFG_SUBSECTION, CFG_NAME_VARIABLE | CFG_UNSUPPORTED | CFG_DEFAULT_COMMENTED, vsn(1, 0, 0), vsn(3, 0, 0), NULL, NULL)
cfg(disk_area_start_sector_CFG, "start_sector", disk_area_CFG_SUBSECTION, CFG_UNSUPPORTED | CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, 0, vsn(1, 0, 0), NULL, vsn(3, 0, 0), NULL, NULL)
cfg(disk_area_size_CFG, "size", disk_area_CFG_SUBSECTION, CFG_UNSUPPORTED | CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, 0, vsn(1, 0, 0), NULL, vsn(3, 0, 0), NULL, NULL)
cfg(disk_area_id_CFG, "id", disk_area_CFG_SUBSECTION, CFG_UNSUPPORTED | CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(1, 0, 0), NULL, vsn(3, 0, 0), NULL, NULL)
cfg_section(metadata_disk_areas_CFG_SUBSECTION, "disk_areas", metadata_CFG_SECTION, CFG_UNSUPPORTED | CFG_DEFAULT_COMMENTED, vsn(1, 0, 0), vsn(2, 3, 0), NULL, NULL)
cfg_section(disk_area_CFG_SUBSECTION, "disk_area", metadata_disk_areas_CFG_SUBSECTION, CFG_NAME_VARIABLE | CFG_UNSUPPORTED | CFG_DEFAULT_COMMENTED, vsn(1, 0, 0), vsn(2, 3, 0), NULL, NULL)
cfg(disk_area_start_sector_CFG, "start_sector", disk_area_CFG_SUBSECTION, CFG_UNSUPPORTED | CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, 0, vsn(1, 0, 0), NULL, vsn(2, 3, 0), NULL, NULL)
cfg(disk_area_size_CFG, "size", disk_area_CFG_SUBSECTION, CFG_UNSUPPORTED | CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, 0, vsn(1, 0, 0), NULL, vsn(2, 3, 0), NULL, NULL)
cfg(disk_area_id_CFG, "id", disk_area_CFG_SUBSECTION, CFG_UNSUPPORTED | CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(1, 0, 0), NULL, vsn(2, 3, 0), NULL, NULL)
cfg(report_output_format_CFG, "output_format", report_CFG_SECTION, CFG_PROFILABLE | CFG_DEFAULT_COMMENTED | CFG_DISALLOW_INTERACTIVE, CFG_TYPE_STRING, DEFAULT_REP_OUTPUT_FORMAT, vsn(2, 2, 158), NULL, 0, NULL,
"Format of LVM command's report output.\n"

View File

@@ -18,8 +18,18 @@
#include "device_mapper/vdo/vdo_limits.h"
#define DEFAULT_PE_ALIGN 2048
#define DEFAULT_PE_ALIGN_OLD 128
/*
* By default the first PE is placed at 1 MiB.
*
* If default_data_alignment is 2, then the first PE
* is placed at 2 * 1 MiB.
*
* If default_data_alignment is 3, then the first PE
* is placed at 3 * 1 MiB.
*/
#define FIRST_PE_AT_ONE_MB_IN_SECTORS 2048 /* 1 MiB in 512 byte sectors */
#define FIRST_PE_AT_ONE_MB_IN_MB 1
#define DEFAULT_ARCHIVE_ENABLED 1
#define DEFAULT_BACKUP_ENABLED 1
@@ -60,6 +70,7 @@
#define DEFAULT_METADATA_READ_ONLY 0
#define DEFAULT_LVDISPLAY_SHOWS_FULL_DEVICE_PATH 0
#define DEFAULT_UNKNOWN_DEVICE_NAME "[unknown]"
#define DEFAULT_USE_AIO 1
#define DEFAULT_SANLOCK_LV_EXTEND_MB 256
@@ -113,6 +124,8 @@
#define DEFAULT_THIN_POOL_CHUNK_SIZE_POLICY "generic"
#define DEFAULT_THIN_POOL_CHUNK_SIZE 64 /* KB */
#define DEFAULT_THIN_POOL_CHUNK_SIZE_PERFORMANCE 512 /* KB */
/* Chunk size big enough it no longer needs jump by power-of-2 */
#define DEFAULT_THIN_POOL_CHUNK_SIZE_ALIGNED 1024 /* KB */
#define DEFAULT_THIN_POOL_DISCARDS "passdown"
#define DEFAULT_THIN_POOL_ZERO 1
#define DEFAULT_POOL_METADATA_SPARE 1 /* thin + cache */
@@ -142,14 +155,13 @@
/* VDO defaults */
#define DEFAULT_VDO_USE_COMPRESSION (true)
#define DEFAULT_VDO_USE_DEDUPLICATION (true)
#define DEFAULT_VDO_EMULATE_512_SECTORS (false)
#define DEFAULT_VDO_USE_METADATA_HINTS (true)
#define DEFAULT_VDO_MINIMUM_IO_SIZE (4096)
#define DEFAULT_VDO_BLOCK_MAP_CACHE_SIZE_MB (DM_VDO_BLOCK_MAP_CACHE_SIZE_MINIMUM_MB)
#define DEFAULT_VDO_BLOCK_MAP_PERIOD (DM_VDO_BLOCK_MAP_PERIOD_MAXIMUM)
#define DEFAULT_VDO_BLOCK_MAP_ERA_LENGTH (DM_VDO_BLOCK_MAP_ERA_LENGTH_MAXIMUM)
#define DEFAULT_VDO_USE_SPARSE_INDEX (false)
#define DEFAULT_VDO_CHECK_POINT_FREQUENCY (0)
#define DEFAULT_VDO_INDEX_MEMORY_SIZE_MB (DM_VDO_INDEX_MEMORY_SIZE_MINIMUM_MB)
#define DEFAULT_VDO_USE_READ_CACHE (false)
#define DEFAULT_VDO_READ_CACHE_SIZE_MB (0)
#define DEFAULT_VDO_SLAB_SIZE_MB (2 * 1024) // 2GiB ... 19 slabbits
#define DEFAULT_VDO_ACK_THREADS (1)
#define DEFAULT_VDO_BIO_THREADS (1)
@@ -159,6 +171,7 @@
#define DEFAULT_VDO_LOGICAL_THREADS (1)
#define DEFAULT_VDO_PHYSICAL_THREADS (1)
#define DEFAULT_VDO_WRITE_POLICY "auto"
#define DEFAULT_VDO_MAX_DISCARD (DM_VDO_MAX_DISCARD_MINIMUM)
#define DEFAULT_VDO_FORMAT_OPTIONS_CONFIG "#S" ""
/*
@@ -179,7 +192,6 @@
#define DEFAULT_RECORD_LVS_HISTORY 0
#define DEFAULT_LVS_HISTORY_RETENTION_TIME 0
#define DEFAULT_PVMETADATAIGNORE 0
#define DEFAULT_PVMETADATASIZE 255
#define DEFAULT_PVMETADATACOPIES 1
#define DEFAULT_VGMETADATACOPIES 0
#define DEFAULT_LABELSECTOR UINT64_C(1)
@@ -211,7 +223,7 @@
#define DEFAULT_VERBOSE 0
#define DEFAULT_SILENT 0
#define DEFAULT_LOGLEVEL 0
#define DEFAULT_INDENT 1
#define DEFAULT_INDENT 0
#define DEFAULT_ABORT_ON_INTERNAL_ERRORS 0
#define DEFAULT_UNITS "r"
#define DEFAULT_SUFFIX 1
@@ -300,6 +312,12 @@
#define DEFAULT_VDO_POOL_AUTOEXTEND_THRESHOLD 100
#define DEFAULT_VDO_POOL_AUTOEXTEND_PERCENT 20
#define DEFAULT_SCAN_LVS 1
#define DEFAULT_SCAN_LVS 0
#define DEFAULT_HINTS "all"
#define DEFAULT_IO_MEMORY_SIZE_KB 8192
#define DEFAULT_MD_COMPONENT_CHECKS "auto"
#endif /* _LVM_DEFAULTS_H */

View File

@@ -12,8 +12,6 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#define _GNU_SOURCE
#include "lib/device/bcache.h"
#include "base/data-struct/radix-tree.h"
@@ -329,7 +327,7 @@ struct io_engine *create_async_io_engine(void)
e->aio_context = 0;
r = io_setup(MAX_IO, &e->aio_context);
if (r < 0) {
log_warn("io_setup failed");
log_debug("io_setup failed %d", r);
free(e);
return NULL;
}
@@ -372,8 +370,11 @@ static void _sync_destroy(struct io_engine *ioe)
static bool _sync_issue(struct io_engine *ioe, enum dir d, int fd,
sector_t sb, sector_t se, void *data, void *context)
{
int r;
uint64_t len = (se - sb) * 512, where;
int rv;
off_t off;
uint64_t where;
uint64_t pos = 0;
uint64_t len = (se - sb) * 512;
struct sync_engine *e = _to_sync(ioe);
struct sync_io *io = malloc(sizeof(*io));
if (!io) {
@@ -382,35 +383,99 @@ static bool _sync_issue(struct io_engine *ioe, enum dir d, int fd,
}
where = sb * 512;
r = lseek(fd, where, SEEK_SET);
if (r < 0) {
log_warn("unable to seek to position %llu", (unsigned long long) where);
off = lseek(fd, where, SEEK_SET);
if (off == (off_t) -1) {
log_warn("Device seek error %d for offset %llu", errno, (unsigned long long)where);
free(io);
return false;
return false;
}
if (off != (off_t) where) {
log_warn("Device seek failed for offset %llu", (unsigned long long)where);
free(io);
return false;
}
while (len) {
do {
if (d == DIR_READ)
r = read(fd, data, len);
else
r = write(fd, data, len);
/*
* If bcache block goes past where lvm wants to write, then clamp it.
*/
if ((d == DIR_WRITE) && _last_byte_offset && (fd == _last_byte_fd)) {
uint64_t offset = where;
uint64_t nbytes = len;
sector_t limit_nbytes = 0;
sector_t extra_nbytes = 0;
} while ((r < 0) && ((r == EINTR) || (r == EAGAIN)));
if (r < 0) {
log_warn("io failed %d", r);
if (offset > _last_byte_offset) {
log_error("Limit write at %llu len %llu beyond last byte %llu",
(unsigned long long)offset,
(unsigned long long)nbytes,
(unsigned long long)_last_byte_offset);
free(io);
return false;
}
return false;
}
len -= r;
if (offset + nbytes > _last_byte_offset) {
limit_nbytes = _last_byte_offset - offset;
if (limit_nbytes % _last_byte_sector_size)
extra_nbytes = _last_byte_sector_size - (limit_nbytes % _last_byte_sector_size);
if (extra_nbytes) {
log_debug("Limit write at %llu len %llu to len %llu rounded to %llu",
(unsigned long long)offset,
(unsigned long long)nbytes,
(unsigned long long)limit_nbytes,
(unsigned long long)(limit_nbytes + extra_nbytes));
nbytes = limit_nbytes + extra_nbytes;
} else {
log_debug("Limit write at %llu len %llu to len %llu",
(unsigned long long)offset,
(unsigned long long)nbytes,
(unsigned long long)limit_nbytes);
nbytes = limit_nbytes;
}
}
where = offset;
len = nbytes;
}
if (len) {
log_warn("short io %u bytes remaining", (unsigned) len);
free(io);
while (pos < len) {
if (d == DIR_READ)
rv = read(fd, (char *)data + pos, len - pos);
else
rv = write(fd, (char *)data + pos, len - pos);
if (rv == -1 && errno == EINTR)
continue;
if (rv == -1 && errno == EAGAIN)
continue;
if (!rv)
break;
if (rv < 0) {
if (d == DIR_READ)
log_debug("Device read error %d offset %llu len %llu", errno,
(unsigned long long)(where + pos),
(unsigned long long)(len - pos));
else
log_debug("Device write error %d offset %llu len %llu", errno,
(unsigned long long)(where + pos),
(unsigned long long)(len - pos));
free(io);
return false;
}
pos += rv;
}
if (pos < len) {
if (d == DIR_READ)
log_warn("Device read short %u bytes remaining", (unsigned)(len - pos));
else
log_warn("Device write short %u bytes remaining", (unsigned)(len - pos));
/*
free(io);
return false;
*/
}
@@ -1004,7 +1069,8 @@ void bcache_destroy(struct bcache *cache)
if (cache->nr_locked)
log_warn("some blocks are still locked");
bcache_flush(cache);
if (!bcache_flush(cache))
stack;
_wait_all(cache);
_exit_free_list(cache);
radix_tree_destroy(cache->rtree);

View File

@@ -15,7 +15,6 @@
#ifndef BCACHE_H
#define BCACHE_H
#include "configure.h"
#include "device_mapper/all.h"
#include <linux/fs.h>

View File

@@ -479,7 +479,7 @@ static struct device *_get_device_for_sysfs_dev_name_using_devno(const char *dev
return NULL;
}
devno = MKDEV((dev_t)major, (dev_t)minor);
devno = MKDEV(major, minor);
if (!(dev = (struct device *) btree_lookup(_cache.devices, (uint32_t) devno))) {
/*
* If we get here, it means the device is referenced in sysfs, but it's not yet in /dev.
@@ -666,10 +666,9 @@ struct dm_list *dev_cache_get_dev_list_for_lvid(const char *lvid)
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)))
if (dm_hash_lookup(_cache.names, path))
dm_hash_remove(_cache.names, path);
dm_list_iterate_items(strl, &dev->aliases) {
@@ -948,7 +947,7 @@ static int _dev_cache_iterate_sysfs_for_index(const char *path)
continue;
}
devno = MKDEV((dev_t)major, (dev_t)minor);
devno = MKDEV(major, minor);
if (!(dev = (struct device *) btree_lookup(_cache.devices, (uint32_t) devno)) &&
!(dev = (struct device *) btree_lookup(_cache.sysfs_only_devices, (uint32_t) devno))) {
if (!dm_device_get_name(major, minor, 1, devname, sizeof(devname)) ||
@@ -1474,7 +1473,7 @@ struct device *dev_cache_get(struct cmd_context *cmd, const char *name, struct d
return d;
if (f && !(d->flags & DEV_REGULAR)) {
ret = f->passes_filter(cmd, f, d);
ret = f->passes_filter(cmd, f, d, NULL);
if (ret == -EAGAIN) {
log_debug_devs("get device by name defer filter %s", dev_name(d));
@@ -1506,7 +1505,7 @@ static struct device *_dev_cache_seek_devt(dev_t dev)
* TODO This is very inefficient. We probably want a hash table indexed by
* major:minor for keys to speed up these lookups.
*/
struct device *dev_cache_get_by_devt(struct cmd_context *cmd, dev_t dev, struct dev_filter *f)
struct device *dev_cache_get_by_devt(struct cmd_context *cmd, dev_t dev, struct dev_filter *f, int *filtered)
{
char path[PATH_MAX];
const char *sysfs_dir;
@@ -1514,6 +1513,9 @@ struct device *dev_cache_get_by_devt(struct cmd_context *cmd, dev_t dev, struct
struct device *d = _dev_cache_seek_devt(dev);
int ret;
if (filtered)
*filtered = 0;
if (d && (d->flags & DEV_REGULAR))
return d;
@@ -1547,7 +1549,7 @@ struct device *dev_cache_get_by_devt(struct cmd_context *cmd, dev_t dev, struct
if (!f)
return d;
ret = f->passes_filter(cmd, f, d);
ret = f->passes_filter(cmd, f, d, NULL);
if (ret == -EAGAIN) {
log_debug_devs("get device by number defer filter %s", dev_name(d));
@@ -1558,6 +1560,8 @@ struct device *dev_cache_get_by_devt(struct cmd_context *cmd, dev_t dev, struct
if (ret)
return d;
if (filtered)
*filtered = 1;
return NULL;
}
@@ -1604,7 +1608,7 @@ struct device *dev_iter_get(struct cmd_context *cmd, struct dev_iter *iter)
f = iter->filter;
if (f && !(d->flags & DEV_REGULAR)) {
ret = f->passes_filter(cmd, f, d);
ret = f->passes_filter(cmd, f, d, NULL);
if (ret == -EAGAIN) {
log_debug_devs("get device by iter defer filter %s", dev_name(d));

View File

@@ -25,11 +25,12 @@ struct cmd_context;
* predicate for devices.
*/
struct dev_filter {
int (*passes_filter) (struct cmd_context *cmd, struct dev_filter *f, struct device *dev);
int (*passes_filter) (struct cmd_context *cmd, struct dev_filter *f, struct device *dev, const char *use_filter_name);
void (*destroy) (struct dev_filter *f);
void (*wipe) (struct dev_filter *f);
void *private;
unsigned use_count;
const char *name;
};
int dev_cache_index_devs(void);
@@ -54,8 +55,7 @@ int dev_cache_add_dir(const char *path);
struct device *dev_cache_get(struct cmd_context *cmd, const char *name, struct dev_filter *f);
const char *dev_cache_filtered_reason(const char *name);
// TODO
struct device *dev_cache_get_by_devt(struct cmd_context *cmd, dev_t device, struct dev_filter *f);
struct device *dev_cache_get_by_devt(struct cmd_context *cmd, dev_t device, struct dev_filter *f, int *filtered);
void dev_set_preferred_name(struct dm_str_list *sl, struct device *dev);

View File

@@ -53,111 +53,33 @@
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, dev_io_reason_t reason)
{
int fd = dev_fd(where->dev);
ssize_t n = 0;
size_t total = 0;
if (fd < 0) {
log_error("Attempt to read an unopened device (%s).",
dev_name(where->dev));
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.
*/
if (should_write && test_mode())
return 1;
if (where->size > SSIZE_MAX) {
log_error("Read size too large: %" PRIu64, where->size);
return 0;
}
if (lseek(fd, (off_t) where->start, SEEK_SET) == (off_t) -1) {
log_error("%s: lseek %" PRIu64 " failed: %s",
dev_name(where->dev), (uint64_t) where->start,
strerror(errno));
return 0;
}
while (total < (size_t) where->size) {
do
n = should_write ?
write(fd, buffer, (size_t) where->size - total) :
read(fd, buffer, (size_t) where->size - total);
while ((n < 0) && ((errno == EINTR) || (errno == EAGAIN)));
if (n < 0)
log_error_once("%s: %s failed after %" PRIu64 " of %" PRIu64
" at %" PRIu64 ": %s", dev_name(where->dev),
should_write ? "write" : "read",
(uint64_t) total,
(uint64_t) where->size,
(uint64_t) where->start, strerror(errno));
if (n <= 0)
break;
total += n;
buffer += n;
}
return (total == (size_t) where->size);
}
/*-----------------------------------------------------------------
* LVM2 uses O_DIRECT when performing metadata io, which requires
* block size aligned accesses. If any io is not aligned we have
* to perform the io via a bounce buffer, obviously this is quite
* inefficient.
*---------------------------------------------------------------*/
/*
* Get the physical and logical block size for a device.
*/
int dev_get_block_size(struct device *dev, unsigned int *physical_block_size, unsigned int *block_size)
{
const char *name = dev_name(dev);
int needs_open;
int fd = dev->bcache_fd;
int do_close = 0;
int r = 1;
needs_open = (!dev->open_count && (dev->phys_block_size == -1 || dev->block_size == -1));
if ((dev->phys_block_size > 0) && (dev->block_size > 0)) {
*physical_block_size = (unsigned int)dev->phys_block_size;
*block_size = (unsigned int)dev->block_size;
return 1;
}
if (needs_open && !dev_open_readonly(dev))
return_0;
if (fd <= 0) {
if (!dev->open_count) {
if (!dev_open_readonly(dev))
return_0;
do_close = 1;
}
fd = dev_fd(dev);
}
if (dev->block_size == -1) {
if (ioctl(dev_fd(dev), BLKBSZGET, &dev->block_size) < 0) {
if (ioctl(fd, BLKBSZGET, &dev->block_size) < 0) {
log_sys_error("ioctl BLKBSZGET", name);
r = 0;
goto out;
@@ -168,7 +90,7 @@ int dev_get_block_size(struct device *dev, unsigned int *physical_block_size, un
#ifdef BLKPBSZGET
/* BLKPBSZGET is available in kernel >= 2.6.32 only */
if (dev->phys_block_size == -1) {
if (ioctl(dev_fd(dev), BLKPBSZGET, &dev->phys_block_size) < 0) {
if (ioctl(fd, BLKPBSZGET, &dev->phys_block_size) < 0) {
log_sys_error("ioctl BLKPBSZGET", name);
r = 0;
goto out;
@@ -178,7 +100,7 @@ int dev_get_block_size(struct device *dev, unsigned int *physical_block_size, un
#elif defined (BLKSSZGET)
/* if we can't get physical block size, just use logical block size instead */
if (dev->phys_block_size == -1) {
if (ioctl(dev_fd(dev), BLKSSZGET, &dev->phys_block_size) < 0) {
if (ioctl(fd, BLKSSZGET, &dev->phys_block_size) < 0) {
log_sys_error("ioctl BLKSSZGET", name);
r = 0;
goto out;
@@ -196,107 +118,12 @@ int dev_get_block_size(struct device *dev, unsigned int *physical_block_size, un
*physical_block_size = (unsigned int) dev->phys_block_size;
*block_size = (unsigned int) dev->block_size;
out:
if (needs_open && !dev_close_immediate(dev))
if (do_close && !dev_close_immediate(dev))
stack;
return r;
}
/*
* Widens a region to be an aligned region.
*/
static void _widen_region(unsigned int block_size, struct device_area *region,
struct device_area *result)
{
uint64_t mask = block_size - 1, delta;
memcpy(result, region, sizeof(*result));
/* adjust the start */
delta = result->start & mask;
if (delta) {
result->start -= delta;
result->size += delta;
}
/* adjust the end */
delta = (result->start + result->size) & mask;
if (delta)
result->size += block_size - delta;
}
static int _aligned_io(struct device_area *where, char *buffer,
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;
if (!(where->dev->flags & DEV_REGULAR) &&
!dev_get_block_size(where->dev, &physical_block_size, &block_size))
return_0;
if (!block_size)
block_size = lvm_getpagesize();
mask = block_size - 1;
_widen_region(block_size, where, &widened);
/* 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 = malloc((size_t) widened.size + block_size))) {
log_error("Bounce buffer malloc failed");
return 0;
}
/*
* Realign start of bounce buffer (using the extra sector)
*/
if (((uintptr_t) bounce) & mask)
bounce = (char *) ((((uintptr_t) bounce) + mask) & ~mask);
/* 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);
}
if (should_write) {
memcpy(bounce + (where->start - widened.start), buffer,
(size_t) where->size);
/* ... then we write */
if (!(r = _io(&widened, bounce, 1, reason)))
stack;
goto out;
}
memcpy(buffer, bounce + (where->start - widened.start),
(size_t) where->size);
r = 1;
out:
free(bounce_buf);
return r;
}
static int _dev_get_size_file(struct device *dev, uint64_t *size)
{
const char *name = dev_name(dev);
@@ -570,7 +397,6 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet)
dev->flags |= DEV_O_DIRECT_TESTED;
#endif
dev->open_count++;
dev->flags &= ~DEV_ACCESSED_W;
if (need_rw)
dev->flags |= DEV_OPENED_RW;
@@ -632,16 +458,6 @@ int dev_open_readonly_quiet(struct device *dev)
return dev_open_flags(dev, O_RDONLY, 1, 1);
}
int dev_test_excl(struct device *dev)
{
int flags = 0;
flags |= O_EXCL;
flags |= O_RDWR;
return dev_open_flags(dev, flags, 1, 1);
}
static void _close(struct device *dev)
{
if (close(dev->fd))
@@ -664,11 +480,6 @@ static int _dev_close(struct device *dev, int immediate)
return 0;
}
#ifndef O_DIRECT_SUPPORT
if (dev->flags & DEV_ACCESSED_W)
dev_flush(dev);
#endif
if (dev->open_count > 0)
dev->open_count--;
@@ -691,131 +502,3 @@ int dev_close_immediate(struct device *dev)
{
return _dev_close(dev, 1);
}
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;
if (!dev->open_count)
return_0;
where.dev = dev;
where.start = offset;
where.size = len;
ret = _aligned_io(&where, buffer, 0, reason);
return ret;
}
/*
* Read from 'dev' into 'buf', possibly in 2 distinct regions, denoted
* by (offset,len) and (offset2,len2). Thus, the total size of
* 'buf' should be len+len2.
*/
int dev_read_circular(struct device *dev, uint64_t offset, size_t len,
uint64_t offset2, size_t len2, dev_io_reason_t reason, char *buf)
{
if (!dev_read(dev, offset, len, reason, buf)) {
log_error("Read from %s failed", dev_name(dev));
return 0;
}
/*
* The second region is optional, and allows for
* a circular buffer on the device.
*/
if (!len2)
return 1;
if (!dev_read(dev, offset2, len2, reason, buf + len)) {
log_error("Circular read from %s failed",
dev_name(dev));
return 0;
}
return 1;
}
/* FIXME If O_DIRECT can't extend file, dev_extend first; dev_truncate after.
* But fails if concurrent processes writing
*/
/* FIXME pre-extend the file */
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, reason, buffer);
dev->end += (uint64_t) len;
#ifndef O_DIRECT_SUPPORT
dev_flush(dev);
#endif
return r;
}
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;
if (!dev->open_count)
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, reason);
return ret;
}
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)));
if (!dev_open(dev))
return_0;
if ((offset % SECTOR_SIZE) || (len % SECTOR_SIZE))
log_debug_devs("Wiping %s at %" PRIu64 " length %" PRIsize_t,
dev_name(dev), offset, len);
else
log_debug_devs("Wiping %s at sector %" PRIu64 " length %" PRIsize_t
" sectors", dev_name(dev), offset >> SECTOR_SHIFT,
len >> SECTOR_SHIFT);
memset(buffer, value, sizeof(buffer));
while (1) {
s = len > sizeof(buffer) ? sizeof(buffer) : len;
if (!dev_write(dev, offset, s, reason, buffer))
break;
len -= s;
if (!len)
break;
offset += s;
}
dev->flags |= DEV_ACCESSED_W;
if (!dev_close(dev))
stack;
return (len == 0);
}

View File

@@ -88,8 +88,21 @@ static uint64_t _v1_sb_offset(uint64_t size, md_minor_version_t minor_version)
return sb_offset;
}
/*
* _udev_dev_is_md_component() only works if
* external_device_info_source="udev"
*
* but
*
* udev_dev_is_md_component() in dev-type.c only works if
* obtain_device_list_from_udev=1
*
* and neither of those config setting matches very well
* with what we're doing here.
*/
#ifdef UDEV_SYNC_SUPPORT
static int _udev_dev_is_md(struct device *dev)
static int _udev_dev_is_md_component(struct device *dev)
{
const char *value;
struct dev_ext *ext;
@@ -97,14 +110,17 @@ static int _udev_dev_is_md(struct device *dev)
if (!(ext = dev_ext_get(dev)))
return_0;
if (!(value = udev_device_get_property_value((struct udev_device *)ext->handle, DEV_EXT_UDEV_BLKID_TYPE)))
if (!(value = udev_device_get_property_value((struct udev_device *)ext->handle, DEV_EXT_UDEV_BLKID_TYPE))) {
dev->flags |= DEV_UDEV_INFO_MISSING;
return 0;
}
return !strcmp(value, DEV_EXT_UDEV_BLKID_TYPE_SW_RAID);
}
#else
static int _udev_dev_is_md(struct device *dev)
static int _udev_dev_is_md_component(struct device *dev)
{
dev->flags |= DEV_UDEV_INFO_MISSING;
return 0;
}
#endif
@@ -112,7 +128,7 @@ 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, int full)
static int _native_dev_is_md_component(struct device *dev, uint64_t *offset_found, int full)
{
md_minor_version_t minor;
uint64_t size, sb_offset;
@@ -188,19 +204,35 @@ out:
return ret;
}
int dev_is_md(struct device *dev, uint64_t *offset_found, int full)
int dev_is_md_component(struct device *dev, uint64_t *offset_found, int full)
{
int ret;
/*
* If non-native device status source is selected, use it
* only if offset_found is not requested as this
* information is not in udev db.
*/
if ((dev->ext.src == DEV_EXT_NONE) || offset_found)
return _native_dev_is_md(dev, offset_found, full);
if ((dev->ext.src == DEV_EXT_NONE) || offset_found) {
ret = _native_dev_is_md_component(dev, offset_found, full);
if (dev->ext.src == DEV_EXT_UDEV)
return _udev_dev_is_md(dev);
if (!full) {
if (!ret || (ret == -EAGAIN)) {
if (udev_dev_is_md_component(dev))
ret = 1;
}
}
if (ret && (ret != -EAGAIN))
dev->flags |= DEV_IS_MD_COMPONENT;
return ret;
}
if (dev->ext.src == DEV_EXT_UDEV) {
ret = _udev_dev_is_md_component(dev);
if (ret && (ret != -EAGAIN))
dev->flags |= DEV_IS_MD_COMPONENT;
return ret;
}
log_error(INTERNAL_ERROR "Missing hook for MD device recognition "
"using external device info source %s", dev_ext_name(dev));
@@ -422,14 +454,14 @@ int dev_is_md_with_end_superblock(struct dev_types *dt, struct device *dev)
log_very_verbose("Device %s %s is %s.",
dev_name(dev), attribute, version_string);
if (!strcmp(version_string, "1.0"))
if (!strcmp(version_string, "1.0") || !strcmp(version_string, "0.90"))
return 1;
return 0;
}
#else
int dev_is_md(struct device *dev __attribute__((unused)),
int dev_is_md_component(struct device *dev __attribute__((unused)),
uint64_t *sb __attribute__((unused)))
{
return 0;

View File

@@ -15,15 +15,13 @@
#include "base/memory/zalloc.h"
#include "lib/misc/lib.h"
#include "lib/device/dev-type.h"
#include "lib/device/device-types.h"
#include "lib/mm/xlate.h"
#include "lib/config/config.h"
#include "lib/metadata/metadata.h"
#include "lib/device/bcache.h"
#include "lib/label/label.h"
#include <libgen.h>
#include <ctype.h>
#ifdef BLKID_WIPING_SUPPORT
#include <blkid.h>
#endif
@@ -33,7 +31,83 @@
#include "lib/device/dev-ext-udev-constants.h"
#endif
#include "lib/device/device-types.h"
#include <libgen.h>
#include <ctype.h>
/*
* dev is pmem if /sys/dev/block/<major>:<minor>/queue/dax is 1
*/
int dev_is_pmem(struct device *dev)
{
FILE *fp;
char path[PATH_MAX];
char buffer[64];
int is_pmem = 0;
if (dm_snprintf(path, sizeof(path), "%sdev/block/%d:%d/queue/dax",
dm_sysfs_dir(),
(int) MAJOR(dev->dev),
(int) MINOR(dev->dev)) < 0) {
log_warn("Sysfs path for %s dax is too long.", dev_name(dev));
return 0;
}
if (!(fp = fopen(path, "r")))
return 0;
if (!fgets(buffer, sizeof(buffer), fp)) {
log_warn("Failed to read %s.", path);
if (fclose(fp))
log_sys_debug("fclose", path);
return 0;
} else if (sscanf(buffer, "%d", &is_pmem) != 1) {
log_warn("Failed to parse %s '%s'.", path, buffer);
if (fclose(fp))
log_sys_debug("fclose", path);
return 0;
}
if (fclose(fp))
log_sys_debug("fclose", path);
if (is_pmem) {
log_debug("%s is pmem", dev_name(dev));
return 1;
}
return 0;
}
int dev_is_lv(struct device *dev)
{
FILE *fp;
char path[PATH_MAX];
char buffer[64];
if (dm_snprintf(path, sizeof(path), "%sdev/block/%d:%d/dm/uuid",
dm_sysfs_dir(),
(int) MAJOR(dev->dev),
(int) MINOR(dev->dev)) < 0) {
log_warn("Sysfs dm uuid path for %s is too long.", dev_name(dev));
return 0;
}
if (!(fp = fopen(path, "r")))
return 0;
if (!fgets(buffer, sizeof(buffer), fp)) {
log_warn("Failed to read %s.", path);
fclose(fp);
return 0;
}
fclose(fp);
if (!strncmp(buffer, "LVM-", 4))
return 1;
return 0;
}
struct dev_types *create_dev_types(const char *proc_dir,
const struct dm_config_node *cn)
@@ -506,7 +580,7 @@ int dev_get_primary_dev(struct dev_types *dt, struct device *dev, dev_t *result)
*/
if ((parts = dt->dev_type_array[major].max_partitions) > 1) {
if ((residue = minor % parts)) {
*result = MKDEV((dev_t)major, (dev_t)(minor - residue));
*result = MKDEV(major, (minor - residue));
ret = 2;
} else {
*result = dev->dev;
@@ -576,7 +650,7 @@ int dev_get_primary_dev(struct dev_types *dt, struct device *dev, dev_t *result)
path, buffer);
goto out;
}
*result = MKDEV((dev_t)major, (dev_t)minor);
*result = MKDEV(major, minor);
ret = 2;
out:
if (fp && fclose(fp))
@@ -792,7 +866,7 @@ static int _wipe_known_signatures_with_lvm(struct device *dev, const char *name,
wiped = &wiped_tmp;
*wiped = 0;
if (!_wipe_signature(dev, "software RAID md superblock", name, 4, yes, force, wiped, dev_is_md) ||
if (!_wipe_signature(dev, "software RAID md superblock", name, 4, yes, force, wiped, dev_is_md_component) ||
!_wipe_signature(dev, "swap signature", name, 10, yes, force, wiped, dev_is_swap) ||
!_wipe_signature(dev, "LUKS signature", name, 8, yes, force, wiped, dev_is_luks))
return 0;
@@ -1005,25 +1079,23 @@ int dev_is_rotational(struct dev_types *dt, struct device *dev)
* failed already due to timeout in udev - in both cases the
* udev_device_get_is_initialized returns 0.
*/
#define UDEV_DEV_IS_MPATH_COMPONENT_ITERATION_COUNT 100
#define UDEV_DEV_IS_MPATH_COMPONENT_USLEEP 100000
#define UDEV_DEV_IS_COMPONENT_ITERATION_COUNT 100
#define UDEV_DEV_IS_COMPONENT_USLEEP 100000
int udev_dev_is_mpath_component(struct device *dev)
static struct udev_device *_udev_get_dev(struct device *dev)
{
struct udev *udev_context = udev_get_library_context();
struct udev_device *udev_device = NULL;
const char *value;
int initialized = 0;
unsigned i = 0;
int ret = 0;
if (!udev_context) {
log_warn("WARNING: No udev context available to check if device %s is multipath component.", dev_name(dev));
return 0;
return NULL;
}
while (1) {
if (i >= UDEV_DEV_IS_MPATH_COMPONENT_ITERATION_COUNT)
if (i >= UDEV_DEV_IS_COMPONENT_ITERATION_COUNT)
break;
if (udev_device)
@@ -1031,7 +1103,7 @@ int udev_dev_is_mpath_component(struct device *dev)
if (!(udev_device = udev_device_new_from_devnum(udev_context, 'b', dev->dev))) {
log_warn("WARNING: Failed to get udev device handler for device %s.", dev_name(dev));
return 0;
return NULL;
}
#ifdef HAVE_LIBUDEV_UDEV_DEVICE_GET_IS_INITIALIZED
@@ -1043,19 +1115,35 @@ int udev_dev_is_mpath_component(struct device *dev)
#endif
log_debug("Device %s not initialized in udev database (%u/%u, %u microseconds).", dev_name(dev),
i + 1, UDEV_DEV_IS_MPATH_COMPONENT_ITERATION_COUNT,
i * UDEV_DEV_IS_MPATH_COMPONENT_USLEEP);
i + 1, UDEV_DEV_IS_COMPONENT_ITERATION_COUNT,
i * UDEV_DEV_IS_COMPONENT_USLEEP);
usleep(UDEV_DEV_IS_MPATH_COMPONENT_USLEEP);
usleep(UDEV_DEV_IS_COMPONENT_USLEEP);
i++;
}
if (!initialized) {
log_warn("WARNING: Device %s not initialized in udev database even after waiting %u microseconds.",
dev_name(dev), i * UDEV_DEV_IS_MPATH_COMPONENT_USLEEP);
dev_name(dev), i * UDEV_DEV_IS_COMPONENT_USLEEP);
goto out;
}
out:
return udev_device;
}
int udev_dev_is_mpath_component(struct device *dev)
{
struct udev_device *udev_device;
const char *value;
int ret = 0;
if (!obtain_device_list_from_udev())
return 0;
if (!(udev_device = _udev_get_dev(dev)))
return 0;
value = udev_device_get_property_value(udev_device, DEV_EXT_UDEV_BLKID_TYPE);
if (value && !strcmp(value, DEV_EXT_UDEV_BLKID_TYPE_MPATH)) {
log_debug("Device %s is multipath component based on blkid variable in udev db (%s=\"%s\").",
@@ -1075,6 +1163,34 @@ out:
udev_device_unref(udev_device);
return ret;
}
int udev_dev_is_md_component(struct device *dev)
{
struct udev_device *udev_device;
const char *value;
int ret = 0;
if (!obtain_device_list_from_udev()) {
dev->flags |= DEV_UDEV_INFO_MISSING;
return 0;
}
if (!(udev_device = _udev_get_dev(dev)))
return 0;
value = udev_device_get_property_value(udev_device, DEV_EXT_UDEV_BLKID_TYPE);
if (value && !strcmp(value, DEV_EXT_UDEV_BLKID_TYPE_SW_RAID)) {
log_debug("Device %s is md raid component based on blkid variable in udev db (%s=\"%s\").",
dev_name(dev), DEV_EXT_UDEV_BLKID_TYPE, value);
dev->flags |= DEV_IS_MD_COMPONENT;
ret = 1;
goto out;
}
out:
udev_device_unref(udev_device);
return ret;
}
#else
int udev_dev_is_mpath_component(struct device *dev)
@@ -1082,4 +1198,10 @@ int udev_dev_is_mpath_component(struct device *dev)
return 0;
}
int udev_dev_is_md_component(struct device *dev)
{
dev->flags |= DEV_UDEV_INFO_MISSING;
return 0;
}
#endif

View File

@@ -57,11 +57,12 @@ 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 full);
int dev_is_md_component(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 udev_dev_is_md_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);
@@ -92,4 +93,8 @@ unsigned long dev_discard_granularity(struct dev_types *dt, struct device *dev);
int dev_is_rotational(struct dev_types *dt, struct device *dev);
int dev_is_pmem(struct device *dev);
int dev_is_lv(struct device *dev);
#endif

View File

@@ -20,7 +20,6 @@
#include <fcntl.h>
#define DEV_ACCESSED_W 0x00000001 /* Device written to? */
#define DEV_REGULAR 0x00000002 /* Regular file? */
#define DEV_ALLOCED 0x00000004 /* malloc used */
#define DEV_OPENED_RW 0x00000008 /* Opened RW */
@@ -36,6 +35,9 @@
#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 */
#define DEV_SCAN_FOUND_LABEL 0x00010000 /* label scan read dev and found label */
#define DEV_IS_MD_COMPONENT 0x00020000 /* device is an md component */
#define DEV_UDEV_INFO_MISSING 0x00040000 /* we have no udev info for this device */
/*
* Support for external device info.
@@ -143,17 +145,10 @@ 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);
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, 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, 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

@@ -18,13 +18,15 @@
#include "lib/filters/filter.h"
#include "lib/device/device.h"
static int _and_p(struct cmd_context *cmd, struct dev_filter *f, struct device *dev)
static int _and_p(struct cmd_context *cmd, struct dev_filter *f, struct device *dev, const char *use_filter_name)
{
struct dev_filter **filters;
int ret;
for (filters = (struct dev_filter **) f->private; *filters; ++filters) {
ret = (*filters)->passes_filter(cmd, *filters, dev);
if (use_filter_name && strcmp((*filters)->name, use_filter_name))
continue;
ret = (*filters)->passes_filter(cmd, *filters, dev, use_filter_name);
if (!ret)
return 0; /* No 'stack': a filter, not an error. */
@@ -33,12 +35,12 @@ static int _and_p(struct cmd_context *cmd, struct dev_filter *f, struct device *
return 1;
}
static int _and_p_with_dev_ext_info(struct cmd_context *cmd, struct dev_filter *f, struct device *dev)
static int _and_p_with_dev_ext_info(struct cmd_context *cmd, struct dev_filter *f, struct device *dev, const char *use_filter_name)
{
int r;
dev_ext_enable(dev, external_device_info_source());
r = _and_p(cmd, f, dev);
r = _and_p(cmd, f, dev, use_filter_name);
dev_ext_disable(dev);
return r;
@@ -93,6 +95,7 @@ struct dev_filter *composite_filter_create(int n, int use_dev_ext_info, struct d
cft->wipe = _wipe;
cft->use_count = 0;
cft->private = filters_copy;
cft->name = "composite";
log_debug_devs("Composite filter initialised.");

View File

@@ -65,7 +65,7 @@ static int _dev_is_fwraid(struct device *dev)
#define MSG_SKIPPING "%s: Skipping firmware RAID component device"
static int _ignore_fwraid(struct cmd_context *cmd, struct dev_filter *f __attribute__((unused)),
struct device *dev)
struct device *dev, const char *use_filter_name)
{
int ret;
@@ -113,6 +113,7 @@ struct dev_filter *fwraid_filter_create(struct dev_types *dt __attribute__((unus
f->destroy = _destroy;
f->use_count = 0;
f->private = NULL;
f->name = "fwraid";
log_debug_devs("Firmware RAID filter initialised.");

View File

@@ -38,7 +38,7 @@ void internal_filter_clear(void)
}
static int _passes_internal(struct cmd_context *cmd, struct dev_filter *f __attribute__((unused)),
struct device *dev)
struct device *dev, const char *use_filter_name)
{
struct device_list *devl;
@@ -74,6 +74,7 @@ struct dev_filter *internal_filter_create(void)
f->passes_filter = _passes_internal;
f->destroy = _destroy;
f->use_count = 0;
f->name = "internal";
log_debug_devs("Internal filter initialised.");

View File

@@ -46,7 +46,7 @@
* 3. use udev to detect components
*
* mode 1 will not detect and exclude components of md devices
* that use superblock version 1.0 which is at the end of the device.
* that use superblock version 0.9 or 1.0 which is at the end of the device.
*
* mode 2 will detect these, but mode 2 doubles the i/o done by label
* scan, since there's a read at both the start and end of every device.
@@ -59,11 +59,11 @@
*
* - the command is pvcreate/vgcreate/vgextend, which format new
* devices, and if the user ran these commands on a component
* device of an md device 1.0, then it would cause problems.
* device of an md device 0.9 or 1.0, then it would cause problems.
* FIXME: this would only really need to scan the end of the
* devices being formatted, not all devices.
*
* - it sees an md device on the system using version 1.0.
* - it sees an md device on the system using version 0.9 or 1.0.
* The point of this is just to avoid displaying md components
* from the 'pvs' command.
* FIXME: the cost (double i/o) may not be worth the benefit
@@ -82,7 +82,7 @@
* that will not pass.
*/
static int _passes_md_filter(struct cmd_context *cmd, struct dev_filter *f __attribute__((unused)), struct device *dev)
static int _passes_md_filter(struct cmd_context *cmd, struct dev_filter *f __attribute__((unused)), struct device *dev, const char *use_filter_name)
{
int ret;
@@ -93,7 +93,7 @@ static int _passes_md_filter(struct cmd_context *cmd, struct dev_filter *f __att
if (!md_filtering())
return 1;
ret = dev_is_md(dev, NULL, cmd->use_full_md_check);
ret = dev_is_md_component(dev, NULL, cmd->use_full_md_check);
if (ret == -EAGAIN) {
/* let pass, call again after scan */
@@ -106,6 +106,7 @@ static int _passes_md_filter(struct cmd_context *cmd, struct dev_filter *f __att
return 1;
if (ret == 1) {
log_debug_devs("md filter full %d excluding md component %s", cmd->use_full_md_check, dev_name(dev));
if (dev->ext.src == DEV_EXT_NONE)
log_debug_devs(MSG_SKIPPING, dev_name(dev));
else
@@ -144,6 +145,7 @@ struct dev_filter *md_filter_create(struct cmd_context *cmd, struct dev_types *d
f->destroy = _destroy;
f->use_count = 0;
f->private = dt;
f->name = "md";
log_debug_devs("MD filter initialised.");

View File

@@ -27,6 +27,14 @@
#define MPATH_PREFIX "mpath-"
struct mpath_priv {
struct dm_pool *mem;
struct dev_filter f;
struct dev_types *dt;
struct dm_hash_table *hash;
};
static const char *_get_sysfs_name(struct device *dev)
{
const char *name;
@@ -174,7 +182,8 @@ static int _udev_dev_is_mpath(struct device *dev)
static int _native_dev_is_mpath(struct dev_filter *f, struct device *dev)
{
struct dev_types *dt = (struct dev_types *) f->private;
struct mpath_priv *mp = (struct mpath_priv *) f->private;
struct dev_types *dt = mp->dt;
const char *part_name, *name;
struct stat info;
char path[PATH_MAX], parent_name[PATH_MAX];
@@ -182,6 +191,7 @@ static int _native_dev_is_mpath(struct dev_filter *f, struct device *dev)
int major = MAJOR(dev->dev);
int minor = MINOR(dev->dev);
dev_t primary_dev;
long look;
/* Limit this filter only to SCSI devices */
if (!major_is_scsi_device(dt, MAJOR(dev->dev)))
@@ -201,12 +211,12 @@ static int _native_dev_is_mpath(struct dev_filter *f, struct device *dev)
return_0;
break;
default: /* 0, error. */
log_error("Failed to get primary device for %d:%d.", major, minor);
log_warn("Failed to get primary device for %d:%d.", major, minor);
return 0;
}
if (dm_snprintf(path, sizeof(path), "%s/block/%s/holders", sysfs_dir, name) < 0) {
log_error("Sysfs path to check mpath is too long.");
log_warn("Sysfs path to check mpath is too long.");
return 0;
}
@@ -215,7 +225,7 @@ static int _native_dev_is_mpath(struct dev_filter *f, struct device *dev)
return 0;
if (!S_ISDIR(info.st_mode)) {
log_error("Path %s is not a directory.", path);
log_warn("Path %s is not a directory.", path);
return 0;
}
@@ -228,7 +238,22 @@ static int _native_dev_is_mpath(struct dev_filter *f, struct device *dev)
if (major != dt->device_mapper_major)
return 0;
return lvm_dm_prefix_check(major, minor, MPATH_PREFIX);
/* Avoid repeated detection of multipath device and use first checked result */
look = (long) dm_hash_lookup_binary(mp->hash, &minor, sizeof(minor));
if (look > 0) {
log_debug_devs("%s(%u:%u): already checked as %sbeing mpath.",
parent_name, major, minor, (look > 1) ? "" : "not ");
return (look > 1) ? 1 : 0;
}
if (lvm_dm_prefix_check(major, minor, MPATH_PREFIX)) {
(void) dm_hash_insert_binary(mp->hash, &minor, sizeof(minor), (void*)2);
return 1;
}
(void) dm_hash_insert_binary(mp->hash, &minor, sizeof(minor), (void*)1);
return 0;
}
static int _dev_is_mpath(struct dev_filter *f, struct device *dev)
@@ -247,7 +272,7 @@ static int _dev_is_mpath(struct dev_filter *f, struct device *dev)
#define MSG_SKIPPING "%s: Skipping mpath component device"
static int _ignore_mpath(struct cmd_context *cmd, struct dev_filter *f, struct device *dev)
static int _ignore_mpath(struct cmd_context *cmd, struct dev_filter *f, struct device *dev, const char *use_filter_name)
{
if (_dev_is_mpath(f, dev) == 1) {
if (dev->ext.src == DEV_EXT_NONE)
@@ -263,35 +288,65 @@ static int _ignore_mpath(struct cmd_context *cmd, struct dev_filter *f, struct d
static void _destroy(struct dev_filter *f)
{
struct mpath_priv *mp = (struct mpath_priv*) f->private;
if (f->use_count)
log_error(INTERNAL_ERROR "Destroying mpath filter while in use %u times.", f->use_count);
free(f);
dm_hash_destroy(mp->hash);
dm_pool_destroy(mp->mem);
}
struct dev_filter *mpath_filter_create(struct dev_types *dt)
{
const char *sysfs_dir = dm_sysfs_dir();
struct dev_filter *f;
struct dm_pool *mem;
struct mpath_priv *mp;
struct dm_hash_table *hash;
if (!*sysfs_dir) {
log_verbose("No proc filesystem found: skipping multipath filter");
return NULL;
}
if (!(f = zalloc(sizeof(*f)))) {
log_error("mpath filter allocation failed");
if (!(hash = dm_hash_create(128))) {
log_error("mpath hash table creation failed.");
return NULL;
}
f->passes_filter = _ignore_mpath;
f->destroy = _destroy;
f->use_count = 0;
f->private = dt;
if (!(mem = dm_pool_create("mpath", 256))) {
log_error("mpath pool creation failed.");
dm_hash_destroy(hash);
return NULL;
}
if (!(mp = dm_pool_zalloc(mem, sizeof(*mp)))) {
log_error("mpath filter allocation failed.");
goto bad;
}
if (!(mp = dm_pool_zalloc(mem, sizeof(*mp)))) {
log_error("mpath filter allocation failed.");
goto bad;
}
mp->f.passes_filter = _ignore_mpath;
mp->f.destroy = _destroy;
mp->f.use_count = 0;
mp->f.private = mp;
mp->f.name = "mpath";
mp->mem = mem;
mp->dt = dt;
mp->hash = hash;
log_debug_devs("mpath filter initialised.");
return f;
return &mp->f;
bad:
dm_pool_destroy(mem);
dm_hash_destroy(hash);
return NULL;
}
#else

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