1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-09-15 13:44:18 +03:00

Compare commits

...

728 Commits

Author SHA1 Message Date
Petr Rockai
4aaffe0650 lvmetad: Avoid duplicate entries in the list of alternate devices. 2015-04-28 17:25:06 +02:00
Alasdair G Kergon
d0c46c9ed5 conf: Avoid temp files when generating config. 2015-04-28 13:02:19 +01:00
Zdenek Kabelac
71dbfd7c20 tests: more help# 2015-04-28 11:35:56 +02:00
Zdenek Kabelac
3fbb7b6e35 tests: always zero disk header
It appear that older wipefs doesn't wipe partition table.
So ensure there is no partition on LVM_TEST_BACKING_DEVICE.
2015-04-28 11:32:52 +02:00
Zdenek Kabelac
1bb5b498f0 tests: more descriptive aux
Tell what's reason of aux fail here.
2015-04-28 11:23:16 +02:00
Zdenek Kabelac
a378e5a6dd tests: drop debug test
Remove 'debug leftover' from test.
2015-04-28 11:23:16 +02:00
David Teigland
0c1bda9b53 example.conf.in: regenerate
From recent config_settings.h changes.
2015-04-27 14:15:24 -05:00
David Teigland
cfb0174fed config: fix a couple mistakes with defaults
for archive, archive_dir, and cache
2015-04-27 13:54:45 -05:00
Zdenek Kabelac
a7d28639eb tests: use new help in aux
Simplify tests and use aux mdadm helpers.
2015-04-25 00:40:02 +02:00
Zdenek Kabelac
1e3c135d71 tests: aux for mdadm
Implement aux helper fce for mdadm.
2015-04-25 00:40:02 +02:00
Zdenek Kabelac
f50229041b tests: allow add printable skip message 2015-04-25 00:40:02 +02:00
Zdenek Kabelac
a939857a63 tests: check sysfs more generically
Allow to access more files in device sysfs subtree.
2015-04-25 00:40:02 +02:00
Ondrej Kozina
d9176782fe tests: add double quotes around add_to_kill_list parms 2015-04-25 00:40:02 +02:00
Zdenek Kabelac
d7888e8316 tests: try more advanced clean
When test is executed on real device - lets try a more complete
cleanup - discard whole device first and try to wipe any
headers it might be left from previous test.
2015-04-25 00:39:43 +02:00
Peter Rajnoha
066d0a4e19 cleanup: ancestors -> lv_ancestors, descendants -> lv_descendants
Use "lv_" prefix as they're LV fields.
2015-04-24 14:19:28 +02:00
Peter Rajnoha
6e4aee0492 report: add lv_ancestors and lv_descendants reporting fields
Show full chain of ancestors and descendants for snapshots
(both thick and thin - in case of thick, the "ancestor" field
is actually equal to "origin" field as snapshots can't be
chained for thick snapshots).

These fields display current state as it is, they do not
display any history! If the snapshot chain is broken in
the middle, we don't report the historical origin (this
is going to be a part of another patch and a different
set of fields or just a switch for existing fields to
show ancestors and descendants with history included).

For example:

(origin --> snapshot)

lvol1 --> lvol2 --> lvol3 --> lvol4
              \
                --> lvol5 --> lvol6 --> lvol7 --> lvol8

$ lvs -o name,pool_lv,origin,ancestors,descendants vg
  LV    Pool Origin Ancestors                     Descendants
  lvol1 pool                                      lvol2,lvol3,lvol4,lvol5,lvol6,lvol7,lvol8
  lvol2 pool lvol1  lvol1                         lvol3,lvol4,lvol5,lvol6,lvol7,lvol8
  lvol3 pool lvol2  lvol2,lvol1                   lvol4
  lvol4 pool lvol3  lvol3,lvol2,lvol1
  lvol5 pool lvol2  lvol2,lvol1                   lvol6,lvol7,lvol8
  lvol6 pool lvol5  lvol5,lvol2,lvol1             lvol7,lvol8
  lvol7 pool lvol6  lvol6,lvol5,lvol2,lvol1       lvol8
  lvol8 pool lvol7  lvol7,lvol6,lvol5,lvol2,lvol1
2015-04-24 11:51:52 +02:00
Peter Rajnoha
82f6dbfaf7 select: fix matching reserved values while <,<=,>,>= is used in selection criteria
Scenario:

$ vgs -o+vg_mda_copies
  VG     #PV #LV #SN Attr   VSize VFree #VMdaCps
  fedora   1   2   0 wz--n- 9.51g    0  unmanaged
  vg      16   9   0 wz--n- 1.94g 1.83g         2

$ lvs -o+read_ahead vg/lvol6 vg/lvol7
  LV    VG   Attr       LSize Pool Origin Data%  Rahead
  lvol6 vg   Vwi-a-tz-- 1.00g pool lvol5  0.00      auto
  lvol7 vg   Vwi---tz-k 1.00g pool lvol6         256.00k

Before this patch:

$vgs -o vg_name,vg_mda_copies -S 'vg_mda_copies < unmanaged'
  VG   #VMdaCps
  vg          2

Problem:
Reserved values can be only used with exact match = or !=, not <,<=,>,>=.
In the example above, the "unamanaged" is internally represented as
18446744073709551615, but this should be ignored while not comparing
field directly with "unmanaged" reserved name with = or !=. Users
should not be aware of this internal mapping of the reserved value
name to its internal value and hence it doesn't make sense for such
reserved value to take place in results of <,<=,> and >=.
There's no order defined for reserved values!!! It's a special
*reserved* value that is taken out of the usual value range
of that type.

This is very similar to what we have already fixed with
2f7f6932dc, but it's the other way round
now - we're using reserved value name in selection criteria now
(in the patch 2f7f693, we had concrete value and we compared it
with the reserved value). So this patch completes patch 2f7f693.

This patch also fixes this problem:

$ lvs -o+read_ahead vg/lvol6 vg/lvol7 -S 'read_ahead > 32k'
  LV    VG   Attr       LSize Pool Origin Data%  Rahead
  lvol6 vg   Vwi-a-tz-- 1.00g pool lvol5  0.00      auto
  lvol7 vg   Vwi---tz-k 1.00g pool lvol6         256.00k

Problem:
In the example above, the internal reserved value "auto" is in the
range of selection "> 32k" - it shouldn't match as well. Here the
"auto" is internally represented as MAX_DBL and of course, numerically,
MAX_DBL > 256k. But for users, the reserved value should be uncomparable
to any number so the mapping of the reserved value name to its interna
 value is transparent to users. Again, there's no order defined for
reserved values and hence it should never match if using <,<=,>,>=
operators.

This is actually exactly the same problem as already described in
2f7f6932dc, but that patch failed for
size field types because of incorrect internal representation used.

With this patch applied, both problematic scenarios mentioned
above are fixed now:

$ vgs -o vg_name,vg_mda_copies -S 'vg_mda_copies < unmanaged'
(blank)

$ lvs -o+read_ahead vg/lvol6 vg/lvol7 -S 'read_ahead > 32k'
  LV    VG   Attr       LSize Pool Origin Rahead
  lvol7 vg   Vwi---tz-k 1.00g pool lvol6  256.00k
2015-04-24 09:48:57 +02:00
Zdenek Kabelac
de0ce46361 tests: fix md raid test on real /dev
Zero raid signatures when raid is stopped - so signatures
are not requiring wipe when pvcreate follows.

Handle real /dev
2015-04-23 20:28:44 +02:00
Alasdair G Kergon
8853462528 libdm: Add uuid/devno to ioctl failure log message. 2015-04-23 19:26:52 +01:00
Alasdair G Kergon
1906619187 libdm: Add DM_INTERNAL_SUSPEND_FLAG.
Still needs to be reported by dmsetup.
2015-04-23 18:39:04 +01:00
David Teigland
95da21cc18 config: fix check_options array
The code used it as both a single string, and as
an array of strings in different places.  Fix it
so that it's an array of strings everywhere.
2015-04-23 10:35:34 -05:00
David Teigland
a8bdfbe959 config: thin_disabled_features default should be undefined
An array that's empty by default should be flagged as
undefined.
2015-04-23 10:19:00 -05:00
David Teigland
3fc9615d15 Improve duplicate PV handling
Make the processing of duplicate PVs the
same with and without lvmetad.
2015-04-22 13:22:14 -05:00
Petr Rockai
92607ecfe6 man: Escape single quotes in an example to avoid groff's unicode conversion. 2015-04-22 17:31:11 +02:00
David Teigland
33429ea083 make: autoconfisms for generate 2015-04-22 10:05:02 -05:00
David Teigland
808f88f9f0 make: let generate use the just built libdm 2015-04-22 09:37:56 -05:00
Alasdair G Kergon
81d03b46b0 doc: Update dm kernel files.
v4.0-9804-gdb4fd9c
2015-04-22 15:34:25 +01:00
Zdenek Kabelac
2fea720881 tests: add missing "" around dev 2015-04-22 11:18:31 +02:00
Zdenek Kabelac
4b161de2e5 tests: aux works better with installed_testsuite
When test suite is used from installed rpm package
we need to handle things better.

This patch is rather first approach - expecting few more
tweaks needed.
2015-04-22 11:18:31 +02:00
Zdenek Kabelac
7a64a157e1 tests: simplify teardown
If TESTNAME has not been created yet, avoid running complex teardown.
2015-04-22 11:18:31 +02:00
Zdenek Kabelac
7f8d942268 makefiles: avoid // in datadir usage
DESTDIR already comes with '/'
2015-04-22 10:59:03 +02:00
Zdenek Kabelac
d8874556cd tests: install also api test
Install .t & .py binaries.
On 'make clean'  ensure also -t files are removed.
2015-04-22 10:57:42 +02:00
Zdenek Kabelac
3216a9a819 tests: drop DEBUG log after success
At this moment LVM_LOG_FILE_EPOCH with
LVM_EXPECTED_EXIT_STATUS  properly deletes debug logs
only for real commands - support for lvm2 API does not yet
exists
2015-04-22 10:55:37 +02:00
Zdenek Kabelac
14c3f9603e tests: use 800ms delay
Worked better with pvmove-abort-all so use here as well.
2015-04-22 09:09:26 +02:00
Zdenek Kabelac
3f8da60079 tests: notify drops log always
Even on success remove debug.log here.
2015-04-22 09:09:26 +02:00
Zdenek Kabelac
afdff40542 tests: explicitely ignore result code 2015-04-22 09:09:26 +02:00
Zdenek Kabelac
30e8b284a7 tests: allow to use sysfs filter
Current filtering logic in lvm2 needs some rework.
For now at least enable it in test suite.
2015-04-22 09:09:26 +02:00
Zdenek Kabelac
16ee4642c7 nix: install also mdadm
Some tests are checking functinality of lvm2 with mdadm.
2015-04-22 09:09:26 +02:00
David Teigland
2e035162a1 config: thin_repair_options and cache_repair_options are undefined
By default these are empty strings, so the config settings
should be flagged as undefined, so they will be commented
out of the generated config.  Otherwise, the lines:

thin_repair_options=""
cache_repair_options=""

in the dump output cause a warning when processed since
lvm doesn't want an empty string.

Also regenerate lvm.conf.in.
2015-04-21 16:03:54 -05:00
David Teigland
3b15f79bf0 generate example.conf.in, lvmlocal.conf.in
These were created by 'make generate'.
2015-04-21 15:04:22 -05:00
David Teigland
47ed4cdc35 config: remove duplication of settings
The specific config settings have been removed
from the lvm.conf(5) man page, and replaced with
a description of how to use lvm dumpconfig to
view the settings.

The sample lvm.conf and lvmlocal.conf files are now generated:

example.conf.base  - initial ungenerated part of the file
example.conf.gen   - generated portion from dumpconfig
example.conf.in    - combination of .base and .gen files
example.conf       - result of configure processing .in file

lvmlocal.conf.base - initial ungenerated part of the file
lvmlocal.conf.gen  - generated portion from dumpconfig
lvmlocal.conf.in   - combination of .base and .gen files
lvmlocal.conf      - result of configure processing .in file

Do not edit the .in files, but edit config_settings.h
or the .base files, and then use 'make generate' to create
the new .in files.

- configure
  with options

- make
  creates tools/lvm

- make generate
  uses tools/lvm to create example.conf.in and lvmlocal.conf.in
  by combining .base files with dumpconfig output.

- configure
  with same options as above
  creates example.conf and lvmlocal.conf from .in files
2015-04-21 14:55:03 -05:00
David Teigland
9b86e8e8f4 dumpconfig: add --ignorelocal
When generating a sample lvm.conf file, we don't want to
include the "local" section, which is kept in lvmlocal.conf.
2015-04-21 14:55:03 -05:00
David Teigland
0d0d50182d toollib: fix duplicate handling in process_each_pv
With use_lvmetad=0, duplicate PVs /dev/loop0 and /dev/loop1,
where in this example, /dev/loop1 is the cached device
referenced by pv->dev, the command 'pvs /dev/loop0' reports:

Failed to find physical volume "/dev/loop0".

This is because the duplicate PV detection by pvid is
not working because _get_all_devices() is not setting
any dev->pvid for any entries.  This is because the
pvid information has not yet been saved in lvmcache.
This is fixed by calling _get_vgnameids_on_system()
before _get_all_devices(), which has the effect of
caching the necessary pvid information.

With this fix, running pvs /dev/loop0, or pvs /dev/loop1,
produces no error and one line of output for the PV (the
device printed is the one cached in pv->dev, in this
example /dev/loop1.)

Running 'pvs /dev/loop0 /dev/loop1' produces no error
and two lines of output, with each device displayed
on one of the lines.

Running 'pvs -a' shows two PVs, one with loop0 and one
with loop1, and both shown as a member of the same VG.

Running 'pvs' shows only one of the duplicate PVs,
and that shows the device cached in pv->dev (loop1).

The above output is what the duplicate handling code
was previously designed to output in commits:

b64da4d8b5 toollib: search for duplicate PVs only when needed
3a7c47af0e toollib: pvs -a should display VG name for each duplicate PV
57d74a45a0 toollib: override the PV device with duplicates
c1f246fedf toollib: handle duplicate pvs in process_in_pv

As a further step after this, we may choose to change
some of those.

For all of these commands, a warning is printed about
the existence of the duplicate PVs:

Found duplicate PV ...: using /dev/loop1 not /dev/loop0
2015-04-20 17:07:58 -05:00
Zdenek Kabelac
caa9223c85 tests: update to renamed envvars
Enhance 'not' so 'should' now shows log trace from
command which has failed but should not.
2015-04-20 19:18:56 +02:00
Zdenek Kabelac
85e833c172 tests: add extra keyword for timing control
Control logging of timer with
"## timing off"  and "## timing on"
2015-04-20 19:18:56 +02:00
Zdenek Kabelac
2b4f10ac66 debug: change envvar
Rename envvar LVM_LOG_FILE_UNLINK_STATUS to LVM_EXPECTED_EXIT_STATUS
and change compare sign from  '!' to  '>'.

Validate LVM_LOG_FILE_EPOCH and support strictly only
up-to 32 alpha chars. If the content doesn't pass
epoch is simply ignored.
2015-04-20 19:18:56 +02:00
Zdenek Kabelac
cf4df9e349 tests: use new debug logging feature
Enhance 'not' to manage autodeletion of log files in right cases.
Use separately marked epoch log files for clvmd and dmeventd.
Properly manage stack tracing for new debug.log names.
2015-04-20 12:12:22 +02:00
Zdenek Kabelac
bff3a1651d debug: use epoch for dmeventd logging
When LVM_LOG_FILE_EPOCH is set, route lvm command debug message
to lvm.conf log file instead of syslog.
2015-04-20 12:12:22 +02:00
Zdenek Kabelac
5723a7cd7e debug: add new envvar
Add support for 2 new envvars for internal lvm2 test suite
(though it could be possible usable for other cases)

LVM_LOG_FILE_EPOCH

Whether to add 'epoch' extension that consist from
the envvar 'string' + pid + starttime in kernel units
obtained from /proc/self/stat.

LVM_LOG_FILE_UNLINK_STATUS

Whether to unlink the log depending on return status value,
so if the command is successful the log is automatically
deleted.

API is still for now experimental to catch various issue.
2015-04-20 12:12:22 +02:00
Ondrej Kozina
de4791c052 WHATS_NEW: update for various commits
add info for various commits, most significant were:

- toollib: close connection to lvmetad after fork
  (fe30658a4d)

- toollib: do not spawn polling in lv_change_activate
  (c26d81d6e6)

- pvmove: split pvmove_update_metadata function
  (65623b63a2)

- lvconvert: move poll code in before refactoring
  (5190f56605)

- pvmove: move poll code in before refactoring
  (a098aa419f)
2015-04-20 10:38:54 +02:00
David Teigland
5cd6381717 dumpconfig: add --unconfigured option
Using this option, default string values that are
configurable are printed as unconfigured values,
e.g. "@CONFDIR@" instead of "/etc".
2015-04-17 11:35:34 -05:00
Ondrej Kozina
061e371319 pvmove: fix wrong error path in _update_metadata
fix regression introduced in 65623b63a2

should return zero no matter the result of resume_lvs fn in error
path
2015-04-16 17:54:00 +02:00
David Teigland
105c07d1b4 config: edit descriptions
Take some new information and wording from lvm.conf.5.
2015-04-15 14:21:20 -05:00
David Teigland
5f6ac1c812 dumpconfig: add --withfullcomments option
--withfullcomments prints all comment lines for each config option.
--withcomments prints only the first comment line, which should be
a short one-line summary of the option.
2015-04-15 10:56:42 -05:00
Petr Rockai
9ce52430de NIX: Also install device-mapper-persistent-data on CentOS 7 & FC 19+. 2015-04-15 16:44:15 +02:00
Zdenek Kabelac
191f3cf52a tests: shell-fu
Preserve quotes for devs and use  shell arrays to pass things around.
2015-04-15 15:09:45 +02:00
Zdenek Kabelac
43a6f9e726 tests: move print of replaced vars 2015-04-15 15:09:45 +02:00
Zdenek Kabelac
53c2c45625 tests: align test result in batch mode 2015-04-15 13:35:42 +02:00
Zdenek Kabelac
e478471dd5 tests: move stamp handling
Shift stamp handling into TimedBuffer,
so it's same everywhere.
2015-04-15 13:35:42 +02:00
Zdenek Kabelac
5d4695569d tests: hide error output
Hide error message if pid is already away.
2015-04-15 13:35:42 +02:00
Zdenek Kabelac
930f0aae84 tests: fix aux have test
Previous commit has made have_cache & have_thin producing
false return value.

Fix it and at the some time provide much better reconfiguring
warning message.

If the test machine is missing needed and configured binaries
it will produce TEST WARNING result.
2015-04-15 13:35:42 +02:00
Zdenek Kabelac
1a7dd13e70 tests: no tables for no devices
If dm table does't contain any PREFIX device, don't bother
to call other commands

No tracing if test is skipped.
2015-04-15 13:35:42 +02:00
Zdenek Kabelac
f5466fe435 tests: preserve "" around dev 2015-04-15 13:35:42 +02:00
Zdenek Kabelac
1a814af46b makefiles: fix usage of default value
When a var like LVM_TEST_THIN_CHECK_CMD is set to ""
(which is valid) we need to correctly use '-'.
Otherwise ':-' replaces such value with built-in default.
2015-04-15 13:35:42 +02:00
Peter Rajnoha
22defdac64 man: fix some formatting and also mention -vv 2015-04-15 09:19:11 +02:00
David Teigland
6cdab82cf3 config: edit descriptions
Rewording so the first line of the description
works as a single line summary of the option.
2015-04-14 17:00:28 -05:00
Petr Rockai
7e58ae7dac test: Show all lvmetad messages (errors, warnings), not just debug+wire. 2015-04-14 20:18:27 +02:00
Petr Rockai
026c38ac1e NIX: Disable profiling in all but one configuration. 2015-04-14 20:18:27 +02:00
Petr Rockai
24352aff2b lvmetad: Issue warnings about duplicate PV UUIDs (client-side). 2015-04-14 20:18:27 +02:00
Petr Rockai
a1dd61459c lvmetad: Track alternate devices for PVs.
There are two reasons for this: first, this allows the client side to notice
that some PV has multiple devices associated with it and print appropriate
warnings. Second, if a duplicate device pops up and disappears, after this
change the original connection between the PV and device is not lost.
2015-04-14 20:18:27 +02:00
Petr Rockai
2ebb4f4ca3 libdaemon: Export chain_node from config-utils.c. 2015-04-14 20:16:53 +02:00
Peter Rajnoha
e3c831030d WHATS_NEW: commit 375ed98 2015-04-14 15:28:42 +02:00
Peter Rajnoha
375ed98ae9 make: move blkdeactivate script and blkdeactivate.8 man page installation from install_lvm2 to install_device-mapper target
This completes commit 7a4e27eee5.
2015-04-14 15:24:37 +02:00
Peter Rajnoha
7a4e27eee5 blkdeactivate: check for lvm binary and skip LVM processing if not present
This removes dependency on lvm binary - if it's not present, all LVM
processing is skipped (shouldn't normally happen because if lvm binary
is missing then there's obviously nothing that would activate it, but
let's make sure).

Without this tight dependency on lvm, the blkdeactivate script can
be packaged with libdevmapper/dmsetup (in contrast to lvm as it was
before) and as such the script can still be used to handle other DM
devices.
2015-04-14 13:35:11 +02:00
Zdenek Kabelac
d1a770107d tests: update pvmove tests
Put in pvmove background process into list quickly.
Update API for aux add_to_kill_list()/kill_listed_processes().
Run on 'background' (&) only non-background pvmoves.
2015-04-14 13:29:43 +02:00
Zdenek Kabelac
75454c2b32 tests: rusage skipped only for skipped 2015-04-14 13:29:43 +02:00
Zdenek Kabelac
4cdf155a87 makefiles: check lcov file has content
genhtml may get confused without content.
2015-04-14 13:29:43 +02:00
Zdenek Kabelac
a084b3122f tests: integrate default thin/cache tool paths
If the system is correctly configure (cache & thin tools are present)
avoid 'extra' rebuild of configuration.

On the other hand - if some tool is missing - duplicate ##LVMCONF should
make it more straighforward to see.
2015-04-14 10:11:36 +02:00
Zdenek Kabelac
c6bcfcba85 tests: stacktrace understands fullpath
$0 as name of script could be either relative or full path.
When it's fullpath don't prepend $TESTOLDPWD.
2015-04-14 10:11:36 +02:00
Zdenek Kabelac
c969e05aab tests: avoid dup of lvm.conf
When running lvmetad test - avoid duplicate create of lvm.conf
Also as lvmetad cannot be used with cluster make it as 2 code paths.
2015-04-14 10:11:35 +02:00
Zdenek Kabelac
ee6fc17663 makefiles: skip lvmetad tests
When build without lvmetad, skip  n/udev-lvmetad flavour execution.
Update help test.
2015-04-14 10:11:35 +02:00
Peter Rajnoha
d5651f44e3 man: lvmconf: more notes on --services option 2015-04-14 09:49:56 +02:00
Ondrej Kozina
96124c6c0b tests: [new] check pvmove resume works as expected
various methods of resuming interrupted pvmove are tested:
- pvmove
- pvmove -b
- lvchange
- vgchange

tests for commits:
- c26d81d6e6
- fe30658a4d
2015-04-13 20:53:18 +02:00
Ondrej Kozina
fe30658a4d toollib: close connection to lvmetad after fork
sharing connection between parent command and background
processes spawned from parent could lead to occasional failures
due to unexpected corruption in daemon responses sent to either child
or a parent.

lvmetad issued warning about duplicate config values in request.
LVM commands occasionaly failed w/ internal error after receving
corrupted response.

lvmetad connection is renewed when needed after explicit disconnect
in child
2015-04-13 20:52:32 +02:00
Ondrej Kozina
c26d81d6e6 toollib: do not spawn polling in lv_change_activate
spawning a background polling from within the lv_change_activate
fn went to two problems:

1) vgchange should not spawn any background polling until after
   the whole activation process for a VG is finished. Otherwise
   it could lead to a duplicite request for spawning background
   polling. This statement was alredy true with one exception of
   mirror up-conversion polling (fixed by this commit).

2) due to current conditions in lv_change_activate lvchange cmd
   couldn't start background polling for pvmove LVs if such LV was
   about to get activated by the command in the same time.

This commit however doesn't alter the lvchange cmd so that it works same as
vgchange with regard to not to spawn duplicate background pollings per
unique LV.
2015-04-13 20:52:22 +02:00
Ondrej Kozina
59c417379e vgchange: remove redundant check
pvmove LVs are invisible thus already skipped due to check
lv_is_visible() at the beginning of the cycle.
2015-04-13 20:52:12 +02:00
David Teigland
fa16c9b7cb config: fix description syntax errors
from previous commit
2015-04-13 13:48:01 -05:00
David Teigland
29220a181a config: update descriptions
- filter, preferred_names
2015-04-13 13:40:11 -05:00
Zdenek Kabelac
e4261ba037 tests: update runner
Reenable TESTDIR  & PREFIX replacement.
Since we need to replace string in proper order (1st. @TESTDIR@,
2nd. @PREFIX@), drop map and use plain string.

Drop timestamp logging when 'stacktracing'
2015-04-13 16:38:32 +02:00
Zdenek Kabelac
0aef2b719f tests: log parallel debug.log usage as problem 2015-04-13 16:38:32 +02:00
Zdenek Kabelac
0457224feb tests: sections in test separated
Use  <========  to separate sections.
Use ##  to prefix these outputs.
Drop $top_srcdir from sed  (it's been replacing '..')
Hide more /dev  dirs.
2015-04-13 16:38:31 +02:00
Zdenek Kabelac
f080ebc123 tests: hide unwanted output 2015-04-13 16:38:31 +02:00
Zdenek Kabelac
391500643c tests: slowdown mirroring more
Since some of test machines are very slow, slowdown mirroring
even more.
2015-04-13 16:38:31 +02:00
Zdenek Kabelac
29467abe59 cleanup: put easier tests first
If we could 'break' before calling strcmp() do it.
Use fputc for single char output (\n).
2015-04-13 16:38:31 +02:00
Zdenek Kabelac
0b99d648ef cleanup: typo in comment 2015-04-13 16:38:30 +02:00
Peter Rajnoha
695237f2ae WHATS_NEW: previous commit f814d7wq 2015-04-13 15:49:25 +02:00
Peter Rajnoha
f814d763c6 lvmconf: add --enable-halvm, --disable-halvm, --services, --mirrorservice, --startstopservices options and use proper global/use_lvmetad default value
This patch adds new options to lvmconf:

  --enable-halvm (just like --enable-cluster, but configure LVM
                  for use in HA LVM - meaning disabling lvmetad and
                  making sure we have locking_type=1)

  --disable-halvm (just like --disable-cluster, but configure LVM
                   back from HA LVM - meaning enabling lvmetad if
                   it's enabled by default and making sure we have
                   default locking type set)

  --services (causes clvmd and lvmetad services to be enabled or
              disabled appropriately and conforming to the changes
              in lvm configuration we've just made with lvmconf)

  --mirrorservice (in addition to clvmd and lvmetad services, also
                   enable or disable cmirrord service appropriately;
                   this is a separate option because cmirrord is
                   optional and it doesn't need to be always enabled
                   when clvmd is enabled)

  --startstopservices (in addition to enabling or disabling services,
                       start and stop these services immediately)

These options are supposed to help users to make their system ready
for cluster with clvmd (active-active) or HA LVM (active-passive) use
while lvmconf script can handle services as well so users don't need
to bother about setting them manually.

Also, before this patch, we hardcoded global/use_lvmetad=0 as default
value in lvmconf script. Howeverm this default may change by just
flipping the value in config_settings.h and we may forget to edit
the lvmconf. It's better to use lvm dumpconfig --type default global/use_lvmetad
to get the actual default value and use this one instead of hardcoded one.
2015-04-13 15:27:17 +02:00
Alasdair G Kergon
cc26085b62 alloc: Respect cling_tag_list in contig alloc.
When performing initial allocation (so there is nothing yet to
cling to), use the list of tags in allocation/cling_tag_list to
partition the PVs.  We implement this by maintaining a list of
tags that have been "used up" as we proceed and ignoring further
devices that have a tag on the list.

https://bugzilla.redhat.com/983600
2015-04-11 01:55:24 +01:00
David Teigland
b851b74cba config: editing descriptions
Update wording and formatting.
2015-04-10 16:43:38 -05:00
Alasdair G Kergon
2872e8c289 alloc: Add A_PARTITION_BY_TAGS to avoid sharing.
Add A_PARTITION_BY_TAGS set when allocated areas should not share tags
with each other and allow _match_pv_tags to accept an alternative list
of tags.  (Not used yet.)
2015-04-10 21:57:52 +01:00
Tony Asleson
0523c71844 python: Fix ws liblvm.c
Signed-off-by: Tony Asleson <tasleson@redhat.com>
2015-04-10 11:01:46 -05:00
Tony Asleson
f29df9acfe python: Unit test ws fixes
pep8 corrections for:
    - mixed leading ws (tabs & spaces)
    - spacing around arithmetic operators

Signed-off-by: Tony Asleson <tasleson@redhat.com>
2015-04-10 10:52:12 -05:00
Tony Asleson
2b557b595a python: Make lv addTag/removeTag persistent
Added lvm_vg_write in the addTag/removeTag paths to make the
changes persist.  Added unit test to ensure functionality.

https://bugzilla.redhat.com/show_bug.cgi?id=1210020

Signed-off-by: Tony Asleson <tasleson@redhat.com>
2015-04-10 10:38:43 -05:00
Peter Rajnoha
394250ef67 report: lv_metadata_size, data_lv and metadata_lv also reports properties for cache pools 2015-04-10 14:55:28 +02:00
Peter Rajnoha
463fd954bb config: add note about 'vsn' macro use in config_settings.h 2015-04-10 09:51:08 +02:00
David Teigland
4eaa399b54 config: comments update
missing \n
2015-04-09 16:35:20 -05:00
David Teigland
303c5ba803 config: update description
Remove examples that simply replicate the default shown.
2015-04-09 16:09:53 -05:00
David Teigland
6f3f421228 config: include full comments
Comments from the sample config files are copied into
the comment field of the config settings structure.
This includes only minimal changes to the text.

With this in place, the sample config files can
be generated from 'lvm dumpconfig', and content
for an lvm.conf man page can also be generated.
2015-04-09 15:35:28 -05:00
Alasdair G Kergon
a9d48bae2f cache: Set correct vgid when changing PV header.
pv_write is called both to write orphans and to rewrite PV headers
of PVs in VGs.  It needs to select the correct VG id so that the
internal cache state gets updated correctly.

It only affected commands that involved further steps after
the pv_write and was often masked because the metadata would
be re-read off disk and correct itself.

"Incorrect metadata area header checksum" warnings appeared.

Example:
  Create vg1 containing dev1, dev2 and dev3.
  Hide dev1 and dev2 from the system.
  Fix up vg1 with vgreduce --removemissing.
  Bring back dev1 and dev2.
  In a single operation reinstate dev1 and dev2 into vg1 (vgextend).
Done as separate operations (automatically fix-up dev1 and dev2 as orphans,
then vgextend) it worked, but done all in one go the internal cache got
corrupted and warnings about checksum errors appeared.
2015-04-09 21:13:55 +01:00
Zdenek Kabelac
249d4a921c tests: extend delay
400 was appeared to be good value in pvmove-abort.sh
so use also in abort-all.
2015-04-09 13:16:53 +02:00
Zdenek Kabelac
1a7c9ce3bd tests: handle debug.log from clvmd
When clvmd starts, it starts it's own command logging into debug.log.
This is interferring with our other command debug.log.
As as sideeffect we may experience log from command,
followed but lots of zeros and continued with clvmd log.

Fix it by renaming debug.log and now we could also print this trace
to get full list of clvmd activity nicely.

Also improve some post-mortem prints from udevadm and dmsetup to
make the output more usable.
2015-04-09 13:13:36 +02:00
Zdenek Kabelac
073643c9a2 tests: slowdown write on dev3 even more 2015-04-08 23:19:38 +02:00
Zdenek Kabelac
ebde60beab tests: use single lvmconf call 2015-04-08 23:19:37 +02:00
Zdenek Kabelac
a5b34f0f1b tests: put "" around dev path 2015-04-08 23:19:37 +02:00
Zdenek Kabelac
4459413225 clvmd: singlenode signals only when lock changes
There is no benefit in waking-up all the waiters
when there is no actual change in lock state.
This avoid some unnecessarily ping-pong effects like:

 Resource V_LVMTEST15724vg retrying lock in mode:WRITE...
 Resource V_LVMTEST15724vg already locked lockid=40, mode:WRITE
 Resource V_LVMTEST15724vg retrying lock in mode:WRITE...
 Resource V_LVMTEST15724vg already locked lockid=40, mode:WRITE
2015-04-08 23:19:34 +02:00
Peter Rajnoha
f32973c78e select: mention { } use in lvm.8 man page and '-S help' properly 2015-04-08 11:14:16 +02:00
Zdenek Kabelac
8fdca0de79 tests: check scsi_debug support opt_blks
Some older kernels (i.e. lenny) do not have such options.
2015-04-07 14:59:13 +02:00
Heinz Mauelshagen
035276ab83 lvcreate: do not silently accept '-m #' with raid4/5/6
If the user provides '-m #' (# > 0) with mappings
raid4/5/6, the command silently creates
'#mirrors * #stripes + #parity' image component pairs.

Patch rejects '-m #' altogether for those mappings
in order to avoid LV creation with unexpected layout.

- resolves bz#1209445
2015-04-07 14:32:25 +02:00
Zdenek Kabelac
64353ff74b tests: when test fails collect more info
In some case it might be worth to know some more surrouding info
when command has crashed.

So collect  tables and some udev db content in this case.
2015-04-07 13:40:15 +02:00
Zdenek Kabelac
ba049e203b tests: skip clvmd testing of mirrored LV vgsplit
There is something wrong when even inactive LV can't be splitted
without cmirrord being present for clustered VG.
2015-04-03 20:14:26 +02:00
Zdenek Kabelac
87cb0a3e9f tests: change default to 30s.
Keep rather the default lower and avoid to pass it with every call.
2015-04-03 19:40:43 +02:00
Zdenek Kabelac
32a0f625a5 tests: slow down devices in outer loop
Since now we have metadata parts running with normal speed,
we could avoid reinitilising delayed dev for every test.
(Saving seconds on cookie waits...)
2015-04-03 19:40:42 +02:00
Zdenek Kabelac
4f94669eca pvmove: don't crash when name is not found
If the device name is not found in our metadata,
we cannot call strdup few lines later with NULL name.

More intersting story goes behind how it happens -
pvmove removal is unfortunatelly 'multi-state' process
and at some point (for now)  we have in lvm2 metadata
LV  pvmove0 as stripe  and mirror image as error.

If such metadata are left - we fail with any further removal.
2015-04-03 17:18:11 +02:00
Zdenek Kabelac
c88ffbf9df tests: delay only data portion of device 2015-04-03 17:18:11 +02:00
Zdenek Kabelac
93ab6d5184 tests: better check for empty set
Even when no arg is passed - there is still one "" arg there...
So taky it easy and check for empty string instead.
2015-04-03 16:38:05 +02:00
Zdenek Kabelac
ce3c61c4af tests: delay only data area 2015-04-03 14:54:22 +02:00
Zdenek Kabelac
385457de23 tests: test update
Really wait till fsck is running (sleep 2 is not ideal)
Use new  'delay_dev'.
2015-04-03 14:54:22 +02:00
Zdenek Kabelac
d3a591a7b3 tests: hide unwanted output 2015-04-03 14:54:22 +02:00
Zdenek Kabelac
dc41859220 tests: enhance delay_dev
Use common code for error_dev & delay_dev.
Both functions now take list of sectors.

From now on we could delay just 'extent' section, while
keeping running  lvm commands fast (having native metadata area).
2015-04-03 14:53:36 +02:00
Zdenek Kabelac
bd84389c68 tests: add get first_extent_sector
Trvial function to figure out sector position of 1st. extent.
2015-04-03 14:20:03 +02:00
Zdenek Kabelac
308f9bcc18 tests: simplify check sysfs_queue
Pass just device name and let figure out
sysfs path inside the function.
2015-04-03 10:27:00 +02:00
Zdenek Kabelac
a701d337d4 tests: slowdown pvmove devs more
Once pvmove is running - slow it even more
since some test machines tend to be very very slow.
2015-04-02 16:02:06 +02:00
Zdenek Kabelac
1966025245 tests: split bigger test
Use separate new test and avoid teardown_devs
in the middle of single test.
2015-04-02 16:01:01 +02:00
Zdenek Kabelac
a16324b0d3 tests: drop check for awk 2015-04-02 13:38:41 +02:00
Zdenek Kabelac
ee65528547 tests: fix test warning
We cannot print TEST WARNING within test shell script
(since it's running in debug mode and thus always prints it)

Use 'should false' trick let the string printed in this case.
So 'non cluster cases' should now end properly.
2015-04-02 13:38:41 +02:00
Zdenek Kabelac
536f5fa0a3 tests: deal with kernel and broken lcm
If the kernel has 'new lcm()' (3.19) it provides wrong
optimal_io_size value for dm device so lvm2 command cannot
create properly aligned devices.

Use 'should' for this case - so test ends with 'TEST WARNING'.
2015-04-02 13:38:41 +02:00
Zdenek Kabelac
7a6e3838e9 tests: add check sysfs_queue
Add check function for content of /sys/block/$1/queue/$2 == $3
2015-04-02 13:38:41 +02:00
Zdenek Kabelac
95dbedb301 tests: move exa test to separate file
Make it visible the 'exa' test passed on an arch.
2015-04-02 13:38:41 +02:00
Zdenek Kabelac
6d1c9a0eb8 tests: more duplicate testing 2015-04-02 13:38:41 +02:00
Zdenek Kabelac
53ef14fca0 debug: log scanned value
Fix verbose print of scanned value for topology attribute.
Result is set afterwards in sectors.
2015-04-02 13:38:41 +02:00
Zdenek Kabelac
e28e22b9e1 lvmcache: skip drop when vg_write lock is not held
Commit 80f4b4b803
introduced undesirable side-effects for lvm2app user
which happens to be our own python binding.

It appear obtaing pvs list keeps global lock.

So restricting this to VG_GLOBAL READ locks and skip
the drop skip if WRITE lock is held.
2015-04-02 13:38:32 +02:00
Ondrej Kozina
f199aeb9ea polldaemon: alter few lines related to interval
we do not allow 0 interval for pvmove command issued
without parameters with classical polldaemon. It would
query the kernel too often with possibly many pvmoves
in-progress.
2015-04-01 20:41:52 +02:00
Ondrej Kozina
7abb7894e4 polldaemon: separate daemon_parms initialisation 2015-04-01 20:41:39 +02:00
Ondrej Kozina
3929b00466 polldaemon: prepare wrapper poll_daemon function
with lvmpolld we'll have two polldaemon implementations
2015-04-01 20:41:30 +02:00
Ondrej Kozina
65623b63a2 pvmove: split pvmove_update_metadata function
So far pvmove_update_metadata (originaly _update_metadata) was
used for both initial and subsequent metadata updates during polling.
With a new polldaemon (lvmpolld) all operations that require polling
have to be split in two parts: The initiating one and the polling one.
The later step will be used from lvm command spawned by lvmpolld to
monitor and advance the mirror on next segment if required.

1) The initiation part is _update_metadata in pvmove.c which performs
only the first update, setting up the pvmove itself in metadata.

2) pvmove_update_metadata in pvmove_poll.c now handles all other
subsequent metadata updates except the last one.

Due to the split we could remove some code. Also some functions were
moved back to pvmove.c as they were suited for initialisation of pvmove
only.
2015-04-01 20:41:03 +02:00
Ondrej Kozina
5190f56605 lvconvert: move poll code in before refactoring
This commit has no impact on functionality. Code required to
be visible outside lvconvert.c is just moved into new file
lvconvert_poll.c and some calls are made non-static and
declared in new header file lvconvert.h
2015-04-01 20:40:50 +02:00
Ondrej Kozina
a098aa419f pvmove: move poll code in before refactoring
This commit has no impact on functionality. Code required to
be visible outside pvmove.c is just moved into new file
pvmove_poll.c and some calls are made non-static and declared in
new header file pvmove.h
2015-04-01 20:40:39 +02:00
David Teigland
bf2d831e7e tests: add clvm case to system_id.sh 2015-03-31 14:45:14 -05:00
Peter Rajnoha
20c6192fbb systemd: stop lvm2-monitor.service before dm-event.service 2015-03-31 15:50:16 +02:00
Michael Lass
666738d57a systemd: stop lvm2-pvscan@.service before lvm2-lvmetad.service
When lvm2-pvscan@.service and lvm2-lvmetad.service are scheduled to be
stopped lvm2-pvscan@.service should be stopped first since pvscan uses
lvmetad.

This is especially important if lvm2-lvmetad.socket is also scheduled to
be stopped as in this case connection requests are suppressed causing
pvscan to fail.
2015-03-31 15:47:01 +02:00
Michael Lass
139df7c4a3 README: fix link to lvm-devel mailing list 2015-03-31 15:44:00 +02:00
Peter Rajnoha
974a029a8a lvm.conf: fix typo as -> is in read_only_volume_list comments 2015-03-31 15:38:29 +02:00
Ondrej Kozina
04826db7c4 polldaemon: fix indentation in _poll_vg fn 2015-03-31 13:16:01 +02:00
Ondrej Kozina
663254d7a5 polldaemon: proper error check in _poll_vg fn
could theoretically cause NULL pointer dereference
2015-03-31 11:26:53 +02:00
Ondrej Kozina
b9e6e66de1 tests: add pvmove --abort for all moves in progress
test for bug described in c282a66132
2015-03-30 18:39:30 +02:00
Ondrej Kozina
5f7428e4d5 tests: add pvmove --abort test
test for bug described in c282a66132
2015-03-30 18:39:24 +02:00
Ondrej Kozina
c282a66132 pvmove: fix pvmove --abort or pvmove w/o parameters
_check_lv_status was called from within dm_list_iterate_items cycle.
This was utterly wrong! _check_lv_status may remove more than one LV from
vg->lvs list we iterated in the same time.

In some scenarios this could lead to deadlock iterationg over same LV
indefinitely or segfault depending on the circumstances.

Fixed by moving the _check_lv_status outside iterating the vg->lvs
list.

Note that commit 6e7b24d34f was not enough
as _check_lv_status may result in removal of more than one LV from the list.
2015-03-30 18:38:50 +02:00
Ondrej Kozina
7c66850ce5 tests: add helper routine for pvmove status check 2015-03-30 18:38:50 +02:00
Ondrej Kozina
c8caa04b1c tests: fix check for existence of a pvmove Lv 2015-03-30 18:38:50 +02:00
Alasdair G Kergon
f1e3e99169 alloc: Log PV tags when reserving areas. 2015-03-26 21:13:26 +00:00
Alasdair G Kergon
e8fa3354f0 alloc: Pass alloc_handle through to _reserve_area. 2015-03-26 20:32:59 +00:00
Alasdair G Kergon
f9d74ba3d1 alloc: Only report cling tag errors once. 2015-03-26 19:43:51 +00:00
Alasdair G Kergon
4b1219ee87 metadata: Move alloc_handle init/destroy fns. 2015-03-26 18:44:24 +00:00
Alasdair G Kergon
9506760c7e datastruct: Add str_list_add_list. 2015-03-26 18:30:37 +00:00
Zdenek Kabelac
8a87fadbb0 tests: drop vg2 at end of test 2015-03-26 16:11:29 +01:00
Zdenek Kabelac
22d43ee14a tests: skip system_id test in cluster
Let's see what we can do in cluster for system_id,
until resolved skip test for check_cluster.
2015-03-26 16:10:48 +01:00
Zdenek Kabelac
147b0a1700 tests: pvmove better delay check
Improve testing for condition that pvmove0 is already running in the
table (so we do not kill pvmove while it has loaded target, but
it's not yet Live).

Also delay_dev for 200ms.
2015-03-26 16:03:24 +01:00
Zdenek Kabelac
d24b6cfb1f tests: temporarily trace prepare_vg 2015-03-26 15:11:15 +01:00
Zdenek Kabelac
f08154cc7b tests: update aux
When we use /dev/loopX device - shift first PV1 sector by 1M
so /dev/loop0 and dm device do not appear as same device.

Also notify lvmetad once 'devs' are created - so in case this
command is called in the middle of test - lvmetad properly
drops its metadata for these devices.

Drop used test.img file between reuse so the 'prepare_vg'
always starts with zeroed disks.

When LVM_TEST_AUX_TRACE is set, allow shell tracing of aux commands.
2015-03-26 15:10:31 +01:00
Zdenek Kabelac
b7ebab7657 tests: avoid multiple pids
On some systems (parisc) pgrep prints more then 1 pid
(all thread IDs are printed)
So print only leading pid and avoid 'kill' being confused.
2015-03-26 15:10:04 +01:00
Peter Rajnoha
0bffd99daa tests: move thin-related test from select-tools.sh to select-tools-thin.sh
And skip this test if thin target is not available.
2015-03-24 10:12:27 +01:00
Peter Rajnoha
9dbe2d760f tests: select-tools.sh: add test for fix in commit c9f021de0b 2015-03-24 09:50:35 +01:00
Peter Rajnoha
8759f7d755 metadata: vg: add removed_lvs field to collect LVs which have been removed
Do not keep dangling LVs if they're removed from the vg->lvs list and
move them to vg->removed_lvs instead (this is actually similar to already
existing vg->removed_pvs list, just it's for LVs now).

Once we have this vg->removed_lvs list indexed so it's possible to
do lookups for LVs quickly, we can remove the LV_REMOVED flag as
that one won't be needed anymore - instead of checking the flag,
we can directly check the vg->removed_lvs list if the LV is present
there or not and to say if the LV is removed or not then. For now,
we don't have this index, but it may be implemented in the future.
2015-03-24 08:43:08 +01:00
Peter Rajnoha
c9f021de0b metadata: process_each_lv_in_vg: get the list of LVs to process first, then do the processing
This avoids a problem in which we're using selection on LV list - we
need to do the selection on initial state and not on any intermediary
state as we process LVs one by one - some of the relations among LVs
can be gone during this processing.

For example, processing one LV can cause the other LVs to lose the
relation to this LV and hence they're not selectable anymore with
the original selection criteria as it would be if we did selection
on inital state. A perfect example is with thin snapshots:

$ lvs -o lv_name,origin,layout,role vg
  LV    Origin Layout      Role
  lvol1        thin,sparse public,origin,thinorigin,multithinorigin
  lvol2 lvol1  thin,sparse public,snapshot,thinsnapshot
  lvol3 lvol1  thin,sparse public,snapshot,thinsnapshot
  pool         thin,pool   private

$ lvremove -ff -S 'lv_name=lvol1 || origin=lvol1'
  Logical volume "lvol1" successfully removed

The lvremove command above was supposed to remove lvol1 as well as
all its snapshots which have origin=lvol1. It failed to do so, because
once we removed the origin lvol1, the lvol2 and lvol3 which were
snapshots before are not snapshots anymore - the relations change
as we're processing these LVs one by one.

If we do the selection first and then execute any concrete actions on
these LVs (which is what this patch does), the behaviour is correct
then - the selection is done on the *initial state*:

$ lvremove -ff -S 'lv_name=lvol1 || origin=lvol1'
  Logical volume "lvol1" successfully removed
  Logical volume "lvol2" successfully removed
  Logical volume "lvol3" successfully removed

Similarly for all the other situations in which relations among
LVs are being changed by processing the LVs one by one.

This patch also introduces LV_REMOVED internal LV status flag
to mark removed LVs so they're not processed further when we
iterate over collected list of LVs to be processed.

Previously, when we iterated directly over vg->lvs list to
process the LVs, we relied on the fact that once the LV is removed,
it is also removed from the vg->lvs list we're iterating over.
But that was incorrect as we shouldn't remove LVs from the list
during one iteration while we're iterating over that exact list
(dm_list_iterate_items safe can handle only one removal at
one iteration anyway, so it can't be used here).
2015-03-24 08:43:07 +01:00
Alasdair G Kergon
83587f0555 post-release 2015-03-24 02:02:07 +00:00
Alasdair G Kergon
8bb1dfdd32 pre-release 2015-03-24 01:59:35 +00:00
Ondrej Kozina
192a83def3 tests: add omitted --atomic mode in pvmove-restart 2015-03-23 14:55:13 +01:00
Peter Rajnoha
6e7b24d34f pvmove: use safe version of iteration when iterating over vg->lvs list in _poll_vg
When we're iterating over LVs in _poll_vg fn, we need to use the safe
version of iteration - the LV can be removed from the list which we're
just iterating over if we're finishing or aborting pvmove operation.
2015-03-23 13:40:39 +01:00
Zdenek Kabelac
361e2d8df7 tests: revert should removal in mirror test
Since cluster test was actually not been working,
removal of should has been premature.
So restore 'should' back - bug in mirror code is still there.
2015-03-20 11:08:44 +01:00
Zdenek Kabelac
21343ffbfe tests: start clvmd without lib/ 2015-03-20 11:08:21 +01:00
Alasdair G Kergon
a515a91fcc format_text: Fix precommitted segfault.
The code never mixes reads of committed and precommitted metadata,
so there's no need to attempt to set PRECOMMITTED when
*use_previous_vg is being set.
2015-03-19 11:14:47 +00:00
Zdenek Kabelac
e4fa756385 tests: export shell vars
Export vars so they are visible in  'aux' calls as well.
(reenables cluster testing)
2015-03-19 11:23:44 +01:00
Zdenek Kabelac
a13d261466 makefiles: add more dirs for lcov
lvmetad lcovered.
2015-03-19 10:24:34 +01:00
Alasdair G Kergon
6407d184d1 cache: Store metadata size and checksum.
Refactor the recent metadata-reading optimisation patches.

Remove the recently-added cache fields from struct labeller
and struct format_instance.

Instead, introduce struct lvmcache_vgsummary to wrap the VG information
that lvmcache holds and add the metadata size and checksum to it.

Allow this VG summary information to be looked up by metadata size +
checksum.  Adjust the debug log messages to make it clear when this
shortcut has been successful.

(This changes the optimisation slightly, and might be extendable
further.)

Add struct cached_vg_fmtdata to format-specific vg_read calls to
preserve state alongside the VG across separate calls and indicate
if the details supplied match, avoiding the need to read and
process the VG metadata again.
2015-03-18 23:43:02 +00:00
Alasdair G Kergon
19c3851d9c toollib: Reorder process_each_pv initialisation.
Perform cheaper command line-based validation before more-expensive
processing and scanning.
2015-03-18 23:34:46 +00:00
Alasdair G Kergon
5bf74f2997 pvs: Hide inaccessible clustered PVs.
Inaccessible clustered PVs can be hidden from pvs -a in the same way as
foreign PVs, rather than showing them as if they do not belong to a VG.
2015-03-18 23:31:46 +00:00
Alasdair G Kergon
87941ccd17 systemid: Use correct mempool.
libmem is necessary when this ends up in cmd->system_id.
2015-03-18 23:25:30 +00:00
Alasdair G Kergon
80f4b4b803 cache: Retain orphans while global lock held.
Fixes segfault when 'pvs' encounters two different PVs sharing the same
uuid but one an orphan, the other in a VG.

If VG_GLOBAL is held, there seems no point in doing a full scan more
than once.

If undesirable side-effects show up, we can try restricting this to
VG_GLOBAL READ locks.  The original code dates back to 2.02.40.
2015-03-18 23:20:09 +00:00
Zdenek Kabelac
32a6c11877 pvscan: check sysfs dev entry before rescan
When pvscan --cache --major --minor command is issued from
udev REMOVE event, it basically resulted into a whole device
scan since the device was missing. So avoid such scan
and first check via /sysfs (when available) if such device actually
exists.
2015-03-18 16:19:58 +01:00
Zdenek Kabelac
1260b86b2b config: use timestamp with nanosecond precision
Since kernel 2.6 we can use more precise timestamping,
so e.g. we could better recognize configs are slightly
older then generated .cache file.
2015-03-18 13:42:56 +01:00
Zdenek Kabelac
6606b1bff3 lvm-file: wrapper to read ctim from stat
When available use nanosecond stat info.

If commands are running closely enough after config update,
the .cache file from persistent filter could have been ignored.

This happens sometimes during i.e. synthetic test suite run.
2015-03-18 13:42:24 +01:00
Zdenek Kabelac
17583f1b59 configure: detect st_ctim
Check stat has nanosecond precision for ctim.
2015-03-18 13:42:24 +01:00
Zdenek Kabelac
a10a11bd54 lvchange: disable persistent minors for pools
There is no reason to support persistent major/minor numbers
for pool volumes - it's only meant to be supported for filesystems
(since i.e. nfs may need to keep volume on a persistent device node.)

Support for pools is now explicitely disabled and documented.
2015-03-18 13:42:13 +01:00
Alasdair G Kergon
95fbbf4f40 metadata: Fix recent vg_validate message text. 2015-03-17 17:48:56 +00:00
Peter Rajnoha
038013cf42 lvmetad: pvscan: do not scan and read ignored MDAs from PVs
Metadata areas which are marked as ignored should not be scanned
and read during pvscan --cache. Otherwise, this can cause lvmetad
to cache out-of-date metadata in case other PVs with fresh metadata
are missing by chance.

Make this to work like in non-lvmetad case where the behaviour would
be the same as if the PV was orphan (in case we have no other PVs
with valid non-ignored metadata areas).
2015-03-16 17:00:36 +01:00
Zdenek Kabelac
ff5217f850 tests: add ""
Add missing "" around 'devs' (since they could
theoritically constain spaces in its name - not
likely supported with udev these day but anyway....)
2015-03-16 15:06:05 +01:00
Zdenek Kabelac
36bcbeadd0 tests: fix select report
Simplify the function usage and clean up parameter parsing.

There were 2 significant changes made in the test itself
(they passed before because of incorrect shell string handling)

-pvs_sel 'tags="pv_tag1"' "$dev1 $dev2"
+sel pv 'tags="pv_tag1"' "$dev1" "$dev6"

-lvs_sel '(lv_name=vol1 || lv_name=vol2) || vg_tags=vg_tag1' "vol1 vol2
abc orig snap"
+sel lv '(lv_name=vol1 || lv_name=vol2) || vg_tags=vg_tag1' vol1 vol2
orig snap xyz
2015-03-16 15:02:39 +01:00
Zdenek Kabelac
0e1d1aaca8 tests: check for dmeventd first
Check there is no dmeventd before creating vg.
2015-03-16 12:26:00 +01:00
Zdenek Kabelac
e6a69af2d7 tests: drop unused "" 2015-03-13 12:12:54 +01:00
Peter Rajnoha
05f23e7763 systemd: blk-availability.service: add After=iscsi-shutdown.service
The iscsi-shutdown.service is the one responsible for logging out
iscsi sessions so blk-availability.service (running the blkdeactivate
script) should be run before that on shutdown (so we need to use
After=iscsi-shutdown.service because "After" relates to starting
the service and the opposite order is automatically applied on
stopping the service at shutdown).
2015-03-13 12:08:20 +01:00
Zdenek Kabelac
c6d96efc38 tests: few more warnings for gcc only
g++ doesn't like them.
2015-03-12 00:12:15 +01:00
Zdenek Kabelac
eded54df7b tests: avoid loop on older system
Cleanup overload of 'push'.
Don't busy-loop when reading is finished.
2015-03-12 00:07:45 +01:00
Zdenek Kabelac
26f5ec0e98 tests: update runner
Avoid busy-looping on CPU while reading socket pipe
and always call read only when select tells there is
something for read.

Change the batch output to old nicer output.
2015-03-11 21:17:23 +01:00
Zdenek Kabelac
1ad9677cb3 tests: update makefile
Respect $LVM_TEST_RESULT dir
Share same target for  clean: & distclean:
Cleanup path-common
2015-03-11 21:17:23 +01:00
Zdenek Kabelac
bbe4f7e4c5 tests: drop unneeded comment 2015-03-11 21:17:23 +01:00
Zdenek Kabelac
243a135fe9 tests: capture and print thrown errors 2015-03-11 21:17:23 +01:00
Zdenek Kabelac
bdf4e3e2f2 tests: do not leak in mem in destructor 2015-03-11 21:17:23 +01:00
Zdenek Kabelac
e7e499e80f makefiles: split gcc -W options
Avoid using gcc only Warnings for compilation of g++ object files.
2015-03-11 21:17:23 +01:00
Zdenek Kabelac
8a2b9f045f tests: extend race
Mark test as skipped, if the test could not be made.
2015-03-11 11:02:35 +01:00
Zdenek Kabelac
ed2dcb796f tests: drop old workaround
Should be usable now without this 'should'.
2015-03-11 11:02:35 +01:00
Zdenek Kabelac
a042678a83 tests: specify old mirror type
Use old mirror (otherwise it would need  aux have_raid)
2015-03-11 11:02:35 +01:00
Zdenek Kabelac
6cecf61cc3 tests: cleanup some cxx warnings 2015-03-11 11:02:35 +01:00
Zdenek Kabelac
3f7e62b340 tests: enable kmsg by default
By default we want to capture kernel log into test trace
(since when test crashes it could be problem to reproduce).
2015-03-11 11:02:35 +01:00
Zdenek Kabelac
db5166fbfa tests: extend test timeout to 180sec
Some test could take more then minute (with slow udev and slow
emulation) - extend timeout to 180sec.
2015-03-11 11:02:35 +01:00
David Teigland
760cebf47d reporting: should not fail with foreign option if lvm1 pvs exist
When lvm1 PVs are visible, and lvmetad is used, and the foreign
option was included in the reporting command, the reporting
command would fail after the 'pvscan all devs' function saw
the lvm1 PVs.  There is no reason the command should fail
because of the lvm1 PVs; they should just be ignored.
2015-03-10 13:56:25 -05:00
David Teigland
c7290759b0 tests: update to not run vgconvert -M with lvmetad 2015-03-10 09:59:52 -05:00
David Teigland
f5cc96a54e WHATS_NEW vgconvert -M fix 2015-03-10 09:38:43 -05:00
David Teigland
321e19d9cc vgconvert: require lvmetad to not be used
lvmetad does not work with lvm1/format1 metadata,
and vgconvert -M converts to or from lvm1 metadata,
so disallow vgconvert -M when lvmetad is used.
2015-03-10 09:31:54 -05:00
Ondrej Kozina
5dbcbbea58 libdaemon: map error level properly
internal daemon error log level was wrongly mapped to debug syslog
level causing most error messages were lost in non-debug mode.
2015-03-10 14:42:40 +01:00
Zdenek Kabelac
0982c5c79f configure: check for sync-nand
Check whether gcc support this flag.
Some older compilers (gcc version 4.3.2) miss it.
2015-03-10 14:10:18 +01:00
Zdenek Kabelac
47b704462e display: fix return values
Return 1 on success in pvdisplay_short() and lvdisplay_full()
so commands like vgdisplay are not printinig stracktraces
on successful passes.

As the results of fail/success have been internally ignored for those
calls, it had no other visible side effect - command's return value was
still 0 (success).
2015-03-10 14:10:18 +01:00
Alasdair G Kergon
1d3711c0b2 format_text: Set system id directly.
Rearrange _read_vg code to set the appropriate system id field directly.
2015-03-09 19:33:27 +00:00
Alasdair G Kergon
379d9ec8ec systemid: Use temp status var for LVM_WRITE_LOCKED 2015-03-09 19:18:14 +00:00
Alasdair G Kergon
458b0210d1 vgchange: Additional system ID warnings.
Also prompt before setting a system ID on a VG when none is set
on the host.
Put quotes round system ID in messages where it could be blank.
2015-03-09 19:03:11 +00:00
Alasdair G Kergon
1334ea214e vgconvert: Check system ID compatibility.
If system ID is set, don't switch to a format that doesn't support it.
2015-03-09 19:01:12 +00:00
Alasdair G Kergon
a854546234 metadata: Detect internal use of LVM_WRITE_LOCKED.
Generate internal error if LVM_WRITE_LOCKED ever appears
in struct volume_group: it's only used in external
metadata.
2015-03-09 18:56:24 +00:00
Alasdair G Kergon
faccdeda83 comments: Use full flag names. 2015-03-09 18:53:22 +00:00
David Teigland
e9a233ee8e system_id: detect an lvm1 system id
Detect an lvm1 system id by looking at the WRITE_LOCKED flag.
Don't copy this lvm1 system id into vg->system_id so that the
restrictions associated with the new system id are not applied
to the old VG with the inherited lvm1 system id.
2015-03-09 13:27:34 -05:00
David Teigland
08371a8b80 tests: fix systemid uname test
The string reported by uname -n may include characters
that lvm omits from the system id (like parens, as seen
on a test machine.)  Check against the final system id
string that lvm uses.
2015-03-06 09:57:37 -06:00
Zdenek Kabelac
588b3bd7a1 tests: speed of many PVS in a VG 2015-03-06 14:29:26 +01:00
Zdenek Kabelac
85ef614b37 tests: slightly more efficient vgcreate
With larger set of devices it's faster to directly call
vgcreate on empty set of devices then going though separate
pvcreate call first.
2015-03-06 14:05:06 +01:00
Zdenek Kabelac
04101bc430 lib: drop unneeded vg_read call
Since we take a lock inside vg_lock_newname() and we do a full
detection of presence of  vgname inside all scanned labels,
there is no point to do this for second time to be sure
there is no such vg.

The only side-effect of such call would be a full validation of
some already exising VG metadata - but that's not the task for
vgcreate when create a new VG.

This call noticable reduces number of scans during 'vgcreate'.
2015-03-06 14:05:06 +01:00
Zdenek Kabelac
a9b28a4f21 lib: reduce parsing in vgname_from_mda
Use similar logic as with text_vg_import_fd() and avoid repeated
parsing of same mda and its config tree for vgname_from_mda().

Remember last parsed vgname, vgid and creation_host in labeller
structure and if the  metadata have the same size and checksum,
return this stored info.

TODO: The reuse of labeller struct is not ideal, some lvmcache API for
this functionality would be nicer.
2015-03-06 13:53:13 +01:00
Zdenek Kabelac
7e7411966a lib: avoid reparsing same metadata
When reading VG mda from multiple PVs - do all the validation only
when mda is seen for the first time and  when mda checksum and length
is same just return already existing VG pointer.

(i.e. using 300PVs for a VG would lead to create and destroy 300 config trees....)
2015-03-06 13:53:12 +01:00
Zdenek Kabelac
6a2ae250ff cleanup: add stack trace
Missed stack in error path.
2015-03-06 13:51:54 +01:00
Zdenek Kabelac
60427d5d42 lib: return value
Drop label out: with goto and return NULL directly.
Add log_debug() for zero metadata offset.
2015-03-06 13:51:43 +01:00
Zdenek Kabelac
4d16bfaabb lib: zero returned labeller struct
Return zeroed struct.
(Structure will be extended, so ensure all members are initilized.)
2015-03-06 13:17:39 +01:00
Zdenek Kabelac
6f68f4364b devices: avoid extra open() syscall
If the device is already opened by lvm's device cache,
avoid extra syscall opening devices for obtaining its size.
2015-03-06 13:17:39 +01:00
David Teigland
b48ff3b94e man: add info to lvmsystemid
about losing access to a VG if lvm is downgraded
to an earlier version.
2015-03-05 12:12:42 -06:00
David Teigland
5e25bca1a9 system_id: avoid munging vg and lv fields
Munge the WRITE/WRITE_LOCKED flags in a temp variable
instead of in the vg/lv fields.
2015-03-05 10:23:16 -06:00
David Teigland
8bb76aea81 system_id: undo the previous changes to the lvm1 code
The system_id and lock_type compat changes do not apply
to the lvm1 code.
2015-03-05 10:13:05 -06:00
David Teigland
1e65fdd9ba system_id: make new VGs read-only for old lvm versions
Previous versions of lvm will not obey the restrictions
imposed by the new system_id, and would allow such a VG
to be written.  So, a VG with a new system_id is further
changed to force previous lvm versions to treat it as
read-only.  This is done by removing the WRITE flag from
the metadata status line of these VGs, and putting a new
WRITE_LOCKED flag in the flags line of the metadata.

Versions of lvm that recognize WRITE_LOCKED, also obey the
new system_id.  For these lvm versions, WRITE_LOCKED is
identical to WRITE, and the rules associated with matching
system_id's are imposed.

A new VG lock_type field is also added that causes the same
WRITE/WRITE_LOCKED transformation when set.  A previous
version of lvm will also see a VG with lock_type as read-only.

Versions of lvm that recognize WRITE_LOCKED, must also obey
the lock_type setting.  Until the lock_type feature is added,
lvm will fail to read any VG with lock_type set and report an
error about an unsupported lock_type.  Once the lock_type
feature is added, lvm will allow VGs with lock_type to be
used according to the rules imposed by the lock_type.

When both system_id and lock_type settings are removed, a VG
is written with the old WRITE status flag, and without the
new WRITE_LOCKED flag.  This allows old versions of lvm to
use the VG as before.
2015-03-05 09:50:43 -06:00
David Teigland
c6a57dc4f3 Revert "systemid: Add ACCESS_NEEDS_SYSTEM_ID VG flag."
This reverts commit bfbb5d269a.

This will be done differently.
2015-03-05 09:50:43 -06:00
David Teigland
06b408ecce system_id: enable the options in config file and command line 2015-03-05 09:50:43 -06:00
Peter Rajnoha
190d591fbe report: fix seg_monitor field to display monitoring status for thick snapshots and mirrors
The seg_monitor did not display monitored status for thick snapshots
and mirrors (with mirror log *not* mirrored). The seg monitor did work
correctly even before for other segtypes - thins and raids.

Before (mirrors and snapshots, only mirrors with mirrored log properly displayed monitoring status):

[0] f21/~ # lvs -a -o lv_name,lv_layout,lv_role,seg_monitor vg
  LV                                     Layout     Role                             Monitor
  mirror                                 mirror     public
  [mirror_mimage_0]                      linear     private,mirror,image
  [mirror_mimage_1]                      linear     private,mirror,image
  [mirror_mlog]                          linear     private,mirror,log

  mirror_with_mirror_log                 mirror     public                           monitored
  [mirror_with_mirror_log_mimage_0]      linear     private,mirror,image
  [mirror_with_mirror_log_mimage_1]      linear     private,mirror,image
  [mirror_with_mirror_log_mlog]          mirror     private,mirror,log               monitored
  [mirror_with_mirror_log_mlog_mimage_0] linear     private,mirror,image
  [mirror_with_mirror_log_mlog_mimage_1] linear     private,mirror,image

  thick_origin                           linear     public,origin,thickorigin
  thick_snapshot                         linear     public,snapshot,thicksnapshot

With this patch applied (monitoring status displayed for all mirrors and snapshots):

[0] f21/~ # lvs -a -o lv_name,lv_layout,lv_role,seg_monitor vg
  LV                                     Layout     Role                             Monitor
  mirror                                 mirror     public                           monitored
  [mirror_mimage_0]                      linear     private,mirror,image
  [mirror_mimage_1]                      linear     private,mirror,image
  [mirror_mlog]                          linear     private,mirror,log

  mirror_with_mirror_log                 mirror     public                           monitored
  [mirror_with_mirror_log_mimage_0]      linear     private,mirror,image
  [mirror_with_mirror_log_mimage_1]      linear     private,mirror,image
  [mirror_with_mirror_log_mlog]          mirror     private,mirror,log               monitored
  [mirror_with_mirror_log_mlog_mimage_0] linear     private,mirror,image
  [mirror_with_mirror_log_mlog_mimage_1] linear     private,mirror,image

  thick_origin                           linear     public,origin,thickorigin
  thick_snapshot                         linear     public,snapshot,thicksnapshot    monitored
2015-03-05 14:05:34 +01:00
Alasdair G Kergon
56606b5f21 post-release 2015-03-04 14:00:46 +00:00
Alasdair G Kergon
930fa3290d pre-release 2015-03-04 13:49:51 +00:00
Peter Rajnoha
a7bfc2cbb5 cleanup: tools: "or use -S for selection" --> "or use --select for selection" 2015-03-04 14:40:58 +01:00
Alasdair G Kergon
733bfe36f5 systemid: Disable --systemid.
Disable use of --systemid for this release.
2015-03-04 13:14:51 +00:00
Peter Rajnoha
67c52a4453 config: add CFG_DISABLED flag and mark system_id settings with that flag
If configuration setting is marked in config_setting.h with CFG_DISABLED
flag, default value is always used for such setting, no matter if it's defined
by user (in --config/lvm.conf/lvmlocal.conf).

A warning message is displayed if this happens:

For example:

[1] f21/~ # lvm dumpconfig --validate
  WARNING: Configuration setting global/system_id_source is disabled. Using default value.
  LVM configuration valid.

[1] f21/~ # pvs
  WARNING: Configuration setting global/system_id_source is disabled. Using default value.
  PV         VG     Fmt  Attr PSize   PFree
  /dev/sdb          lvm2 ---  128.00m 128.00m
  ...
2015-03-04 14:08:47 +01:00
Peter Rajnoha
e73dad7874 vgremove: select: direct selection to be done per-VG, not per-LV
Though vgremove operates per VG by definition, internally, it
actually means iterating over each LV it contains to do the
remove.

So we need to direct selection a bit in this case so that the
selection is done per-VG, not per-LV.

That means, use processing handle with void_handle.internal_report_for_select=0
for the process_each_lv_in_vg that is called later in vgremove_single fn.
We need to disable internal selection for process_each_lv_in_vg
here as selection is already done by process_each_vg which calls
vgremove_single. Otherwise selection would be done per-LV and not
per-VG as we intend!

An intra-release fix for commit 00744b053f.
2015-03-04 10:44:31 +01:00
Alasdair G Kergon
bfbb5d269a systemid: Add ACCESS_NEEDS_SYSTEM_ID VG flag.
Set ACCESS_NEEDS_SYSTEM_ID VG status flag whenever there is
a non-lvm1 system_id set.  Prevents concurrent access from
older LVM2 versions.
Not set on VGs that bear a system_id only due to conversion
from lvm1 metadata.
2015-03-04 01:16:32 +00:00
Alasdair G Kergon
3562b5ab39 systemid: Init and merge lvm2 and lvm1 fields.
Use system_id field in preference to lvm1_system_id.
Initialise both for now.
2015-03-04 01:00:51 +00:00
Alasdair G Kergon
dcba4781ea vgchange: Prevent lvm1 system ID changes.
(This system_id setting code shouldn't be in two places.)
2015-03-04 00:50:54 +00:00
Alasdair G Kergon
340369ab25 format1: Export generate_lvm1_system_id.
Export _lvm1_system_id as generate_lvm1_system_id and call it in
vg_setup() so it is set before writing the metadata to disk
and not missing from the initial metadata backup file.
2015-03-04 00:44:15 +00:00
Alasdair G Kergon
4e6f3e5162 archives: Preserve format type in file.
format_text processes both lvm2 on-disk metadata and metadata read
from other sources such as backup files.  Add original_fmt field
to retain the format type of the original metadata.
Before this patch, /etc/lvm/archives would contain backups of
lvm1 metadata with format = "lvm2" unless the source was lvm1 on-disk
metadata.
2015-03-04 00:30:26 +00:00
David Teigland
2477495922 lvchange, vgchange: fix the system_id check
The check for matching system_id needs to check
that the system_id is not blank.
2015-03-03 16:45:16 -06:00
David Teigland
cccc2b2980 vgchange: deactivate LVs in foreign VG
Apply the same logic as lvchange, which allows
deactivating LVs in a foreign VG.
2015-03-03 13:23:13 -06:00
Petr Rockai
926b38c0d7 spec: Add lvmlocal.conf to RPMs. 2015-03-03 15:47:13 +01:00
Peter Rajnoha
1a41e649a6 metadata: vg: alloc lvm1_system_id in alloc_vg sooner 2015-03-02 13:00:45 +01:00
Peter Rajnoha
eeaf3f2e88 metadata: vg: add missing vg->lvm1_system_id initialization
The vg->lvm1_systemd_id needs to be initialized as all the code around
counts with that. Just like we initialize lvm1_system_id in vg_create
(no matter if it's actually LVM1 or LVM2 format), this patch adds this
init in alloc_vg as well so the rest of the code does not segfaul
 when trying to access vg->lvm1_system_id.
2015-03-02 12:17:27 +01:00
Peter Rajnoha
047fe6c59f report: check value of args_are_pvs, not the pointer (fix for commit 9ea77b7) 2015-03-02 10:36:32 +01:00
David Teigland
c32efc7f7e system_id: apply consistent naming
In log messages refer to it as system ID (not System ID).

Do not put quotes around the system_id string when printing.

On the command line use systemid.

In code, metadata, and config files use system_id.

In lvmsystemid refer to the concept/entity as system_id.
2015-02-27 13:32:00 -06:00
Peter Rajnoha
e09f8a82f1 initscripts: lvm2-monitor: use @DMEVENTD_PIDFILE@ instead of hardcoded /var/run/dmeventd.pid 2015-02-27 15:48:10 +01:00
Jose Castillo
57e9e76da4 initscripts: lvm2-monitor: implement status action
Two new functions added in the init script: rh_status and rh_status_q.
First one to be used in status() and second one to be used in start(),
stop(), force_stop(). Check for 'dmeventd' added and print list of
lvs being monitored in status().
2015-02-27 15:38:34 +01:00
Peter Rajnoha
379fb90b05 cleanup: change check order in condition in _check_pv_list fn
"!dev_cache_get(argv[i], cmd->full_filter) && !rescan_done" --> "!rescan_done && !dev_cache_get(argv[i], cmd->full_filter)

Check the simple condition first (variable), then the function return value
(which in this case certainly takes more time to evaluate) - save some time.
2015-02-27 14:52:38 +01:00
Alasdair G Kergon
ee4cd2c737 lvchange: Allow -pr to change kernel only. 2015-02-27 13:38:26 +00:00
Peter Rajnoha
5b154ae4a3 report: one more comment explaining change of report type when tags are used for original LABEL reporting 2015-02-27 13:48:47 +01:00
Peter Rajnoha
9ea77b788b report: fix handling of reports with pure label fields
Two problems fixed by this patch:
  - PV tags were not recognized at all when using them with pvs
    report that has only label fields (regression since 2.02.105)
  - incorrect persistent .cache file to be generated after pvs
    report that has only label fields (regression since 2.02.106)

These bugs come from the transition from process_each_pv to
process_each_label introduced by commit
67a7b7a87d and commit
490226fc47 and related.
2015-02-27 13:39:25 +01:00
Peter Rajnoha
8bceb1e0bb conf: be more clear about wipe_signatures_when_zeroing_new_lvs option in comments 2015-02-27 09:17:10 +01:00
David Teigland
0a19238aa3 system_id: remove unwanted foreign error for some commands
Commands that can never use foreign VGs begin with
cmd->error_foreign_vgs = 1.  This tells the vg_read
lib layer to print an error as soon as a foreign VG
is read.

The toollib process_each layer also prints an error if a
foreign VG is read, but is more selective about it.  It
won't print an error if the command did not explicitly
name the foreign VG.  We want to silently ignore foreign VGs
unless a command attempts to use one explicitly.

So, foreign VG errors are printed from two different layers:
vg_read (lower layer) and process_each (upper layer).

Commands that use toollib process_each, only want errors from
the process_each layer, not from both layers.  So, process_each
disables the lower layer vg_read error message by setting
error_foreign_vgs = 0.

Commands that do not use toollib process_each, want errors
from the vg_read layer, otherwise they would get no error
message.  The original cmd->error_foreign_vgs setting
enables this error.

(Commands that are allowed to operate on foreign VGs always
begin with cmd->error_foreign_vgs = 0, and all the commands
in this group use toollib process_each with the selective
error reporting.)
2015-02-26 16:33:36 -06:00
Alasdair G Kergon
a432066c7c mirror: Explicit cast in region_size_max 2015-02-26 19:49:25 +00:00
Alasdair G Kergon
cb727a1ccc mirror: Avoid region size compiler warning.
format ‘%u’ expects type ‘unsigned int’, but argument 7 has type ‘uint64_t’
2015-02-26 19:45:55 +00:00
David Teigland
66d074e913 tests: more system_id tests 2015-02-26 13:23:22 -06:00
Alasdair G Kergon
b5394c8f26 lvchange: Allow -prw to change kernel only.
If an LV is already rw but still ro in the kernel, allow -prw to issue a
refresh to try to change the kernel state to rw.

Intended for use after clearing activation/read_only_volume_list in
lvm.conf.
2015-02-26 18:38:26 +00:00
David Teigland
71d97fd88a man: lvmsystemid: empty string equals no system_id 2015-02-25 16:55:56 -06:00
David Teigland
efd7480de3 tests: add more system_id tests 2015-02-25 16:13:28 -06:00
David Teigland
1248f94a42 pvscan, vgscan: include foreign vgs with --cache
pvscan --cache and vgscan --cache scan devices to refresh lvmetad,
and they should also refresh the lvmetad copy of foreign vgs.
2015-02-25 15:46:27 -06:00
David Teigland
bbaabb8a59 WHATS_NEW: vgimport with lvmetad 2015-02-25 14:59:24 -06:00
David Teigland
2c50cbe8cb tests: fix the system_id tests
That were broken by yesterday's system_id changes.
2015-02-25 14:58:49 -06:00
David Teigland
ebb2205b4c tests: add more systemid tests 2015-02-25 14:58:49 -06:00
David Teigland
dd6a202831 lvchange: deactivate is always possible in foreign vgs
The only realistic way for a host to have active LVs in a
foreign VG is if the host's system_id (or system_id_source)
is changed while LVs are active.

In this case, the active LVs produce an warning, and access
to the VG is implicitly allowed (without requiring --foreign.)
This allows the active LVs to be deactivated.

In this case, rescanning PVs for the VG offers no benefit.
It is not possible that rescanning would reveal an LV that
is active but wasn't previously in the VG metadata.
2015-02-25 14:58:49 -06:00
Jonathan Brassow
dd0ee35378 cmirror: Adjust region size to work around CPG msg limit to avoid hang.
cmirror uses the CPG library to pass messages around the cluster and maintain
its bitmaps.  When a cluster mirror starts-up, it must send the current state
to any joining members - a checkpoint.  When mirrors are large (or the region
size is small), the bitmap size can exceed the message limit of the CPG
library.  When this happens, the CPG library returns CPG_ERR_TRY_AGAIN.
(This is also a bug in CPG, since the message will never be successfully sent.)

There is an outstanding bug (bug 682771) that is meant to lift this message
length restriction in CPG, but for now we work around the issue by increasing
the mirror region size.  This limits the size of the bitmap and avoids any
issues we would otherwise have around checkpointing.

Since this issue only affects cluster mirrors, the region size adjustments
are only made on cluster mirrors.  This patch handles cluster mirror issues
involving pvmove, lvconvert (from linear to mirror), and lvcreate.  It also
ensures that when users convert a VG from single-machine to clustered, any
mirrors with too many regions (i.e. a bitmap that would be too large to
properly checkpoint) are trapped.
2015-02-25 14:42:15 -06:00
Petr Rockai
a88430c6a1 lvcreate.8: Mention --cachepolicy and --cachesettings. 2015-02-25 18:34:01 +01:00
Petr Rockai
0d313282f2 lvmcache.7: add a section on --cachepolicy/--cachesettings 2015-02-25 18:21:30 +01:00
David Teigland
aa30e95271 vgcfgbackup: enable foreign VG access
Backup of a foreign VG is allowed.
2015-02-25 11:01:37 -06:00
David Teigland
8668a9e81c systemid: silently ignore foreign vgs unless named
A foreign VG should be silently ignored by a reporting/display
command like 'vgs'.  If the reporting/display command specifies
a foreign VG by name on the command line, it should produce an
error message.

Scanning commands pvscan/vgscan/lvscan are always allowed to
read and update caches from all PVs, including those that belong
to foreign VGs.

Other non-report/display/scan commands always ignore a foreign
VG, or report an error if they attempt to use a foreign VG.

vgimport should always invalidate the lvmetad cache because
lvmetad likely holds a pre-vgexported copy of the VG.
(This is unrelated to using foreign VGs; the pre-vgexported
VG may have had no system_id at all.)
2015-02-25 10:53:52 -06:00
Alasdair G Kergon
4ff9abd01f toolcontext: Fix lvmlocal.conf load fail path. 2015-02-25 16:36:47 +00:00
Alasdair G Kergon
1e59c0346a example.conf: Update systemid comments.
Avoid using 'cluster' (ambiguous).
Add holding ref for machine-id source.
2015-02-25 14:22:24 +00:00
Alasdair G Kergon
809a5e142e systemid: Improve concurrent warning. 2015-02-25 14:17:35 +00:00
Alasdair G Kergon
ac6a4cd707 systemid: Allow empty systemid with warnings.
Add warning messages when empty system ID is set.
2015-02-25 14:12:24 +00:00
Petr Rockai
7d615a3fe5 cache: Fix a segfault when passing --cachepolicy without --cachesettings. 2015-02-24 11:39:35 +01:00
Alasdair G Kergon
5793ecd165 systemid: Extend --foreign to reporting commands.
Add --foreign to the remaining reporting and display commands plus
vgcfgbackup.
Add a NEEDS_FOREIGN_VGS flag for vgimport to always set --foreign.
If lvmetad is being used with --foreign, scan foreign VGs (currently
implemented as a full PV scan).
Handle these things centrally in lvmcmdline.c.
Also allow lvchange and vgchange -an/-aln to deactivate any foreign
LVs that happen to be active if something went wrong.
Remember to set the system ID when creating a new VG in vgsplit.
2015-02-23 23:41:38 +00:00
Alasdair G Kergon
b18feb98e5 systemid: Fix access restrictions.
When checking whether the system ID permits access to a VG, check for
each permitted situation first, and only then issue the appropriate
error message.  Always issue a message for now.  (We'll try to
suppress some of those later when the VG concerned wasn't explicitly
requested.)
Add more messages to try to ensure every return code is checked and
every error path (and only an error path) contains a log_error().
Add self-correction to vgchange -c to deal with situations where
the cluster state and system ID state are out-of-sync (e.g. if
old tools were used).
2015-02-23 23:19:36 +00:00
Alasdair G Kergon
df227be37c lvm1: Reenable sys ID.
Move the lvm1 sys ID into vg->lvm1_system_id and reenable the #if 0
LVM1 code.  Still display the new-style system ID in the same
reporting field, though, as only one can be set.
Add a format feature flag FMT_SYSTEM_ON_PVS for LVM1 and disallow
access to LVM1 VGs if a new-style system ID has been set.
Treat the new vg->system_id as const.
2015-02-23 23:03:52 +00:00
Alasdair G Kergon
2fc2928978 config: Rename allow_system_id to extra_system_ids.
Add warnings to the config file templates and briefly document
each value.
Configure lvmlocal.conf and install in /etc/lvm.
2015-02-23 22:19:08 +00:00
Alasdair G Kergon
3d406e5a8d config: Adjust system_id defaults.
Allow cmd->unknown_system_id to be cleared during toolcontext
refresh.
Set a default value of "none" for global/system_id_source.
Allow local/system_id to be empty so it's not impossible for
a later config file to remove it.
2015-02-23 21:20:51 +00:00
Alasdair G Kergon
e15b439bf3 systemid: Define file content more precisely.
In a file containing a system ID:
  Any whitespace at the start of a line is ignored;
  Blank lines are ignored;
  Any characters after a # are ignored along with the #.
  The system ID is obtained by processing the first line with
non-ignored characters.
  If further lines with non-ignored characters follow, a warning is
issued.
2015-02-23 20:49:15 +00:00
Alasdair G Kergon
c2ed5feee5 systemid: Add warnings if invalid.
Add WARNING messages if there are problems setting the requested
system ID.
Ban "localhost" as a prefix regardless of the system_id_source.
Use cmd->hostname instead of calling uname again.
Make system_id_source values case-insensitive (as with new settings like
log_debug_classes) and also accept machine-id to match the filename.
2015-02-23 20:36:27 +00:00
Alasdair G Kergon
6b6934b009 toolcontext: Include system_id in refresh.
Move _init_system_id() into _process_config() so it's also called when
refreshing the toolcontext.  Add WARNING to log_warn messages.
2015-02-23 20:21:00 +00:00
Alasdair G Kergon
72e6888dc3 toolcontext: Move lvmlocal.conf loading.
Load lvmlocal.conf after basic initialisation from lvm.conf.
2015-02-23 20:11:00 +00:00
Alasdair G Kergon
0551d1c56e systemid: Require alphanumeric 1st character.
Require system ID to begin with an alphanumeric character.
Rename fn to make clear it's only validation for systemid
and always terminate result rather than imposing this on the caller.
2015-02-23 19:47:03 +00:00
Alasdair G Kergon
a5df78e0f0 format_text: Fix creation_host_system_id.
Don't escape quotes - forbidden characters.
2015-02-23 19:19:48 +00:00
Alasdair G Kergon
cc5e3dbf24 format_text: Store creation_host_system_id.
Record the current system ID at the time of writing out VG metadata
in the outer section of it alongside the hostname and time.
2015-02-23 17:54:47 +00:00
Alasdair G Kergon
2a1189ebc3 config: Reinstate recursive tags setting.
In 2.02.99, _init_tags() inadvertently began to ignore the
dm_config_tree struct passed to it.  "tags" sections are not
merged together, so the "tags" section in the main config file was
being processed repeatedly and other "tags" sections were ignored.
2015-02-23 17:40:58 +00:00
Alasdair G Kergon
36a6c0df46 systemid: Add built-in systemid command.
Make it easy to find the system ID when testing.
Also show in general debug output.
2015-02-23 17:26:50 +00:00
Alasdair G Kergon
fcebf27a9f lvm-string: Fix HYPEN typo. 2015-02-23 17:09:35 +00:00
Alasdair G Kergon
4847836310 lvmetad: Add fn to scan only foreign VGs.
Not implemented yet - just a wrapper.
2015-02-23 17:03:03 +00:00
David Teigland
42ba7974c5 man lvmsystemid: update changing the system_id 2015-02-20 16:55:27 -06:00
David Teigland
cfd1b8eae2 man lvm: document --foreign option 2015-02-20 16:26:04 -06:00
David Teigland
37a47c0eec vgchange, vgcreate: add systemid option to command help 2015-02-20 15:31:17 -06:00
David Teigland
3361e662f4 man: systemid option for vgcreate and vgchange 2015-02-20 14:58:01 -06:00
David Teigland
55dd45239a tests: skip system_id machineid case when not available
instead of creating a fake /etc/machine-id file on the
system to test with.
2015-02-20 13:12:38 -06:00
David Teigland
e0946dca69 man lvmsystemid: expanded limitations and warnings 2015-02-20 12:21:23 -06:00
David Teigland
6bc35a351a report: fix foreign reporting without lvmetad 2015-02-19 15:24:31 -06:00
David Teigland
b896bf8f5a tests: add system_id test 2015-02-19 14:42:39 -06:00
David Teigland
0c6faaab43 doc: explanation of caching foreign VGs 2015-02-19 11:33:23 -06:00
David Teigland
97e3e84c2c man: update lvmthin about repair and recovery
Explain the thin metadata repair might not work.
Clarify that a full thin pool won't require fsck for journaled fs.
2015-02-19 10:49:39 -06:00
Peter Rajnoha
f80e7bb61b configure: typo in configure --with-default-raid10-segtype causing it to be unrecognized
AC_ARG_WITH(default-raid10r-segtype --> AC_ARG_WITH(default-raid10-segtype

(...raid10r... --> ...raid10... - extra "r")
2015-02-19 16:19:15 +01:00
Zdenek Kabelac
af395e61d5 cleanup: drop unused header file 2015-02-19 14:44:04 +01:00
Zdenek Kabelac
a18d789684 cleanup: simplify error path code
Mempool needs to free only with first alllocated element,
everything allocated afterwards is released as well.
2015-02-19 14:44:04 +01:00
Zdenek Kabelac
4c184e9d6b cleanup: drop unused value assign
Dop unused value assignments.

Unknown is detected via other combination
(!linear && !striped).

Also change the log_error() message into a warning,
since the function is not really returning error,
but still keep the INTERNAL_ERROR.

Ret value is always set later.
2015-02-19 14:43:25 +01:00
Peter Rajnoha
ed420fb691 pvcreate: switch to "none" dev-ext source during pvcreate
The dev ext source must be reset for the dev_cache_get call
(which evaluates filters), not lvmcache_label_scan - so fix
original commit 727c7ff85d.

Also, add comments in _pvcreate_check fn explaining why
refresh filter and rescan is needed and exactly in which
situations.
2015-02-19 14:34:55 +01:00
Peter Rajnoha
69b1e32c8a wiping: blkid: do not count skipped signatures in final number of wipes
We exclude some signatures from being wiped when using blkid wiping.
These are signatures which we simply overwrite. For example, the
LVM2_member signature which denotes a PV - if we call pvcreate on
existing PV, we just overwrite the PV header, no need to wipe it.

Previously, we counted such signatures as if they were wiped
and they were counted in the final number of wiped signatures
that _wipe_known_signatures_with_blkid fn returned in the "wiped"
output arg. Then the code checking this output arg could be
mislead that wiping happened while no wiping took place in real
and we could fire some code uselessly based on this information
(e.g. refreshing filters/rescanning - see also
commit 6b4066585f).
2015-02-19 13:30:05 +01:00
Petr Rockai
373f855684 clvmd: Fix BZ 1140095 by updating lastfd upon EINTR. 2015-02-18 12:45:43 +01:00
Petr Rockai
88411fb6f9 test: Avoid a race in pvmove-restart.sh. 2015-02-18 12:27:47 +01:00
Petr Rockai
733e3f6f98 test: Make pvmove0 device removal more robust, in pvmove-restart.sh. 2015-02-18 10:21:06 +01:00
Zdenek Kabelac
10b8d2a4ea tests: hide uninteresting output
We don't care about diff output.
2015-02-17 15:54:21 +01:00
Petr Rockai
973afcbb20 NIX: Fix a typo that broke evaluation of fc19+. 2015-02-17 15:32:04 +01:00
Zdenek Kabelac
a009c0fb40 cleanup: fix compate of return value
Drop '!' for 'ret' compare.
Since the effect of false compare was only stack trace printing,
it present no real code flow change.
2015-02-17 13:40:35 +01:00
Zdenek Kabelac
4bb60c05bf cleanup: drop !! from code
It's unused piece of code - but gcc5 noticed problem with
usage of !! on the leftside.
2015-02-17 13:39:47 +01:00
Zdenek Kabelac
cb144c0097 cleanup: drop unused val 2015-02-17 13:39:26 +01:00
Zdenek Kabelac
cd1a76a492 tests: syncaction update
Improve syncaction testing with some minor
workaround for current upstream kernel
2015-02-17 11:05:04 +01:00
Zdenek Kabelac
120e1aa4bd tests: ensure lv1 goes away first
$lv1 may appear in the table after -pvmove0 which could make -pvmove0
unremovable.
2015-02-17 11:05:04 +01:00
Peter Rajnoha
6b4066585f filters: no need to refresh filters/rescan if no signature is wiped during pvcreate at all
Before, we refreshed filters and we did full rescan of devices if
we passed through wiping (wipe_known_signatures fn call). However,
this fn returns success even if no signatures were found and so
nothing was wiped. In this case, it's not necessary to do the
filter refresh/rescan of devices as nothing changed clearly.

This patch exports number of wiped signatures from all the
wiping functions below. The caller (_pvcreate_check) then checks
whether any wiping was done at all and if not, no refresh/rescan
is done, saving some time and resources.
2015-02-17 09:46:34 +01:00
Petr Rockai
1ee82b545b spec: Include lvmsystemid.7 in RPMs. 2015-02-16 17:15:03 +01:00
Petr Rockai
78d7466713 NIX: Fix CentOS builds. 2015-02-16 15:32:01 +01:00
Petr Rockai
df28c4d912 NIX: Resolve issues with fedora-release and kernel-modules-extra. 2015-02-16 15:32:01 +01:00
Peter Rajnoha
727c7ff85d pvcreate: switch to "none" dev-ext source during pvcreate
pvcreate code path executes signature wiping if there are any signatures
found on device to prepare the device for PV. When the signature is wiped,
the WATCH udev rule triggers the event which then updates udev database
with fresh info, clearing the old record about previous signature.

However, when we're using udev db as dev-ext source, we'd need to wait
for this WATCH-triggered event. But we can't synchronize against such
events (at least not at this moment). Without this sync, if the code
continues, the device could still be marked as containing the old
signature if reading udev db. This may end up even with the device
to be still filtered, though the signature is already wiped.

This problem is then exposed as (an example with md components):

$  mdadm --create /dev/md0 --level=1 --raid-devices=2 /dev/sda /dev/sdb --run
$  mdadm -S /dev/md0
$  pvcreate -y /dev/sda
Wiping linux_raid_member signature on /dev/sda.
/dev/sda: Couldn't find device.  Check your filters?
$ echo $?
5

So we need to temporarily switch off "udev" dev-ext source here
in this part of pvcreate code until we find a way how to sync
with WATCH events.

(This problem does not occur with signature wiping which we do
on newly created LVs since we already handle this properly with
our udev flags - the LV_NOSCAN/LV_TEMPORARY flag. But we can't use
this technique for non-dm devices to keep WATCH rule under control.)
2015-02-16 15:07:00 +01:00
Alasdair G Kergon
032c9178ca conf: Set default global/etc from --with-confdir. 2015-02-13 19:10:10 +00:00
David Teigland
d726246f78 system_id: warn if the system_id_file cannot be opened 2015-02-13 11:37:11 -06:00
David Teigland
def0866ded system_id: omit leading hyphens from system_id 2015-02-13 11:14:46 -06:00
David Teigland
737c992431 toollib: add underscore to static ignore_vg function 2015-02-13 11:01:55 -06:00
David Teigland
d3f3878ffd WHATS_NEW for system_id 2015-02-13 10:27:17 -06:00
David Teigland
8cdec4c434 system_id: use for VG ownership
See included lvmsystemid(7) for full description.
2015-02-13 10:10:27 -06:00
David Teigland
f5d06efbab vgextend: Use process_each_vg.
Tags and --select are not yet supported because new code is needed
to ensure exactly one VG matches before the VG starts to be processed.
2015-02-13 14:58:51 +00:00
Peter Rajnoha
1ced5562cd tests: fix pvcreate-operation-md test to properly clean up devs before their reuse
pvcreate filters out devices with existing partitions defined on them,
we need to properly clean up the devs before we reuse them.
2015-02-13 14:53:26 +01:00
Peter Rajnoha
993c988895 tests: comment in select-tools.sh 2015-02-13 11:45:13 +01:00
Peter Rajnoha
e0ce728579 tolllib: process_each_pv: always use full_filter unconditionally when getting all devices
(This reverts patch #d95c6154)

Filter complete device list through full_filter unconditionally when
we're getting the list of *all* devices even in case we're interested
only in fraction of those devices - the PVs, not the other devices
which are not PVs yet (e.g. pvs vs. pvs -a).

We need to do this full filtering whenever we're handling *complete*
list of devices, we need to be safe here, mainly if there are any
future changes and we'd forgot to change to use proper filtering then.
Also properly preventing duplicates if there are any block subsystem
components used (mpath, MD ...).

Thing here is that (under use_lvmetad=1), cmd->filter can be used
only if we're sure that the list of devices we're filtering contains
only PVs. We have to use cmd->full_filter otherwise (like it is in
case of _get_all_devices fn which acquires complete list of devices,
no matter if it is a PV or not).

Of course, cmd->full_filter is more extensive than cmd->filter
which is only a subset of full_filter.

We could optimize this in a way that if we're interested in PVs only
during process_each_pv processing (e.g. using pvs in contrast to pvs -a),
we'd get the list of PV devices directly from lvmetad from the
lvmcache_seed_infos_from_lvmetad fn call which currently updates
lvmcache only. We'd add an additional output arg for this fn to get
the list of PV devices directly in addition, without a need to iterate
over all devices which include non-PVs which we're not interested in
anyway, hence we could use only cmd->filter, not the cmd->full_filter.

So the code would look something like this:

static int _get_all_devices(....)
{
	struct device_id_list *dil;

	if (interested_in_pvs_only)
		lvmcache_seed_infos_from_lvmetad(cmd, &dil); /* new "dil" arg */
		/* the "dil" list would be filtered through cmd->filter inside lvmcache_seed_infos_from_lvmetad */
	else {
		lvmcache_seed_infos_from_lvmetad(cmd, NULL);
		dev_iter_create(cmd->full_filter)
		while (dev = dev_iter_get ...) {
			dm_list_add(all_devices, &dil->list);
		}
	}
}
2015-02-13 11:27:09 +01:00
Peter Rajnoha
1c005b557a tests: select-tools.sh: pvchange now uses process_each_pv
pvchange now uses process_each_pv so uncomment parts of the test
which check proper functionality of intersection between selection
result and PVs or PV tags directly provided on command line. This
didn't work properly before when pvchange was not using process_each_pv.

For example:

  pvchange -u -S 'pv_name=/dev/sda' /dev/sdb

..changes nothing since clearly the intersection of /dev/sda and
/dev/sdb is empty set. The same applies for tags:

  pvchange -u -S 'pv_name=/dev/sda' @some_tag

..changes nothing if /dev/sda is not tagged with some_tag.
2015-02-13 11:27:09 +01:00
Peter Rajnoha
969d2bf448 cleanup: remove deallocate_handle_root arg from destroy_procesing_handle fnw 2015-02-13 11:27:09 +01:00
Peter Rajnoha
66b10d6d12 cleanup: replace static struct processing_handle initializer with common init_processing_handle
It's cleaner this way - do not mix static and dynamic
(init_processing_handle) initializers. Use the dynamic one everywhere.
This makes it easier to manage the code - there are no "exceptions"
then and we don't need to take care about two ways of initializing the
same thing - just use one common initializer throughout and it's clear.

Also, add more comments, mainly in the report_for_selection fn explaining
what is being done and why with respect to the processing_handle and
selection_handle.
2015-02-13 11:26:57 +01:00
Peter Rajnoha
1a72933143 pvchange: no need to initialize selection handle directly, process_each_pv will do that automatically 2015-02-13 09:29:30 +01:00
Peter Rajnoha
e1710f34bb lvchange: change msg about required params (LV or selection) to be consistent with msgs used in other tools 2015-02-13 09:04:21 +01:00
Alasdair G Kergon
e4e703ab60 pvchange: Use process_each_pv.
Invalid devices no longer included in the counters printed at the end.
May now need to use --ignoreskippedcluster if relying upon exit status.
If more than one change is requested per-PV, attempt to perform them
all.  Note that different arguments still handle exit status
differently.
2015-02-12 16:37:47 +00:00
Peter Rajnoha
acb6c06207 autoreconf: recent changes
autoconf-2.69-14.fc20.noarch
automake-1.13.4-6.fc20.noarch
2015-02-12 15:48:12 +01:00
Zdenek Kabelac
77ceb3ee47 valgrind: when executed within valrind skip close
Since valgrind uses internal file descriptors for communication,
don't try to close them in this case.
2015-02-12 15:40:54 +01:00
Zdenek Kabelac
9809038b9d memory: disable check with valgrind pool build
When lvm2 is build with valgrind pool detection - always disable
memcheck, since pool memory allocation are unconditionaly passed
into valgrind library.
2015-02-12 15:40:53 +01:00
Zdenek Kabelac
425c04e4dc configure.in: AC_SUBST needs to be always executed 2015-02-12 15:40:53 +01:00
Zdenek Kabelac
d303d9973f tests: BACKING_DEV
Reset BACKING_DEV when it's same as LOOP.
Reset only 64K - so just eats a bit less space from underlaying loop
devices...
2015-02-12 15:40:52 +01:00
Zdenek Kabelac
4b7097b96c tests: ensure array is synchronized
Before continue of repair test, ensure mirror is in sync
2015-02-12 15:38:51 +01:00
Zdenek Kabelac
739b751046 tests: don't crash if checked string is shorter
Not really sure what is this testing - just avoid coredump if
the test cannot happen since the index would too high.
2015-02-12 15:38:51 +01:00
Zdenek Kabelac
b1002e98e0 makefiles: more _CFLAGS for -MM
Move of valgrind flags to _CFLAGS make the -MM generation
not compilable (d571eab3b2)

Add these _CFLAGS right into .c->.d rules
(as well as  UDEV)
2015-02-12 15:38:50 +01:00
Zdenek Kabelac
65d95caad5 tests: respect LVM_TEST_DIR
Check for empty LVM_TEST_DIR
(regression from 48275c7836)
2015-02-12 15:38:50 +01:00
Peter Rajnoha
d95c6154ff toollib: process_each_pv: fix commit d38d047e which worked for processing "all devices", but didn't work for "all PVs"
We still need to get the list as the calls underneath process_each_pv
rely on this list. But still keep the change related to the filters -
if we're processing all devices, we need to use cmd->full_filter.
If we're processing only PVs, we can use cmd->filter only to save
some time which would be spent in filtering code.
2015-02-12 14:14:45 +01:00
Peter Rajnoha
e52c998c49 toollib: process_each_pv: use cmd->full_filter, not cmd->filter if we're getting full list of PV-capable devices (not just PVs)
When lvmetad is used and at the same time we're getting list of all
PV-capable devices, we can't use cmd->filter (which is used to filter
out lvmetad responses - so we're sure that the devices are PVs already).

To get the list of PV-capable devices, we're bypassing lvmetad (since
lvmetad only caches PVs, not all the other devices which are not PVs).
For this reason, we have to use the "full_filter" filter chain (just
like we do when we're running without lvmetad).

Example scenario:
- sdo and sdp components of MD device md0
- sdq, sdr and sds components of mpatha multipath device
- mpatha multipath device partitioned
- vda device partitioned

=> sdo,sdp,sdr,sds, mpatha and vda should be filtered!

$ lsblk -o NAME,TYPE
NAME            TYPE
sdn             disk
sdo             disk
`-md0           raid0
sdp             disk
`-md0           raid0
sdq             disk
`-mpatha        mpath
  `-mpatha1     part
sdr             disk
`-mpatha        mpath
  `-mpatha1     part
sds             disk
`-mpatha        mpath
  `-mpatha1     part
vda             disk
|-vda1          part
`-vda2          part
  |-fedora-swap lvm
  `-fedora-root lvm

Before this patch:
==================
use_lvmetad=0 (correct behaviour!)
$ pvs -a
  PV                  VG     Fmt  Attr PSize PFree
  /dev/fedora/root                ---     0     0
  /dev/fedora/swap                ---     0     0
  /dev/mapper/mpatha1             ---     0     0
  /dev/md0                        ---     0     0
  /dev/sdn                        ---     0     0
  /dev/vda1                       ---     0     0
  /dev/vda2           fedora lvm2 a--  9.51g    0

use_lvmetad=1 (incorrect behaviour - sdo,sdp,sdq,sdr,sds and mpatha not filtered!)
$ pvs -a
  PV                  VG     Fmt  Attr PSize PFree
  /dev/fedora/root                ---     0     0
  /dev/fedora/swap                ---     0     0
  /dev/mapper/mpatha              ---     0     0
  /dev/mapper/mpatha1             ---     0     0
  /dev/md0                        ---     0     0
  /dev/sdn                        ---     0     0
  /dev/sdo                        ---     0     0
  /dev/sdp                        ---     0     0
  /dev/sdq                        ---     0     0
  /dev/sdr                        ---     0     0
  /dev/sds                        ---     0     0
  /dev/vda                        ---     0     0
  /dev/vda1                       ---     0     0
  /dev/vda2           fedora lvm2 a--  9.51g    0

With this patch applied:
========================
use_lvmetad=1
$ pvs -a
  PV                  VG     Fmt  Attr PSize PFree
  /dev/fedora/root                ---     0     0
  /dev/fedora/swap                ---     0     0
  /dev/mapper/mpatha1             ---     0     0
  /dev/md0                        ---     0     0
  /dev/sdn                        ---     0     0
  /dev/vda1                       ---     0     0
  /dev/vda2           fedora lvm2 a--  9.51g    0
2015-02-12 13:46:11 +01:00
Peter Rajnoha
d38d047eec toollib: process_each_pv: do not acquire list of all devices if not necessary
List of all devices is only needed if we want to process devices
which are not PVs (e.g. pvs -a). But if this is not the case, it's
useless to get the list of all devices and then discard it without
any use, which is exactly what happened in process_each_pv where
the code was never reached and the list was unused if we were
processing just PVs, not all PV-capable devices:

int process_each_pv(...)
{
	...
	process_all_devices = process_all_pvs &&
			      (cmd->command->flags & ENABLE_ALL_DEVS) &&
			      arg_count(cmd, all_ARG);
	...
	/*
	 * If the caller wants to process all devices (not just PVs), then all PVs
	 * from all VGs are processed first, removing them from all_devices.  Then
	 * any devs remaining in all_devices are processed.
	*/
	_get_all_devices(cmd, &all_devices);
	...
	ret = _process_pvs_in_vgs(...);
	...
	if (!process_all_devices)
		goto out;

        ret = _process_device_list(cmd, &all_devices, handle, process_single_pv);
	...
}

This patch adds missing check for "process_all_devices" and it gets the
list of all (including non-PV) devices only if needed:
2015-02-12 13:46:11 +01:00
Marian Csontos
0e9f3dba75 test: Fix missing return in new test harness. 2015-02-12 13:28:26 +01:00
Peter Rajnoha
cc755853c2 config: fix version of introduction for devices/external_device_info_source (v115->v116) 2015-02-12 09:30:40 +01:00
Peter Rajnoha
54c2e9859f tests: add select-tools.sh to test selection support in toollib
Tests for selection within non-reporting tools while using process_each_* fns.
2015-02-11 18:39:47 +01:00
Peter Rajnoha
599cb41f99 tests: rename report-select.sh to select-report.sh
Let's name all selection-related tests with the "select-" prefix for
better sorting.
2015-02-11 16:17:05 +01:00
Peter Rajnoha
263f7831df report: define ba_start, vg_free and seg_start fields as DM_REPORT_FIELD_TYPE_SIZE instead of DM_REPORT_FIELD_TYPE_NUM
This makes a difference when using selection criteria based on
these fields - if those fields are defined as DM_REPORT_FIELD_TYPE_SIZE
(in contrast to DM_REPORT_FIELD_TYPE_NUMBER), units are also
recognize in selection clause.

For example:
$ lvs -o+seg_start vg1/lv2
  LV   VG   Attr       LSize  Start
  lv2  vg1  -wi-a----- 12.00m    0
  lv2  vg1  -wi-a----- 12.00m 8.00m

Before this patch:
$ lvs -o+seg_start --select 'seg_start=8m'
  Found size unit specifier but numeric value expected for selection field seg_start.
  Selection syntax error at 'seg_start=8m'.
  Use 'help' for selection to get more help.

With this patch applied:
$lvs -o+seg_start --select 'seg_start=8m'
  LV   VG   Attr       LSize  Start
  lv2  vg1  -wi-a----- 12.00m 8.00m

(the same applies for ba_start and vg_free fields)
2015-02-11 13:57:18 +01:00
Peter Rajnoha
b88b75f55f conf: update profile templates for recent changes 2015-02-11 13:22:31 +01:00
Peter Rajnoha
437b17964c man: reference -S/--select in {vg,lv,pv}change, {vg,lv}remove, {vg,lv,pv}display and vg{import,export} man pages 2015-02-11 10:04:21 +01:00
Peter Rajnoha
bc1bb7f8c5 toollib: select: issue an error message for failed VG/LV/PV selection 2015-02-11 09:36:09 +01:00
Peter Rajnoha
3505e88b18 man: dumpconfig: mention LVM_COMMAND_PROFILE env var and add more references to --mergedconfig option
The LVM_COMMAND_PROFILE env var is new - mention it in dumpconfig's
man page.

Also, dumpconfig always displays the top of the config cascade.
To display all the config found in the cascade merged (just like
it's used during LVM command processing), --mergedconfig option
must be used - this one's already described in that man page,
just make sure it's clear and add reference for this option also
in --profile/--commandprofile/--metadataprofile description.
2015-02-11 09:34:19 +01:00
Petr Rockai
801e47e089 NIX: Drop Fedora 16 builds. 2015-02-10 17:27:10 +01:00
Petr Rockai
79dc8f5ddd NIX: Adjust lists of extra RPMs to install. 2015-02-10 17:27:10 +01:00
Marian Csontos
a8b45b7a4c test: Fix harness not building on RHEL5 2015-02-10 17:02:01 +01:00
Peter Rajnoha
7f2eebf519 select: initialize selection handle for process_each_* fns with initial report type
This is a followup patch for previous patchset that enables selection in
process_each_* fns to fix an issue where field prefixes are not
automatically used for fields in selection criteria.

Use initial report type that matches the intention of each process_each_* functions:
- _process_pvs_in_vg - PVS
- process_each_vg - VGS
- process_each_lv and process_each_lv_in_vg - LVS

This is not normally needed for the selection handle init, BUT we would
miss the field prefix matching, e.g.

lvchange -ay -S 'name=lvol0'

The "name" above would not work if we didn't initialize reporting with
the LVS type at its start. If we pass proper init type, reporting code
can deduce the prefix automatically ("lv_name" in this case).

This report type is then changed further based on what selection criteria we
have. When doing pure selection, not report output, the final report type
is purely based on combination of this initial report type and report types
of the fields used in selection criteria.
2015-02-10 16:10:17 +01:00
Peter Rajnoha
80cca53611 tools: allow -S|--select for vgexport and vgimport 2015-02-10 16:10:17 +01:00
Peter Rajnoha
b93f586954 tools: allow -S|--select for vgdisplay, lvdisplay and pvdisplay without -C
We already allowed -S|--select with {vg,lv,pv}display -C (which
was then equal to {vg,lv,pv}s command. Since we support selection
in toolib now, we can support -S also without using -C in *display
commands now.
2015-02-10 16:09:40 +01:00
Peter Rajnoha
00744b053f tools: allow -S|--select for vgremove and lvremove 2015-02-10 16:08:42 +01:00
Peter Rajnoha
f784c60cd6 tools: allow -S|--select for vgchange, lvchange and pvchange 2015-02-10 16:08:04 +01:00
Peter Rajnoha
d6c8f0de28 pvchange: use processing_handle when processing items for pvchange
pvchange is an exception that does not use toollib yet for iterating
over the list of PVs (process_each_pv) so intialize the
processing_handle and use just like it's used in toollib.
2015-02-10 16:07:01 +01:00
Peter Rajnoha
56846d7873 report: implement report_for_selection
We have 3 input report types:
  - LVS (representing "_select_match_lv")
  - VGS (representing "_select_match_vg")
  - PVS (representing "_select_match_pv")

The input report type is saved in struct selection_handle's "orig_report_type"
 variable.

However, users can use any combination of fields of different report types in
selection criteria - the resulting report type can thus differ. The struct
selection_handle's "report_type" variable stores this resulting report type.

The resulting report_type can end up as one of:
  - LVS
  - VGS
  - PVS
  - SEGS
  - PVSEGS

This patch adds logic to report_for_selection based on (sensible) combination
of orig_report_type and report_type and calls appropriate reporting functions
or iterates over multiple items that need reporting to determine the selection
result.
2015-02-10 16:06:53 +01:00
Peter Rajnoha
984ae7f72d report: add report_for_selection and use it in select_match_{pv,vg,lv}
The report_for_selection does the actual "reporting for selection only".
The selection status will be saved in struct selection_handle's "selected"
variable.
2015-02-10 16:05:36 +01:00
Peter Rajnoha
e5b345aff3 refactor: report: factor out code to determine final report type
The code to determine final report type based on combination of input
report type (determined from fields used for reporting to output and selection)
can be reused for pure reporting for selection - factor out this code into
_get_final_report_type function.
2015-02-10 16:05:35 +01:00
Peter Rajnoha
de27324711 toollib: select the whole structure if at least one of its items is selected
This applies to:
  - process_each_lv_in_vg - the VG is selected only if at least one of its LVs is selected
  - process_each_segment_in_lv - the LV is selected only if at least one of its LV segments is selected
  - process_each_pv_in_vg - the VG is selected only if at least one of its PVs is selected
  - process_each_segment_in_pv - the PV is selected only if at least one of its PV segments is selected

So this patch causes the selection result to be properly propagated up to callers.
2015-02-10 16:05:32 +01:00
Peter Rajnoha
56011918e6 toollib: initialize handles (including reporting for selection) for _select_match_* used in process_each_* fns
Call _init_processing_handle, _init_selection_handle and
_destroy_processing_handle in process_each_* and related functions to
set up and destroy handles used while processing items.
2015-02-10 16:05:29 +01:00
Peter Rajnoha
a91bc7a19b toollib: add init_processing_handle, init_selection_handle and destroy_processing_handle helper functions
The init_processing_handle, init_selection_handle and
destroy_processing_handle are helper functions that allocate and
initialize the handles used when processing items in process_each_*
and related functions.
2015-02-10 16:05:27 +01:00
Peter Rajnoha
c3180c4a05 toollib: pass struct processing_handle to _select_match_* functions
The "struct processing_handle" contains handles to drive the selection/matching
so pass it to the _select_match_* functions which are entry points to the
selection mechanism used in process_each_* and related functions.

This is revised and edited version of former Dave Teigland's patch which
provided starting point for all the select support in process_each_* fns.
2015-02-10 16:05:26 +01:00
Peter Rajnoha
a64b39aef8 report: add report_init_for_selection fn and modify report_object to support reporting for selection only
The new "report_init_for_selection" is just a wrapper over
dm_report_init_with_selection that initializes reporting for selection
only. This means we're not going to do the actual reporting to output
for display and as such we intialize reporting as if no fields are reported
or sorted. The only fields "reported" are taken from the selection criteria
string and all such fields are marked as hidden automatically (FLD_HIDDEN flag).
These fields are used solely for selection criteria matching.

Also, modify existing report_object function that was used for reporting to
output for display. Now, it can either cause reporting to output or reporting
for selection only. The selection result is stored in struct selection_handle's
"selected" variable which can be handled further by any report_object caller.
2015-02-10 16:05:25 +01:00
Peter Rajnoha
51d96a1703 toollib: replace void *handle with struct processing_handle for use in processing functions (process_each_*/process_single_* and related)
This patch replaces "void *handle" with "struct processing_handle *handle"
in process_each_*, process_single_* and related functions.

The struct processing_handle consists of two handles inside now:

  - the "struct selection_handle *selection_handle" used for
    applying selection criteria while processing process_each_*,
    process_single_* and related functions (patches using this
    logic will follow)

  - the "void* custom_handle" (this is actually the original handle
    used before this patch - a pointer to custom data passed into
    process_each_*, process_single_* and related functions).
2015-02-10 16:05:24 +01:00
Peter Rajnoha
2a19866a74 cleanup: make report type condition consistent with the rest of the code
It's just more readable this way (each condition resulting in a certain
report type is always on one line), just like it's used elsewhere in the
code.
2015-02-10 16:05:23 +01:00
David Teigland
455ef6f2f5 toollib: prepare select_match_{pv,vg,lv} hooks
These hooks will check currently processed PV/VG/LV with current selection
criteria and the processing continues only if there's a match.
2015-02-10 16:04:41 +01:00
Peter Rajnoha
123a3383a0 libdm: report: add dm_report_object_is_selected
The new dm_report_object_is_selected fn makes it possible to opt whether the
object reported should be displayed on output or not. Also, in addition to
that, it makes it possible to save the result of selection (either 0 or 1).

So dm_report_object_is_selected is simply  more general form of object
reporting fn - combinations now allow for:

  dm_report_object_is_selected(rh, object, 1, NULL):
  This is exactly the original dm_report_object fn and it's fully equal
  to it.

  dm_report_object_is_selected(rh, object, 0, selected):
  Do not display the result on output, but save info whether the object
  is selected or not in 'selected' variable.

  dm_report_object_is_selected(rh, object, 1, selected):
  Display the result on output (if it passes selection criteria) and save
  whether the object is selected or not in 'selected' variable.

  dm_report_object(rh, object, 0, NULL):
  This combination is not allowed - it will end up with internal error.
  We're either interested in selection status or we want to display the
  result on output or both, but never nothing of the two.
2015-02-10 16:04:38 +01:00
Petr Rockai
2ee3bcb877 test: Fix a typo in shell/pvmove-restart.sh. 2015-02-10 12:42:05 +01:00
Peter Rajnoha
b6f558adcc lvm: recognize LVM_COMMAND_PROFILE env var for default command profile to use in LVM commands
Once LVM_COMMAND_PROFILE environment variable is specified, the profile
referenced is used just like it was specified using "<lvm command> --commandprofile".
If both --commandprofile cmd line option and LVM_COMMAND_PROFILE env
var is used, the --commandprofile cmd line option gets preference.
2015-02-09 14:16:30 +01:00
Peter Rajnoha
4e4ea46cfe reporter: properly check for _do_info_and_status return value and free the mempool if created within the fn 2015-02-09 11:48:21 +01:00
Petr Rockai
4065741a67 configure: Fix a warning about test/Makefile.in. 2015-02-05 16:30:50 +01:00
Petr Rockai
43d6b44a9f NIX: Request {fedora,centos}-release packages explicitly. 2015-02-05 14:21:31 +01:00
Petr Rockai
b9a017d94c NIX: Adjust install_rpms (kernel rpm is now required). 2015-02-05 13:51:39 +01:00
Petr Rockai
81b34dce61 NIX: We need to install lcov for ./configure now as well. 2015-02-05 13:51:38 +01:00
Petr Rockai
5cd6cce5a4 NIX: Move corosynclib-devel & valgrind-devel out of common. 2015-02-05 13:51:37 +01:00
Petr Rockai
57c39ecbcd NIX: Allow adding/overriding test configurations. 2015-02-05 13:51:07 +01:00
Petr Rockai
7c9d690f9e NIX: Set ulimit -c to unlimited, to get backtraces in logs. 2015-02-05 13:51:07 +01:00
Petr Rockai
6ba05212f7 NIX: Add a CentOS 7.0 64b build. 2015-02-05 13:51:06 +01:00
Petr Rockai
4686b8cea5 test: Fix a segfault in the test runner. 2015-02-05 13:51:06 +01:00
Petr Rockai
45e2aee8f9 test: It is not an error for a test daemon to exit before teardown. 2015-02-05 13:51:06 +01:00
Petr Rockai
78ba413ed1 test: Remove spurious set -x in lvm-wrapper. 2015-02-05 13:51:06 +01:00
Petr Rockai
d8983d4bd4 test: Properly detect warnings from testcases. 2015-02-05 13:51:06 +01:00
Petr Rockai
c96e42006d test: Only force an IO sync when the testcase has finished. 2015-02-05 13:51:06 +01:00
Petr Rockai
72ee3f920b test: Allow a longer timeout for lvextend-snapshot-dmeventd. 2015-02-05 13:51:06 +01:00
Petr Rockai
839ea48aa9 test: Make dmsetup remove more robust in pvmove-restart. 2015-02-05 13:51:06 +01:00
Petr Rockai
210a66fbf8 test: Make killing local (test) daemons more robust. 2015-02-05 13:51:06 +01:00
Petr Rockai
17575403d4 test: Disable lvmetad debug log on another bunch of tests. 2015-02-05 13:51:06 +01:00
Petr Rockai
1f727f3f3d test: Call $VALGRIND directly in lvm-wrapper. 2015-02-05 13:51:06 +01:00
Petr Rockai
3af008d405 NIX: Add valgrind-devel to the build environment. 2015-02-05 13:51:04 +01:00
Petr Rockai
2a8dc7fb53 memlock: Do not check memory balance if RUNNING_ON_VALGRIND. 2015-02-05 13:50:34 +01:00
Petr Rockai
d571eab3b2 configure: Look for valgrind.h independently of VALGRIND_POOLS. 2015-02-05 13:50:34 +01:00
Petr Rockai
5d833fd458 test: Add support for running LVM commands in tests through strace. 2015-02-05 13:50:34 +01:00
Petr Rockai
a6d006d9db test: Make lvm-wrapper available in the installed testsuite, too. 2015-02-05 13:50:33 +01:00
Petr Rockai
41c2e07a8d NIX: Install valgrind, gdb and strace in the test environment. 2015-02-05 13:50:23 +01:00
Petr Rockai
e4d5e22c91 NIX: Make timeout and test envvars configurable via --arg. 2015-02-05 13:47:21 +01:00
Petr Rockai
c2b7642d4d test: Fix prepare_scsi_debug_dev. 2015-02-05 13:47:21 +01:00
Petr Rockai
580370bea3 test: Avoid passing -c to flock. 2015-02-05 13:47:21 +01:00
Petr Rockai
7a0aa25c28 test: Re-try with loopback if a backing device is too small. 2015-02-05 13:47:21 +01:00
Petr Rockai
f3cc6576ee NIX: Detect that the VM booted up more directly. 2015-02-05 13:47:21 +01:00
Petr Rockai
734a183c56 NIX: Avoid a spurious failure when all tests pass. 2015-02-05 13:47:21 +01:00
Petr Rockai
bd0806e1f5 test: Fix failures due to undefined abs_top_builddir. 2015-02-05 13:47:21 +01:00
Petr Rockai
c6f9c46223 test: Avoid running 'dmsetup remove' with no devices. 2015-02-05 13:47:21 +01:00
Petr Rockai
ad0267b2ad test: Fix 100%FREE RAID tests since test device sizes changed slightly. 2015-02-05 13:47:20 +01:00
Petr Rockai
c82c69bb56 test: Update brick-shelltest (configurable timeout, better banner, exit code). 2015-02-05 13:47:20 +01:00
Petr Rockai
b6884f8a87 NIX: Mark builds with failed tests as such. 2015-02-05 13:47:20 +01:00
Petr Rockai
8b80e949ea test: Do not rely on dev/mapper/* nodes in pvmove-restart.sh. 2015-02-05 13:47:20 +01:00
Petr Rockai
d04c7ca0b6 test: Fix implementation of check targets with new flavour system. 2015-02-05 13:47:20 +01:00
Petr Rockai
68f7b422c1 NIX: Update path to /xchg (was /tmp/xchg with older nixpkgs). 2015-02-05 13:47:20 +01:00
Petr Rockai
f1d273a0b0 NIX: Do not fail aggregation when a sub-job fails to produce output. 2015-02-05 13:47:20 +01:00
Petr Rockai
93d8455faa NIX: Run each test flavour as a separate derivation. 2015-02-05 13:47:20 +01:00
Petr Rockai
003bf24723 NIX: Add --kmsg to lvm2-testsuite invocations. 2015-02-05 13:47:20 +01:00
Petr Rockai
7ed8fc8f7d test: Update brick-shelltest.h. 2015-02-05 13:47:20 +01:00
Petr Rockai
f9df76f8b3 NIX: Keep the udev log out of tmpfs. 2015-02-05 13:47:20 +01:00
Petr Rockai
e2dbf44116 NIX: Some kernels need ide/ata modules (i.e. no builtin ata). 2015-02-05 13:47:20 +01:00
Petr Rockai
eaa9f35540 NIX: Use IDE drive emulation instead of virtio. 2015-02-05 13:47:20 +01:00
Petr Rockai
c2aa918c53 libdaemon: Use select to yield CPU on a blocked read or write. 2015-02-05 13:47:20 +01:00
Petr Rockai
19bb62e2ec test: Update brick-shelltest, adding timestamps to logs. 2015-02-05 13:47:20 +01:00
Petr Rockai
f9dfc5f8a4 NIX: Use the new --heartbeat option on lvm2-testsuite. 2015-02-05 13:47:19 +01:00
Petr Rockai
8646b50aa9 test: Package up the test runner in a reusable C++ "brick". 2015-02-05 13:47:19 +01:00
Petr Rockai
f28407943f NIX: Pass --fatal-timeouts to the testsuite. 2015-02-05 13:47:19 +01:00
Petr Rockai
eec99ffa8c test: Implement --fatal-timeouts to allow a timely VM restart. 2015-02-05 13:47:19 +01:00
Petr Rockai
34e818042e test: Make the runner's heartbeat more reliable. 2015-02-05 13:47:19 +01:00
Petr Rockai
f0d314bd6d test: Disable lvmetad logging in lvconvert-{mirror,raid}*. 2015-02-05 13:47:19 +01:00
Petr Rockai
fa2e84caa8 NIX: Re-work VM monitoring. 2015-02-05 13:47:19 +01:00
Petr Rockai
f96c310eea NIX: Add Fedora 20 jobs. 2015-02-05 13:47:19 +01:00
Petr Rockai
0abad40f41 NIX: Existence of results list no longer indicates that the suite has finished. 2015-02-05 13:47:19 +01:00
Petr Rockai
e3ac180ab3 NIX: Drop -h from rpm invocations as it messes up logs. 2015-02-05 13:47:19 +01:00
Petr Rockai
6380869f27 NIX: Use nixpkgs kernel for building, distro kernel for testing. 2015-02-05 13:47:19 +01:00
Petr Rockai
2b6f9152cc NIX: Adapt to the append-based test journal. 2015-02-05 13:47:19 +01:00
Petr Rockai
285db7a240 NIX: Implement a smarter VM monitoring loop. 2015-02-05 13:47:19 +01:00
Petr Rockai
dcf5182a96 NIX: Use --batch mode for running the testsuite. 2015-02-05 13:47:19 +01:00
Petr Rockai
4b5ae31404 NIX: Refactor around the new test runner.
- The RPM build and the tests are now executed in separate VMs.
- Run the testsuite by using the new lvm2-testsuite RPM.
- The VM running the tests is restarted from the outside if it hangs, and the
  runner keeps a journal to avoid running a bad test ad infinitum.
- TODO: lcov reports and more intelligent VM rebooting (track the journal)
2015-02-05 13:47:19 +01:00
Petr Rockai
d5537e7d6b spec: Add an (optional) lvm2-testsuite subpackage. 2015-02-05 13:47:18 +01:00
Petr Rockai
d488f03229 test: Implement --only option to runner. 2015-02-05 13:47:18 +01:00
Petr Rockai
a8eb702093 test: Fix loading of an append-mode journal. 2015-02-05 13:47:18 +01:00
Petr Rockai
d74c147223 test: Add a missing copyright/licence notice to journal.h. 2015-02-05 13:47:18 +01:00
Petr Rockai
10c992e861 test: Fix a precedence bug in the runner. 2015-02-05 13:47:18 +01:00
Petr Rockai
b3caba849d test: Use append for journal maintenance instead of rename. 2015-02-05 13:47:18 +01:00
Petr Rockai
23b5a006d4 test: Implement specialised --batch output style w/ rusage stats. 2015-02-05 13:47:18 +01:00
Petr Rockai
a665b90623 test: Add time/rusage formatting to the runner. 2015-02-05 13:47:18 +01:00
Petr Rockai
3fbea6029d test: Print a heartbeat file (every 20s) in the runner. 2015-02-05 13:47:18 +01:00
Petr Rockai
e8cc9254e0 test: Avoid sleeps in the runner monitoring loop. 2015-02-05 13:47:18 +01:00
Petr Rockai
48275c7836 test: Run in /tmp if LVM_TEST_DIR is unset. 2015-02-05 13:47:18 +01:00
Petr Rockai
246fecee27 test: Rename the --quiet option to --batch. 2015-02-05 13:47:18 +01:00
Petr Rockai
feb2c7bc47 test: Targets and sources can't have the same name if builddir == srcdir. 2015-02-05 13:47:18 +01:00
Petr Rockai
2bc76bcdab test: Run the testcases chdir'd into --testdir. 2015-02-05 13:47:18 +01:00
Petr Rockai
efb3e7ca00 test: Improve IO handling in the runner. 2015-02-05 13:47:18 +01:00
Petr Rockai
8c8fb67fc2 test: Improve tracking of silence (stuck testcases) in the runner. 2015-02-05 13:47:18 +01:00
Petr Rockai
dc1d157878 test: Make the runner's journal more reliable. 2015-02-05 13:47:17 +01:00
Petr Rockai
d27833ba7c test: Implement flavours in the runner. 2015-02-05 13:47:17 +01:00
Petr Rockai
f3bf89ebcc test: Fix handling of envvars in the runner. 2015-02-05 13:47:17 +01:00
Petr Rockai
0bd2a9b7b1 test: Makefile updates.
- make check now uses the new test runner
- the testsuite can be installed (make -C test install)
2015-02-05 13:47:17 +01:00
Petr Rockai
b4215f956f test: Make it possible to run tests from an installed location. 2015-02-05 13:47:17 +01:00
Petr Rockai
5698953948 test: Use the new flavour setup files in lib/inittest. 2015-02-05 13:47:17 +01:00
Petr Rockai
9752ee8ed2 test: Fix IO sink destructors in the runner. 2015-02-05 13:47:17 +01:00
Petr Rockai
df27c64041 test: Add a buffer-backed IO sink (for interactive runs). 2015-02-05 13:47:17 +01:00
Petr Rockai
f53fcc0746 test: Implement a file-backed IO sink in the runner. 2015-02-05 13:47:17 +01:00
Petr Rockai
bdd0bc83eb test: Make runner use bigger IO buffers, put them on stack. 2015-02-05 13:47:17 +01:00
Petr Rockai
7957fc4a44 test: Allow test devices backed by a permanent block device. 2015-02-05 13:47:17 +01:00
Petr Rockai
c5a120c443 test: Add new flavour definition files. 2015-02-05 13:47:17 +01:00
Petr Rockai
fa46385164 test: Write a results/list at the end of a test run. 2015-02-05 13:47:17 +01:00
Petr Rockai
bf16937869 test: Clean up fds properly in the runner. 2015-02-05 13:47:16 +01:00
Petr Rockai
d2dbc65f00 test: Implement journalling and --continue. 2015-02-05 13:47:16 +01:00
Petr Rockai
9dfbce0aa7 test: Split up the new runner into multiple files. 2015-02-05 13:47:16 +01:00
Petr Rockai
b726d66882 test: Use the new runner in make check. 2015-02-05 13:47:16 +01:00
Petr Rockai
1ec2023cbf test: Build the new test runner. 2015-02-05 13:47:16 +01:00
Petr Rockai
9d6a92b4d0 configure: Add libexecdir/datadir to make.tmpl.in. 2015-02-05 13:47:16 +01:00
Petr Rockai
bf1f22cc99 configure: Allow C++ components. 2015-02-03 08:49:35 +01:00
Petr Rockai
f476655fee test: Import first draft of a new test runner. 2015-02-03 08:49:35 +01:00
Ondrej Kozina
f73526f58c libdaemon: set CLOEXEC flag on systemd socket
all sockets opened by a daemon or handed over by systemd
have to have CLOEXEC flag set. Otherwise we get nasty
warnings about leaking descriptors in processes spawned by
daemon.
2015-02-02 10:20:35 +01:00
Ondrej Kozina
9dd81df8b2 libdaemon: set CLOEXEC on client socket fd 2015-02-02 10:15:52 +01:00
Alasdair G Kergon
99c443facc post-release 2015-01-30 16:18:43 +00:00
Alasdair G Kergon
d0837dcceb pre-release 2015-01-30 16:16:51 +00:00
Zdenek Kabelac
71e88f761d tests: add --force to sfdisk
Avoid udev sync troubles for now.
2015-01-30 16:46:06 +01:00
Zdenek Kabelac
04b60e9274 WHATS_NEW
For thin fix.
2015-01-30 16:34:19 +01:00
Zdenek Kabelac
40102ae014 thin: fix upgrade regression
Older lvm2 tools where always providing linear mapping for thin pool.
Recent lvm2 version however support external usage of thin pool and
empty/unused pools are loaded without such external linear mapping.

So this patch covers 'upgrade' problem, where older tool has activated
thin-pool with 'linear' layer mapping, and newer tools didn't expected
such mapping to exist and were not able to deactivate such table.

So before checking for new layout in dm-table, check if there is not
an old one already there.
2015-01-30 16:22:11 +01:00
Zdenek Kabelac
a29a3ed3c3 thin: report proper status for thin pool
After commit 158e998876 where we may
start to readlv_attr with a 'shared' ioctl call for a single lvs line
we where obtaing single status for thin pools.
However this is not properly reflecting lvm2 reality.

Correcting this by reading lv status from layered thin pool, but lv info
from non-layered (linear) mapped device which is maintained for proper
cluster locking.
2015-01-30 15:58:12 +01:00
Peter Rajnoha
e8aab3a7fd cleanup: conf: auxiliary_device_status_source -> external_device_info_source
auxiliary_device_status_source was name used during development
of this feature, renamed later.
2015-01-30 15:41:42 +01:00
Zdenek Kabelac
434031719e raid: check lock holding LV
Since raid could be used as stacked LV - check lock holding LV
for proper locking type for clustered usage.
2015-01-30 14:16:27 +01:00
Peter Rajnoha
c99cb20715 WHATS_NEW 2015-01-30 13:29:51 +01:00
Peter Rajnoha
28ba0450e9 cleanup: add dev-ext-udev-constants.h with constants/names of the properties/values used from udev db 2015-01-30 13:17:12 +01:00
Peter Rajnoha
1c7a509bed filters: add firmware RAID filter
Just like MD filtering that detects components of software RAID (md),
add detection for firmware RAID.

We're not adding any native code to detect this - there are lots of
firmware RAIDs out there which is just out of LVM scope. However,
with current changes with which we're able to get device info from
external sources (e.g. external_device_info_source="udev"), we can
do this easily if the external device status source has this kind
of information - which is the case of "udev" source where the results
of blkid scans are stored.

This detection should cover all firmware RAIDs that blkid can detect and
which are identified as:
  ID_FS_TYPE = {adaptec,ddf,hpt45x,hpt37x,isw,jmicron,lsi_mega,nvidia,promise_fasttrack,silicon_medley,via}_raid_member
2015-01-30 13:17:12 +01:00
Peter Rajnoha
787f6ce04a filter-partitioned: use new 'udev' device status source to get partition status
Partitioned devices are marked in udev db as:
  ID_PART_TABLE="<partition table type name>"
and at the same time they are *not* marked with:
  ID_PART_ENTRY_DISK="<parent disk major:minor>"

Where partition table type name is dos/gpt/... But checking the presence
of this variable is enough for LVM here - it just needs to know whether
there's a partition table or not, not interested in the actual type.
The same applies for parent disk major:minor.
2015-01-30 13:17:12 +01:00
Peter Rajnoha
2fc126b00d filter-usable: move check for pv_min_size from filter-partitioned to filter-usable and use new 'udev' external device info source for this check
The filter-partitioned code should contain only checks in "partition" domain.

The check for pv_min_size should actually be a part of filter-usable.
If the device size is less than pv_min_size, such device is not usable
as a PV so this check clearly belongs here logically.

With udev external info source, we can get device size via libudev's
sysfs reading interface and we can avoid opening the device this way
effectively.
2015-01-30 13:01:12 +01:00
Peter Rajnoha
9c030e81a4 filter-mpath: use new 'udev' external device info source to get mpath component status
mpath components are marked in udev db as:
  ID_FS_TYPE="mpath_member"
or
  DM_MULTIPATH_DEVICE_PATH="1"

(it depends on udev rule/blkid version used for handling mpath)
2015-01-30 13:01:12 +01:00
Peter Rajnoha
590fbd8961 filter-md: use new 'udev' external device info source to get MD component status
MD components are marked in udev db as:
  ID_FS_TYPE="linux_raid_member"
2015-01-30 13:01:12 +01:00
Peter Rajnoha
bf8943b0f6 conf: add devices/external_device_info_source to lvm.conf 2015-01-30 13:01:12 +01:00
Peter Rajnoha
c50a90c9e6 filter-composite: add external device info hooks
Composite filter is a filter that can put several filters in one set.
This patch adds a switch when creating the composite filter which will
enable or disable external device info handles for all the filters
the composite filter encompasses.

We want to use this external device info for majority of the filters
which are in the "lvmetad filter chain" (or the respective part if
we're not using lvmetad).

Following patches will use the enabled external device handle in
concrete filters from the composite filter...
2015-01-30 13:01:12 +01:00
Peter Rajnoha
fbfde21e7c device: add infrastructure to support external device info 2015-01-30 13:01:12 +01:00
Zdenek Kabelac
578b236a19 revert "cache: add pool deps for preload"
This reverts commit c3bb6d77dd.

Since we now have  for_each_sub_lv() scanning all sub LVs,
this commit could be safely reverted.
2015-01-30 12:33:52 +01:00
Zdenek Kabelac
d021284bcf tests: test stacked raid 2015-01-30 12:33:52 +01:00
Zdenek Kabelac
2055b04c11 cleanup: indent tabs 2015-01-30 12:33:52 +01:00
Zdenek Kabelac
2e35c68122 lv_manip: add for_each_sub_lv_except_pools()
for_each_sub_lv() now scans in depth also pools, however for
rename we actually do want to skip pools.

So add a new for_each_sub_lv_except_pools() to be used by rename,
every other user of for_each_sub_lv() scans every sub LV with pools
included.

This is i.e. necessary for properly working preload of pools
that are using raid arrays.
2015-01-30 12:33:52 +01:00
Peter Rajnoha
c35503e0f7 WHATS_NEW: previous commit 2015-01-30 11:28:10 +01:00
Peter Rajnoha
8650404df1 properties: also recognize LVSINFO, LVSSTATUS and LVSINFOSTATUS as subtypes of LVS
LVSINFO, LVSSTATUS and LVSINFOSTATUS is the same as LVS, just with some
extra info/status decoration attached to it. Recognize this when looking
for properties for lvm2app. This fixes lvm_lv_get_property lvm2app call
for fields which already use LVS{INFO,STATUS,INFOSTATUS} - currently,
this is lv_attr field which was converted to LVSINFOSTATUS from
pure LVS type.
2015-01-30 11:13:49 +01:00
Peter Rajnoha
531cc58d89 lvm2app: fix lvm_lv_get_attr regression causing unknown values
This is a regression from v115 where some of the fields/properties
were converted to using the common "struct lvinfo" and
"struct lv_seg_status" so we don't need to issue info and status
ioctl several times per one reported line. Not all fields are
converted yet, but one that *is* converted is the lv_attr field
with the lv_attr_dup counterpart used in lvm_lv_get_attr lvm2app fn.

These changes were introduced with e34b004422
and later - this patch introduced the "info_ok" field in the
lv_with_info_and_seg_status structure which encapsulates the lvinfo
and lv_seg_status struct.

For the lv_attr_dup, the lv_attr_dup code  missed the
assignment for the "info_ok" flag which saves the result of the
lv_info_with_seg_status call. Hence such info was marked
as unusable - unknown and it was returned as such via lvm_lv_get_attr
lvm2app fn.
2015-01-30 09:53:34 +01:00
Zdenek Kabelac
8dc1da2cbe cache: use writethrough cache_mode for older metadata
When cache_mode is undefined, the read of metadata will miss to
set a bit with mode and fails to process metadata on internal
error:

  Internal error: LV vg/lvol1 has uknown feature flags 0.

Fix it by setting it to writethrough mode.
2015-01-29 12:05:58 +01:00
Zdenek Kabelac
bfeabea631 raid: preload splitted LV only when active
Check splitted leg is active before preload.
(Since splitmirrors currently only does work active raid volumes
it's not a change for current code flow).

Minor optimization included - when already positively checked
for raid image don't check again for raid metadata.
2015-01-28 18:30:08 +01:00
Zdenek Kabelac
c3bb6d77dd cache: add pool deps for preload
for_each_sub_lv() normally does not put  pool_lv into deps.

So for now go around it in 'lv_preload()' and add explicit
call with pool.

TODO: think about a better way, we want pool_lv deps only in certain
moments, so maybe for_each_sub_lv() needs new arg for this.
2015-01-28 16:29:35 +01:00
Zdenek Kabelac
4f1309080a thin: preserve chunksize with lvconvert
When repairing thin pool or swapping thin pool metadata,
preserve  chunk_size property and avoid to be automatically changed
later in the code to better match thin pool metadata size.
2015-01-28 15:15:52 +01:00
Zdenek Kabelac
d2d3f0d747 cleanup: use macro lv_is_visible() 2015-01-28 13:45:27 +01:00
Zdenek Kabelac
553f37da71 raid: lock holder will skip visible raid LVs
RAID marks legs as VISIBLE with notion it's not longer
true raid leg - so skip tree scannig and take this LV
as top-level LV.
2015-01-28 13:45:27 +01:00
Zdenek Kabelac
93b9015760 raid: fix raid image splitting
When raid leg is extracted, now the preload code handles this state
correctly and put proper new table entry into dm tree,
so the activation of extracted leg and removed metadata works
after commit.
2015-01-28 13:45:18 +01:00
Zdenek Kabelac
b254d330e4 raid: fix tree preload for splitting raid images
When raid is being splitted, extracted leg & metadata
is still floating in the table - and thus we need to
detect this case and properly preload their matching
table so consequent activation of extracted LVs properly
renames (and FREES) existing raid images, so ongoing
image name shifting will work.
2015-01-28 13:44:06 +01:00
Alasdair G Kergon
3e11d85c77 devices: DASD doesn't need to be stackable. 2015-01-23 20:32:31 +00:00
Alasdair G Kergon
dab3ebce4c devices: Do not support unpartitioned DASD. 2015-01-23 20:01:34 +00:00
David Teigland
4f5ce1fa43 lvm.conf: update error_when_full description
Relate it to the --errorwhenfull option.
2015-01-22 13:01:02 -06:00
David Teigland
4b099d06b1 lvmthin: update monitor and autoextend
and some more in data exhaustion
2015-01-22 12:53:25 -06:00
Peter Rajnoha
0fddc5ab5c coverity: missing return value check
Reported by coverity for code added recently - _avoid_pvs_with_other_images_of_lv
which calls process_each_sub_lv and not checking return value.
2015-01-22 10:11:19 +01:00
David Teigland
e0dc3d5efb lvmthin: update data space exhaustion 2015-01-21 14:31:36 -06:00
Peter Rajnoha
bea003e94c config: improve config validation to check if setting with string value can be empty.
For example, with dmeventd/executable set to "" which is not allowed for
this setting, the config validation now ends up with:

$ lvm dumpconfig --validate
  Configuration setting "dmeventd/executable" invalid. It cannot be set to an empty value.
  LVM configuration invalid.

This check for empty values for string config settings was not
done before (we only checked empty arrays, but not scalar strings).
2015-01-21 16:44:02 +01:00
Alasdair G Kergon
57f67ce855 post-release 2015-01-21 13:25:10 +00:00
Alasdair G Kergon
fa01faaa4a pre-release 2015-01-21 13:08:12 +00:00
Alasdair G Kergon
25d906dbde dmeventd: Reduce waitevent EINTR message severity. 2015-01-21 12:54:00 +00:00
Alasdair G Kergon
7cfc9a4f64 libdevmapper: Improve incompatible version msg. 2015-01-21 12:23:56 +00:00
Peter Rajnoha
338d98be97 cleanup: for commit 7bcb3fb02d 2015-01-21 11:29:12 +01:00
Peter Rajnoha
7bcb3fb02d report: rename lv_error_when_full field to lv_when_full and display either "error", "queue" or ""
Rename original lv_error_when_full field to lv_when_full and also
convert it from binary field to string field displaying three
possible values: "error", "queueu" or "" (blank for undefined).

$ lvs vg/pool vg/pool1 vg/linear_lv -o+lv_when_full
  LV        VG   Attr       LSize Data%  Meta%  WhenFull
  linear_lv vg   -wi-a----- 4.00m
  pool      vg   twi-aotz-- 4.00m 0.00   0.98   queue
  pool1     vg   twi-a-tz-- 4.00m 0.00   0.88   error

For -S|--select these synonyms are recognized:

"error" -> "error when full", "error if no space"
"queue" -> "queue when full", "queue if no space"
   ""   -> "undefined"
2015-01-21 10:50:32 +01:00
David Teigland
5e8f362c9e lvmthin: include errorwhenfull
and don't display the size of pmspare to avoid setting an
expectation of a specific size.
2015-01-20 13:28:34 -06:00
David Teigland
a164d603d3 vgimportclone: remove arg check that uses pvs
The arg check using pvs is unnecessary.  If the arg is not a PV,
the command will just fail later.  Using the pvs command at this
point in the command is a problem when lvmetad is running, because
the pvs command does not report duplicate PVs when using lvmetad.
(Alternatively, use_lvmetad could be disabled by adding a --config
override to this pvs command.)
2015-01-20 13:08:22 -06:00
Alasdair G Kergon
404c834e14 report: Fix warning in _str_list_append.
../../lib/report/report.c: In function ‘_str_list_append’:
../../lib/report/report.c:256: warning: declaration of ‘dup’ shadows a global declaration
2015-01-20 17:15:28 +00:00
Zdenek Kabelac
87e80b6aac report: proper lv_attr_dup emulation
We need to create a mempool for proper emulation of lv_attr_dup
for lvm2api.
2015-01-20 16:24:45 +01:00
Peter Rajnoha
158e998876 report: add separate LVSINFOSTATUS field type for info+status combined fields
Add separate LVSINFOSTATUS field type for fields which display both
dm info-like and dm status-like information.

The internal interface is there with the introduction of LVSSTATUS
field type which can cope with the combination of LVSSTATUS
and LVSINFO field types (several fields).

However, till now, we considered that *single* field can display
either LVSINFO or LVSSTATUS, but not both at the same time.

Till now, we haven't had single field which needs both - hence
add LVSINFOSTATUS field type for such fields as we currently
need this for the lv_attr field which requires combination of
info and status.

This patch just adds interface for an ability to register such fields
(the code that copes with this is already in).
2015-01-20 16:10:59 +01:00
Zdenek Kabelac
75b786c5ef thin: support errorwhenfull with thin creation
When thinpool and thinvolume are created at the same time,
still support usage of --errorwhenfull.
2015-01-20 15:43:16 +01:00
Zdenek Kabelac
a625812bec report: use info
Use LVSINFO since  LVSSTATUS only fills status
2015-01-20 15:25:05 +01:00
Zdenek Kabelac
3b78d5237d cleanup: indent 2015-01-20 15:02:19 +01:00
Zdenek Kabelac
3cef00c4ca man: errorwhenfull doc 2015-01-20 15:02:19 +01:00
Zdenek Kabelac
d80d832ae9 report: seg_monitor undefined
Add 'undefined' value for segment which do not support monitoring.
Fixes crash for commands like 'pvs -o+seg_monitor'.
2015-01-20 15:02:10 +01:00
Zdenek Kabelac
ae8b9baa04 report: update report_object API
Internal API change - pass single struct for both info & seg_status.
2015-01-20 14:58:43 +01:00
Zdenek Kabelac
b3a348c03c report: use same info also for lv_attr
Recently the single 'status' code has been used for number of cache
features.

Extend the API a little bit to allow usage also for lv_attr_dup.

As the function itself is used in lvm2api - add a new function:
lv_attr_dup_with_info_and_seg_status() that is able to use
grabbed info & status information.

report_init() is now using directly passed lvdm struct pointer
which holds the infomation whether lv_info() was correctly obtained or
there was some error when trying to read it.

Move 'healt' attribute to status.
TODO convert raid function to use the already known status.
2015-01-20 14:58:41 +01:00
Zdenek Kabelac
e34b004422 report: reporting unknown status
Add SEG_STATUS_UNKNOWN when status cannot be parsed.
Also add 'info_ok' variable when info was correctly obtained.
2015-01-20 14:53:07 +01:00
Zdenek Kabelac
64d8ed502d thin: lvchange support for errorwhenfull
Support lvchange --errorwhenfull y|n for thin pools.
2015-01-20 14:53:03 +01:00
Zdenek Kabelac
07eb1c7dc8 cleanup: add lv_is_error_when_full() macro
Like with other status bits use macro for testing.
(in-release update)
2015-01-20 14:52:06 +01:00
Alasdair G Kergon
8f90f632f5 vgimportclone: Say safe to ignore lvmetad message. 2015-01-17 11:29:38 +00:00
Alasdair G Kergon
e5ffacc434 man: Remove renamed writebehind field from lvs.8. 2015-01-17 11:05:25 +00:00
Alasdair G Kergon
651549594e libdm-report: Fix order of NULL dm_report check. 2015-01-17 10:50:54 +00:00
Heinz Mauelshagen
302b6c99a7 raid_manip: v2 fix multi-segment misallocation on 'lvconvert --repair'
The previous patch felt short WRT disabling allocation on PVs holding other
legs of the RAID LV persistently; this patch introduces an internal,
transient PV flag PV_ALLOCATION_PROHIBITED to address this very problem.

General problem description for completeness:

An 'lvconvert --repair $RAID_LV" to replace a failed leg of a multi-segment
RAID10/4/5/6 logical volume can lead to allocation of (parts of) the replacement
image component pair on the physical volume of another image component
(e.g. image 0 allocated on the same PV as image 1 silently impeding resilience).

Patch fixes this severe resilince issue by prohibiting allocation on PVs
already holding other legs of the RAID set. It allows to allocate free space
on any operational PV already holding parts of the image component pair.
2015-01-16 13:44:16 +01:00
David Teigland
0bcc0cf95d WHATS_NEW: previous commits related to duplicate PVs 2015-01-14 14:52:12 -06:00
David Teigland
b64da4d8b5 toollib: search for duplicate PVs only when needed
A full search for duplicate PVs in the case of pvs -a
is only necessary when duplicates have previously been
detected in lvmcache.  Use a global variable from lvmcache
to indicate that duplicate PVs exist, so we can skip the
search for duplicates when none exist.
2015-01-14 14:47:08 -06:00
David Teigland
3a7c47af0e toollib: pvs -a should display VG name for each duplicate PV
Previously, 'pvs -a' displayed the VG name for only the device
associated with the cached PV (pv->dev), and other duplicate
devices would have a blank VG name.  This commit displays the
VG name for each of the duplicate devices.  The cost of doing
this is not small: for each PV processed, the list of all
devices must be searched for duplicates.
2015-01-14 14:16:03 -06:00
David Teigland
57d74a45a0 toollib: override the PV device with duplicates
When multiple duplicate devices are specified on the
command line, the PV is processed once for each of them,
but pv->dev is the device used each time.

This overrides the PV device to reflect the duplicate
device that was specified on the command line.  This is
done by hacking the lvmcache to replace pv->dev with the
device of the duplicate being processed.  (It would be
preferable to override pv->dev without munging the content
of the cache, and without sprinkling special cases throughout
the code.)

This override only applies when multiple duplicate devices are
specified on the command line.  When only a single duplicate
device of pv->dev is specified, the priority is to display the
cached pv->dev, so pv->dev is not overridden by the named
duplicate device.

In the examples below, loop3 is the cached device referenced
by pv->dev, and is given priority for processing.  Only after
loop3 is processed/displayed, will other duplicate devices
loop0/loop1 appear (when requested on the command line.)

With two duplicate devices, loop0 and loop3:

  # pvs
  Found duplicate PV XhLbpVo0hmuwrMQLjfxuAvPFUFZqD4vr: using /dev/loop3 not /dev/loop0
  PV         VG           Fmt  Attr PSize   PFree
  /dev/loop3 loopa        lvm2 a--   12.00m  12.00m

  # pvs /dev/loop3
  Found duplicate PV XhLbpVo0hmuwrMQLjfxuAvPFUFZqD4vr: using /dev/loop3 not /dev/loop0
  PV         VG    Fmt  Attr PSize  PFree
  /dev/loop3 loopa lvm2 a--  12.00m 12.00m

  # pvs /dev/loop0
  Found duplicate PV XhLbpVo0hmuwrMQLjfxuAvPFUFZqD4vr: using /dev/loop3 not /dev/loop0
  PV         VG    Fmt  Attr PSize  PFree
  /dev/loop3 loopa lvm2 a--  12.00m 12.00m

  # pvs -o+dev_size /dev/loop0 /dev/loop3
  Found duplicate PV XhLbpVo0hmuwrMQLjfxuAvPFUFZqD4vr: using /dev/loop3 not /dev/loop0
  PV         VG    Fmt  Attr PSize  PFree  DevSize
  /dev/loop0 loopa lvm2 a--  12.00m 12.00m  16.00m
  /dev/loop3 loopa lvm2 a--  12.00m 12.00m  32.00m

With three duplicate devices, loop0, loop1, loop3:

  # pvs -o+dev_size
  Found duplicate PV XhLbpVo0hmuwrMQLjfxuAvPFUFZqD4vr: using /dev/loop1 not /dev/loop0
  Found duplicate PV XhLbpVo0hmuwrMQLjfxuAvPFUFZqD4vr: using /dev/loop3 not /dev/loop1
  PV         VG           Fmt  Attr PSize   PFree   DevSize
  /dev/loop3 loopa        lvm2 a--   12.00m  12.00m  32.00m

  # pvs -o+dev_size /dev/loop3
  Found duplicate PV XhLbpVo0hmuwrMQLjfxuAvPFUFZqD4vr: using /dev/loop1 not /dev/loop0
  Found duplicate PV XhLbpVo0hmuwrMQLjfxuAvPFUFZqD4vr: using /dev/loop3 not /dev/loop1
  PV         VG    Fmt  Attr PSize  PFree  DevSize
  /dev/loop3 loopa lvm2 a--  12.00m 12.00m  32.00m

  # pvs -o+dev_size /dev/loop0
  Found duplicate PV XhLbpVo0hmuwrMQLjfxuAvPFUFZqD4vr: using /dev/loop1 not /dev/loop0
  Found duplicate PV XhLbpVo0hmuwrMQLjfxuAvPFUFZqD4vr: using /dev/loop3 not /dev/loop1
  PV         VG    Fmt  Attr PSize  PFree  DevSize
  /dev/loop3 loopa lvm2 a--  12.00m 12.00m  32.00m

  # pvs -o+dev_size /dev/loop1
  Found duplicate PV XhLbpVo0hmuwrMQLjfxuAvPFUFZqD4vr: using /dev/loop1 not /dev/loop0
  Found duplicate PV XhLbpVo0hmuwrMQLjfxuAvPFUFZqD4vr: using /dev/loop3 not /dev/loop1
  PV         VG    Fmt  Attr PSize  PFree  DevSize
  /dev/loop3 loopa lvm2 a--  12.00m 12.00m  32.00m

  # pvs -o+dev_size /dev/loop3 /dev/loop0
  Found duplicate PV XhLbpVo0hmuwrMQLjfxuAvPFUFZqD4vr: using /dev/loop1 not /dev/loop0
  Found duplicate PV XhLbpVo0hmuwrMQLjfxuAvPFUFZqD4vr: using /dev/loop3 not /dev/loop1
  PV         VG    Fmt  Attr PSize  PFree  DevSize
  /dev/loop0 loopa lvm2 a--  12.00m 12.00m  16.00m
  /dev/loop3 loopa lvm2 a--  12.00m 12.00m  32.00m

  # pvs -o+dev_size /dev/loop3 /dev/loop1
  Found duplicate PV XhLbpVo0hmuwrMQLjfxuAvPFUFZqD4vr: using /dev/loop1 not /dev/loop0
  Found duplicate PV XhLbpVo0hmuwrMQLjfxuAvPFUFZqD4vr: using /dev/loop3 not /dev/loop1
  PV         VG    Fmt  Attr PSize  PFree  DevSize
  /dev/loop1 loopa lvm2 a--  12.00m 12.00m  32.00m
  /dev/loop3 loopa lvm2 a--  12.00m 12.00m  32.00m

  # pvs -o+dev_size /dev/loop0 /dev/loop1
  Found duplicate PV XhLbpVo0hmuwrMQLjfxuAvPFUFZqD4vr: using /dev/loop1 not /dev/loop0
  Found duplicate PV XhLbpVo0hmuwrMQLjfxuAvPFUFZqD4vr: using /dev/loop3 not /dev/loop1
  PV         VG    Fmt  Attr PSize  PFree  DevSize
  /dev/loop1 loopa lvm2 a--  12.00m 12.00m  32.00m
  /dev/loop3 loopa lvm2 a--  12.00m 12.00m  32.00m

  # pvs -o+dev_size /dev/loop0 /dev/loop1 /dev/loop3
  Found duplicate PV XhLbpVo0hmuwrMQLjfxuAvPFUFZqD4vr: using /dev/loop1 not /dev/loop0
  Found duplicate PV XhLbpVo0hmuwrMQLjfxuAvPFUFZqD4vr: using /dev/loop3 not /dev/loop1
  PV         VG    Fmt  Attr PSize  PFree  DevSize
  /dev/loop0 loopa lvm2 a--  12.00m 12.00m  16.00m
  /dev/loop1 loopa lvm2 a--  12.00m 12.00m  32.00m
  /dev/loop3 loopa lvm2 a--  12.00m 12.00m  32.00m
2015-01-14 11:57:29 -06:00
David Teigland
c1f246fedf toollib: handle duplicate pvs in process_in_pv
Processes a PV once for each time a device with its PV ID
exists on the command line.

This fixes a regression in the case where:

. devices /dev/sdA and /dev/sdB where clones (same PV ID)

. the cached VG references /dev/sdA

. before the regression, the command: pvs /dev/sdB
  would display the cached device clone /dev/sdA

. after the regression, pvs /dev/sdB would display nothing,
  causing vgimportclone /dev/sdB to fail.

. with this fix, pvs /dev/sdB displays /dev/sdA

Also, pvs /dev/sdA /dev/sdB will report two lines, one for each
device on the command line, but /dev/sdA is displayed for each.

This only works without lvmetad.
2015-01-14 11:57:29 -06:00
Petr Rockai
eac4e1e939 dmeventd: Call lvscan --cache also for mirrors (in addition to RAID). 2015-01-14 18:05:44 +01:00
Zdenek Kabelac
4a55175bac WHATS_NEW
More news
2015-01-14 15:15:29 +01:00
Zdenek Kabelac
2908ab3eed thin: errrorwhenfull support
Support error_if_no_space feature for thin pools.
Report more info about thinpool status:
(out_of_data (D), metadata_read_only (M), failed  (F) also as health
attribute.)
2015-01-14 14:52:05 +01:00
Zdenek Kabelac
1e050a77ff cleanup: missed for build without devmapper
configure --disable-devmapper build fixes.
2015-01-14 14:50:08 +01:00
Zdenek Kabelac
0869631d7d lv_status: enable lv_status for thinpool
Support also status for thin pools.
2015-01-14 14:50:08 +01:00
Zdenek Kabelac
0b7ccf835b lv_status: track layered device
For info of i.e. thin-pool we need layered device.
Needs some more thinking about proper interface here.
For now it's usable for cache and thin-pool.
2015-01-14 14:50:08 +01:00
Zdenek Kabelac
d0f26440ee cleanup: properly align code lines
Misaligned indetion in branches.
2015-01-14 14:50:08 +01:00
Zdenek Kabelac
d202f43fff cleanup: update API for segment reporting
API for seg reporting is breaking internal lvm coding - it cannot
use vgmem mem pool for allocation of reported value.
So use separate pool instead of 'vgmem' for non vg related allocations

Add consts for many function params - but still many other are left
for now as non-const - needs deeper level of change even on libdm side.
2015-01-14 14:50:08 +01:00
Heinz Mauelshagen
cdd17eee37 raid_manip: fix multi-segment misallocation on 'lvconvert --repair'
An 'lvconvert --repair $RAID_LV" to replace a failed leg of a multi-segment
RAID10/4/5/6 logical volume can lead to allocation of (parts of) the replacement
image component pair on the physical volume of another image component
(e.g. image 0 allocated on the same PV as image 1 silently impeding resilience).

Patch fixes this severe resilince issue by prohibiting allocation on PVs
already holding other legs of the RAID set. It allows to allocate free space
on any operational PV already holding parts of the image component pair.
2015-01-14 13:41:55 +01:00
Peter Rajnoha
8804023825 tests: pvscan --cache DevicePath does not fail if the device is just filtered
It's not an error if the device is filtered out and hence cleared from
lvmetad cache - "pvscan --cache DevPath" has now the same behaviour in
this case as "pvscan --cache major:minor" (which is more consistent).

Before, the tests expected failure return code for "pvscan --cache DevicePath"
if the device was filtered (which is a different situation if the device
is missing in the system completely!).
2015-01-12 15:16:57 +01:00
Peter Rajnoha
99d895014d dev-type: filter out partitioned device-mapper devices as unsuitable for use as PVs
Normally, if there are partitions defined on top of device-mapper
device, there should be a device-mapper device created for each
partiton on top of the old one and once the underlying DM device
is used by another devices (partition mappings in this case),
it can't be used as a PV anymore.

However, sometimes, it may happen the partition mappings are
missing - either the partitioning tool is not creating them if
it does not contain full support for device-mapper devices or
the mappings were removed.

Better safe than sorry - check for partition header on DM devs
and filter them out as unsuitable for PVs in case the check is
positive. Whatever the user is doing, let's do our best to prevent
unwanted corruption (...by running pvcreate on top of such device
that would corrupt the partition header).
2015-01-12 14:10:44 +01:00
Peter Rajnoha
8dbe767340 pvscan: notify lvmetad about device that is gone and pvscan is run with device path instead of major:minor pair
If pvscan is run with device path instead of major:minor pair and this
device still exists in the system and the device is not visible anymore
(due to a filter that is applied), notify lvmetad properly about this.

This makes it more consistent with respect to existing pvscan with
major:minor which already notifies lvmetad about device that is gone
due to filters.

However, if the device is not in the system anymore, we're not able
to translate the original device path into major:minor pair which
lvmetad needs for its action (lvmetad_pv_gone fn). So in this case,
we still need to use major:minor pair only, not device path. But at
least make "pvscan --cache DevicePath" as near as possible to "pvscan
--cahce <major>:<minor>" functionality.

Also add a note to pvscan man page about this difference when using
pvscan --cache with DevicePath and major:minor pair.
2015-01-12 13:59:51 +01:00
David Teigland
1e4a4d48ae toollib: process_each_pv should match by device
When processing PVs specified on the command line, the arg
name was being matched against pv_dev_name, which will not
always work:

- The PV specified on the command line could be an alias,
  e.g. /dev/disk/by-id/...

- The PV specified on the command line could be any random
  path to the device, e.g. /dev/../dev/sdb

To fix this, first resolve the named PV args to struct device's,
then iterate through the devices for processing.
2015-01-09 10:03:31 -06:00
Peter Rajnoha
6a77b6f43c scripts: clvmd: replace awk functionality with LVM's selection
No need to use awk now to get appropriate VGs/LVs, use LVM's
own --select - it's quicker, it removes a need for external
dependency on awk and it's also more readable.
2015-01-09 16:41:07 +01:00
Peter Rajnoha
fb7e2ff493 metadata: add "Failed to write VG <vg_name>." on failed vg_write and revert previous patch
Better than previous patch which changed log_warn to log_error -
we can have multiple MDAs and if one of them fails to be written,
we can still continue with other MDAs if we're in a mode where
we can handle missing PVs - so keep the log_warn for single
failed MDA write as it was before.

However, add log_error with "Failed to write VG <vg_name>." in
case we're not handling missing PVs or no MDA was written at all
during VG write process. This also prevents an internal error in
which the vg_write fails and we're not issuing any other log_error
in vg_write caller or above, so we end up with:
  "Internal error: Failed command did not use log_error".
2015-01-09 14:04:44 +01:00
Peter Rajnoha
db7351d313 metadata: log_error instead of log_warn on failed mda write 2015-01-09 12:00:03 +01:00
Peter Rajnoha
08ac12d5e7 WHATS_NEW: line for previous commit 2015-01-09 11:57:25 +01:00
Peter Rajnoha
c0e17bca90 dev_manager: do not mark snapshot origins as unusable devices just because of possible blocked mirror underneath
At first, all snapshot-origins where marked as unusable unconditionally
here, but we can't cut off whole snapshot-origin use in a stack just
because of this possible mirror state. This whole "device_is_usable"
check was even incorrectly part of persistent filter before commit
a843d0d97c66aae1872c05b0f6cf4bda176aae2 (where filter cleanup was
done).

The persistent filter is used only if obtain_device_list_from_udev=0,
which means that the former check for snapshot-origin here had not even
been hit with default configuration for a few years before commit
a843d0d97c66aae1872c05b0f6cf4bda176aae2 (the check for snapshot-origin and
skipping of this LV was introduced with commit a71d6051ed
back in 2010).

The obtain_device_list_from_udev=1 (and hence not using persistent
filter and hence not hitting this check for snapshot-origins and skipping) has been
in action since commit edcda01a1e (that is 2011).
So for 3 years this condition was not even checked with default configuration,
making it superfluous.

This all changed in 2014 with commit 8a843d0d97
where "filter-usable" is introduced  and since then all snapshot-origins
have been marked as unusable more often than before and making snapshot-origins
practically unusable in a stack.

This patch removes this incorrect check from commit a71d6051ed
which caused snapshot-origins to be unusable more often recently.

If we want to fix this eventually in a correct way, we need to look
down the stack and if snapshot-origin is hit and there's a blocked
mirror underneath, only then mark the device as unusable. But mirrors
in stack are not supported anymore so it's questionable whether it's
worth spending more time on this at all...
2015-01-09 11:24:16 +01:00
Peter Rajnoha
9dbeacf303 WHATS_NEW: previous commit 2015-01-07 13:47:16 +01:00
Heinz Mauelshagen
aaecbb1818 raid: fix mirror image naming when converting from mirror to raid1
$ lvcreate -l1 -m1 --type mirror vg
  Logical volume "lvol0" created.
$ lvconvert --type raid1 vg/lvol0

Before:
$ lvs -a vg
  LV                        VG     Active Attr       LSize   Cpy%Sync Layout     Role
  lvol0                     vg     active rwi-a-r---   4.00m 100.00   raid,raid1 public
  [lvol0_mimage_0_rimage_0] vg     active iwi-aor---   4.00m          linear     private,raid,image
  [lvol0_mimage_1_rimage_1] vg     active iwi-aor---   4.00m          linear     private,raid,image
  [lvol0_rmeta_0]           vg     active ewi-aor---   4.00m          linear     private,raid,metadata
  [lvol0_rmeta_1]           vg     active ewi-aor---   4.00m          linear     private,raid,metadata

Incorrect name: lvol0_mimage_0_rimage_0

With this patch applied:
$ lvs -a vg
  LV               VG   Active Attr       LSize Cpy%Sync Layout     Role
  lvol0            vg   active rwi-a-r--- 4.00m 100.00   raid,raid1 public
  [lvol0_rimage_0] vg   active iwi-aor--- 4.00m          linear     private,raid,image
  [lvol0_rimage_1] vg   active iwi-aor--- 4.00m          linear     private,raid,image
  [lvol0_rmeta_0]  vg   active ewi-aor--- 4.00m          linear     private,raid,metadata
  [lvol0_rmeta_1]  vg   active ewi-aor--- 4.00m          linear     private,raid,metadata

Proper name: lvol0_rimage_0
2015-01-07 13:25:08 +01:00
Peter Rajnoha
ff1eca3b6f mirror: do not try to reactivate inactive mirror when removing its LVs which have missing PVs
When mirror has missing PVs and there are mirror images on those missing
PVs, we delete the images and during this delete operation, we also
reactivate the LV. But if we're trying to reactivate the LV in cluster
which is not active and at the same time cmirrord is not running (which
is OK since we may have created the mirror LV as inactive), we end up
with:
  "Error locking on node <node_name>: Shared cluster mirrors are not available."

That is because we're trying to activate the mirror LV without cmirrord.
However, there's no need to do this reactivation if the mirror LV (and
hence it's sub LVs) were not activated before.

This issue caused failure in mirror-vgreduce-removemissing.sh test
recently with this sequence (excerpt from the test script):

  prepare_lvs_
  lvcreate -an -Zn -l2 --type mirror -m1 --nosync -n $lv1 $vg "$dev1" $dev2" "$dev3":$BLOCKS
  mimages_are_on_ $lv1 "$dev1" "$dev2"
  mirrorlog_is_on_ $lv1 "$dev3"
  aux disable_dev "$dev2"
  vgreduce --removemissing --force $vg

The important thing about that test is that we're not running cmirrord,
we're activating the mirror with "-an" so it's inactive and then
vgreduce --removemissing tries to reactivate the mirror images
as part of the _delete_lv function call inside and since cmirrord
is not running, we end up with the "Shared cluster mirrors are not
available." error.
2015-01-07 11:16:19 +01:00
Petr Rockai
e97023804a pvremove: Avoid metadata re-reads & related error messages. 2015-01-06 14:27:30 +01:00
Petr Rockai
0987f290a7 lvmetad: Re-use fmt from the VG for PVs when possible. 2015-01-06 14:27:30 +01:00
Peter Rajnoha
509650ec4c cmirror: do not check for cmirror availability when creating deactivated cluster mirrors
When creating cluster mirrors while they're not supposed to be activated
immediately after creation, we don't need to check for cmirrord availability.
We can just create these mirrors and let the check to be done on activation
later on. This is addendum for commit cba6186325.
2015-01-06 09:59:04 +01:00
Peter Rajnoha
cba6186325 cmirror: check for cmirror availability during cluster mirror creation and activation
When creating/activating clustered mirrors, we should have cmirrord
available and running. If it's not, we ended up with rather cryptic
errors like:

$ lvcreate -l1 -m1 --type mirror vg
  Error locking on node 1: device-mapper: reload ioctl on  failed: Invalid argument
  Failed to activate new LV.

$ vgchange -ay vg
  Error locking on node node 1: device-mapper: reload ioctl on failed: Invalid argument

This patch adds check for cmirror availability and it errors out
properly, also giving a more precise error messge so users are able
to identify the source of the problem easily:

$ lvcreate -l1 -m1 --type mirror vg
  Shared cluster mirrors are not available.

$ vgchange -ay vg
  Error locking on node 1: Shared cluster mirrors are not available.

Exclusively activated cluster mirror LVs are OK even without cmirrord:

$ vgchange -aey vg
  1 logical volume(s) in volume group "vg" now active
2015-01-05 16:54:07 +01:00
Peter Rajnoha
3e0ed83bc8 libdm: report: add more comments about helper macros to get reserved values
Since GET_FIELD_RESERVED_VALUE always returns a pointer, don't reference
it with "&" when used - we already have that pointer value (this is an
addendum to recent commit 028ff30947).

Only GET_TYPE_RESERVED_VALUE needs to be referenced with "&" as it
returns directly the value of that type.
2014-12-19 09:23:05 +01:00
Peter Rajnoha
57af48d734 report: fix segfault on NULL value hit in cache_settings field
We have to use empty list, not NULL if we want to denote that the list
has no items. Otherwise, the code further can segfault as it expects
there's always a sane value (= some list), including empty list,
but never NULL.
2014-12-18 17:26:12 +01:00
Peter Rajnoha
da9da0d8c2 report: properly set "undefined" reserved value for cache_policy field
Use helper macros to handle reserved values and also define "undefined"
reserved value as:

FIELD_RESERVED_VALUE(cache_policy, cache_policy_undef, "", "", "undefined")

Which means:

 - print "" if the cache_policy value is undefined (the first name for this reserved value is "")
 - recognize "undefined" reserved name as synonym to ""
   (so statements like "lvs -S cache_policy=undefined" are still recognized)
2014-12-18 15:21:21 +01:00
Peter Rajnoha
028ff30947 cleanup: use helper macros to get reserved value from values.h for vg_mda_copies and lv_read_ahead fields
Avoid making a copy of the keyword which is already registered in
values.h for "unmanaged" (vg_mda_copies field) and "auto" reserved
value (lv_read_ahead field). Also use helper macros to handle these
reserved - this is the correct approach - just do not copy the same
thing again and do not mix it! The GET_FIELD_RESERVED_VALUE and
GET_FIRST_RESERVED_NAME macros guarantees this - use it!

In addition to that, rename reserved values:
  vg_mda_copies --> vg_mda_copies_unmanaged
  lv_read_ahead --> lv_read_ahead_auto

So the field reserved values follows this scheme:

   "<field_name>_<reserved_value_name>".

The same applies for type reserved values with this scheme:

  "<report type name in lowercase>_<reserved_value_name>"

Add a comment about this scheme for others to follow as well
when adding new fields and their reserved values. This makes
it a bit easier to read the code then.
2014-12-18 15:07:46 +01:00
Peter Rajnoha
7e85d4f5f6 refactor: rename existing helper macros for reserved value handling and add GET_FIELD_RESERVED_VALUE macro
RESERVED(id)   --> GET_TYPE_RESERVED_VALUE(id)
FIRST_NAME(id) --> GET_FIRST_RESERVED_NAME(id)

Also add GET_FIELD_RESERVED_VALUE(id) macro to get per-field reserved value.

This makes it much more readable and hopefully it'll make it
easier to use these helper macros when adding new reporting
fields with reserved values if needed.
2014-12-18 14:42:14 +01:00
Peter Rajnoha
f6f32f39e4 report: dup cache policy name string for report in cache_policy field
The cache policy name taken as LV segment property must be duped
for report as the VG/LV/seg structure is destroyed after processing,
reporting happens later:

$ valgrind lvs -o+cache_policy
...
==16589== Invalid read of size 1
==16589==    at 0x54ABCC3: dm_report_compact_fields
(libdm-report.c:1739)
==16589==    by 0x153FC7: _report (reporter.c:619)
==16589==    by 0x1540A6: lvs (reporter.c:641)
==16589==    by 0x148021: lvm_run_command (lvmcmdline.c:1452)
==16589==    by 0x1495CB: lvm2_main (lvmcmdline.c:1907)
==16589==    by 0x164712: main (lvm.c:21)
==16589==  Address 0x7d465f2 is 8,338 bytes inside a block of size
16,384 free'd
==16589==    at 0x4C2ACE9: free (in
/usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==16589==    by 0x54B8C85: _free_chunk (pool-fast.c:318)
==16589==    by 0x54B84FB: dm_pool_destroy (pool-fast.c:78)
==16589==    by 0x1E59C7: _free_vg (vg.c:78)
==16589==    by 0x1E5A6D: release_vg (vg.c:95)
==16589==    by 0x159B6E: _process_lv_vgnameid_list (toollib.c:1967)
==16589==    by 0x159DD7: process_each_lv (toollib.c:2030)
==16589==    by 0x153ED8: _report (reporter.c:598)
==16589==    by 0x1540A6: lvs (reporter.c:641)
==16589==    by 0x148021: lvm_run_command (lvmcmdline.c:1452)
==16589==    by 0x1495CB: lvm2_main (lvmcmdline.c:1907)
==16589==    by 0x164712: main (lvm.c:21)
2014-12-18 11:54:40 +01:00
Peter Rajnoha
aaf25ec6bd libdm: report: also check whether field type is supported for field-specific reserved value
We only checked global per-report-type reserved values for compatibility
with selection code. This patch also adds a check for per-report-field
reserved values. This avoids problems where unsupported report type is
used as reserved value which could cause hard to debug problems
otherwise. So this additional check stops from registering unsupported
and unhandled per-field reserved values.

Registerting such unsupported reserved value is a programmatic error,
so report internal error in this case to stop us from making a mistake
here in the future or even today where STR_LIST fields can't have
reserved values yet.
2014-12-18 11:29:48 +01:00
Peter Rajnoha
e471ea7890 WHATS_NEW: previous commit 2014-12-17 15:06:48 +01:00
Petr Rockai
00ad13eb71 report: Add cache_policy and cache_settings (LV) segment fields. 2014-12-17 14:43:12 +01:00
Peter Rajnoha
2e905d4540 man: put back the --binary reference in {pv,vg,lv}display man page 2014-12-11 15:50:37 +01:00
Peter Rajnoha
3b02ccd201 tools, man: --binary option is available with -C for {pv,vg,lv}display
The {pv,vg,lv}display *do* use reporting in case "-C|--columns" is used.
The man page was correct, the recognition for the --binary was missing
in the code though!
2014-12-11 15:20:16 +01:00
Peter Rajnoha
3ec482a379 man: remove reference to --binary in {pv,vg,lv}display man page
The {pv,vg,lv}display commands don't use reporting capabilites and
as such they can't use --binary. This got into the man pages by
mistake - the display commands do not recognize --binary option.
2014-12-11 10:42:31 +01:00
Peter Rajnoha
b21a8412c4 vgimportclone: also notify lvmetad about changes if it's used
All the LVM commands are run in mode without lvmetad use (since lvmetad
can't handle duplicates). When we're finished with vgimportclone, we
need to notify lvmetad about changes.

Before this patch (/dev/sda and /dev/sdb contains a copy VG called "vg"):
$ vgimportclone --basevgname vg_snap /dev/sdb
  WARNING: lvmetad is running but disabled. Restart lvmetad before enabling it!
  WARNING: lvmetad is running but disabled. Restart lvmetad before enabling it!
  WARNING: lvmetad is running but disabled. Restart lvmetad before enabling it!
  WARNING: Activation disabled. No device-mapper interaction will be attempted.
  WARNING: lvmetad is running but disabled. Restart lvmetad before enabling it!
  Physical volume "/tmp/snap.zcJ8LCmj/vgimport0" changed  1 physical volume changed / 0 physical volumes not changed
  WARNING: lvmetad is running but disabled. Restart lvmetad before enabling it!
  WARNING: lvmetad is running but disabled. Restart lvmetad before enabling it!
  WARNING: Activation disabled. No device-mapper interaction will be attempted.
  WARNING: lvmetad is running but disabled. Restart lvmetad before enabling it!
  Volume group "vg" successfully changed
  WARNING: lvmetad is running but disabled. Restart lvmetad before enabling it!
  WARNING: lvmetad is running but disabled. Restart lvmetad before enabling it!
  Volume group "vg" successfully renamed to "vg_snap"
  Reading all physical volumes.  This may take a while...
  Found volume group "vg" using metadata type lvm2
  Found volume group "fedora" using metadata type lvm2

$ vgs
  VG     #PV #LV #SN Attr   VSize   VFree
  fedora   1   2   0 wz--n-   9.50g      0
  vg       1   1   0 wz--n- 124.00m 120.00m

(...lvmetad doesn't see the new "vg_snap"!)

With this patch applied:
$ vgimportclone --basevgname vg_snap /dev/sdb
  ...
  WARNING: lvmetad is running but disabled. Restart lvmetad before enabling it!
  Volume group "vg" successfully renamed to "vg_snap"
Notifying lvmetad about changes since it was disabled temporarily.
  Reading all physical volumes.  This may take a while...
  Found volume group "vg_snap" using metadata type lvm2
  Found volume group "fedora" using metadata type lvm2
  Found volume group "vg" using metadata type lvm2

$ vgs
  VG      #PV #LV #SN Attr   VSize   VFree
  fedora    1   2   0 wz--n-   9.50g      0
  vg        1   1   0 wz--n- 124.00m 120.00m
  vg_snap   1   1   0 wz--n- 124.00m 120.00m

The "restart lvmetad before enabling it" message is a bit misleading
here - we should probably suppress this one, but we can't suppress
warning messages selectively at the moment and we don't want to lose
other warning/error messages printed...
2014-12-10 14:00:56 +01:00
Peter Rajnoha
00b36ef06a vgimportclone: replace awk with dumpconfig to generate temporary lvm.conf for vgimportclone
With current dumpconfig, we can generate lvm.conf easily - we can merge
current lvm.conf with the config given on cmd line:
  lvm dumpconfig --mergedconfig --config "..."

This is a bit simpler than using awk and it also avoids problems when some of
the configuration is missing in existing lvm.conf file and hardcoded defaults
are used instead. The dumpconfig handles this transparently.
2014-12-10 13:59:38 +01:00
Peter Rajnoha
5378a1a63e WHATS_NEW: f94f846 actually fixes DM issue, not LVM issue 2014-12-09 10:52:07 +01:00
Peter Rajnoha
f94f8463b0 libdm: report: fix incorrect memory use while using --select with --unbuffered for reporting
Under certain circumstances, the selection code can segfault:

$ vgs --select 'pv_name=~/dev/sda' --unbuffered vg0
  VG   #PV #LV #SN Attr   VSize   VFree
  vg0    6   3   0 wz--n- 744.00m 588.00m
Segmentation fault (core dumped)

The problem here is the use of --ubuffered together with regex used in
selection criteria. If the report output is not buffered, each row is
discarded as soon as it is reported. The bug is in the use of report
handle's memory - in the example above, what happens is:

  1) report handle is initialized together with its memory pool

  2) selection tree is initialized from selection criteria string
     (using the report handle's memory pool!)

    2a) this also means the regex is initialized from report handle's mem pool

  3) the object (row) is reported

    3a) any memory needed for output is intialized out of report handle's mem pool
    3b) selection criteria matching is executed - if the regex is checked the
        very first time (for the very first row reported), some more memory
        allocation happens as regex allocates internal structures "on-demand",
        it's allocating from report handle's mem pool (see also step 2a)

  4) the report output is executed

  5) the object (row) is discarded, meaning discarding all the mem pool
     memory used since step 3.

Now, with step 5) we have discarded the regex internal structures from step 3b.
When we execute reporting for another object (row), we're using the same
selection criteria (step 3b), but tihs is second time we're using the regex
and as such, it's already initialized completely. But the regex is missing the
internal structures now as they got discarded in step 5) from previous
object (row) reporting (because we're using "unbuffered" reporting).

To resolve this issue and to prevent any similar future issues where each
object/row memory is discarded after output (the unbuffered reporting) while
selection tree is global for all the object/rows, use separate memory pool
for report's selection.

This patch replaces "struct selection_node *selection_root" in struct
dm_report with new struct selection which contains both "selection_root"
and "mem" for separate mem pool used for selection.

We can change struct dm_report this way as it is not exposed via libdevmapper.

(This patch will have even more meaning for upcoming patches where selection
is used even for non-reporting commands where "internal" reporting and
selection criteria matching happens and where the internal reporting is
not buffered.)
2014-12-09 10:41:55 +01:00
Peter Rajnoha
4c62215bd1 configure: fix automatic use of configure --enable-udev-systemd-background-jobs
Fix incorrect test in configure which sets --enable-udev-systemd-background-jobs
automatically if proper systemd version is available.

The UDEV_SYSTEMD_BACKGROUND_JOBS variable was not properly set to "yes" in
case systemd is available and we had "maybe" for this variable before.
2014-12-08 10:52:47 +01:00
Peter Rajnoha
42d71b9af3 libdm: report: return immediately from dm_report_compact_fields without error if there are no rows
Let's make dm_report_compact_fields consistent with dm_report_output fn
which also returns with success immediately if there are no rows.
2014-12-05 15:10:50 +01:00
Peter Rajnoha
f867dc6b29 libdm: report: compact output applicable only if report is buffered 2014-12-05 14:18:51 +01:00
Zdenek Kabelac
f3bd9a2797 raid: properly rename split image
When we split leg from raid - we take a proper new lock for a new LV.
However for now activation checks only 'existince' of device UUID,
but it's not validating device has a proper name.

As a quick fix call suspend()/resume() to rename after split mirror.
2014-12-05 13:39:42 +01:00
Peter Rajnoha
00d53d5fc1 config: add report/compact_output lvm.conf setting to enable or isable field compacting
$ lvm dumpconfig report/compact_output
compact_output=0

$ lvs vg
  LV    VG   Attr       LSize Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  lvol0 vg   owi-a-s--- 4.00m
  lvol1 vg   -wi-a----- 4.00m
  lvol2 vg   swi-a-s--- 4.00m      lvol0  0.00

$ lvm dumpconfig report/compact_output
compact_output=1

$ lvs vg
  LV    VG   Attr       LSize Origin Data%
  lvol0 vg   owi-a-s--- 4.00m
  lvol1 vg   -wi-a----- 4.00m
  lvol2 vg   swi-a-s--- 4.00m lvol0  0.00
2014-12-05 12:00:28 +01:00
Peter Rajnoha
5edf6a56c4 libdm: report: add dm_report_compact_fields
Add new dm_report_compact_fields function to cause report outout
(dm_report_output) to ignore fields which don't have any value set
in any of the rows reported. This provides support for compact report
output where only fields which have something to report are displayed.
2014-12-05 12:00:28 +01:00
Peter Rajnoha
44394cd246 libdm: remove unimplemented dm_report_set_output_selection fn
The dm_report_set_output_selection was not implemented in the end -
we have dm_report_init_with_selection instead. This is just a remnant
from development code that got into libdevmapper.h by mistake.
2014-12-05 11:54:25 +01:00
Peter Rajnoha
a5baf13a06 pool: fix typo in error message: then -> than 2014-12-04 09:18:16 +01:00
Alasdair G Kergon
a057f40155 mirror: Validate raid region size config setting.
If necessary, round down to a power of 2 the raid/mirror region size
taken from the config files.
2014-12-03 22:47:08 +00:00
Alasdair G Kergon
de53e0955d mirror: Restrict region size to power of 2. 2014-12-02 14:24:21 +00:00
Alasdair G Kergon
9258e57a50 post-release 2014-11-28 23:07:31 +00:00
Alasdair G Kergon
e492861749 pre-release 2014-11-28 23:06:07 +00:00
Alasdair G Kergon
6521c4b215 libdaemon: Fix some client leaks.
Free (and clear) h.protocol string on daemon_open() error paths
so it's OK for caller to skip calling daemon_close() if returned
h.socket_fd is -1.

Close h.socket_fd in daemon_close() to avoid possible leak.

https://bugzilla.redhat.com/1164234
2014-11-28 21:31:51 +00:00
Petr Rockai
530ebd8976 Update WHATS_NEW. 2014-11-27 20:23:57 +01:00
Petr Rockai
5b2726fc61 lvcreate: Implement --cachepolicy/--cachesettings. 2014-11-27 20:22:03 +01:00
Petr Rockai
2c3db52356 metadata: Add cache_policy to lvcreate_params and honour it. 2014-11-27 20:20:48 +01:00
Petr Rockai
9290854163 toollib: Fix uninitialised config value type in get_cachepolicy_params. 2014-11-27 20:19:28 +01:00
Zdenek Kabelac
4bfdb01f78 toollib: fix regression in parsing /dev/mapper/vg-lv
Commit b0dde9e8f0 introduced regression in parsing
/dev/mapper prefix - and tried to check for '/' one char behind.
2014-11-26 17:29:35 +01:00
Peter Rajnoha
c8890e3ac1 coverity: remove dead code in lv_info_with_seg_status (continued) 2014-11-26 11:58:25 +01:00
Peter Rajnoha
193f9b26a0 coverity: fix possible NULL dereference
The call to dm_config_destroy can derefence result->mem
while result is still NULL:

struct dm_config_tree *get_cachepolicy_params(struct cmd_context *cmd)
{
	...
	int ok = 0;
	...
	if (!(result = dm_config_flatten(current)))
		goto_out;
	...
	ok = 1;
out:
	 if (!ok) {
		dm_config_destroy(result)
		...
	}
	...
}
2014-11-26 11:46:13 +01:00
Peter Rajnoha
86ae68a5f7 coverity: remove dead code in lv_info_with_seg_status
Just call return 0 directly on error path, without using
"goto" - the code is short, no need to use it this way
(the dead code appeared as part of further changes in this
function).
2014-11-26 11:30:01 +01:00
Zdenek Kabelac
2cd98b2782 makefiles: avoid regeneration of Makefile
When Makefile.in is touched, it's been matched by 'man' rule
and it's been wrongly regnerated.

Put in explicit rules to avoid Makefile sed processing.
2014-11-26 09:36:12 +01:00
Zdenek Kabelac
2de11c9e9e thin: add missing 64KB rounding
When chunk size needs to be estimated, the code missed to round
to proper 64kb boundaries  (or power of 2 for older thin pool driver).
So for some data and metadata size (i.e. 10GB and 4MB) it resulted
in incorrect chunk size (not being a multiple of 64KB)

Fix it by adding proper rounding and also use 1 routine for 2 places
where the same calculation is made.

Fix also incorrect printed warning that has used 'ffs()'
(which returns first 'least significant' bit in word)
and it was not really giving any useful size info and replace it
with properly estimated chunk size.
2014-11-26 09:29:25 +01:00
Peter Rajnoha
13e2049c32 initscripts: fix typo in clvmd initscript causing CLVMD_STOP_TIMEOUT variable to be ignored 2014-11-25 15:19:11 +01:00
Peter Rajnoha
62f3a4d2d8 pvresize: fix size in 'Resizing to ...' verbose message to show proper result size 2014-11-25 15:19:10 +01:00
Alasdair G Kergon
cd3b6070aa post-release 2014-11-24 17:48:25 +00:00
Alasdair G Kergon
2aca834724 pre-release 2014-11-24 17:46:50 +00:00
Zdenek Kabelac
e50c9bd7cd cache: comment out unsupported pooldatasize
Support for pooldatasize is not yet finished, so keep it commented out
for now.
2014-11-24 17:38:39 +01:00
Zdenek Kabelac
d184e8d0ba man: update
Improve lvconvert.
Put ENV section downward in lvm.8.
2014-11-24 14:48:13 +01:00
Zdenek Kabelac
74e6135c4f tests: use proper LVMTEST prefix for VG name
Cleaner needs prefix to do its jobs and clean any left VG from python
test as well.
2014-11-24 14:39:04 +01:00
Zdenek Kabelac
1e80265c36 lvconvert: earlier detection of conflicting names
Detect same LV names for lvconvert prior opening VG.
i.e. lvconvert --thinpool vg/lvol0  -T lvol0
2014-11-24 14:39:04 +01:00
Zdenek Kabelac
a058fab118 man: fix pages for generators
Properly generate man page for systemd generators on make.
Simplified  install_clusters
2014-11-24 14:39:04 +01:00
Zdenek Kabelac
8bc7b4f926 libdm: there is no element in item 0
Items[0] holds only counter in .len.
So don't zero already zeroed items[0].len assigned above.

(finishing fc935495c8)
2014-11-24 14:38:54 +01:00
Peter Rajnoha
fb220314ec report: add some comments about how string list is stored internally 2014-11-24 13:14:33 +01:00
Peter Rajnoha
b9601b8353 report: add some comments about how string list is stored internally 2014-11-24 10:48:01 +01:00
Petr Rockai
ced0c17f21 man/lvchange: Mention --cachepolicy and --cachesettings. 2014-11-24 00:02:55 +01:00
Petr Rockai
1445a74d76 man/lvm.conf: Update to reflect changes in config parser. 2014-11-23 23:41:58 +01:00
Petr Rockai
14472d62ba Update WHATS_NEW. 2014-11-23 23:30:27 +01:00
Zdenek Kabelac
a6a7a3a074 cleanup: add missing error path check
New code misses error path check.
2014-11-23 00:49:04 +01:00
Zdenek Kabelac
ccdea661fa cleanup: warning: declaration of 'remove' shadows a global declaration
Don't shadow stdio.h declaration.
2014-11-23 00:49:04 +01:00
Zdenek Kabelac
678cc4e375 libdm: report fix memleak on error path
When _alloc_selection_node() fails, rh should be destroyed.

Use 'bad:' label since we have goto_bad with stack embeded.
2014-11-23 00:49:04 +01:00
Zdenek Kabelac
8eb111dfb8 pool: prevent pool conversion with same name
When same name is given for converted volume and pool volume,
stop further command processing.
2014-11-23 00:49:04 +01:00
Zdenek Kabelac
0782309713 tests: reduce thin test 2014-11-22 18:51:02 +01:00
Zdenek Kabelac
4607cbcb0d tests: use old virt snaps in the test
Don't use thin with its thin requirements for the test.
2014-11-22 18:51:02 +01:00
Zdenek Kabelac
fc935495c8 libdm: fix reporting of empty string list
Don't write behind the allocated array when list is empty.
Use index 0 for the allocated element.

Error triggered by i.e.:  lvs -a -o all,lv_modules
2014-11-22 18:50:53 +01:00
Zdenek Kabelac
75d79f3dad makefiles: standard usage of make.tmpl
Use lvm2 standard TARGETS.

Make liblvm_python.c as intermediate target (gets deleted after use)

Properly delete build dir on make distclean.

Mark install_python_bindings as .PHONY.
2014-11-22 09:58:31 +01:00
Zdenek Kabelac
4dc602f79b dev_manager: fix mknodes
Fix regression introduced with a2c1024f6a

_setup_task(mknodes ? name : NULL...

has been replaced with:

_setup_task(type != MKNODES ? name : NULL....

Use '=='
2014-11-22 09:57:31 +01:00
Zdenek Kabelac
6ce8e57989 configure: fix CLVMD_PATH location
Commit d2c116058e introduced regression
with CLVMD_PATH.

+        CLVMD_PATH="$clvmd_prefix/sbin/clvmd"
         test "$prefix" != NONE && clvmd_prefix=$prefix

It has set CLVMD_PATH before clvmd_prefix got its final value.
Move it one line below.
2014-11-22 09:55:46 +01:00
Zdenek Kabelac
089bdc0be4 cleanup: drop unused vars 2014-11-20 17:49:32 +01:00
Petr Rockai
71271cf905 test: Also test repeated --cachesettings in lvchange-cache. 2014-11-20 16:51:07 +01:00
Petr Rockai
c75ae0846e cache: Implement 'default' as a policy settings value to clear the record. 2014-11-20 16:51:07 +01:00
Petr Rockai
4b9b8e1282 toollib: Split --cachesettings from --cachepolicy. 2014-11-20 16:51:07 +01:00
Petr Rockai
310beb73a8 test: Add a test for lvchange --cachepolicy. 2014-11-20 16:51:07 +01:00
Petr Rockai
c164f59631 lvchange: Accept --cachepolicy. 2014-11-20 16:51:07 +01:00
Petr Rockai
f67e1fadb0 toollib: Add --cachepolicy and implement get_cachepolicy_params. 2014-11-20 16:51:06 +01:00
Petr Rockai
d22ffd8c28 cache: Add lv_cache_setpolicy to cache_manip.c. 2014-11-20 16:51:06 +01:00
Petr Rockai
0050480c0e libdm-config: Warn about duplicate keys. 2014-11-20 16:51:06 +01:00
Petr Rockai
de2c5ab2ac libdm-config: Implement dm_config_remove_node. 2014-11-20 16:51:06 +01:00
Petr Rockai
8bc9966763 libdm-config: Interpret barewords after '=' as strings. 2014-11-20 16:51:06 +01:00
Petr Rockai
274a7a68b8 libdm-config: Implement dm_config_flatten. 2014-11-20 16:51:06 +01:00
Petr Rockai
956c192841 libdm-config: Re-link config trees to reflect file order of keys/sections. 2014-11-20 16:51:06 +01:00
Petr Rockai
687029cbbd libdm-config: Allow paths (section/key = value) in config files.
The order of the resulting tree is based on the first appearance of
sections. With no section repeats, the sections stay as listed in the
config file. Sections using the brace syntax 'section { key = value }' are
treated the same way: 'section { x = 1 } section { y = 2 }' is the same as
'section/x = 1 section/y = 2' is the same as 'section { x = 1 y = 2 }'
2014-11-20 16:47:30 +01:00
Zdenek Kabelac
9f2961f259 cache: check for internal error
Don't try to duplicate NULL on internal error path.
2014-11-20 16:35:46 +01:00
Zdenek Kabelac
e55c6999ae toollib: release vg on ignore path
Missing call to release_vg().
2014-11-20 08:53:30 +01:00
Peter Rajnoha
a61c5c5b3a revert: 7639eae and 4a52a92
Revert 7639eae891 and
4a52a9212c. We need a better fix here.
2014-11-20 08:22:34 +01:00
Zdenek Kabelac
8d8c1b6624 tests: use snapshot targets 2014-11-19 23:24:18 +01:00
Zdenek Kabelac
c75548300d tests: prepare control node before clvmd
Make sure there is 'control' node before clvmd is started.
Somehow  'clvmd' is not allowed by selinux to create one.

TODO: Check is selinux policy is right here...
2014-11-19 23:22:52 +01:00
Zdenek Kabelac
d7985ebead thin: fix error path
Print pool name and not the origin name.
2014-11-19 18:58:30 +01:00
Peter Rajnoha
4a52a9212c systemd: clvmd and cmirrord systemd unit - use usrsbindir instead of sbindir 2014-11-19 16:06:05 +01:00
Peter Rajnoha
7639eae891 configure: expand prefix and exec_prefix directly in configure
In case someone wants to use @some_path@ that contains
prefix or exec_prefix and it's used in other files than Makefiles
(Makefiles used make.tmpl to expand these).
2014-11-19 16:03:27 +01:00
Peter Rajnoha
74ed1ba9f9 configure: make configure --enable-udev-systemd-background-jobs only for systemd >= 205
systemd-run is available in systemd>=205. Also, this fix prevents
systemd-specific udev rules in 69-dm-lvm-metad.rules to appear in
case systemd environment is not available - make configure to check
this automatically and use these systemd specific rules only if it
is applicable.
2014-11-19 13:47:18 +01:00
Zdenek Kabelac
422d1ac8d2 man: clvmd updates
- closer to the recommendation of man-pages (7) if possible
- Add crossrefs
- Sort options and crossrefs
- Fix default timeout (60 secs) of -t
- Documents -I[auto]

Signed-off-by: Stéphane Aulery <saulery@free.fr>
2014-11-19 01:09:52 +01:00
Zdenek Kabelac
5226181329 man: clvmd help output
Closer to the recommendation of groff_man (7) if possible

Signed-off-by: Stéphane Aulery <saulery@free.fr>
2014-11-19 01:09:52 +01:00
Zdenek Kabelac
10330b8782 man: blkdeactivate help output
- Closer to the recommendation of man-pages and groff_man (7) if
  possible
- Sort options and crossrefs
- Relocate sub-options on the right places

Signed-off-by: Stéphane Aulery <saulery@free.fr>
2014-11-19 01:09:24 +01:00
Zdenek Kabelac
731e99025b man: lvchange update
Fix \fI usage.
2014-11-19 00:31:23 +01:00
Zdenek Kabelac
53d2db31c6 cleanup: drop unused var 2014-11-18 16:50:49 +01:00
Zdenek Kabelac
01760967b4 locking: rename LCK_CONVERT
All 'MODE' bits are using _MODE suffix so rename to LCK_CONVERT_MODE
(part of rhbz 735445).
No functional change.
2014-11-18 16:50:49 +01:00
David Teigland
aaa6205d5a toollib: improve ignore_vg case in _process_pvs_in_vgs
ignore_vg now returns 0 for the FAILED_CLUSTERED case,
so all the ignore_vg 1 cases will return vg's with an
empty vg->pvs, so we do not need to iterate through
vg->pvs to remove the entries from the devices list.

Clean up whitespace problems in that area from the
previous commit.
2014-11-18 09:25:56 -06:00
Petr Rockai
cf37c04347 memlock: Make malloc reserve more robust against glibc tricks. 2014-11-18 03:17:27 +01:00
Zdenek Kabelac
542b03ee00 tests: deactivate repaired before swap 2014-11-17 08:44:53 +01:00
Zdenek Kabelac
740fcdae7d tests: thin repair testing
More checks for thin related tools.
Add same functionality for cache related tools.
2014-11-17 00:41:33 +01:00
Zdenek Kabelac
3a1c609ac4 tests: reduce number of sync waiting
Lets assume faster systems, if we have too big raid arrays,
reduce them.
2014-11-17 00:34:44 +01:00
Zdenek Kabelac
776934aa08 tests: skip another older kernel from raid456 2014-11-17 00:32:49 +01:00
David Teigland
b622a7fe3f toollib: fixes and cleanup of recent changes
- Fix problems with recent changes related to skipping in:
  . _process_vgnameid_list
  . _process_pvs_in_vgs

- Undo unnecessary changes to the code structure and readability.

- Preserve valid but minor changes:
  . testing FAILED bit values in ignore_vg
  . using "skip" value from ignore_vg instead of "ret" value
  . applying the sigint check to the start of all loops
  . setting stack backtrace when ECMD_PROCESSED is not returned,
    i.e. apply the following pattern:

	ret = process_foo();
	if (ret != ECMD_PROCESSED)
		stack;
	if (ret > ret_max)
		ret_max = ret;
2014-11-14 16:58:09 -06:00
Zdenek Kabelac
513105c6ac toollib: ignore_vg() with skip is not locked
Extend/fix d8923457b8 commit.

'skip'-ed VG is not holding any lock - so don't unlock such VG.

At the same time simplify the code around and relase VG at a single
place and unlock only not skiped and not ignored VGs.
2014-11-14 19:32:03 +01:00
Zdenek Kabelac
27182e1ddb tests: explicit raid sync 2014-11-14 18:12:44 +01:00
Zdenek Kabelac
fd32bb1991 debug: switch to verbose
When there is no real error from the function - avoid using log_error().
2014-11-14 18:12:44 +01:00
Zdenek Kabelac
b6f921e5cb debug: better message for pool zeroing state 2014-11-14 18:12:35 +01:00
Zdenek Kabelac
38200c2000 cleanup: add '.' to log messages 2014-11-14 18:12:35 +01:00
Zdenek Kabelac
f36080a05d vg_read: correct warning
Use log_warn when we are effectively not creating an error -
we 'allowed' inconsistent read for a reason - so it's just warning
level we process inconsistent VG - it's upto caller later to decide
error level of command return value and in case of error it needs
to use log_error then.
2014-11-14 18:12:35 +01:00
Zdenek Kabelac
d8923457b8 toolib: fix ignore_vg
Rework ignore_vg() API so it properly handles
multiple kind of vg_read_error() states.

Skip processing only otherwise valid VG.

Always return ECMD_FAILED when break is detected.

Check sigint_caught() in front of dm iterator loop.

Add stack for _process failing ret codes.
2014-11-14 18:10:45 +01:00
Zdenek Kabelac
06e3f1757e vg_read: use new error flag
Failed recovery provides different (NULL) VG then FAILED_INCONSISTENT.
Mark it with different failure bit - since FAILED_INCONSISTENT is
supposed to contain something 'usable' (thought inconsistent).
2014-11-14 18:09:27 +01:00
David Teigland
01bbbc27bf lvmcache: remove unnecessary line break syntax 2014-11-13 11:07:34 -06:00
David Teigland
474c6a5271 lvmcache.7: remove unwanted line continuation syntax 2014-11-13 11:04:15 -06:00
Stéphane Aulery
271252eff7 lvconvert.8: fix bold and italic syntax mistake
Signed-off-by: Stéphane Aulery <saulery@free.fr>
2014-11-13 17:49:42 +01:00
Zdenek Kabelac
88e944b5a3 cleanup: remove unused headers 2014-11-13 17:49:42 +01:00
Zdenek Kabelac
428b9fcd87 cleanup: validate pointers
Mostly on almost impossible to happen paths - but stay safe.
2014-11-13 17:49:42 +01:00
Zdenek Kabelac
7278556c76 lvm2api: use fully initilized struct
Don't pass partially initialized struct.
2014-11-13 17:49:41 +01:00
Zdenek Kabelac
49e3fd1ce8 reporter: drop mem on error path
Coverity noticed.
2014-11-13 17:44:31 +01:00
Zdenek Kabelac
6308a8b06d cache: wrong feature in seg is internal error 2014-11-13 17:44:31 +01:00
Peter Rajnoha
48874703d2 cleanup: free mempool memory used for LV status in PVSEGS reporting
Addendum to previous commit 4de7699855.
2014-11-13 14:41:01 +01:00
Peter Rajnoha
4de7699855 cleanup: unify LV info and LV segment status reporting in combination with LVS, SEGS and PVSEGS reporting
Move common code into shared internal fn so the logic for getting the
LV info as well LV segment status is not scattered around - call common
_do_info_and_status to gather required parts in reporting handlers.
2014-11-13 14:28:51 +01:00
Peter Rajnoha
83308fdff9 cleanup: cleanup internal interface to acquire segment status
- Add separate lv_status fn (if we're interested only in seg status,
   but not lv info at the same time as it is with existing
   lv_info_with_seg_status fn). So we 3 fns:

     - lv_info (existing one, runs only info ioctl, fills in struct lvinfo only)

     - lv_status (new one, runs status ioctl, fills in struct lv_seg_status only)

     - lv_info_with_seg_status (existing one, runs status ioctl, fills
       in struct lvinfo as well as lv_seg_status)

 - Add more comments in the code explaining the difference between lv_info,
   lv_status and lv_info_with_seg_status and their return values.

 - Move decision whether lv_info_with_seg_status needs to call only
   status ioctl (in case the segment for which we require status is from
   the LV for which we require info) or separate status and info ioctl
   (in case the segment for which we require status is from different
    LV that the one for which we require info) into
   lv_info_with_seg_status fn so caller doesn't need to bother about
   this at all.

 - Cleanup internal interface for this seg status so it's more readable.
2014-11-13 14:28:51 +01:00
Alasdair G Kergon
efe5245e47 pvck: Use non-zero exit status after failure. 2014-11-13 12:26:43 +00:00
Zdenek Kabelac
c3e2990359 cleanu: drop duplicate const 2014-11-13 13:15:58 +01:00
Zdenek Kabelac
8cb79dad0b pool: fix removal of pool metadata spare
Since we support device stack of pools over pool
(thin-pool with cache data volume) the existing code
is no longer able to detect orphan _pmspare.

So instead do a _pmspare check after volume removal,
and remove spare afterwards.
2014-11-13 13:09:07 +01:00
Zdenek Kabelac
fba86dd42b cache: improve pending_delete
We need to stop guessing deleted names - so rather collect
deleted  UUID into a string list - and then remove them properly
in _clean_tree. Restore origin _clean_tree behaviour them for
currently unconverted removal of snapshots.

Pending delete feature now properly tracks whole subtree of cache
(so i.e. data or metadata as raid volumes).
It properly replaces all related volumes with 'errors' in suspend
preload, then resume them as error and remove collected UUIDs
from root - since they are not longer part of any volume deps.
2014-11-13 11:54:41 +01:00
Peter Rajnoha
359dc6fa76 coverity: commit ba2302346 - report log_sys_error properly
log_sys_error uses errno, hence we need to report the first
failure before reporting another failure that uses errno as well.
2014-11-12 15:16:54 +01:00
Peter Rajnoha
c03d8473ea coverity: fix possible dereference of NULL pointer
This would be in case the pool segment was not found.

LVM2.2.02.112/lib/metadata/pool_manip.c:238:36: warning: Access to field 'segtype' results in a dereference of a null pointer (loaded from variable 'pool_seg')
2014-11-12 10:17:17 +01:00
Peter Rajnoha
ce8730b508 coverity: fix possible integer overflow
LVM2.2.02.112/lib/metadata/cache_manip.c:73: overflow_before_widen: Potentially overflowing expression "*pool_metadata_extents *vg->extent_size" with type "unsigned int" (32 bits, unsigned) is evaluated using 32-bit arithmetic, and then used in a context that expects an expression of type "uint64_t" (64 bits, unsigned).
LVM2.2.02.112/lib/activate/dev_manager.c:217: overflow_before_widen: Potentially overflowing expression "seg_status->seg->len * extent_size" with type "unsigned int" (32 bits, unsigned) is evaluated using 32-bit arithmetic, and then used in a context that expects an expression of type "uint64_t" (64 bits, unsigned).
LVM2.2.02.112/lib/activate/dev_manager.c:217: overflow_before_widen: Potentially overflowing expression "seg_status->seg->le * extent_size" with type "unsigned int" (32 bits, unsigned) is evaluated using 32-bit arithmetic, and then used in a context that expects an expression of type "uint64_t" (64 bits, unsigned).
2014-11-12 10:03:27 +01:00
Peter Rajnoha
60cc666c94 coverity: fix compiler warning
LVM2.2.02.112/lib/activate/dev_manager.c:196:5: warning: 'dmtask' may be used uninitialized in this function [-Wmaybe-uninitialized]

In _info_run fn:

switch (type) {
	case INFO:
		...
	case STATUS:
		...
	case MKNODES:
		...
}

The "type" is enum and currently only those three types are supported,
but if we added a new type in the future, this would end up with a bug
(if we forgot to add the new "case" in that "switch"). So let's make
sure proper internal error is printed:

	default:
		log_error(INTERNAL_ERROR "_info_run: unhandled info type");
                return 0;
2014-11-12 09:55:12 +01:00
Zdenek Kabelac
57c618b0ed cache: fix clean_tree
Fix 8121074fda - the patch
incorrectly removed also other top-level nodes.

It needs to deactivate purely subnodes of _corig.
2014-11-12 09:40:27 +01:00
Stéphane Aulery
112302d41a man: fix (\+) syntax warning of Groff
Signed-off-by: Stéphane Aulery <saulery@free.fr>
2014-11-12 09:39:19 +01:00
Peter Rajnoha
eccc97f15a coverity: remove redundant condition
LVM2.2.02.112/daemons/clvmd/clvmd.c:1131: warning[arrayIndexOutOfBoundsCond]: Array 'row[8]' accessed at index 8, which is out of bounds. Otherwise condition 'j==8' is redundant.

This code:

int i,j = 0;
...
for (i = 0; i < len; ++i) {
	...
	if ((j == 8) || (i + 1 == len)) {
		for (;j < 8; ++j) {
			...
		}
		...
		j = 0;
	}
}

Indeed - j is 0 at the beginning, then iterating till j < 8,
then always zeroed at the end of the outer loop - so "j" never
reaching value of 8 - the j == 8 condition is redundant.
2014-11-12 09:30:02 +01:00
Peter Rajnoha
ba23023464 coverity: fix resource leaks
LVM2.2.02.112/tools/toollib.c:1991: leaked_storage: Variable "iter" going out of scope leaks the storage it points to.
LVM2.2.02.112/lib/filters/filter-usable.c:89: leaked_storage: Variable "f" going out of scope leaks the storage it points to.
LVM2.2.02.112/lib/activate/dev_manager.c:1874: leaked_handle: Handle variable "fd" going out of scope leaks the handle.
2014-11-12 09:19:14 +01:00
Alasdair G Kergon
131aaeb634 post-release 2014-11-11 14:15:32 +00:00
309 changed files with 18550 additions and 5767 deletions

View File

@@ -95,6 +95,11 @@ DISTCLEAN_TARGETS += cscope.out
check check_system check_cluster check_local check_lvmetad unit: all
$(MAKE) -C test $(@)
conf.generate: tools
generate: conf.generate
$(MAKE) -C conf generate
install_system_dirs:
$(INSTALL_DIR) $(DESTDIR)$(DEFAULT_SYS_DIR)
$(INSTALL_ROOT_DIR) $(DESTDIR)$(DEFAULT_ARCHIVE_DIR)
@@ -122,8 +127,11 @@ endif
install_tmpfiles_configuration:
$(MAKE) -C scripts install_tmpfiles_configuration
LCOV_TRACES = libdm.info lib.info tools.info \
daemons/dmeventd.info daemons/clvmd.info
LCOV_TRACES = libdm.info lib.info liblvm.info tools.info \
libdaemon/client.info libdaemon/server.info \
daemons/clvmd.info daemons/dmeventd.info \
daemons/lvmetad.info
CLEAN_TARGETS += $(LCOV_TRACES)
ifneq ("$(LCOV)", "")
@@ -152,7 +160,7 @@ lcov: $(LCOV_TRACES)
$(RM) -r $(LCOV_REPORTS_DIR)
$(MKDIR_P) $(LCOV_REPORTS_DIR)
for i in $(LCOV_TRACES); do \
test -s $$i && lc="$$lc $$i"; \
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

2
README
View File

@@ -18,7 +18,7 @@ Mailing list for general discussion related to LVM2:
Mailing lists for LVM2 development, patches and commits:
lvm-devel@redhat.com
Subscribe from https://www.redhat.com/mailman/listinfo/linux-lvm
Subscribe from https://www.redhat.com/mailman/listinfo/lvm-devel
lvm2-commits@lists.fedorahosted.org (Read-only archive of commits)
Subscribe from https://fedorahosted.org/mailman/listinfo/lvm2-commits

View File

@@ -1 +1 @@
2.02.112(2)-git (2014-11-11)
2.02.119(2)-git (2015-03-24)

View File

@@ -1 +1 @@
1.02.91-git (2014-11-11)
1.02.96-git (2015-03-24)

142
WHATS_NEW
View File

@@ -1,3 +1,145 @@
Version 2.02.119 -
==================================
Add lv_ancestors and lv_descendants reporting fields.
Add --ignorelocal option to dumpconfig to ignore the local section.
Close connection to lvmetad after fork.
Make lvchange able to resume background pvmove polling again.
Split pvmove update metadata fn in an initial one and a subsequent one.
Refactor shared pvmove and lvconvert code into new _poll files.
Add --unconfigured option to dumpconfig to print strings unconfigured.
Add --withfullcomments option to dumpconfig to print full comment.
Check for lvm binary in blkdeactivate and skip LVM processing if not present.
Add --enable-halvm and --disable-halvm options to lvmconf script.
Add --services, --mirrorservice and --startstopservices option to lvmconf.
Use proper default value of global/use_lvmetad when processing lvmconf script.
Respect allocation/cling_tag_list during intial contiguous allocation.
Add A_PARTITION_BY_TAGS set when allocated areas should not share tags.
Set correct vgid when updating cache when writing PV metadata.
More efficient clvmd singlenode locking emulation.
Don't skip invalidation of cached orphans if vg write lck is held (2.02.118).
Log relevant PV tags when using cling allocation.
Add str_list_add_list() to combine two lists.
Fix LV processing with selection to always do the selection on initial state.
Version 2.02.118 - 23rd March 2015
==================================
Store metadata size + checksum in lvmcache and add struct lvmcache_vgsummary.
Remove inaccessible clustered PVs from 'pvs -a'.
Don't invalidate cached orphan information while global lock is held.
Avoid rescan of all devices when requested pvscan for removed device.
Measure configuration timestamps with nanoseconds when available.
Disable lvchange of major and minor of pool LVs.
Fix pvscan --cache to not scan and read ignored metadata areas on PVs.
Add After=iscsi-shutdown.service to blk-availability.service systemd unit.
Disallow vgconvert from changing metadata format when lvmetad is used.
Don't do a full read of VG when creating a new VG with an existing name.
Reduce amount of VG metadata parsing when looking for vgname on a PV.
Avoid reparsing same metadata when reading same metadata from multiple PVs.
Save extra device open/close when scanning device for size.
Fix seg_monitor field to report status also for mirrors and thick snapshots.
Replace LVM_WRITE with LVM_WRITE_LOCKED flags in metadata if system ID is set.
Remove ACCESS_NEEDS_SYSTEM_ID VG status flag. (2.02.117)
Enable system ID features.
Version 2.02.117 - 4th March 2015
=================================
Add CFG_DISABLED for new system ID config settings that must not yet be used.
Preserve original format type field when processing backup files.
Implement status action for lvm2-monitor initscript to display monitored LVs.
Allow lvchange -p to change kernel state only if metadata state differs.
Fix incorrect persistent .cache after report with label fields only (2.02.106).
Reinstate PV tag recognition for pvs if reporting label fields only (2.02.105).
Rescan devices before vgimport with lvmetad so exported VG is seen.
Fix hang by adjusting cluster mirror regionsize, avoiding CPG msg limit.
Do not crash when --cachepolicy is given without --cachesettings.
Add NEEDS_FOREIGN_VGS flag to vgimport so --foreign is always supplied.
Add --foreign to the 6 display and reporting tools and vgcfgbackup.
Install /etc/lvm/lvmlocal.conf template with local section for systemid.
Record creation_host_system_id in lvm2 metadata (never set yet).
Reinstate recursive config file tag section processing. (2.02.99)
Add 'lvm systemid' to display the current system ID (never set yet).
Fix configure to properly recognize --with-default-raid10-segtype option.
Do not refresh filters/rescan if no signature is wiped during pvcreate.
Enforce none external dev info for wiping during pvcreate to avoid races.
Add global/system_id_source and system_id_file to lvm.conf (disabled).
Add support for VG system_id to control host access to VGs.
Update vgextend to use process_each_vg.
Add --ignoreskippedcluster to pvchange.
Allow pvchange to modify several properties at once.
Update pvchange to use process_each_pv.
Fix pvs -a used with lvmetad to filter out devices unsuitable for PVs.
Fix selection to recognize units for ba_start, vg_free and seg_start fields.
Add support for -S/--select to vgexport and vgimport.
Add support for -S/--select to vgdisplay, lvdisplay and pvdisplay without -C.
Add support for -S/--select to vgremove and lvremove.
Add support for -S/--select to vgchange,lvchange and pvchange.
Add infrastructure to support selection for non-reporting tools.
Add LVM_COMMAND_PROFILE env var to set default command profile name to use.
Set CLOEXEC flag on file descriptors originating in libdaemon.
Version 2.02.116 - 30th January 2015
====================================
Deactivate unused thin pools activated with lvm2 pre-2.02.112 versions.
Check lock holding LV when lvconverting stacked raid LV in cluster.
Support udev external dev info for filters: PV min size, mpath, md, partition.
Add fw_raid_component_detection lvm.conf option to enable FW raid detection.
Add devices/external_device_info_source lvm.conf option ("none" by default).
Scan pools in for_each_sub_lv() and add for_each_sub_lv_except_pools().
Fix lvm2app lvm_lv_get_property return value for fields with info/status ioctl.
Fix lvm2app regression in lvm_lv_get_attr causing unknown values (2.02.115).
Set default cache_mode to writehrough when missing in metadata.
Preserve chunk size with repair and metadata swap of a thin pool.
Fix raid --splitmirror 1 functionality (2.02.112).
Fix tree preload to handle splitting raid images.
Do not support unpartitioned DASD devices.
Improve config validation to check if setting with string value can be empty.
Version 2.02.115 - 21st January 2015
====================================
Report segment types without monitoring support as undefined.
Support lvchange --errorwhenfull for thin pools.
Improve the processing and reporting of duplicate PVs.
Report lv_health_status and health attribute also for thin pool.
Add lv_when_full reporting field.
Add support for lvcreate --errorwhenfull y|n for thin pools.
Fix lvconvert --repair to honour resilience requirement for segmented RAID LV.
Filter out partitioned device-mapper devices as unsuitable for use as PVs.
Also notify lvmetad about filtered device if using pvscan --cache DevicePath.
Use LVM's own selection instead of awk expressions in clvmd startup scripts.
Do not filter out snapshot origin LVs as unusable devices for an LVM stack.
Fix incorrect rimage names when converting from mirror to raid1 LV (2.02.112).
Introduce pvremove_many to avoid excessive metadata re-reading and messages.
Check for cmirror availability during cluster mirror creation and activation.
Add cache_policy and cache_settings reporting fields.
Add missing recognition for --binary option with {pv,vg,lv}display -C.
Fix vgimportclone to notify lvmetad about changes done if lvmetad is used.
Fix vgimportclone to properly override config if it is missing in lvm.conf.
Fix automatic use of configure --enable-udev-systemd-background-jobs.
Correctly rename active split LV with -splitmirrors for raid1.
Add report/compact_output to lvm.conf to enable/disable compact report output.
Still restrict mirror region size to power of 2 when VG extent size is not.
Version 2.02.114 - 28th November 2014
=====================================
Release socket in daemon_close and protocol string in daemon_open error path.
Add --cachepolicy and --cachesettings to lvcreate.
Fix regression when parsing /dev/mapper dir (2.02.112).
Fix missing rounding to 64KB when estimating optimal thin pool chunk size.
Fix typo in clvmd initscript causing CLVMD_STOP_TIMEOUT var to be ignored.
Fix size in pvresize "Resizing to ..." verbose msg to show proper result size.
Version 2.02.113 - 24th November 2014
=====================================
Add --cachepolicy and --cachesettings options to lvchange.
Validate that converted volume and specified pool volume differ in lvconvert.
Fix regression in vgscan --mknodes usage (2.02.112).
Respect --prefix when setting CLMVD_PATH configure (2.02.89).
Default to configure --enable-udev-systemd-background-jobs for systemd>=205.
Fix ignore_vg() to properly react on various vg_read errors (2.02.112).
Failed recovery returns FAILED_RECOVERY status flag for vg_read().
Exit with non-zero status code when pvck encounters a problem.
Fix clean_tree after activation/resume for cache target (2.02.112).
Version 2.02.112 - 11th November 2014
=====================================
Add cache_{read,write}_{hits,misses} reporting fields.

View File

@@ -1,3 +1,35 @@
Version 1.02.96 -
=================================
Fix selection to not match if using reserved value in criteria with >,<,>=,<.
Fix selection to not match reserved values for size fields if using >,<,>=,<.
Include uuid or device number in log message after ioctl failure.
Add DM_INTERNAL_SUSPEND_FLAG to dm-ioctl.h.
Install blkdeactivate script and its man page with make install_device-mapper.
Version 1.02.95 - 15th March 2015
=================================
Makefile regenerated.
Version 1.02.94 - 4th March 2015
================================
Add dm_report_object_is_selected for generalized interface for report/select.
Version 1.02.93 - 21st January 2015
===================================
Reduce severity of ioctl error message when dmeventd waitevent is interrupted.
Report 'unknown version' when incompatible version numbers were not obtained.
Report more info from thin pool status (out of data, metadata-ro, fail).
Support error_if_no_space for thin pool target.
Fix segfault while using selection with regex and unbuffered reporting.
Add dm_report_compact_fields to remove empty fields from report output.
Remove unimplemented dm_report_set_output_selection from libdevmapper.h.
Version 1.02.92 - 24th November 2014
====================================
Fix memory corruption with sorting empty string lists (1.02.86).
Fix man dmsetup.8 syntax warning of Groff
Accept unquoted strings and / in place of {} when parsing configs.
Version 1.02.91 - 11th November 2014
====================================
Update cache creation and dm_config_node to pass policy.

View File

@@ -37,6 +37,10 @@ AC_DEFUN([AC_TRY_CCFLAG],
fi
])
dnl AC_IF_YES([TEST-FOR-YES], [ACTION-IF-TRUE], [ACTION-IF-FALSE])
dnl AS_IF() abstraction, checks shell variable for 'yes'
AC_DEFUN([AC_IF_YES], [AS_IF([test $$1 = yes], [$2], [$3])])
dnl AC_TRY_LDFLAGS([LDFLAGS], [VAR], [ACTION-IF-WORKS], [ACTION-IF-FAILS])
dnl check if $CC supports given ld flags

View File

@@ -17,24 +17,37 @@ top_builddir = @top_builddir@
CONFSRC=example.conf
CONFDEST=lvm.conf
CONFLOCAL=lvmlocal.conf
PROFILE_TEMPLATES=command_profile_template.profile metadata_profile_template.profile
PROFILES=$(PROFILE_TEMPLATES) $(srcdir)/thin-generic.profile $(srcdir)/thin-performance.profile
include $(top_builddir)/make.tmpl
.PHONY: install_conf install_localconf install_profiles
generate:
(cat $(top_srcdir)/conf/example.conf.base && LD_LIBRARY_PATH=$(top_builddir)/libdm:$(LD_LIBRARY_PATH) $(top_builddir)/tools/lvm dumpconfig --type default --unconfigured --withfullcomments --ignorelocal) > example.conf.in
(cat $(top_srcdir)/conf/lvmlocal.conf.base && LD_LIBRARY_PATH=$(top_builddir)/libdm:$(LD_LIBRARY_PATH) $(top_builddir)/tools/lvm dumpconfig --type default --unconfigured --withfullcomments local) > lvmlocal.conf.in
install_conf: $(CONFSRC)
@if [ ! -e $(confdir)/$(CONFDEST) ]; then \
echo "$(INSTALL_WDATA) -D $< $(confdir)/$(CONFDEST)"; \
$(INSTALL_WDATA) -D $< $(confdir)/$(CONFDEST); \
fi
install_localconf: $(CONFLOCAL)
@if [ ! -e $(confdir)/$(CONFLOCAL) ]; then \
echo "$(INSTALL_WDATA) -D $< $(confdir)/$(CONFLOCAL)"; \
$(INSTALL_WDATA) -D $< $(confdir)/$(CONFLOCAL); \
fi
install_profiles: $(PROFILES)
$(INSTALL_DIR) $(DESTDIR)$(DEFAULT_PROFILE_DIR)
$(INSTALL_DATA) $(PROFILES) $(DESTDIR)$(DEFAULT_PROFILE_DIR)/
install_lvm2: install_conf install_profiles
install_lvm2: install_conf install_localconf install_profiles
install: install_lvm2
DISTCLEAN_TARGETS += $(CONFSRC) $(PROFILE_TEMPLATES)
DISTCLEAN_TARGETS += $(CONFSRC) $(CONFLOCAL) $(PROFILE_TEMPLATES)

View File

@@ -18,6 +18,7 @@ global {
lvdisplay_shows_full_device_path=0
}
report {
compact_output=0
aligned=1
buffered=1
headings=1

12
conf/example.conf.base Normal file
View File

@@ -0,0 +1,12 @@
# This is an example configuration file for the LVM2 system.
# It contains the default settings that would be used if there was no
# @DEFAULT_SYS_DIR@/lvm.conf file.
#
# Refer to 'man lvm.conf' for further information including the file layout.
#
# To put this file in a different directory and override @DEFAULT_SYS_DIR@ set
# the environment variable LVM_SYSTEM_DIR before running the tools.
#
# N.B. Take care that each setting only appears once if uncommenting
# example settings in this file.

File diff suppressed because it is too large Load Diff

19
conf/lvmlocal.conf.base Normal file
View File

@@ -0,0 +1,19 @@
# This is a local configuration file template for the LVM2 system
# which should be installed as @DEFAULT_SYS_DIR@/lvmlocal.conf .
#
# Refer to 'man lvm.conf' for information about the file layout.
#
# To put this file in a different directory and override
# @DEFAULT_SYS_DIR@ set the environment variable LVM_SYSTEM_DIR before
# running the tools.
#
# The lvmlocal.conf file is normally expected to contain only the
# "local" section which contains settings that should not be shared or
# repeated among different hosts. (But if other sections are present,
# they *will* get processed. Settings in this file override equivalent
# ones in lvm.conf and are in turn overridden by ones in any enabled
# lvm_<tag>.conf files.)
#
# Please take care that each setting only appears once if uncommenting
# example settings in this file and never copy this file between hosts.

53
conf/lvmlocal.conf.in Normal file
View File

@@ -0,0 +1,53 @@
# This is a local configuration file template for the LVM2 system
# which should be installed as @DEFAULT_SYS_DIR@/lvmlocal.conf .
#
# Refer to 'man lvm.conf' for information about the file layout.
#
# To put this file in a different directory and override
# @DEFAULT_SYS_DIR@ set the environment variable LVM_SYSTEM_DIR before
# running the tools.
#
# The lvmlocal.conf file is normally expected to contain only the
# "local" section which contains settings that should not be shared or
# repeated among different hosts. (But if other sections are present,
# they *will* get processed. Settings in this file override equivalent
# ones in lvm.conf and are in turn overridden by ones in any enabled
# lvm_<tag>.conf files.)
#
# Please take care that each setting only appears once if uncommenting
# example settings in this file and never copy this file between hosts.
# Configuration section local.
# LVM settings that are specific to the local host.
local {
# Configuration option local/system_id.
# Defines the local system ID for lvmlocal mode.
# This is used when global/system_id_source is set
# to 'lvmlocal' in the main configuration file,
# e.g. lvm.conf.
# When used, it must be set to a unique value
# among all hosts sharing access to the storage,
# e.g. a host name.
# Example:
# Set no system ID.
# system_id = ""
# Example:
# Set the system_id to the string 'host1'.
# system_id = "host1"
# This configuration option does not have a default value defined.
# system_id=""
# Configuration option local/extra_system_ids.
# A list of extra VG system IDs the local host can access.
# VGs with the system IDs listed here (in addition
# to the host's own system ID) can be fully accessed
# by the local host. (These are system IDs that the
# host sees in VGs, not system IDs that identify the
# local host, which is determined by system_id_source.)
# Use this only after consulting 'man lvmsystemid'
# to be certain of correct usage and possible dangers.
# This configuration option does not have a default value defined.
# extra_system_ids=[]
}

View File

@@ -16,7 +16,7 @@ allocation {
thin_pool_zero=1
thin_pool_discards="passdown"
thin_pool_chunk_size_policy="generic"
# thin_pool_chunk_size=64
# thin_pool_chunk_size=128
}
activation {
thin_pool_autoextend_threshold=100

510
configure vendored
View File

@@ -639,6 +639,7 @@ CLVMD_PIDFILE
LVMETAD_PIDFILE
DMEVENTD_PIDFILE
WRITE_INSTALL
VALGRIND_POOL
UDEV_HAS_BUILTIN_BLKID
UDEV_RULE_EXEC_DETECTION
UDEV_SYSTEMD_BACKGROUND_JOBS
@@ -681,6 +682,7 @@ LDDEPS
JOBS
INTL_PACKAGE
INTL
HAVE_VALGRIND
HAVE_REALTIME
HAVE_LIBDL
BLKDEACTIVATE
@@ -736,9 +738,10 @@ LVM2CMD_LIB
LVM2APP_LIB
UDEV_LIBS
UDEV_CFLAGS
SYSTEMD_LIBS
SYSTEMD_CFLAGS
BLKID_LIBS
BLKID_CFLAGS
VALGRIND_POOL
VALGRIND_LIBS
VALGRIND_CFLAGS
CUNIT_LIBS
@@ -746,6 +749,7 @@ CUNIT_CFLAGS
GENPNG
GENHTML
LCOV
HAVE_WSYNCNAND
HAVE_WCLOBBERED
HAVE_WJUMP
SACKPT_LIBS
@@ -796,6 +800,9 @@ INSTALL_PROGRAM
EGREP
GREP
CPP
ac_ct_CXX
CXXFLAGS
CXX
OBJEXT
EXEEXT
ac_ct_CC
@@ -874,7 +881,7 @@ with_snapshots
with_mirrors
with_raid
with_default_mirror_segtype
with_default_raid10r_segtype
with_default_raid10_segtype
with_replicators
with_default_sparse_segtype
with_thin
@@ -954,6 +961,9 @@ CFLAGS
LDFLAGS
LIBS
CPPFLAGS
CXX
CXXFLAGS
CCC
CPP
PKG_CONFIG
PKG_CONFIG_PATH
@@ -984,6 +994,8 @@ VALGRIND_CFLAGS
VALGRIND_LIBS
BLKID_CFLAGS
BLKID_LIBS
SYSTEMD_CFLAGS
SYSTEMD_LIBS
UDEV_CFLAGS
UDEV_LIBS'
@@ -1747,6 +1759,8 @@ Some influential environment variables:
LIBS libraries to pass to the linker, e.g. -l<library>
CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
you have headers in a nonstandard directory <include dir>
CXX C++ compiler command
CXXFLAGS C++ compiler flags
CPP C preprocessor
PKG_CONFIG path to pkg-config utility
PKG_CONFIG_PATH
@@ -1791,6 +1805,10 @@ Some influential environment variables:
BLKID_CFLAGS
C compiler flags for BLKID, overriding pkg-config
BLKID_LIBS linker flags for BLKID, overriding pkg-config
SYSTEMD_CFLAGS
C compiler flags for SYSTEMD, overriding pkg-config
SYSTEMD_LIBS
linker flags for SYSTEMD, overriding pkg-config
UDEV_CFLAGS C compiler flags for UDEV, overriding pkg-config
UDEV_LIBS linker flags for UDEV, overriding pkg-config
@@ -1912,6 +1930,44 @@ fi
} # ac_fn_c_try_compile
# ac_fn_cxx_try_compile LINENO
# ----------------------------
# Try to compile conftest.$ac_ext, and return whether this succeeded.
ac_fn_cxx_try_compile ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
rm -f conftest.$ac_objext
if { { ac_try="$ac_compile"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
$as_echo "$ac_try_echo"; } >&5
(eval "$ac_compile") 2>conftest.err
ac_status=$?
if test -s conftest.err; then
grep -v '^ *+' conftest.err >conftest.er1
cat conftest.er1 >&5
mv -f conftest.er1 conftest.err
fi
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; } && {
test -z "$ac_cxx_werror_flag" ||
test ! -s conftest.err
} && test -s conftest.$ac_objext; then :
ac_retval=0
else
$as_echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_retval=1
fi
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
as_fn_set_status $ac_retval
} # ac_fn_cxx_try_compile
# ac_fn_c_try_cpp LINENO
# ----------------------
# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
@@ -3903,6 +3959,263 @@ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
ac_ext=cpp
ac_cpp='$CXXCPP $CPPFLAGS'
ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
if test -z "$CXX"; then
if test -n "$CCC"; then
CXX=$CCC
else
if test -n "$ac_tool_prefix"; then
for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
do
# Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
set dummy $ac_tool_prefix$ac_prog; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_prog_CXX+:} false; then :
$as_echo_n "(cached) " >&6
else
if test -n "$CXX"; then
ac_cv_prog_CXX="$CXX" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi
fi
CXX=$ac_cv_prog_CXX
if test -n "$CXX"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5
$as_echo "$CXX" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
test -n "$CXX" && break
done
fi
if test -z "$CXX"; then
ac_ct_CXX=$CXX
for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_prog_ac_ct_CXX+:} false; then :
$as_echo_n "(cached) " >&6
else
if test -n "$ac_ct_CXX"; then
ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_CXX="$ac_prog"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi
fi
ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
if test -n "$ac_ct_CXX"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5
$as_echo "$ac_ct_CXX" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
test -n "$ac_ct_CXX" && break
done
if test "x$ac_ct_CXX" = x; then
CXX="g++"
else
case $cross_compiling:$ac_tool_warned in
yes:)
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
CXX=$ac_ct_CXX
fi
fi
fi
fi
# Provide some information about the compiler.
$as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5
set X $ac_compile
ac_compiler=$2
for ac_option in --version -v -V -qversion; do
{ { ac_try="$ac_compiler $ac_option >&5"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
$as_echo "$ac_try_echo"; } >&5
(eval "$ac_compiler $ac_option >&5") 2>conftest.err
ac_status=$?
if test -s conftest.err; then
sed '10a\
... rest of stderr output deleted ...
10q' conftest.err >conftest.er1
cat conftest.er1 >&5
fi
rm -f conftest.er1 conftest.err
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }
done
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5
$as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; }
if ${ac_cv_cxx_compiler_gnu+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
main ()
{
#ifndef __GNUC__
choke me
#endif
;
return 0;
}
_ACEOF
if ac_fn_cxx_try_compile "$LINENO"; then :
ac_compiler_gnu=yes
else
ac_compiler_gnu=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5
$as_echo "$ac_cv_cxx_compiler_gnu" >&6; }
if test $ac_compiler_gnu = yes; then
GXX=yes
else
GXX=
fi
ac_test_CXXFLAGS=${CXXFLAGS+set}
ac_save_CXXFLAGS=$CXXFLAGS
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5
$as_echo_n "checking whether $CXX accepts -g... " >&6; }
if ${ac_cv_prog_cxx_g+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_save_cxx_werror_flag=$ac_cxx_werror_flag
ac_cxx_werror_flag=yes
ac_cv_prog_cxx_g=no
CXXFLAGS="-g"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
main ()
{
;
return 0;
}
_ACEOF
if ac_fn_cxx_try_compile "$LINENO"; then :
ac_cv_prog_cxx_g=yes
else
CXXFLAGS=""
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
main ()
{
;
return 0;
}
_ACEOF
if ac_fn_cxx_try_compile "$LINENO"; then :
else
ac_cxx_werror_flag=$ac_save_cxx_werror_flag
CXXFLAGS="-g"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
main ()
{
;
return 0;
}
_ACEOF
if ac_fn_cxx_try_compile "$LINENO"; then :
ac_cv_prog_cxx_g=yes
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
ac_cxx_werror_flag=$ac_save_cxx_werror_flag
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5
$as_echo "$ac_cv_prog_cxx_g" >&6; }
if test "$ac_test_CXXFLAGS" = set; then
CXXFLAGS=$ac_save_CXXFLAGS
elif test $ac_cv_prog_cxx_g = yes; then
if test "$GXX" = yes; then
CXXFLAGS="-g -O2"
else
CXXFLAGS="-g"
fi
else
if test "$GXX" = yes; then
CXXFLAGS="-O2"
else
CXXFLAGS=
fi
fi
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
ac_ext=c
@@ -7260,9 +7573,9 @@ else
fi
# Check whether --with-default-raid10r-segtype was given.
if test "${with_default_raid10r_segtype+set}" = set; then :
withval=$with_default_raid10r_segtype; DEFAULT_RAID10_SEGTYPE=$withval
# Check whether --with-default-raid10-segtype was given.
if test "${with_default_raid10_segtype+set}" = set; then :
withval=$with_default_raid10_segtype; DEFAULT_RAID10_SEGTYPE=$withval
else
DEFAULT_RAID10_SEGTYPE="raid10"
fi
@@ -9902,6 +10215,44 @@ $as_echo "$ac_cv_flag_HAVE_WCLOBBERED" >&6; }
ac_save_CFLAGS=$CFLAGS
CFLAGS=-Wsync-nand
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -Wsync-nand flag" >&5
$as_echo_n "checking whether $CC accepts -Wsync-nand flag... " >&6; }
if ${ac_cv_flag_HAVE_WSYNCNAND+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
main ()
{
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_flag_HAVE_WSYNCNAND=yes
else
ac_cv_flag_HAVE_WSYNCNAND=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_flag_HAVE_WSYNCNAND" >&5
$as_echo "$ac_cv_flag_HAVE_WSYNCNAND" >&6; }
CFLAGS=$ac_save_CFLAGS
HAVE_WSYNCNAND=$ac_cv_flag_HAVE_WSYNCNAND
if test "HAVE_WSYNCNAND" = yes; then
:
else
:
fi
################################################################################
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C optimisation flag" >&5
$as_echo_n "checking for C optimisation flag... " >&6; }
@@ -10362,8 +10713,7 @@ fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $VALGRIND_POOL" >&5
$as_echo "$VALGRIND_POOL" >&6; }
if test "$VALGRIND_POOL" = yes; then
pkg_config_init
pkg_config_init
pkg_failed=no
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for VALGRIND" >&5
@@ -10423,23 +10773,30 @@ fi
# Put the nasty error message in config.log where it belongs
echo "$VALGRIND_PKG_ERRORS" >&5
as_fn_error $? "bailing out" "$LINENO" 5
if test x$VALGRIND_POOL = xyes; then as_fn_error $? "bailing out" "$LINENO" 5; fi
elif test $pkg_failed = untried; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
as_fn_error $? "bailing out" "$LINENO" 5
if test x$VALGRIND_POOL = xyes; then as_fn_error $? "bailing out" "$LINENO" 5; fi
else
VALGRIND_CFLAGS=$pkg_cv_VALGRIND_CFLAGS
VALGRIND_LIBS=$pkg_cv_VALGRIND_LIBS
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
HAVE_VALGRIND=yes
fi
if test x$HAVE_VALGRIND = xyes; then
$as_echo "#define HAVE_VALGRIND 1" >>confdefs.h
fi
if test x$VALGRIND_POOL = xyes; then
$as_echo "#define VALGRIND_POOL 1" >>confdefs.h
fi
################################################################################
@@ -10601,12 +10958,95 @@ $as_echo_n "checking whether to use udev-systemd protocol for jobs in background
if test "${enable_udev_systemd_background_jobs+set}" = set; then :
enableval=$enable_udev_systemd_background_jobs; UDEV_SYSTEMD_BACKGROUND_JOBS=$enableval
else
UDEV_SYSTEMD_BACKGROUND_JOBS=yes
UDEV_SYSTEMD_BACKGROUND_JOBS=maybe
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $UDEV_SYSTEMD_BACKGROUND_JOBS" >&5
$as_echo "$UDEV_SYSTEMD_BACKGROUND_JOBS" >&6; }
if test "$UDEV_SYSTEMD_BACKGROUND_JOBS" != no; then
pkg_config_init
pkg_failed=no
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for SYSTEMD" >&5
$as_echo_n "checking for SYSTEMD... " >&6; }
if test -n "$SYSTEMD_CFLAGS"; then
pkg_cv_SYSTEMD_CFLAGS="$SYSTEMD_CFLAGS"
elif test -n "$PKG_CONFIG"; then
if test -n "$PKG_CONFIG" && \
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"systemd >= 205\""; } >&5
($PKG_CONFIG --exists --print-errors "systemd >= 205") 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
pkg_cv_SYSTEMD_CFLAGS=`$PKG_CONFIG --cflags "systemd >= 205" 2>/dev/null`
test "x$?" != "x0" && pkg_failed=yes
else
pkg_failed=yes
fi
else
pkg_failed=untried
fi
if test -n "$SYSTEMD_LIBS"; then
pkg_cv_SYSTEMD_LIBS="$SYSTEMD_LIBS"
elif test -n "$PKG_CONFIG"; then
if test -n "$PKG_CONFIG" && \
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"systemd >= 205\""; } >&5
($PKG_CONFIG --exists --print-errors "systemd >= 205") 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
pkg_cv_SYSTEMD_LIBS=`$PKG_CONFIG --libs "systemd >= 205" 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
SYSTEMD_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "systemd >= 205" 2>&1`
else
SYSTEMD_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "systemd >= 205" 2>&1`
fi
# Put the nasty error message in config.log where it belongs
echo "$SYSTEMD_PKG_ERRORS" >&5
if test "$UDEV_SYSTEMD_BACKGROUND_JOBS" = maybe; then
UDEV_SYSTEMD_BACKGROUND_JOBS=no
else
as_fn_error $? "bailing out... systemd >= 205 is required" "$LINENO" 5
fi
elif test $pkg_failed = untried; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
if test "$UDEV_SYSTEMD_BACKGROUND_JOBS" = maybe; then
UDEV_SYSTEMD_BACKGROUND_JOBS=no
else
as_fn_error $? "bailing out... systemd >= 205 is required" "$LINENO" 5
fi
else
SYSTEMD_CFLAGS=$pkg_cv_SYSTEMD_CFLAGS
SYSTEMD_LIBS=$pkg_cv_SYSTEMD_LIBS
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
test "$UDEV_SYSTEMD_BACKGROUND_JOBS" = maybe && UDEV_SYSTEMD_BACKGROUND_JOBS=yes
fi
fi
################################################################################
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable synchronisation with udev processing" >&5
$as_echo_n "checking whether to enable synchronisation with udev processing... " >&6; }
@@ -11518,6 +11958,40 @@ $as_echo "$as_me: WARNING: Disabling realtime clock" >&2;}
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for struct stat has st_ctim." >&5
$as_echo_n "checking for struct stat has st_ctim.... " >&6; }
if ${ac_cv_stat_st_ctim+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/stat.h>
long bar(void) { struct stat s; return (long)(s.st_ctim.tv_sec + s.st_ctim.tv_nsec);}
int
main ()
{
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_stat_st_ctim=yes
else
ac_cv_stat_st_ctim=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_stat_st_ctim" >&5
$as_echo "$ac_cv_stat_st_ctim" >&6; }
if test $ac_cv_stat_st_ctim = yes; then :
$as_echo "#define HAVE_STAT_ST_CTIM 1" >>confdefs.h
fi
################################################################################
for ac_header in getopt.h
do :
@@ -11859,6 +12333,11 @@ else
fi
cat >>confdefs.h <<_ACEOF
#define DEFAULT_ETC_DIR "$CONFDIR"
_ACEOF
# Check whether --with-staticdir was given.
if test "${with_staticdir+set}" = set; then :
@@ -12342,8 +12821,8 @@ _ACEOF
if test "$CLVMD" != none; then
clvmd_prefix=$ac_default_prefix
CLVMD_PATH="$clvmd_prefix/sbin/clvmd"
test "$prefix" != NONE && clvmd_prefix=$prefix
CLVMD_PATH="$clvmd_prefix/sbin/clvmd"
cat >>confdefs.h <<_ACEOF
#define CLVMD_PATH "$CLVMD_PATH"
@@ -12657,11 +13136,13 @@ LVM_LIBAPI=`echo "$VER" | $AWK -F '[()]' '{print $2}'`
################################################################################
ac_config_files="$ac_config_files Makefile make.tmpl daemons/Makefile daemons/clvmd/Makefile daemons/cmirrord/Makefile daemons/dmeventd/Makefile daemons/dmeventd/libdevmapper-event.pc daemons/dmeventd/plugins/Makefile daemons/dmeventd/plugins/lvm2/Makefile daemons/dmeventd/plugins/raid/Makefile daemons/dmeventd/plugins/mirror/Makefile daemons/dmeventd/plugins/snapshot/Makefile daemons/dmeventd/plugins/thin/Makefile daemons/lvmetad/Makefile conf/Makefile conf/example.conf conf/command_profile_template.profile conf/metadata_profile_template.profile include/.symlinks include/Makefile lib/Makefile lib/format1/Makefile lib/format_pool/Makefile lib/locking/Makefile lib/mirror/Makefile lib/replicator/Makefile lib/misc/lvm-version.h lib/raid/Makefile lib/snapshot/Makefile lib/thin/Makefile lib/cache_segtype/Makefile libdaemon/Makefile libdaemon/client/Makefile libdaemon/server/Makefile libdm/Makefile libdm/libdevmapper.pc liblvm/Makefile liblvm/liblvm2app.pc man/Makefile po/Makefile python/Makefile python/setup.py scripts/blkdeactivate.sh scripts/blk_availability_init_red_hat scripts/blk_availability_systemd_red_hat.service scripts/clvmd_init_red_hat scripts/cmirrord_init_red_hat scripts/dm_event_systemd_red_hat.service scripts/dm_event_systemd_red_hat.socket scripts/lvm2_cluster_activation_red_hat.sh scripts/lvm2_cluster_activation_systemd_red_hat.service scripts/lvm2_clvmd_systemd_red_hat.service scripts/lvm2_cmirrord_systemd_red_hat.service scripts/lvm2_lvmetad_init_red_hat scripts/lvm2_lvmetad_systemd_red_hat.service scripts/lvm2_lvmetad_systemd_red_hat.socket scripts/lvm2_monitoring_init_red_hat scripts/lvm2_monitoring_systemd_red_hat.service scripts/lvm2_pvscan_systemd_red_hat@.service scripts/lvm2_tmpfiles_red_hat.conf scripts/Makefile test/Makefile test/api/Makefile test/unit/Makefile tools/Makefile udev/Makefile unit-tests/datastruct/Makefile unit-tests/regex/Makefile unit-tests/mm/Makefile"
ac_config_files="$ac_config_files Makefile make.tmpl daemons/Makefile daemons/clvmd/Makefile daemons/cmirrord/Makefile daemons/dmeventd/Makefile daemons/dmeventd/libdevmapper-event.pc daemons/dmeventd/plugins/Makefile daemons/dmeventd/plugins/lvm2/Makefile daemons/dmeventd/plugins/raid/Makefile daemons/dmeventd/plugins/mirror/Makefile daemons/dmeventd/plugins/snapshot/Makefile daemons/dmeventd/plugins/thin/Makefile daemons/lvmetad/Makefile conf/Makefile conf/example.conf conf/lvmlocal.conf conf/command_profile_template.profile conf/metadata_profile_template.profile include/.symlinks include/Makefile lib/Makefile lib/format1/Makefile lib/format_pool/Makefile lib/locking/Makefile lib/mirror/Makefile lib/replicator/Makefile lib/misc/lvm-version.h lib/raid/Makefile lib/snapshot/Makefile lib/thin/Makefile lib/cache_segtype/Makefile libdaemon/Makefile libdaemon/client/Makefile libdaemon/server/Makefile libdm/Makefile libdm/libdevmapper.pc liblvm/Makefile liblvm/liblvm2app.pc man/Makefile po/Makefile python/Makefile python/setup.py scripts/blkdeactivate.sh scripts/blk_availability_init_red_hat scripts/blk_availability_systemd_red_hat.service scripts/clvmd_init_red_hat scripts/cmirrord_init_red_hat scripts/dm_event_systemd_red_hat.service scripts/dm_event_systemd_red_hat.socket scripts/lvm2_cluster_activation_red_hat.sh scripts/lvm2_cluster_activation_systemd_red_hat.service scripts/lvm2_clvmd_systemd_red_hat.service scripts/lvm2_cmirrord_systemd_red_hat.service scripts/lvm2_lvmetad_init_red_hat scripts/lvm2_lvmetad_systemd_red_hat.service scripts/lvm2_lvmetad_systemd_red_hat.socket scripts/lvm2_monitoring_init_red_hat scripts/lvm2_monitoring_systemd_red_hat.service scripts/lvm2_pvscan_systemd_red_hat@.service scripts/lvm2_tmpfiles_red_hat.conf scripts/Makefile test/Makefile test/api/Makefile test/unit/Makefile tools/Makefile udev/Makefile unit-tests/datastruct/Makefile unit-tests/regex/Makefile unit-tests/mm/Makefile"
cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
@@ -13372,6 +13853,7 @@ do
"daemons/lvmetad/Makefile") CONFIG_FILES="$CONFIG_FILES daemons/lvmetad/Makefile" ;;
"conf/Makefile") CONFIG_FILES="$CONFIG_FILES conf/Makefile" ;;
"conf/example.conf") CONFIG_FILES="$CONFIG_FILES conf/example.conf" ;;
"conf/lvmlocal.conf") CONFIG_FILES="$CONFIG_FILES conf/lvmlocal.conf" ;;
"conf/command_profile_template.profile") CONFIG_FILES="$CONFIG_FILES conf/command_profile_template.profile" ;;
"conf/metadata_profile_template.profile") CONFIG_FILES="$CONFIG_FILES conf/metadata_profile_template.profile" ;;
"include/.symlinks") CONFIG_FILES="$CONFIG_FILES include/.symlinks" ;;

View File

@@ -69,6 +69,7 @@ dnl -- Checks for programs.
AC_PROG_SED
AC_PROG_AWK
AC_PROG_CC
AC_PROG_CXX
dnl probably no longer needed in 2008, but...
AC_PROG_GCC_TRADITIONAL
@@ -353,7 +354,7 @@ AC_ARG_WITH(default-mirror-segtype,
AC_HELP_STRING([--with-default-mirror-segtype=TYPE],
[default mirror segtype: raid1/mirror [raid1]]),
DEFAULT_MIRROR_SEGTYPE=$withval, DEFAULT_MIRROR_SEGTYPE="raid1")
AC_ARG_WITH(default-raid10r-segtype,
AC_ARG_WITH(default-raid10-segtype,
AC_HELP_STRING([--with-default-raid10-segtype=TYPE],
[default mirror segtype: raid10/mirror [raid10]]),
DEFAULT_RAID10_SEGTYPE=$withval, DEFAULT_RAID10_SEGTYPE="raid10")
@@ -961,6 +962,8 @@ AC_TRY_CCFLAG([-Wjump-misses-init], [HAVE_WJUMP], [], [])
AC_SUBST(HAVE_WJUMP)
AC_TRY_CCFLAG([-Wclobbered], [HAVE_WCLOBBERED], [], [])
AC_SUBST(HAVE_WCLOBBERED)
AC_TRY_CCFLAG([-Wsync-nand], [HAVE_WSYNCNAND], [], [])
AC_SUBST(HAVE_WSYNCNAND)
################################################################################
dnl -- Override optimisation
@@ -1022,12 +1025,16 @@ AC_ARG_ENABLE(valgrind_pool,
VALGRIND_POOL=$enableval, VALGRIND_POOL=no)
AC_MSG_RESULT($VALGRIND_POOL)
if test "$VALGRIND_POOL" = yes; then
pkg_config_init
PKG_CHECK_MODULES(VALGRIND, valgrind, [], [AC_MSG_ERROR(bailing out)])
pkg_config_init
PKG_CHECK_MODULES(VALGRIND, valgrind, [HAVE_VALGRIND=yes], [if test x$VALGRIND_POOL = xyes; then AC_MSG_ERROR(bailing out); fi])
AC_SUBST(VALGRIND_CFLAGS)
if test x$HAVE_VALGRIND = xyes; then
AC_DEFINE([HAVE_VALGRIND], 1, [valgrind.h found])
fi
if test x$VALGRIND_POOL = xyes; then
AC_DEFINE([VALGRIND_POOL], 1, [Enable a valgrind aware build of pool])
AC_SUBST(VALGRIND_POOL)
AC_SUBST(VALGRIND_CFLAGS)
fi
################################################################################
@@ -1092,13 +1099,26 @@ fi
################################################################################
dnl -- Enable udev-systemd protocol to instantiate a service for background jobs
dnl -- Requires systemd version 205 at least (including support for systemd-run)
AC_MSG_CHECKING(whether to use udev-systemd protocol for jobs in background)
AC_ARG_ENABLE(udev-systemd-background-jobs,
AC_HELP_STRING([--disable-udev-systemd-background-jobs],
[disable udev-systemd protocol to instantiate a service for background job]),
UDEV_SYSTEMD_BACKGROUND_JOBS=$enableval, UDEV_SYSTEMD_BACKGROUND_JOBS=yes)
UDEV_SYSTEMD_BACKGROUND_JOBS=$enableval,
UDEV_SYSTEMD_BACKGROUND_JOBS=maybe)
AC_MSG_RESULT($UDEV_SYSTEMD_BACKGROUND_JOBS)
if test "$UDEV_SYSTEMD_BACKGROUND_JOBS" != no; then
pkg_config_init
PKG_CHECK_MODULES(SYSTEMD, systemd >= 205,
[test "$UDEV_SYSTEMD_BACKGROUND_JOBS" = maybe && UDEV_SYSTEMD_BACKGROUND_JOBS=yes],
[if test "$UDEV_SYSTEMD_BACKGROUND_JOBS" = maybe; then
UDEV_SYSTEMD_BACKGROUND_JOBS=no
else
AC_MSG_ERROR([bailing out... systemd >= 205 is required])
fi])
fi
################################################################################
dnl -- Enable udev synchronisation
AC_MSG_CHECKING(whether to enable synchronisation with udev processing)
@@ -1359,6 +1379,18 @@ if test "$REALTIME" = yes; then
fi
fi
dnl Check if the system has struct stat st_ctim.
AC_CACHE_CHECK([for struct stat has st_ctim.],
[ac_cv_stat_st_ctim],
[AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
[#include <sys/stat.h>
long bar(void) { struct stat s; return (long)(s.st_ctim.tv_sec + s.st_ctim.tv_nsec);}]
)], [ac_cv_stat_st_ctim=yes], [ac_cv_stat_st_ctim=no])])
AC_IF_YES(ac_cv_stat_st_ctim,
AC_DEFINE(HAVE_STAT_ST_CTIM, 1,
[Define if struct stat has a field st_ctim with timespec for ctime]))
################################################################################
dnl -- Check for getopt
AC_CHECK_HEADERS(getopt.h, AC_DEFINE([HAVE_GETOPTLONG], 1, [Define to 1 if getopt_long is available.]))
@@ -1434,6 +1466,8 @@ AC_ARG_WITH(confdir,
AC_HELP_STRING([--with-confdir=DIR],
[configuration files in DIR [/etc]]),
CONFDIR=$withval, CONFDIR='/etc')
AC_DEFINE_UNQUOTED(DEFAULT_ETC_DIR, ["$CONFDIR"],
[Default system configuration directory.])
AC_ARG_WITH(staticdir,
AC_HELP_STRING([--with-staticdir=DIR],
@@ -1532,8 +1566,8 @@ AC_DEFINE_UNQUOTED(LVM_PATH, ["$LVM_PATH"], [Path to lvm binary.])
if test "$CLVMD" != none; then
clvmd_prefix=$ac_default_prefix
CLVMD_PATH="$clvmd_prefix/sbin/clvmd"
test "$prefix" != NONE && clvmd_prefix=$prefix
CLVMD_PATH="$clvmd_prefix/sbin/clvmd"
AC_DEFINE_UNQUOTED(CLVMD_PATH, ["$CLVMD_PATH"], [Path to clvmd binary.])
fi
@@ -1703,6 +1737,7 @@ AC_SUBST(FSADM)
AC_SUBST(BLKDEACTIVATE)
AC_SUBST(HAVE_LIBDL)
AC_SUBST(HAVE_REALTIME)
AC_SUBST(HAVE_VALGRIND)
AC_SUBST(INTL)
AC_SUBST(INTL_PACKAGE)
AC_SUBST(JOBS)
@@ -1762,6 +1797,7 @@ AC_SUBST(UDEV_SYNC)
AC_SUBST(UDEV_SYSTEMD_BACKGROUND_JOBS)
AC_SUBST(UDEV_RULE_EXEC_DETECTION)
AC_SUBST(UDEV_HAS_BUILTIN_BLKID)
AC_SUBST(VALGRIND_POOL)
AC_SUBST(WRITE_INSTALL)
AC_SUBST(DMEVENTD_PIDFILE)
AC_SUBST(LVMETAD_PIDFILE)
@@ -1800,6 +1836,7 @@ daemons/dmeventd/plugins/thin/Makefile
daemons/lvmetad/Makefile
conf/Makefile
conf/example.conf
conf/lvmlocal.conf
conf/command_profile_template.profile
conf/metadata_profile_template.profile
include/.symlinks

View File

@@ -208,8 +208,6 @@ static int _lock_resource(const char *resource, int mode, int flags, int *lockid
pthread_mutex_lock(&_lock_mutex);
retry:
pthread_cond_broadcast(&_lock_cond); /* to wakeup waiters */
if (!(head = dm_hash_lookup(_locks, resource))) {
if (flags & LCKF_CONVERT) {
/* In real DLM, lock is identified only by lockid, resource is not used */
@@ -269,12 +267,14 @@ retry:
dm_list_add(head, &lck->list);
}
out:
pthread_cond_broadcast(&_lock_cond); /* to wakeup waiters */
pthread_mutex_unlock(&_lock_mutex);
DEBUGLOG("Locked resource %s, lockid=%d, mode=%s\n",
resource, lck->lockid, _get_mode(lck->mode));
return 0;
bad:
pthread_cond_broadcast(&_lock_cond); /* to wakeup waiters */
pthread_mutex_unlock(&_lock_mutex);
DEBUGLOG("Failed to lock resource %s\n", resource);

View File

@@ -153,16 +153,11 @@ static if_type_t get_cluster_type(void);
static void usage(const char *prog, FILE *file)
{
fprintf(file, "Usage: %s [options]\n"
" -V Show version of clvmd\n"
" -h Show this help information\n"
" -d[n] Set debug logging (0:none, 1:stderr (implies -f option), 2:syslog)\n"
" -f Don't fork, run in the foreground\n"
" -E<lockuuid> Take this lock uuid as exclusively locked resource (for restart)\n"
" -R Tell all running clvmds in the cluster to reload their device cache\n"
" -S Restart clvmd, preserving exclusive locks\n"
" -C Sets debug level (from -d) on all clvmd instances clusterwide\n"
" -t<secs> Command timeout (default 60 seconds)\n"
" -T<secs> Startup timeout (default none)\n"
" -d[n] Set debug logging (0:none, 1:stderr (implies -f option), 2:syslog)\n"
" -E<uuid> Take this lock uuid as exclusively locked resource (for restart)\n"
" -f Don't fork, run in the foreground\n"
" -h Show this help information\n"
" -I<cmgr> Cluster manager (default: auto)\n"
" Available cluster managers: "
#ifdef USE_COROSYNC
@@ -177,6 +172,11 @@ static void usage(const char *prog, FILE *file)
#ifdef USE_SINGLENODE
"singlenode "
#endif
" -R Tell all running clvmds in the cluster to reload their device cache\n"
" -S Restart clvmd, preserving exclusive locks\n"
" -t<secs> Command timeout (default: 60 seconds)\n"
" -T<secs> Startup timeout (default: 0 seconds)\n"
" -V Show version of clvmd\n"
"\n", prog);
}
@@ -899,8 +899,10 @@ static void main_loop(int cmd_timeout)
ret = thisfd->callback(thisfd, buf, sizeof(buf),
csid, &newfd);
/* Ignore EAGAIN */
if (ret < 0 && (errno == EAGAIN || errno == EINTR))
if (ret < 0 && (errno == EAGAIN || errno == EINTR)) {
lastfd = thisfd;
continue;
}
/* Got error or EOF: Remove it from the list safely */
if (ret <= 0) {
@@ -1128,7 +1130,7 @@ static void dump_message(char *buf, int len)
row[j] = buf[i];
str[j] = (isprint(buf[i])) ? buf[i] : ' ';
if ((j == 8) || (i + 1 == len)) {
if (i + 1 == len) {
for (;j < 8; ++j) {
row[j] = 0;
str[j] = ' ';

View File

@@ -136,7 +136,7 @@ static const char *decode_flags(unsigned char flags)
flags & LCK_DMEVENTD_MONITOR_MODE ? "DMEVENTD_MONITOR|" : "",
flags & LCK_ORIGIN_ONLY_MODE ? "ORIGIN_ONLY|" : "",
flags & LCK_TEST_MODE ? "TEST|" : "",
flags & LCK_CONVERT ? "CONVERT|" : "",
flags & LCK_CONVERT_MODE ? "CONVERT|" : "",
flags & LCK_DMEVENTD_MONITOR_IGNORE ? "DMEVENTD_MONITOR_IGNORE|" : "",
flags & LCK_REVERT_MODE ? "REVERT|" : "");
@@ -375,7 +375,7 @@ static int do_activate_lv(char *resource, unsigned char command, unsigned char l
* of exclusive lock to shared one during activation.
*/
if (!test_mode() && command & LCK_CLUSTER_VG) {
status = hold_lock(resource, mode, LCKF_NOQUEUE | (lock_flags & LCK_CONVERT ? LCKF_CONVERT:0));
status = hold_lock(resource, mode, LCKF_NOQUEUE | ((lock_flags & LCK_CONVERT_MODE) ? LCKF_CONVERT:0));
if (status) {
/* Return an LVM-sensible error for this.
* Forcing EIO makes the upper level return this text

View File

@@ -102,7 +102,8 @@ int dmeventd_lvm2_init(void)
goto out;
if (!_lvm_handle) {
lvm2_log_fn(_temporary_log_fn);
if (!getenv("LVM_LOG_FILE_EPOCH"))
lvm2_log_fn(_temporary_log_fn);
if (!(_lvm_handle = lvm2_init())) {
dm_pool_destroy(_mem_pool);
_mem_pool = NULL;

View File

@@ -135,11 +135,21 @@ static int _remove_failed_devices(const char *device)
#define CMD_SIZE 256 /* FIXME Use system restriction */
char cmd_str[CMD_SIZE];
if (!dmeventd_lvm2_command(dmeventd_lvm2_pool(), cmd_str, sizeof(cmd_str),
"lvscan --cache", device))
return -1;
r = dmeventd_lvm2_run(cmd_str);
if (!r)
syslog(LOG_INFO, "Re-scan of mirror device %s failed.", device);
if (!dmeventd_lvm2_command(dmeventd_lvm2_pool(), cmd_str, sizeof(cmd_str),
"lvconvert --config devices{ignore_suspended_devices=1} "
"--repair --use-policies", device))
return -ENAMETOOLONG; /* FIXME Replace with generic error return - reason for failure has already got logged */
/* if repair goes OK, report success even if lvscan has failed */
r = dmeventd_lvm2_run(cmd_str);
syslog(LOG_INFO, "Repair of mirrored device %s %s.", device,

View File

@@ -68,9 +68,6 @@ static void destroy_metadata_hashes(lvmetad_state *s)
dm_hash_destroy(s->vgid_to_vgname);
dm_hash_destroy(s->vgname_to_vgid);
dm_hash_iterate(n, s->device_to_pvid)
dm_free(dm_hash_get_data(s->device_to_pvid, n));
dm_hash_destroy(s->device_to_pvid);
dm_hash_destroy(s->pvid_to_vgid);
}
@@ -773,11 +770,46 @@ out: /* FIXME: We should probably abort() on partial failures. */
return retval;
}
static dev_t device_remove(lvmetad_state *s, struct dm_config_tree *pvmeta, dev_t device)
{
struct dm_config_node *pvmeta_tmp;
struct dm_config_value *v = NULL;
dev_t alt_device = 0, prim_device = 0;
if ((pvmeta_tmp = dm_config_find_node(pvmeta->root, "pvmeta/devices_alternate")))
v = pvmeta_tmp->v;
prim_device = dm_config_find_int64(pvmeta->root, "pvmeta/device", 0);
/* it is the primary device */
if (device > 0 && device == prim_device && pvmeta_tmp && pvmeta_tmp->v)
{
alt_device = pvmeta_tmp->v->v.i;
pvmeta_tmp->v = pvmeta_tmp->v->next;
pvmeta_tmp = dm_config_find_node(pvmeta->root, "pvmeta/device");
pvmeta_tmp->v->v.i = alt_device;
} else if (device != prim_device)
alt_device = prim_device;
/* it is an alternate device */
if (device > 0 && v && v->v.i == device)
pvmeta_tmp->v = v->next;
else while (device > 0 && pvmeta_tmp && v) {
if (v->next && v->next->v.i == device)
v->next = v->next->next;
v = v->next;
}
return alt_device;
}
static response pv_gone(lvmetad_state *s, request r)
{
const char *pvid = daemon_request_str(r, "uuid", NULL);
int64_t device = daemon_request_int(r, "device", 0);
int64_t alt_device = 0;
struct dm_config_tree *pvmeta;
struct dm_config_node *pvmeta_tmp;
char *pvid_old, *vgid;
DEBUGLOG(s, "pv_gone: %s / %" PRIu64, pvid, device);
@@ -797,10 +829,13 @@ static response pv_gone(lvmetad_state *s, request r)
vgid = dm_hash_lookup(s->pvid_to_vgid, pvid);
dm_hash_remove_binary(s->device_to_pvid, &device, sizeof(device));
dm_hash_remove(s->pvid_to_pvmeta, pvid);
unlock_pvid_to_pvmeta(s);
dm_free(pvid_old);
if (!(alt_device = device_remove(s, pvmeta, device)))
dm_hash_remove(s->pvid_to_pvmeta, pvid);
DEBUGLOG(s, "pv_gone alt_device = %" PRIu64, alt_device);
unlock_pvid_to_pvmeta(s);
if (vgid) {
if (!(vgid = dm_strdup(vgid)))
@@ -815,9 +850,15 @@ static response pv_gone(lvmetad_state *s, request r)
if (!pvmeta)
return reply_unknown("PVID does not exist");
dm_config_destroy(pvmeta);
if (!alt_device)
dm_config_destroy(pvmeta);
return daemon_reply_simple("OK", NULL);
if (alt_device) {
return daemon_reply_simple("OK",
"device = %"PRId64, alt_device,
NULL);
} else
return daemon_reply_simple("OK", NULL );
}
static response pv_clear_all(lvmetad_state *s, request r)
@@ -845,11 +886,11 @@ static response pv_found(lvmetad_state *s, request r)
const char *vgname = daemon_request_str(r, "vgname", NULL);
const char *vgid = daemon_request_str(r, "metadata/id", NULL);
const char *vgid_old = NULL;
struct dm_config_node *pvmeta = dm_config_find_node(r.cft->root, "pvmeta");
struct dm_config_node *pvmeta = dm_config_find_node(r.cft->root, "pvmeta"), *altdev = NULL;
struct dm_config_value *altdev_v;
uint64_t device, device_old_pvid = 0;
struct dm_config_tree *cft, *pvmeta_old_dev = NULL, *pvmeta_old_pvid = NULL;
char *old;
char *pvid_dup;
int complete = 0, orphan = 0;
int64_t seqno = -1, seqno_old = -1, changed = 0;
@@ -861,12 +902,8 @@ static response pv_found(lvmetad_state *s, request r)
if (!dm_config_get_uint64(pvmeta, "pvmeta/device", &device))
return reply_fail("need PV device number");
if (!(cft = dm_config_create()) ||
(!(pvid_dup = dm_strdup(pvid)))) {
if (cft)
dm_config_destroy(cft);
if (!(cft = dm_config_create()))
return reply_fail("out of memory");
}
lock_pvid_to_pvmeta(s);
@@ -875,7 +912,6 @@ static response pv_found(lvmetad_state *s, request r)
if ((old = dm_hash_lookup_binary(s->device_to_pvid, &device, sizeof(device)))) {
pvmeta_old_dev = dm_hash_lookup(s->pvid_to_pvmeta, old);
dm_hash_remove(s->pvid_to_pvmeta, old);
vgid_old = dm_hash_lookup(s->pvid_to_vgid, old);
}
@@ -885,35 +921,69 @@ static response pv_found(lvmetad_state *s, request r)
if (!(cft->root = dm_config_clone_node(cft, pvmeta, 0)))
goto out_of_mem;
pvid = dm_config_find_str(cft->root, "pvmeta/id", NULL);
if (!pvmeta_old_pvid || compare_config(pvmeta_old_pvid->root, cft->root))
changed |= 1;
if (pvmeta_old_pvid && device != device_old_pvid) {
DEBUGLOG(s, "pv %s no longer on device %" PRIu64, pvid, device_old_pvid);
dm_free(dm_hash_lookup_binary(s->device_to_pvid, &device_old_pvid, sizeof(device_old_pvid)));
DEBUGLOG(s, "PV %s duplicated on device %" PRIu64, pvid, device_old_pvid);
dm_hash_remove_binary(s->device_to_pvid, &device_old_pvid, sizeof(device_old_pvid));
if (!dm_hash_insert_binary(s->device_to_pvid, &device_old_pvid,
sizeof(device_old_pvid), (void*)pvid))
goto out_of_mem;
if ((altdev = dm_config_find_node(pvmeta_old_pvid->root, "pvmeta/devices_alternate"))) {
altdev = dm_config_clone_node(cft, altdev, 0);
chain_node(altdev, cft->root, 0);
} else
if (!(altdev = make_config_node(cft, "devices_alternate", cft->root, 0)))
goto out_of_mem;
altdev_v = altdev->v;
while (1) {
if (altdev_v && altdev_v->v.i == device_old_pvid)
break;
if (altdev_v)
altdev_v = altdev_v->next;
if (!altdev_v) {
if (!(altdev_v = dm_config_create_value(cft)))
goto out_of_mem;
altdev_v->next = altdev->v;
altdev->v = altdev_v;
altdev->v->v.i = device_old_pvid;
break;
}
};
altdev_v = altdev->v;
while (altdev_v) {
if (altdev_v->next && altdev_v->next->v.i == device)
altdev_v->next = altdev_v->next->next;
altdev_v = altdev_v->next;
}
changed |= 1;
}
if (!dm_hash_insert(s->pvid_to_pvmeta, pvid, cft) ||
!dm_hash_insert_binary(s->device_to_pvid, &device, sizeof(device), (void*)pvid_dup)) {
!dm_hash_insert_binary(s->device_to_pvid, &device, sizeof(device), (void*)pvid)) {
dm_hash_remove(s->pvid_to_pvmeta, pvid);
out_of_mem:
unlock_pvid_to_pvmeta(s);
dm_config_destroy(cft);
dm_free(pvid_dup);
dm_free(old);
return reply_fail("out of memory");
}
unlock_pvid_to_pvmeta(s);
dm_free(old);
if (pvmeta_old_pvid)
dm_config_destroy(pvmeta_old_pvid);
if (pvmeta_old_dev && pvmeta_old_dev != pvmeta_old_pvid)
dm_config_destroy(pvmeta_old_dev);
if (pvmeta_old_dev && pvmeta_old_dev != pvmeta_old_pvid) {
dev_t d = dm_config_find_int64(pvmeta_old_dev->root, "pvmeta/device", 0);
WARN(s, "pv_found: stray device %"PRId64, d);
if (!device_remove(s, pvmeta_old_dev, device)) {
dm_hash_remove(s->pvid_to_pvmeta, old);
dm_config_destroy(pvmeta_old_dev);
}
}
if (metadata) {
if (!vgid)

View File

@@ -105,6 +105,7 @@ void _dump_vg(daemon_handle h, const char *uuid)
int main(int argc, char **argv) {
daemon_handle h = lvmetad_open();
/* FIXME Missing error path */
if (argc > 1) {
int i;
@@ -114,6 +115,7 @@ int main(int argc, char **argv) {
scan(h, argv[i]);
}
destroy_toolcontext(cmd);
/* FIXME Missing lvmetad_close() */
return 0;
}
@@ -122,6 +124,6 @@ int main(int argc, char **argv) {
_dump_vg(h, vgid);
_pv_add(h, uuid3, NULL);
daemon_close(h);
daemon_close(h); /* FIXME lvmetad_close? */
return 0;
}

View File

@@ -0,0 +1,86 @@
Q: Why should lvmetad cache foreign VGs?
A: It's the most useful behavior in the "steady state".
How to arrive at that conclusion.
Four code configurations to consider, each in two different circumstances.
configurations:
1. lvm not using lvmetad
2. lvm using lvmetad and lvmlockd
3. lvm using lvmetad, and lvmetad does not cache foreign VGs
(Not currently implemented.)
4. lvm using lvmetad, and lvmetad caches foreign VGs
circumstances:
A. steady state: PVs are not added or removed to/from foreign VGs
B. transient state: PVs are added or removed to/from foreign VGs
combinations:
1.A. A PV is correctly shown in the foreign VG.
1.B. A PV is correctly shown in the foreign VG.
The most accurate representation, at the cost of always scanning disks.
2.A. A PV is correctly shown in the foreign VG.
2.B. A PV is correctly shown in the foreign VG.
The most accurate representation, at the cost of using lvmlockd.
3.A. A PV in a foreign VG is shown as unused.
3.B. A PV in a foreign VG is shown as unused.
If lvmetad ignores foreign VGs and does not cache them, the PVs in the
foreign VGs appear to be unused. This largely defeats the purpose of
system_id, which is meant to treat VGs/PVs as foreign instead of free
(albeit imperfectly, see below.)
4.A. A PV is correctly shown in the foreign VG.
4.B. A PV is not correctly shown in the foreign VG.
This avoids the cost of always scanning disks, and avoids the cost of
using lvmlockd. The steady state 4.A. is an improvement over the steady
state 3.A. When the steady state is the common case, this is a big
advantage. When the steady state is *not* the common case, the foreign VG
concept is not as useful (if shared devices are this dynamic, lvmlockd
should be considered.)
The limitations related to the transient state 4.B. are explained in
lvmsystemid(7), along with how to handle it. The specific inaccuracies
possible in 4.B. are:
. PV is shown as belonging to a foreign VG, but is actually unused.
. PV is shown as unused, but actually belongs to a foreign VG.
To resolve the inaccuracies in the transient state (4.B.), and return the
system to an accurate steady state (4.A.), the disks need to be scanned,
which updates lvmetad. The scanning/updating is a manual step, i.e.
running 'pvscan --cache', which by definition scans disks and updates
lvmetad.
--
The --foreign command line option for report/display commands
(vgs/lvs/pvs/vgdisplay/lvdisplay/pvdisplay) is not directly related to
whether or not lvmetad caches foreign VGs.
By default, foreign VGs are silently ignored and not printed by these
commands. However, when the --foreign option is used, these commands do
produce output about foreign VGs.
(When --foreign is not used, and the command specifically requests a
foreign VG by name, an error is produced about not accessing foreign VGs,
and the foreign VG is not displayed.)
The decision to report/display foreign VGs or not is independent of
whether lvmetad is caching those VGs. When lvmetad is caching the foreign
VG, a report/display command run with --foreign will scan disks to read
the foreign VG and give the most up to date version of it (the copy of the
foreign VG in lvmetad may be out of date due to changes to the VG by the
foreign host.)

View File

@@ -30,28 +30,48 @@ multiqueue
This policy is the default.
The multiqueue policy has two sets of 16 queues: one set for entries
waiting for the cache and another one for those in the cache.
The multiqueue policy has three sets of 16 queues: one set for entries
waiting for the cache and another two for those in the cache (a set for
clean entries and a set for dirty entries).
Cache entries in the queues are aged based on logical time. Entry into
the cache is based on variable thresholds and queue selection is based
on hit count on entry. The policy aims to take different cache miss
costs into account and to adjust to varying load patterns automatically.
Message and constructor argument pairs are:
'sequential_threshold <#nr_sequential_ios>' and
'random_threshold <#nr_random_ios>'.
'sequential_threshold <#nr_sequential_ios>'
'random_threshold <#nr_random_ios>'
'read_promote_adjustment <value>'
'write_promote_adjustment <value>'
'discard_promote_adjustment <value>'
The sequential threshold indicates the number of contiguous I/Os
required before a stream is treated as sequential. The random threshold
required before a stream is treated as sequential. Once a stream is
considered sequential it will bypass the cache. The random threshold
is the number of intervening non-contiguous I/Os that must be seen
before the stream is treated as random again.
The sequential and random thresholds default to 512 and 4 respectively.
Large, sequential ios are probably better left on the origin device
since spindles tend to have good bandwidth. The io_tracker counts
contiguous I/Os to try to spot when the io is in one of these sequential
modes.
Large, sequential I/Os are probably better left on the origin device
since spindles tend to have good sequential I/O bandwidth. The
io_tracker counts contiguous I/Os to try to spot when the I/O is in one
of these sequential modes. But there are use-cases for wanting to
promote sequential blocks to the cache (e.g. fast application startup).
If sequential threshold is set to 0 the sequential I/O detection is
disabled and sequential I/O will no longer implicitly bypass the cache.
Setting the random threshold to 0 does _not_ disable the random I/O
stream detection.
Internally the mq policy determines a promotion threshold. If the hit
count of a block not in the cache goes above this threshold it gets
promoted to the cache. The read, write and discard promote adjustment
tunables allow you to tweak the promotion threshold by adding a small
value based on the io type. They default to 4, 8 and 1 respectively.
If you're trying to quickly warm a new cache device you may wish to
reduce these to encourage promotion. Remember to switch them back to
their defaults after the cache fills though.
cleaner
-------

View File

@@ -50,14 +50,16 @@ other parameters detailed later):
which are dirty, and extra hints for use by the policy object.
This information could be put on the cache device, but having it
separate allows the volume manager to configure it differently,
e.g. as a mirror for extra robustness.
e.g. as a mirror for extra robustness. This metadata device may only
be used by a single cache device.
Fixed block size
----------------
The origin is divided up into blocks of a fixed size. This block size
is configurable when you first create the cache. Typically we've been
using block sizes of 256k - 1024k.
using block sizes of 256KB - 1024KB. The block size must be between 64
(32KB) and 2097152 (1GB) and a multiple of 64 (32KB).
Having a fixed block size simplifies the target a lot. But it is
something of a compromise. For instance, a small part of a block may be
@@ -66,10 +68,11 @@ So large block sizes are bad because they waste cache space. And small
block sizes are bad because they increase the amount of metadata (both
in core and on disk).
Writeback/writethrough
----------------------
Cache operating modes
---------------------
The cache has two modes, writeback and writethrough.
The cache has three operating modes: writeback, writethrough and
passthrough.
If writeback, the default, is selected then a write to a block that is
cached will go only to the cache and the block will be marked dirty in
@@ -79,15 +82,38 @@ If writethrough is selected then a write to a cached block will not
complete until it has hit both the origin and cache devices. Clean
blocks should remain clean.
If passthrough is selected, useful when the cache contents are not known
to be coherent with the origin device, then all reads are served from
the origin device (all reads miss the cache) and all writes are
forwarded to the origin device; additionally, write hits cause cache
block invalidates. To enable passthrough mode the cache must be clean.
Passthrough mode allows a cache device to be activated without having to
worry about coherency. Coherency that exists is maintained, although
the cache will gradually cool as writes take place. If the coherency of
the cache can later be verified, or established through use of the
"invalidate_cblocks" message, the cache device can be transitioned to
writethrough or writeback mode while still warm. Otherwise, the cache
contents can be discarded prior to transitioning to the desired
operating mode.
A simple cleaner policy is provided, which will clean (write back) all
dirty blocks in a cache. Useful for decommissioning a cache.
dirty blocks in a cache. Useful for decommissioning a cache or when
shrinking a cache. Shrinking the cache's fast device requires all cache
blocks, in the area of the cache being removed, to be clean. If the
area being removed from the cache still contains dirty blocks the resize
will fail. Care must be taken to never reduce the volume used for the
cache's fast device until the cache is clean. This is of particular
importance if writeback mode is used. Writethrough and passthrough
modes already maintain a clean cache. Future support to partially clean
the cache, above a specified threshold, will allow for keeping the cache
warm and in writeback mode during resize.
Migration throttling
--------------------
Migrating data between the origin and cache device uses bandwidth.
The user can set a throttle to prevent more than a certain amount of
migration occuring at any one time. Currently we're not taking any
migration occurring at any one time. Currently we're not taking any
account of normal io traffic going to the devices. More work needs
doing here to avoid migrating during those peak io moments.
@@ -98,12 +124,11 @@ the default being 204800 sectors (or 100MB).
Updating on-disk metadata
-------------------------
On-disk metadata is committed every time a REQ_SYNC or REQ_FUA bio is
written. If no such requests are made then commits will occur every
second. This means the cache behaves like a physical disk that has a
write cache (the same is true of the thin-provisioning target). If
power is lost you may lose some recent writes. The metadata should
always be consistent in spite of any crash.
On-disk metadata is committed every time a FLUSH or FUA bio is written.
If no such requests are made then commits will occur every second. This
means the cache behaves like a physical disk that has a volatile write
cache. If power is lost you may lose some recent writes. The metadata
should always be consistent in spite of any crash.
The 'dirty' state for a cache block changes far too frequently for us
to keep updating it on the fly. So we treat it as a hint. In normal
@@ -159,7 +184,7 @@ Constructor
block size : cache unit size in sectors
#feature args : number of feature arguments passed
feature args : writethrough. (The default is writeback.)
feature args : writethrough or passthrough (The default is writeback.)
policy : the replacement policy to use
#policy args : an even number of arguments corresponding to
@@ -175,6 +200,13 @@ Optional feature arguments are:
back cache block contents later for performance reasons,
so they may differ from the corresponding origin blocks.
passthrough : a degraded mode useful for various cache coherency
situations (e.g., rolling back snapshots of
underlying storage). Reads and writes always go to
the origin. If a write goes to a cached origin
block, then the cache block is invalidated.
To enable passthrough mode the cache must be clean.
A policy called 'default' is always registered. This is an alias for
the policy we currently think is giving best all round performance.
@@ -184,36 +216,43 @@ the characteristics of a specific policy, always request it by name.
Status
------
<#used metadata blocks>/<#total metadata blocks> <#read hits> <#read misses>
<#write hits> <#write misses> <#demotions> <#promotions> <#blocks in cache>
<#dirty> <#features> <features>* <#core args> <core args>* <#policy args>
<policy args>*
<metadata block size> <#used metadata blocks>/<#total metadata blocks>
<cache block size> <#used cache blocks>/<#total cache blocks>
<#read hits> <#read misses> <#write hits> <#write misses>
<#demotions> <#promotions> <#dirty> <#features> <features>*
<#core args> <core args>* <policy name> <#policy args> <policy args>*
#used metadata blocks : Number of metadata blocks used
#total metadata blocks : Total number of metadata blocks
#read hits : Number of times a READ bio has been mapped
metadata block size : Fixed block size for each metadata block in
sectors
#used metadata blocks : Number of metadata blocks used
#total metadata blocks : Total number of metadata blocks
cache block size : Configurable block size for the cache device
in sectors
#used cache blocks : Number of blocks resident in the cache
#total cache blocks : Total number of cache blocks
#read hits : Number of times a READ bio has been mapped
to the cache
#read misses : Number of times a READ bio has been mapped
#read misses : Number of times a READ bio has been mapped
to the origin
#write hits : Number of times a WRITE bio has been mapped
#write hits : Number of times a WRITE bio has been mapped
to the cache
#write misses : Number of times a WRITE bio has been
#write misses : Number of times a WRITE bio has been
mapped to the origin
#demotions : Number of times a block has been removed
#demotions : Number of times a block has been removed
from the cache
#promotions : Number of times a block has been moved to
#promotions : Number of times a block has been moved to
the cache
#blocks in cache : Number of blocks resident in the cache
#dirty : Number of blocks in the cache that differ
#dirty : Number of blocks in the cache that differ
from the origin
#feature args : Number of feature args to follow
feature args : 'writethrough' (optional)
#core args : Number of core arguments (must be even)
core args : Key/value pairs for tuning the core
#feature args : Number of feature args to follow
feature args : 'writethrough' (optional)
#core args : Number of core arguments (must be even)
core args : Key/value pairs for tuning the core
e.g. migration_threshold
#policy args : Number of policy arguments to follow (must be even)
policy args : Key/value pairs
e.g. 'sequential_threshold 1024
policy name : Name of the policy
#policy args : Number of policy arguments to follow (must be even)
policy args : Key/value pairs
e.g. sequential_threshold
Messages
--------
@@ -229,12 +268,28 @@ The message format is:
E.g.
dmsetup message my_cache 0 sequential_threshold 1024
Invalidation is removing an entry from the cache without writing it
back. Cache blocks can be invalidated via the invalidate_cblocks
message, which takes an arbitrary number of cblock ranges. Each cblock
range's end value is "one past the end", meaning 5-10 expresses a range
of values from 5 to 9. Each cblock must be expressed as a decimal
value, in the future a variant message that takes cblock ranges
expressed in hexidecimal may be needed to better support efficient
invalidation of larger caches. The cache must be in passthrough mode
when invalidate_cblocks is used.
invalidate_cblocks [<cblock>|<cblock begin>-<cblock end>]*
E.g.
dmsetup message my_cache 0 invalidate_cblocks 2345 3456-4567 5678-6789
Examples
========
The test suite can be found here:
https://github.com/jthornber/thinp-test-suite
https://github.com/jthornber/device-mapper-test-suite
dmsetup create my_cache --table '0 41943040 cache /dev/mapper/metadata \
/dev/mapper/ssd /dev/mapper/origin 512 1 writeback default 0'

View File

@@ -4,12 +4,15 @@ dm-crypt
Device-Mapper's "crypt" target provides transparent encryption of block devices
using the kernel crypto API.
For a more detailed description of supported parameters see:
https://gitlab.com/cryptsetup/cryptsetup/wikis/DMCrypt
Parameters: <cipher> <key> <iv_offset> <device path> \
<offset> [<#opt_params> <opt_params>]
<cipher>
Encryption cipher and an optional IV generation mode.
(In format cipher[:keycount]-chainmode-ivopts:ivmode).
(In format cipher[:keycount]-chainmode-ivmode[:ivopts]).
Examples:
des
aes-cbc-essiv:sha256
@@ -19,7 +22,11 @@ Parameters: <cipher> <key> <iv_offset> <device path> \
<key>
Key used for encryption. It is encoded as a hexadecimal number.
You can only use key sizes that are valid for the selected cipher.
You can only use key sizes that are valid for the selected cipher
in combination with the selected iv mode.
Note that for some iv modes the key string can contain additional
keys (for example IV seed) so the key contains more parts concatenated
into a single string.
<keycount>
Multi-key compatibility mode. You can define <keycount> keys and
@@ -44,7 +51,7 @@ Parameters: <cipher> <key> <iv_offset> <device path> \
Otherwise #opt_params is the number of following arguments.
Example of optional parameters section:
1 allow_discards
3 allow_discards same_cpu_crypt submit_from_crypt_cpus
allow_discards
Block discard requests (a.k.a. TRIM) are passed through the crypt device.
@@ -56,11 +63,24 @@ allow_discards
used space etc.) if the discarded blocks can be located easily on the
device later.
same_cpu_crypt
Perform encryption using the same cpu that IO was submitted on.
The default is to use an unbound workqueue so that encryption work
is automatically balanced between available CPUs.
submit_from_crypt_cpus
Disable offloading writes to a separate thread after encryption.
There are some situations where offloading write bios from the
encryption threads to a single thread degrades performance
significantly. The default is to offload write bios to the same
thread because it benefits CFQ to have writes submitted using the
same context.
Example scripts
===============
LUKS (Linux Unified Key Setup) is now the preferred way to set up disk
encryption with dm-crypt using the 'cryptsetup' utility, see
http://code.google.com/p/cryptsetup/
https://gitlab.com/cryptsetup/cryptsetup
[[
#!/bin/sh

108
doc/kernel/era.txt Normal file
View File

@@ -0,0 +1,108 @@
Introduction
============
dm-era is a target that behaves similar to the linear target. In
addition it keeps track of which blocks were written within a user
defined period of time called an 'era'. Each era target instance
maintains the current era as a monotonically increasing 32-bit
counter.
Use cases include tracking changed blocks for backup software, and
partially invalidating the contents of a cache to restore cache
coherency after rolling back a vendor snapshot.
Constructor
===========
era <metadata dev> <origin dev> <block size>
metadata dev : fast device holding the persistent metadata
origin dev : device holding data blocks that may change
block size : block size of origin data device, granularity that is
tracked by the target
Messages
========
None of the dm messages take any arguments.
checkpoint
----------
Possibly move to a new era. You shouldn't assume the era has
incremented. After sending this message, you should check the
current era via the status line.
take_metadata_snap
------------------
Create a clone of the metadata, to allow a userland process to read it.
drop_metadata_snap
------------------
Drop the metadata snapshot.
Status
======
<metadata block size> <#used metadata blocks>/<#total metadata blocks>
<current era> <held metadata root | '-'>
metadata block size : Fixed block size for each metadata block in
sectors
#used metadata blocks : Number of metadata blocks used
#total metadata blocks : Total number of metadata blocks
current era : The current era
held metadata root : The location, in blocks, of the metadata root
that has been 'held' for userspace read
access. '-' indicates there is no held root
Detailed use case
=================
The scenario of invalidating a cache when rolling back a vendor
snapshot was the primary use case when developing this target:
Taking a vendor snapshot
------------------------
- Send a checkpoint message to the era target
- Make a note of the current era in its status line
- Take vendor snapshot (the era and snapshot should be forever
associated now).
Rolling back to an vendor snapshot
----------------------------------
- Cache enters passthrough mode (see: dm-cache's docs in cache.txt)
- Rollback vendor storage
- Take metadata snapshot
- Ascertain which blocks have been written since the snapshot was taken
by checking each block's era
- Invalidate those blocks in the caching software
- Cache returns to writeback/writethrough mode
Memory usage
============
The target uses a bitset to record writes in the current era. It also
has a spare bitset ready for switching over to a new era. Other than
that it uses a few 4k blocks for updating metadata.
(4 * nr_blocks) bytes + buffers
Resilience
==========
Metadata is updated on disk before a write to a previously unwritten
block is performed. As such dm-era should not be effected by a hard
crash such as power failure.
Userland tools
==============
Userland tools are found in the increasingly poorly named
thin-provisioning-tools project:
https://github.com/jthornber/thin-provisioning-tools

140
doc/kernel/log-writes.txt Normal file
View File

@@ -0,0 +1,140 @@
dm-log-writes
=============
This target takes 2 devices, one to pass all IO to normally, and one to log all
of the write operations to. This is intended for file system developers wishing
to verify the integrity of metadata or data as the file system is written to.
There is a log_write_entry written for every WRITE request and the target is
able to take arbitrary data from userspace to insert into the log. The data
that is in the WRITE requests is copied into the log to make the replay happen
exactly as it happened originally.
Log Ordering
============
We log things in order of completion once we are sure the write is no longer in
cache. This means that normal WRITE requests are not actually logged until the
next REQ_FLUSH request. This is to make it easier for userspace to replay the
log in a way that correlates to what is on disk and not what is in cache, to
make it easier to detect improper waiting/flushing.
This works by attaching all WRITE requests to a list once the write completes.
Once we see a REQ_FLUSH request we splice this list onto the request and once
the FLUSH request completes we log all of the WRITEs and then the FLUSH. Only
completed WRITEs, at the time the REQ_FLUSH is issued, are added in order to
simulate the worst case scenario with regard to power failures. Consider the
following example (W means write, C means complete):
W1,W2,W3,C3,C2,Wflush,C1,Cflush
The log would show the following
W3,W2,flush,W1....
Again this is to simulate what is actually on disk, this allows us to detect
cases where a power failure at a particular point in time would create an
inconsistent file system.
Any REQ_FUA requests bypass this flushing mechanism and are logged as soon as
they complete as those requests will obviously bypass the device cache.
Any REQ_DISCARD requests are treated like WRITE requests. Otherwise we would
have all the DISCARD requests, and then the WRITE requests and then the FLUSH
request. Consider the following example:
WRITE block 1, DISCARD block 1, FLUSH
If we logged DISCARD when it completed, the replay would look like this
DISCARD 1, WRITE 1, FLUSH
which isn't quite what happened and wouldn't be caught during the log replay.
Target interface
================
i) Constructor
log-writes <dev_path> <log_dev_path>
dev_path : Device that all of the IO will go to normally.
log_dev_path : Device where the log entries are written to.
ii) Status
<#logged entries> <highest allocated sector>
#logged entries : Number of logged entries
highest allocated sector : Highest allocated sector
iii) Messages
mark <description>
You can use a dmsetup message to set an arbitrary mark in a log.
For example say you want to fsck a file system after every
write, but first you need to replay up to the mkfs to make sure
we're fsck'ing something reasonable, you would do something like
this:
mkfs.btrfs -f /dev/mapper/log
dmsetup message log 0 mark mkfs
<run test>
This would allow you to replay the log up to the mkfs mark and
then replay from that point on doing the fsck check in the
interval that you want.
Every log has a mark at the end labeled "dm-log-writes-end".
Userspace component
===================
There is a userspace tool that will replay the log for you in various ways.
It can be found here: https://github.com/josefbacik/log-writes
Example usage
=============
Say you want to test fsync on your file system. You would do something like
this:
TABLE="0 $(blockdev --getsz /dev/sdb) log-writes /dev/sdb /dev/sdc"
dmsetup create log --table "$TABLE"
mkfs.btrfs -f /dev/mapper/log
dmsetup message log 0 mark mkfs
mount /dev/mapper/log /mnt/btrfs-test
<some test that does fsync at the end>
dmsetup message log 0 mark fsync
md5sum /mnt/btrfs-test/foo
umount /mnt/btrfs-test
dmsetup remove log
replay-log --log /dev/sdc --replay /dev/sdb --end-mark fsync
mount /dev/sdb /mnt/btrfs-test
md5sum /mnt/btrfs-test/foo
<verify md5sum's are correct>
Another option is to do a complicated file system operation and verify the file
system is consistent during the entire operation. You could do this with:
TABLE="0 $(blockdev --getsz /dev/sdb) log-writes /dev/sdb /dev/sdc"
dmsetup create log --table "$TABLE"
mkfs.btrfs -f /dev/mapper/log
dmsetup message log 0 mark mkfs
mount /dev/mapper/log /mnt/btrfs-test
<fsstress to dirty the fs>
btrfs filesystem balance /mnt/btrfs-test
umount /mnt/btrfs-test
dmsetup remove log
replay-log --log /dev/sdc --replay /dev/sdb --end-mark mkfs
btrfsck /dev/sdb
replay-log --log /dev/sdc --replay /dev/sdb --start-mark mkfs \
--fsck "btrfsck /dev/sdb" --check fua
And that will replay the log until it sees a FUA request, run the fsck command
and if the fsck passes it will replay to the next FUA, until it is completed or
the fsck command exists abnormally.

View File

@@ -222,3 +222,5 @@ Version History
1.4.2 Add RAID10 "far" and "offset" algorithm support.
1.5.0 Add message interface to allow manipulation of the sync_action.
New status (STATUSTYPE_INFO) fields: sync_action and mismatch_cnt.
1.5.1 Add ability to restore transiently failed devices on resume.
1.5.2 'mismatch_cnt' is zero unless [last_]sync_action is "check".

186
doc/kernel/statistics.txt Normal file
View File

@@ -0,0 +1,186 @@
DM statistics
=============
Device Mapper supports the collection of I/O statistics on user-defined
regions of a DM device. If no regions are defined no statistics are
collected so there isn't any performance impact. Only bio-based DM
devices are currently supported.
Each user-defined region specifies a starting sector, length and step.
Individual statistics will be collected for each step-sized area within
the range specified.
The I/O statistics counters for each step-sized area of a region are
in the same format as /sys/block/*/stat or /proc/diskstats (see:
Documentation/iostats.txt). But two extra counters (12 and 13) are
provided: total time spent reading and writing in milliseconds. All
these counters may be accessed by sending the @stats_print message to
the appropriate DM device via dmsetup.
Each region has a corresponding unique identifier, which we call a
region_id, that is assigned when the region is created. The region_id
must be supplied when querying statistics about the region, deleting the
region, etc. Unique region_ids enable multiple userspace programs to
request and process statistics for the same DM device without stepping
on each other's data.
The creation of DM statistics will allocate memory via kmalloc or
fallback to using vmalloc space. At most, 1/4 of the overall system
memory may be allocated by DM statistics. The admin can see how much
memory is used by reading
/sys/module/dm_mod/parameters/stats_current_allocated_bytes
Messages
========
@stats_create <range> <step> [<program_id> [<aux_data>]]
Create a new region and return the region_id.
<range>
"-" - whole device
"<start_sector>+<length>" - a range of <length> 512-byte sectors
starting with <start_sector>.
<step>
"<area_size>" - the range is subdivided into areas each containing
<area_size> sectors.
"/<number_of_areas>" - the range is subdivided into the specified
number of areas.
<program_id>
An optional parameter. A name that uniquely identifies
the userspace owner of the range. This groups ranges together
so that userspace programs can identify the ranges they
created and ignore those created by others.
The kernel returns this string back in the output of
@stats_list message, but it doesn't use it for anything else.
<aux_data>
An optional parameter. A word that provides auxiliary data
that is useful to the client program that created the range.
The kernel returns this string back in the output of
@stats_list message, but it doesn't use this value for anything.
@stats_delete <region_id>
Delete the region with the specified id.
<region_id>
region_id returned from @stats_create
@stats_clear <region_id>
Clear all the counters except the in-flight i/o counters.
<region_id>
region_id returned from @stats_create
@stats_list [<program_id>]
List all regions registered with @stats_create.
<program_id>
An optional parameter.
If this parameter is specified, only matching regions
are returned.
If it is not specified, all regions are returned.
Output format:
<region_id>: <start_sector>+<length> <step> <program_id> <aux_data>
@stats_print <region_id> [<starting_line> <number_of_lines>]
Print counters for each step-sized area of a region.
<region_id>
region_id returned from @stats_create
<starting_line>
The index of the starting line in the output.
If omitted, all lines are returned.
<number_of_lines>
The number of lines to include in the output.
If omitted, all lines are returned.
Output format for each step-sized area of a region:
<start_sector>+<length> counters
The first 11 counters have the same meaning as
/sys/block/*/stat or /proc/diskstats.
Please refer to Documentation/iostats.txt for details.
1. the number of reads completed
2. the number of reads merged
3. the number of sectors read
4. the number of milliseconds spent reading
5. the number of writes completed
6. the number of writes merged
7. the number of sectors written
8. the number of milliseconds spent writing
9. the number of I/Os currently in progress
10. the number of milliseconds spent doing I/Os
11. the weighted number of milliseconds spent doing I/Os
Additional counters:
12. the total time spent reading in milliseconds
13. the total time spent writing in milliseconds
@stats_print_clear <region_id> [<starting_line> <number_of_lines>]
Atomically print and then clear all the counters except the
in-flight i/o counters. Useful when the client consuming the
statistics does not want to lose any statistics (those updated
between printing and clearing).
<region_id>
region_id returned from @stats_create
<starting_line>
The index of the starting line in the output.
If omitted, all lines are printed and then cleared.
<number_of_lines>
The number of lines to process.
If omitted, all lines are printed and then cleared.
@stats_set_aux <region_id> <aux_data>
Store auxiliary data aux_data for the specified region.
<region_id>
region_id returned from @stats_create
<aux_data>
The string that identifies data which is useful to the client
program that created the range. The kernel returns this
string back in the output of @stats_list message, but it
doesn't use this value for anything.
Examples
========
Subdivide the DM device 'vol' into 100 pieces and start collecting
statistics on them:
dmsetup message vol 0 @stats_create - /100
Set the auxillary data string to "foo bar baz" (the escape for each
space must also be escaped, otherwise the shell will consume them):
dmsetup message vol 0 @stats_set_aux 0 foo\\ bar\\ baz
List the statistics:
dmsetup message vol 0 @stats_list
Print the statistics:
dmsetup message vol 0 @stats_print 0
Delete the statistics:
dmsetup message vol 0 @stats_delete 0

138
doc/kernel/switch.txt Normal file
View File

@@ -0,0 +1,138 @@
dm-switch
=========
The device-mapper switch target creates a device that supports an
arbitrary mapping of fixed-size regions of I/O across a fixed set of
paths. The path used for any specific region can be switched
dynamically by sending the target a message.
It maps I/O to underlying block devices efficiently when there is a large
number of fixed-sized address regions but there is no simple pattern
that would allow for a compact representation of the mapping such as
dm-stripe.
Background
----------
Dell EqualLogic and some other iSCSI storage arrays use a distributed
frameless architecture. In this architecture, the storage group
consists of a number of distinct storage arrays ("members") each having
independent controllers, disk storage and network adapters. When a LUN
is created it is spread across multiple members. The details of the
spreading are hidden from initiators connected to this storage system.
The storage group exposes a single target discovery portal, no matter
how many members are being used. When iSCSI sessions are created, each
session is connected to an eth port on a single member. Data to a LUN
can be sent on any iSCSI session, and if the blocks being accessed are
stored on another member the I/O will be forwarded as required. This
forwarding is invisible to the initiator. The storage layout is also
dynamic, and the blocks stored on disk may be moved from member to
member as needed to balance the load.
This architecture simplifies the management and configuration of both
the storage group and initiators. In a multipathing configuration, it
is possible to set up multiple iSCSI sessions to use multiple network
interfaces on both the host and target to take advantage of the
increased network bandwidth. An initiator could use a simple round
robin algorithm to send I/O across all paths and let the storage array
members forward it as necessary, but there is a performance advantage to
sending data directly to the correct member.
A device-mapper table already lets you map different regions of a
device onto different targets. However in this architecture the LUN is
spread with an address region size on the order of 10s of MBs, which
means the resulting table could have more than a million entries and
consume far too much memory.
Using this device-mapper switch target we can now build a two-layer
device hierarchy:
Upper Tier - Determine which array member the I/O should be sent to.
Lower Tier - Load balance amongst paths to a particular member.
The lower tier consists of a single dm multipath device for each member.
Each of these multipath devices contains the set of paths directly to
the array member in one priority group, and leverages existing path
selectors to load balance amongst these paths. We also build a
non-preferred priority group containing paths to other array members for
failover reasons.
The upper tier consists of a single dm-switch device. This device uses
a bitmap to look up the location of the I/O and choose the appropriate
lower tier device to route the I/O. By using a bitmap we are able to
use 4 bits for each address range in a 16 member group (which is very
large for us). This is a much denser representation than the dm table
b-tree can achieve.
Construction Parameters
=======================
<num_paths> <region_size> <num_optional_args> [<optional_args>...]
[<dev_path> <offset>]+
<num_paths>
The number of paths across which to distribute the I/O.
<region_size>
The number of 512-byte sectors in a region. Each region can be redirected
to any of the available paths.
<num_optional_args>
The number of optional arguments. Currently, no optional arguments
are supported and so this must be zero.
<dev_path>
The block device that represents a specific path to the device.
<offset>
The offset of the start of data on the specific <dev_path> (in units
of 512-byte sectors). This number is added to the sector number when
forwarding the request to the specific path. Typically it is zero.
Messages
========
set_region_mappings <index>:<path_nr> [<index>]:<path_nr> [<index>]:<path_nr>...
Modify the region table by specifying which regions are redirected to
which paths.
<index>
The region number (region size was specified in constructor parameters).
If index is omitted, the next region (previous index + 1) is used.
Expressed in hexadecimal (WITHOUT any prefix like 0x).
<path_nr>
The path number in the range 0 ... (<num_paths> - 1).
Expressed in hexadecimal (WITHOUT any prefix like 0x).
R<n>,<m>
This parameter allows repetitive patterns to be loaded quickly. <n> and <m>
are hexadecimal numbers. The last <n> mappings are repeated in the next <m>
slots.
Status
======
No status line is reported.
Example
=======
Assume that you have volumes vg1/switch0 vg1/switch1 vg1/switch2 with
the same size.
Create a switch device with 64kB region size:
dmsetup create switch --table "0 `blockdev --getsize /dev/vg1/switch0`
switch 3 128 0 /dev/vg1/switch0 0 /dev/vg1/switch1 0 /dev/vg1/switch2 0"
Set mappings for the first 7 entries to point to devices switch0, switch1,
switch2, switch0, switch1, switch2, switch1:
dmsetup message switch 0 set_region_mappings 0:0 :1 :2 :0 :1 :2 :1
Set repetitive mapping. This command:
dmsetup message switch 0 set_region_mappings 1000:1 :2 R2,10
is equivalent to:
dmsetup message switch 0 set_region_mappings 1000:1 :2 :1 :2 :1 :2 :1 :2 \
:1 :2 :1 :2 :1 :2 :1 :2 :1 :2

View File

@@ -99,13 +99,14 @@ Using an existing pool device
$data_block_size $low_water_mark"
$data_block_size gives the smallest unit of disk space that can be
allocated at a time expressed in units of 512-byte sectors. People
primarily interested in thin provisioning may want to use a value such
as 1024 (512KB). People doing lots of snapshotting may want a smaller value
such as 128 (64KB). If you are not zeroing newly-allocated data,
a larger $data_block_size in the region of 256000 (128MB) is suggested.
$data_block_size must be the same for the lifetime of the
metadata device.
allocated at a time expressed in units of 512-byte sectors.
$data_block_size must be between 128 (64KB) and 2097152 (1GB) and a
multiple of 128 (64KB). $data_block_size cannot be changed after the
thin-pool is created. People primarily interested in thin provisioning
may want to use a value such as 1024 (512KB). People doing lots of
snapshotting may want a smaller value such as 128 (64KB). If you are
not zeroing newly-allocated data, a larger $data_block_size in the
region of 256000 (128MB) is suggested.
$low_water_mark is expressed in blocks of size $data_block_size. If
free space on the data device drops below this level then a dm event
@@ -115,6 +116,35 @@ Resuming a device with a new table itself triggers an event so the
userspace daemon can use this to detect a situation where a new table
already exceeds the threshold.
A low water mark for the metadata device is maintained in the kernel and
will trigger a dm event if free space on the metadata device drops below
it.
Updating on-disk metadata
-------------------------
On-disk metadata is committed every time a FLUSH or FUA bio is written.
If no such requests are made then commits will occur every second. This
means the thin-provisioning target behaves like a physical disk that has
a volatile write cache. If power is lost you may lose some recent
writes. The metadata should always be consistent in spite of any crash.
If data space is exhausted the pool will either error or queue IO
according to the configuration (see: error_if_no_space). If metadata
space is exhausted or a metadata operation fails: the pool will error IO
until the pool is taken offline and repair is performed to 1) fix any
potential inconsistencies and 2) clear the flag that imposes repair.
Once the pool's metadata device is repaired it may be resized, which
will allow the pool to return to normal operation. Note that if a pool
is flagged as needing repair, the pool's data and metadata devices
cannot be resized until repair is performed. It should also be noted
that when the pool's metadata space is exhausted the current metadata
transaction is aborted. Given that the pool will cache IO whose
completion may have already been acknowledged to upper IO layers
(e.g. filesystem) it is strongly suggested that consistency checks
(e.g. fsck) be performed on those layers when repair of the pool is
required.
Thin provisioning
-----------------
@@ -234,6 +264,8 @@ i) Constructor
read_only: Don't allow any changes to be made to the pool
metadata.
error_if_no_space: Error IOs, instead of queueing, if no space.
Data block size must be between 64KB (128 sectors) and 1GB
(2097152 sectors) inclusive.
@@ -255,10 +287,9 @@ ii) Status
should register for the event and then check the target's status.
held metadata root:
The location, in sectors, of the metadata root that has been
The location, in blocks, of the metadata root that has been
'held' for userspace read access. '-' indicates there is no
held root. This feature is not yet implemented so '-' is
always returned.
held root.
discard_passdown|no_discard_passdown
Whether or not discards are actually being passed down to the
@@ -275,6 +306,14 @@ ii) Status
contain the string 'Fail'. The userspace recovery tools
should then be used.
error_if_no_space|queue_if_no_space
If the pool runs out of data or metadata space, the pool will
either queue or error the IO destined to the data device. The
default is to queue the IO until more space is added or the
'no_space_timeout' expires. The 'no_space_timeout' dm-thin-pool
module parameter can be used to change this timeout -- it
defaults to 60 seconds but may be disabled using a value of 0.
iii) Messages
create_thin <dev id>
@@ -341,9 +380,6 @@ then you'll have no access to blocks mapped beyond the end. If you
load a target that is bigger than before, then extra blocks will be
provisioned as and when needed.
If you wish to reduce the size of your thin device and potentially
regain some space then send the 'trim' message to the pool.
ii) Status
<nr mapped sectors> <highest mapped sector>

View File

@@ -11,6 +11,7 @@ Construction Parameters
<data_block_size> <hash_block_size>
<num_data_blocks> <hash_start_block>
<algorithm> <digest> <salt>
[<#opt_params> <opt_params>]
<version>
This is the type of the on-disk hash format.
@@ -62,6 +63,22 @@ Construction Parameters
<salt>
The hexadecimal encoding of the salt value.
<#opt_params>
Number of optional parameters. If there are no optional parameters,
the optional paramaters section can be skipped or #opt_params can be zero.
Otherwise #opt_params is the number of following arguments.
Example of optional parameters section:
1 ignore_corruption
ignore_corruption
Log corrupted blocks, but allow read operations to proceed normally.
restart_on_corruption
Restart the system when a corrupted block is discovered. This option is
not compatible with ignore_corruption and requires user space support to
avoid restart loops.
Theory of operation
===================
@@ -125,7 +142,7 @@ block boundary) are the hash blocks which are stored a depth at a time
The full specification of kernel parameters and on-disk metadata format
is available at the cryptsetup project's wiki page
http://code.google.com/p/cryptsetup/wiki/DMVerity
https://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity
Status
======
@@ -142,7 +159,7 @@ Set up a device:
A command line tool veritysetup is available to compute or verify
the hash tree or activate the kernel device. This is available from
the cryptsetup upstream repository http://code.google.com/p/cryptsetup/
the cryptsetup upstream repository https://gitlab.com/cryptsetup/cryptsetup/
(as a libcryptsetup extension).
Create hash on the device:

View File

@@ -13,6 +13,7 @@
@top_srcdir@/lib/datastruct/btree.h
@top_srcdir@/lib/datastruct/str_list.h
@top_srcdir@/lib/device/dev-cache.h
@top_srcdir@/lib/device/dev-ext-udev-constants.h
@top_srcdir@/lib/device/dev-type.h
@top_srcdir@/lib/device/device.h
@top_srcdir@/lib/device/device-types.h

View File

@@ -56,6 +56,7 @@ SOURCES =\
datastruct/btree.c \
datastruct/str_list.c \
device/dev-cache.c \
device/dev-ext.c \
device/dev-io.c \
device/dev-md.c \
device/dev-swap.c \
@@ -69,6 +70,7 @@ SOURCES =\
filters/filter-regex.c \
filters/filter-sysfs.c \
filters/filter-md.c \
filters/filter-fwraid.c \
filters/filter-mpath.c \
filters/filter-partitioned.c \
filters/filter-type.c \
@@ -220,7 +222,7 @@ CFLOW_LIST_TARGET = $(LIB_NAME).cflow
include $(top_builddir)/make.tmpl
CFLAGS += $(BLKID_CFLAGS) $(UDEV_CFLAGS)
CFLAGS += $(BLKID_CFLAGS) $(UDEV_CFLAGS) $(VALGRIND_CFLAGS)
$(SUBDIRS): $(LIB_STATIC)

View File

@@ -238,6 +238,22 @@ int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s, int use_layer,
{
return 0;
}
int lv_info_with_seg_status(struct cmd_context *cmd, const struct logical_volume *lv,
const struct lv_segment *lv_seg, int use_layer,
struct lv_with_info_and_seg_status *status,
int with_open_count, int with_read_ahead)
{
return 0;
}
int lv_status(struct cmd_context *cmd, const struct lv_segment *lv_seg,
int use_layer, struct lv_seg_status *lv_seg_status)
{
return 0;
}
int lv_cache_status(const struct logical_volume *cache_lv,
struct lv_status_cache **status)
{
}
int lv_check_not_in_use(const struct logical_volume *lv)
{
return 0;
@@ -618,7 +634,9 @@ int target_present(struct cmd_context *cmd, const char *target_name,
}
static int _lv_info(struct cmd_context *cmd, const struct logical_volume *lv,
int use_layer, struct lvinfo *info, struct lv_seg_status *seg_status,
int use_layer, struct lvinfo *info,
const struct lv_segment *seg,
struct lv_seg_status *seg_status,
int with_open_count, int with_read_ahead)
{
struct dm_info dminfo;
@@ -637,8 +655,16 @@ static int _lv_info(struct cmd_context *cmd, const struct logical_volume *lv,
}
/* New thin-pool has no layer, but -tpool suffix needs to be queried */
if (!use_layer && lv_is_new_thin_pool(lv))
use_layer = 1;
if (!use_layer && lv_is_new_thin_pool(lv)) {
/* Check if there isn't existing old thin pool mapping in the table */
if (!dev_manager_info(cmd->mem, lv, NULL, 0, 0, &dminfo, NULL, NULL))
return_0;
if (!dminfo.exists)
use_layer = 1;
}
if (seg_status)
seg_status->seg = seg;
if (!dev_manager_info(cmd->mem, lv,
(use_layer) ? lv_layer(lv) : NULL,
@@ -672,7 +698,7 @@ int lv_info(struct cmd_context *cmd, const struct logical_volume *lv, int use_la
if (!activation())
return 0;
return _lv_info(cmd, lv, use_layer, info, NULL, with_open_count, with_read_ahead);
return _lv_info(cmd, lv, use_layer, info, NULL, NULL, with_open_count, with_read_ahead);
}
int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s, int use_layer,
@@ -690,19 +716,45 @@ int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s, int use_layer,
return r;
}
int lv_info_with_seg_status(struct cmd_context *cmd, const struct logical_volume *lv,
const struct lv_segment *lv_seg, int use_layer,
struct lv_with_info_and_seg_status *lvdm,
int with_open_count, int with_read_ahead)
/*
* Returns 1 if lv_seg_status structure populated,
* else 0 on failure or if device not active locally.
*/
int lv_status(struct cmd_context *cmd, const struct lv_segment *lv_seg,
int use_layer, struct lv_seg_status *lv_seg_status)
{
if (!activation())
return 0;
if (!_lv_info(cmd, lv, use_layer, lvdm->info, lvdm->seg_status,
with_open_count, with_read_ahead))
return _lv_info(cmd, lv_seg->lv, use_layer, NULL, lv_seg, lv_seg_status, 0, 0);
}
/*
* Returns 1 if lv_with_info_and_seg_status structure populated,
* else 0 on failure or if device not active locally.
*
* This is the same as calling lv_info and lv_status,
* but* it's done in one go with one ioctl if possible! ]
*/
int lv_info_with_seg_status(struct cmd_context *cmd, const struct logical_volume *lv,
const struct lv_segment *lv_seg, int use_layer,
struct lv_with_info_and_seg_status *status,
int with_open_count, int with_read_ahead)
{
if (!activation())
return 0;
return 1;
if (lv == lv_seg->lv)
return _lv_info(cmd, lv, use_layer, &status->info, lv_seg, &status->seg_status,
with_open_count, with_read_ahead);
/*
* If the info is requested for an LV and segment
* status for segment that belong to another LV,
* we need to acquire info and status separately!
*/
return _lv_info(cmd, lv, use_layer, &status->info, NULL, NULL, with_open_count, with_read_ahead) &&
_lv_info(cmd, lv_seg->lv, use_layer, NULL, lv_seg, &status->seg_status, 0, 0);
}
#define OPEN_COUNT_CHECK_RETRIES 25
@@ -1713,6 +1765,19 @@ static int _preload_detached_lv(struct logical_volume *lv, void *data)
struct detached_lv_data *detached = data;
struct lv_list *lvl_pre;
/* Check and preload removed raid image leg or metadata */
if (lv_is_raid_image(lv)) {
if ((lvl_pre = find_lv_in_vg_by_lvid(detached->lv_pre->vg, &lv->lvid)) &&
!lv_is_raid_image(lvl_pre->lv) && lv_is_active(lv) &&
!_lv_preload(lvl_pre->lv, detached->laopts, detached->flush_required))
return_0;
} else if (lv_is_raid_metadata(lv)) {
if ((lvl_pre = find_lv_in_vg_by_lvid(detached->lv_pre->vg, &lv->lvid)) &&
!lv_is_raid_metadata(lvl_pre->lv) && lv_is_active(lv) &&
!_lv_preload(lvl_pre->lv, detached->laopts, detached->flush_required))
return_0;
}
if ((lvl_pre = find_lv_in_vg(detached->lv_pre->vg, lv->name))) {
if (lv_is_visible(lvl_pre->lv) && lv_is_active(lv) &&
(!lv_is_cow(lv) || !lv_is_cow(lvl_pre->lv)) &&
@@ -2173,6 +2238,16 @@ static int _lv_activate(struct cmd_context *cmd, const char *lvid_s,
goto out;
}
/*
* Check if cmirrord is running for clustered mirrors.
*/
if (!laopts->exclusive && vg_is_clustered(lv->vg) &&
lv_is_mirror(lv) && !lv_is_raid(lv) &&
!cluster_mirror_is_available(lv->vg->cmd)) {
log_error("Shared cluster mirrors are not available.");
goto out;
}
if (test_mode()) {
_skip("Activating '%s'.", lv->name);
r = 1;

View File

@@ -36,21 +36,29 @@ typedef enum {
SEG_STATUS_RAID,
SEG_STATUS_SNAPSHOT,
SEG_STATUS_THIN,
SEG_STATUS_THIN_POOL
SEG_STATUS_THIN_POOL,
SEG_STATUS_UNKNOWN
} lv_seg_status_type_t;
struct lv_seg_status {
struct dm_pool *mem; /* input */
struct lv_segment *seg; /* input */
const struct lv_segment *seg; /* input */
lv_seg_status_type_t type; /* output */
void *status; /* struct dm_status_* */ /* output */
union {
struct dm_status_cache *cache;
struct dm_status_raid *raid;
struct dm_status_snapshot *snapshot;
struct dm_status_thin *thin;
struct dm_status_thin_pool *thin_pool;
};
};
struct lv_with_info_and_seg_status {
struct logical_volume *lv; /* input */
struct lvinfo *info; /* output */
const struct logical_volume *lv; /* input */
int info_ok;
struct lvinfo info; /* output */
int seg_part_of_lv; /* output */
struct lv_seg_status *seg_status; /* input/output, see lv_seg_status */
struct lv_seg_status seg_status; /* input/output, see lv_seg_status */
};
struct lv_activate_opts {
@@ -111,16 +119,31 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s, const struct logi
int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv);
/*
* Returns 1 if info structure has been populated, else 0.
* Returns 1 if info structure has been populated, else 0 on failure.
* When lvinfo* is NULL, it returns 1 if the device is locally active, 0 otherwise.
*/
int lv_info(struct cmd_context *cmd, const struct logical_volume *lv, int use_layer,
struct lvinfo *info, int with_open_count, int with_read_ahead);
int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s, int use_layer,
struct lvinfo *info, int with_open_count, int with_read_ahead);
/*
* Returns 1 if lv_seg_status structure has been populated,
* else 0 on failure or if device not active locally.
*/
int lv_status(struct cmd_context *cmd, const struct lv_segment *lv_seg,
int use_layer, struct lv_seg_status *lv_seg_status);
/*
* Returns 1 if lv_info_and_seg_status structure has been populated,
* else 0 on failure or if device not active locally.
*
* lv_info_with_seg_status is the same as calling lv_info and then lv_status,
* but this fn tries to do that with one ioctl if possible.
*/
int lv_info_with_seg_status(struct cmd_context *cmd, const struct logical_volume *lv,
const struct lv_segment *lv_seg, int use_layer,
struct lv_with_info_and_seg_status *lvdm,
struct lv_with_info_and_seg_status *status,
int with_open_count, int with_read_ahead);
int lv_check_not_in_use(const struct logical_volume *lv);

View File

@@ -25,6 +25,7 @@
#include "config.h"
#include "activate.h"
#include "lvm-exec.h"
#include "str_list.h"
#include <limits.h>
#include <dirent.h>
@@ -44,6 +45,12 @@ typedef enum {
/* This list must match lib/misc/lvm-string.c:build_dm_uuid(). */
const char *uuid_suffix_list[] = { "pool", "cdata", "cmeta", "tdata", "tmeta", NULL};
struct dlid_list {
struct dm_list list;
const char *dlid;
const struct logical_volume *lv;
};
struct dev_manager {
struct dm_pool *mem;
@@ -54,6 +61,8 @@ struct dev_manager {
int flush_required;
int activation; /* building activation tree */
int skip_external_lv;
struct dm_list pending_delete; /* str_list of dlid(s) with pending delete */
unsigned track_pending_delete;
unsigned track_pvmove_deps;
char *vg_name;
@@ -112,6 +121,7 @@ static int _get_segment_status_from_target_params(const char *target_name,
{
struct segment_type *segtype;
seg_status->type = SEG_STATUS_UNKNOWN;
/*
* TODO: Add support for other segment types too!
* The segment to report status for must be properly
@@ -119,10 +129,11 @@ static int _get_segment_status_from_target_params(const char *target_name,
* linear/striped, old snapshots and raids have proper
* segment selected for status!
*/
if (strcmp(target_name, "cache"))
if (strcmp(target_name, "cache") && strcmp(target_name, "thin-pool"))
return 1;
segtype = get_segtype_from_string(seg_status->seg->lv->vg->cmd, target_name);
if (!(segtype = get_segtype_from_string(seg_status->seg->lv->vg->cmd, target_name)))
return_0;
if (segtype != seg_status->seg->segtype) {
log_error(INTERNAL_ERROR "_get_segment_status_from_target_params: "
@@ -132,30 +143,28 @@ static int _get_segment_status_from_target_params(const char *target_name,
}
if (!strcmp(segtype->name, "cache")) {
if (!dm_get_status_cache(seg_status->mem, params,
(struct dm_status_cache **) &seg_status->status))
return_0;
seg_status->type = SEG_STATUS_CACHE;
if (!dm_get_status_cache(seg_status->mem, params, &(seg_status->cache)))
return_0;
seg_status->type = SEG_STATUS_CACHE;
} else if (!strcmp(segtype->name, "raid")) {
if (!dm_get_status_raid(seg_status->mem, params,
(struct dm_status_raid **) &seg_status->status))
return_0;
seg_status->type = SEG_STATUS_RAID;
if (!dm_get_status_raid(seg_status->mem, params, &seg_status->raid))
return_0;
seg_status->type = SEG_STATUS_RAID;
} else if (!strcmp(segtype->name, "thin")) {
if (!dm_get_status_thin(seg_status->mem, params,
(struct dm_status_thin **) &seg_status->status))
return_0;
seg_status->type = SEG_STATUS_THIN;
if (!dm_get_status_thin(seg_status->mem, params, &seg_status->thin))
return_0;
seg_status->type = SEG_STATUS_THIN;
} else if (!strcmp(segtype->name, "thin-pool")) {
if (!dm_get_status_thin_pool(seg_status->mem, params,
(struct dm_status_thin_pool **) &seg_status->status))
return_0;
seg_status->type = SEG_STATUS_THIN_POOL;
if (!dm_get_status_thin_pool(seg_status->mem, params, &seg_status->thin_pool))
return_0;
seg_status->type = SEG_STATUS_THIN_POOL;
} else if (!strcmp(segtype->name, "snapshot")) {
if (!dm_get_status_snapshot(seg_status->mem, params,
(struct dm_status_snapshot **) &seg_status->status))
return_0;
if (!dm_get_status_snapshot(seg_status->mem, params, &seg_status->snapshot))
return_0;
seg_status->type = SEG_STATUS_SNAPSHOT;
} else {
log_error(INTERNAL_ERROR "Unsupported segment type %s.", segtype->name);
return 0;
}
return 1;
@@ -191,9 +200,12 @@ static int _info_run(info_type_t type, const char *name, const char *dlid,
case MKNODES:
dmtask = DM_DEVICE_MKNODES;
break;
default:
log_error(INTERNAL_ERROR "_info_run: unhandled info type");
return 0;
}
if (!(dmt = _setup_task(type != MKNODES ? name : NULL, dlid, 0, dmtask,
if (!(dmt = _setup_task((type == MKNODES) ? name : NULL, dlid, 0, dmtask,
major, minor, with_open_count)))
return_0;
@@ -214,8 +226,8 @@ static int _info_run(info_type_t type, const char *name, const char *dlid,
do {
target = dm_get_next_target(dmt, target, &target_start,
&target_length, &target_name, &target_params);
if ((seg_status->seg->le * extent_size == target_start) &&
(seg_status->seg->len * extent_size == target_length)) {
if (((uint64_t) seg_status->seg->le * extent_size == target_start) &&
((uint64_t) seg_status->seg->len * extent_size == target_length)) {
params_to_process = target_params;
break;
}
@@ -534,18 +546,22 @@ int device_is_usable(struct device *dev, struct dev_usable_check_params check)
}
/*
* Snapshot origin could be sitting on top of a mirror which
* could be blocking I/O. Skip snapshot origins entirely for
* now.
*
* FIXME: rather than skipping origin, check if mirror is
* underneath and if the mirror is blocking I/O.
* FIXME: Snapshot origin could be sitting on top of a mirror
* which could be blocking I/O. We should add a check for the
* stack here and see if there's blocked mirror underneath.
* Currently, mirrors used as origin or snapshot is not
* supported anymore and in general using mirrors in a stack
* is disabled by default (with a warning that if enabled,
* it could cause various deadlocks).
* This is former check used, but it's not correct as it
* disables snapshot-origins to be used in a stack in
* general, not just over mirrors!
*/
if (check.check_suspended && target_type && !strcmp(target_type, "snapshot-origin")) {
/*if (check.check_suspended && target_type && !strcmp(target_type, "snapshot-origin")) {
log_debug_activation("%s: Snapshot-origin device %s not usable.",
dev_name(dev), name);
goto out;
}
}*/
if (target_type && strcmp(target_type, "error"))
only_error_target = 0;
@@ -1066,6 +1082,8 @@ struct dev_manager *dev_manager_create(struct cmd_context *cmd,
dm_udev_set_sync_support(cmd->current_settings.udev_sync);
dm_list_init(&dm->pending_delete);
return dm;
bad:
@@ -1723,6 +1741,12 @@ static int _add_dev_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
return 0;
}
if (info.exists && dm->track_pending_delete) {
log_debug_activation("Tracking pending delete for %s (%s).", lv->name, dlid);
if (!str_list_add(dm->mem, &dm->pending_delete, dlid))
return_0;
}
return 1;
}
@@ -1871,6 +1895,8 @@ static int _pool_callback(struct dm_tree_node *node,
/* let's assume there is no problem to read 64 bytes */
if (read(fd, buf, sizeof(buf)) < sizeof(buf)) {
log_sys_error("read", argv[args]);
if (close(fd))
log_sys_error("close", argv[args]);
return 0;
}
for (ret = 0; ret < DM_ARRAY_SIZE(buf); ++ret)
@@ -1939,14 +1965,14 @@ static int _pool_register_callback(struct dev_manager *dm,
data->skip_zero = 1;
data->exec = global_thin_check_executable_CFG;
data->opts = global_thin_check_options_CFG;
data->defaults = DEFAULT_THIN_CHECK_OPTIONS;
data->defaults = DEFAULT_THIN_CHECK_OPTION1 " " DEFAULT_THIN_CHECK_OPTION2;
data->global = "thin";
} else if (lv_is_cache(lv)) { /* cache pool */
data->pool_lv = first_seg(lv)->pool_lv;
data->skip_zero = dm->activation;
data->exec = global_cache_check_executable_CFG;
data->opts = global_cache_check_options_CFG;
data->defaults = DEFAULT_CACHE_CHECK_OPTIONS;
data->defaults = DEFAULT_CACHE_CHECK_OPTION1;
data->global = "cache";
} else {
log_error(INTERNAL_ERROR "Registering unsupported pool callback.");
@@ -2039,13 +2065,7 @@ static int _add_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
}
if (lv_is_cache(lv)) {
if (lv_is_pending_delete(lv)) {
if (!_add_lv_to_dtree(dm, dtree, first_seg(lv)->pool_lv, 1)) /* stack */
return_0;
/* Orhan cache LV exits here */
return 1;
}
if (!origin_only && !dm->activation) {
if (!origin_only && !dm->activation && !dm->track_pending_delete) {
/* Setup callback for non-activation partial tree */
/* Activation gets own callback when needed */
/* TODO: extend _cached_dm_info() to return dnode */
@@ -2075,13 +2095,16 @@ static int _add_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
dm->track_pvmove_deps = 1;
}
dm_list_iterate_items(sl, &lv->segs_using_this_lv) {
if (lv_is_pending_delete(sl->seg->lv) && lv_is_cache(sl->seg->lv)) {
if (!_add_lv_to_dtree(dm, dtree, sl->seg->lv, origin_only))
return_0;
break;
if (!dm->track_pending_delete)
dm_list_iterate_items(sl, &lv->segs_using_this_lv) {
if (lv_is_pending_delete(sl->seg->lv)) {
/* LV is referenced by 'cache pending delete LV */
dm->track_pending_delete = 1;
if (!_add_lv_to_dtree(dm, dtree, sl->seg->lv, origin_only))
return_0;
dm->track_pending_delete = 0;
}
}
}
/* Adding LV head of replicator adds all other related devs */
if (lv_is_replicator_dev(lv) &&
@@ -2106,6 +2129,8 @@ static int _add_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
for (s = 0; s < seg->area_count; s++) {
if (seg_type(seg, s) == AREA_LV && seg_lv(seg, s) &&
/* origin only for cache without pending delete */
(!dm->track_pending_delete || !lv_is_cache(lv)) &&
!_add_lv_to_dtree(dm, dtree, seg_lv(seg, s), 0))
return_0;
if (seg_is_raid(seg) &&
@@ -2270,7 +2295,7 @@ int add_areas_line(struct dev_manager *dm, struct lv_segment *seg,
* is used in the CTR table.
*/
if ((seg_type(seg, s) == AREA_UNASSIGNED) ||
((seg_lv(seg, s)->status & VISIBLE_LV) &&
(lv_is_visible(seg_lv(seg, s)) &&
!(seg_lv(seg, s)->status & LVM_WRITE))) {
/* One each for metadata area and data area */
if (!dm_tree_node_add_null_area(node, 0) ||
@@ -2549,21 +2574,24 @@ static int _add_segment_to_dtree(struct dev_manager *dm,
{
uint32_t s;
struct lv_segment *seg_present;
const struct segment_type *segtype;
const char *target_name;
/* Ensure required device-mapper targets are loaded */
seg_present = find_snapshot(seg->lv) ? : seg;
target_name = (seg_present->segtype->ops->target_name ?
seg_present->segtype->ops->target_name(seg_present, laopts) :
seg_present->segtype->name);
segtype = seg_present->segtype;
target_name = (segtype->ops->target_name ?
segtype->ops->target_name(seg_present, laopts) :
segtype->name);
log_debug_activation("Checking kernel supports %s segment type for %s%s%s",
target_name, seg->lv->name,
layer ? "-" : "", layer ? : "");
if (seg_present->segtype->ops->target_present &&
!seg_present->segtype->ops->target_present(seg_present->lv->vg->cmd,
seg_present, NULL)) {
if (segtype->ops->target_present &&
!segtype->ops->target_present(seg_present->lv->vg->cmd,
seg_present, NULL)) {
log_error("Can't process LV %s: %s target support missing "
"from kernel?", seg->lv->name, target_name);
return 0;
@@ -2598,8 +2626,10 @@ static int _add_segment_to_dtree(struct dev_manager *dm,
/* Add any LVs used by this segment */
for (s = 0; s < seg->area_count; ++s) {
if ((seg_type(seg, s) == AREA_LV) &&
(!_add_new_lv_to_dtree(dm, dtree, seg_lv(seg, s),
laopts, NULL)))
/* origin only for cache without pending delete */
(!dm->track_pending_delete || !seg_is_cache(seg)) &&
!_add_new_lv_to_dtree(dm, dtree, seg_lv(seg, s),
laopts, NULL))
return_0;
if (seg_is_raid(seg) &&
!_add_new_lv_to_dtree(dm, dtree, seg_metalv(seg, s),
@@ -2607,7 +2637,13 @@ static int _add_segment_to_dtree(struct dev_manager *dm,
return_0;
}
if (!_add_target_to_dtree(dm, dnode, seg, laopts))
if (dm->track_pending_delete) {
/* Replace target and all its used devs with error mapping */
log_debug_activation("Using error for pending delete %s.",
seg->lv->name);
if (!dm_tree_node_add_error_target(dnode, (uint64_t)seg->lv->vg->extent_size * seg->len))
return_0;
} else if (!_add_target_to_dtree(dm, dnode, seg, laopts))
return_0;
return 1;
@@ -2680,6 +2716,7 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
uint32_t max_stripe_size = UINT32_C(0);
uint32_t read_ahead = lv->read_ahead;
uint32_t read_ahead_flags = UINT32_C(0);
int save_pending_delete = dm->track_pending_delete;
/* LV with pending delete is never put new into a table */
if (lv_is_pending_delete(lv) && !_cached_dm_info(dm->mem, dtree, lv, NULL))
@@ -2767,29 +2804,10 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
/* Create table */
dm->pvmove_mirror_count = 0u;
if (lv_is_pending_delete(lv)) {
if (lv_is_pending_delete(lv))
/* Handle LVs with pending delete */
if (lv_is_cache(lv)) {
/* Use 'error' for cache, metadata and data volumes */
seg = first_seg(lv);
if (!dm_tree_node_add_error_target(dnode, seg_lv(seg, 0)->size))
return_0;
seg = first_seg(seg->pool_lv);
if (!(dlid = build_dm_uuid(dm->mem, seg->metadata_lv, NULL)))
return_0;
if ((dnode = dm_tree_find_node_by_uuid(dtree, dlid)) &&
!dm_tree_node_get_context(dnode) &&
!dm_tree_node_add_error_target(dnode, seg->metadata_lv->size))
return_0;
if (!(dlid = build_dm_uuid(dm->mem, seg_lv(seg, 0), NULL)))
return_0;
if ((dnode = dm_tree_find_node_by_uuid(dtree, dlid)) &&
!dm_tree_node_get_context(dnode) &&
!dm_tree_node_add_error_target(dnode, seg_lv(seg, 0)->size))
return_0;
}
return 1;
}
/* Fow now used only by cache segtype, TODO snapshots */
dm->track_pending_delete = 1;
/* This is unused cache-pool - make metadata accessible */
if (lv_is_cache_pool(lv))
@@ -2875,6 +2893,8 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
return_0;
#endif
dm->track_pending_delete = save_pending_delete; /* restore */
return 1;
}
@@ -2967,12 +2987,20 @@ static int _remove_lv_symlinks(struct dev_manager *dm, struct dm_tree_node *root
return r;
}
static int _clean_tree(struct dev_manager *dm, struct dm_tree_node *root, char *non_toplevel_tree_dlid)
static int _clean_tree(struct dev_manager *dm, struct dm_tree_node *root, const char *non_toplevel_tree_dlid)
{
void *handle = NULL;
struct dm_tree_node *child;
char *vgname, *lvname, *layer;
const char *name, *uuid;
struct dm_str_list *dl;
/* Deactivate any tracked pending delete nodes */
dm_list_iterate_items(dl, &dm->pending_delete) {
log_debug_activation("Deleting tracked UUID %s.", dl->str);
if (!dm_tree_deactivate_children(root, dl->str, strlen(dl->str)))
return_0;
}
while ((child = dm_tree_next_child(&handle, root, 0))) {
if (!(name = dm_tree_node_get_name(child)))
@@ -2987,23 +3015,14 @@ static int _clean_tree(struct dev_manager *dm, struct dm_tree_node *root, char *
}
/* Not meant to be top level? */
if (!*layer && (!(layer = strchr(uuid + 4, '-')) || strstr(layer, "-pool") || strstr(layer, "-tpool")))
continue;
/* FIXME: we still occasionally need to activate these at top-level */
if (((name = strstr(lvname, "_tmeta")) && !name[6]) ||
((name = strstr(lvname, "_tdata")) && !name[6]))
if (!*layer)
continue;
/* If operation was performed on a partial tree, don't remove it */
if (non_toplevel_tree_dlid && !strcmp(non_toplevel_tree_dlid, uuid))
continue;
if ((name = strstr(lvname, "_corig")) && !name[6]) {
/* FIXME: for now just for _corig deactivate LVM subtree, should be generic */
if (!dm_tree_deactivate_children(root, "LVM-", 4))
return_0;
} else if (!dm_tree_deactivate_children(root, uuid, strlen(uuid)))
if (!dm_tree_deactivate_children(root, uuid, strlen(uuid)))
return_0;
}
@@ -3013,7 +3032,7 @@ static int _clean_tree(struct dev_manager *dm, struct dm_tree_node *root, char *
static int _tree_action(struct dev_manager *dm, const struct logical_volume *lv,
struct lv_activate_opts *laopts, action_t action)
{
static const char const _action_names[][24] = {
static const char _action_names[][24] = {
"PRELOAD", "ACTIVATE", "DEACTIVATE", "SUSPEND", "SUSPEND_WITH_LOCKFS", "CLEAN"
};
const size_t DLID_SIZE = ID_LEN + sizeof(UUID_PREFIX) - 1;

129
lib/cache/lvmcache.c vendored
View File

@@ -56,6 +56,8 @@ struct lvmcache_vginfo {
char _padding[7];
struct lvmcache_vginfo *next; /* Another VG with same name? */
char *creation_host;
uint32_t mda_checksum;
size_t mda_size;
size_t vgmetadata_size;
char *vgmetadata; /* Copy of VG metadata as format_text string */
struct dm_config_tree *cft; /* Config tree created from vgmetadata */
@@ -76,6 +78,7 @@ static int _scanning_in_progress = 0;
static int _has_scanned = 0;
static int _vgs_locked = 0;
static int _vg_global_lock_held = 0; /* Global lock held when cache wiped? */
static int _found_duplicate_pvs = 0; /* If we never see a duplicate PV we can skip checking for them later. */
int lvmcache_init(void)
{
@@ -284,6 +287,9 @@ void lvmcache_commit_metadata(const char *vgname)
void lvmcache_drop_metadata(const char *vgname, int drop_precommitted)
{
if (lvmcache_vgname_is_locked(VG_GLOBAL) && !vg_write_lock_held())
return;
/* For VG_ORPHANS, we need to invalidate all labels on orphan PVs. */
if (!strcmp(vgname, VG_ORPHANS)) {
_drop_metadata(FMT_TEXT_ORPHAN_VG_NAME, 0);
@@ -292,7 +298,7 @@ void lvmcache_drop_metadata(const char *vgname, int drop_precommitted)
/* Indicate that PVs could now be missing from the cache */
init_full_scan_done(0);
} else if (!lvmcache_vgname_is_locked(VG_GLOBAL))
} else
_drop_metadata(vgname, drop_precommitted);
}
@@ -402,6 +408,16 @@ int lvmcache_vgs_locked(void)
return _vgs_locked;
}
/*
* When lvmcache sees a duplicate PV, this is set.
* process_each_pv() can avoid searching for duplicates
* by checking this and seeing that no duplicate PVs exist.
*/
int lvmcache_found_duplicate_pvs(void)
{
return _found_duplicate_pvs;
}
static void _vginfo_attach_info(struct lvmcache_vginfo *vginfo,
struct lvmcache_info *info)
{
@@ -1392,6 +1408,26 @@ static int _lvmcache_update_vgstatus(struct lvmcache_info *info, uint32_t vgstat
return 1;
}
static int _lvmcache_update_vg_mda_info(struct lvmcache_info *info, uint32_t mda_checksum,
size_t mda_size)
{
if (!info || !info->vginfo || !mda_size)
return 1;
if (info->vginfo->mda_checksum == mda_checksum || info->vginfo->mda_size == mda_size)
return 1;
info->vginfo->mda_checksum = mda_checksum;
info->vginfo->mda_size = mda_size;
/* FIXME Add checksum index */
log_debug_cache("lvmcache: %s: VG %s: Stored metadata checksum %" PRIu32 " with size %" PRIsize_t ".",
dev_name(info->dev), info->vginfo->vgname, mda_checksum, mda_size);
return 1;
}
int lvmcache_add_orphan_vginfo(const char *vgname, struct format_type *fmt)
{
if (!_lock_hash && !lvmcache_init()) {
@@ -1402,10 +1438,11 @@ int lvmcache_add_orphan_vginfo(const char *vgname, struct format_type *fmt)
return _lvmcache_update_vgname(NULL, vgname, vgname, 0, "", fmt);
}
int lvmcache_update_vgname_and_id(struct lvmcache_info *info,
const char *vgname, const char *vgid,
uint32_t vgstatus, const char *creation_host)
int lvmcache_update_vgname_and_id(struct lvmcache_info *info, struct lvmcache_vgsummary *vgsummary)
{
const char *vgname = vgsummary->vgname;
const char *vgid = (char *)&vgsummary->vgid;
if (!vgname && !info->vginfo) {
log_error(INTERNAL_ERROR "NULL vgname handed to cache");
/* FIXME Remove this */
@@ -1433,10 +1470,11 @@ int lvmcache_update_vgname_and_id(struct lvmcache_info *info,
if (!is_orphan_vg(vgname))
info->status &= ~CACHE_INVALID;
if (!_lvmcache_update_vgname(info, vgname, vgid, vgstatus,
creation_host, info->fmt) ||
if (!_lvmcache_update_vgname(info, vgname, vgid, vgsummary->vgstatus,
vgsummary->creation_host, info->fmt) ||
!_lvmcache_update_vgid(info, info->vginfo, vgid) ||
!_lvmcache_update_vgstatus(info, vgstatus, creation_host))
!_lvmcache_update_vgstatus(info, vgsummary->vgstatus, vgsummary->creation_host) ||
!_lvmcache_update_vg_mda_info(info, vgsummary->mda_checksum, vgsummary->mda_size))
return_0;
return 1;
@@ -1447,6 +1485,11 @@ int lvmcache_update_vg(struct volume_group *vg, unsigned precommitted)
struct pv_list *pvl;
struct lvmcache_info *info;
char pvid_s[ID_LEN + 1] __attribute__((aligned(8)));
struct lvmcache_vgsummary vgsummary = {
.vgname = vg->name,
.vgstatus = vg->status,
.vgid = vg->id
};
pvid_s[sizeof(pvid_s) - 1] = '\0';
@@ -1454,9 +1497,7 @@ int lvmcache_update_vg(struct volume_group *vg, unsigned precommitted)
strncpy(pvid_s, (char *) &pvl->pv->id, sizeof(pvid_s) - 1);
/* FIXME Could pvl->pv->dev->pvid ever be different? */
if ((info = lvmcache_info_from_pvid(pvid_s, 0)) &&
!lvmcache_update_vgname_and_id(info, vg->name,
(char *) &vg->id,
vg->status, NULL))
!lvmcache_update_vgname_and_id(info, &vgsummary))
return_0;
}
@@ -1467,6 +1508,27 @@ int lvmcache_update_vg(struct volume_group *vg, unsigned precommitted)
return 1;
}
/*
* Replace pv->dev with dev so that dev will appear for reporting.
*/
void lvmcache_replace_dev(struct cmd_context *cmd, struct physical_volume *pv,
struct device *dev)
{
struct lvmcache_info *info;
char pvid_s[ID_LEN + 1] __attribute__((aligned(8)));
strncpy(pvid_s, (char *) &pv->id, sizeof(pvid_s) - 1);
pvid_s[sizeof(pvid_s) - 1] = '\0';
if (!(info = lvmcache_info_from_pvid(pvid_s, 0)))
return;
info->dev = dev;
info->label->dev = dev;
pv->dev = dev;
}
struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
struct device *dev,
const char *vgname, const char *vgid,
@@ -1477,6 +1539,14 @@ struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
struct label *label;
struct lvmcache_info *existing, *info;
char pvid_s[ID_LEN + 1] __attribute__((aligned(8)));
struct lvmcache_vgsummary vgsummary = {
.vgname = vgname,
.vgstatus = vgstatus,
};
/* N.B. vgid is not NUL-terminated when called from _text_pv_write */
if (vgid)
strncpy((char *)&vgsummary.vgid, vgid, sizeof(vgsummary.vgid));
if (!_vgname_hash && !lvmcache_init()) {
log_error("Internal cache initialisation failed");
@@ -1539,10 +1609,15 @@ struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
//else if (dm_is_dm_major(MAJOR(existing->dev->dev)) &&
//dm_is_dm_major(MAJOR(dev->dev)))
//
else if (!strcmp(pvid_s, existing->dev->pvid))
log_error("Found duplicate PV %s: using %s not "
"%s", pvid, dev_name(dev),
dev_name(existing->dev));
else if (!strcmp(pvid_s, existing->dev->pvid)) {
log_error("Found duplicate PV %s: using %s not %s",
pvid_s,
dev_name(existing->dev),
dev_name(dev));
strncpy(dev->pvid, pvid_s, sizeof(dev->pvid));
_found_duplicate_pvs = 1;
return NULL;
}
}
if (strcmp(pvid_s, existing->dev->pvid))
log_debug_cache("Updating pvid cache to %s (%s) from %s (%s)",
@@ -1573,7 +1648,7 @@ struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
return NULL;
}
if (!lvmcache_update_vgname_and_id(info, vgname, vgid, vgstatus, NULL)) {
if (!lvmcache_update_vgname_and_id(info, &vgsummary)) {
if (!existing) {
dm_hash_remove(_pvid_hash, pvid_s);
strcpy(info->dev->pvid, "");
@@ -1982,3 +2057,27 @@ uint64_t lvmcache_smallest_mda_size(struct lvmcache_info *info)
const struct format_type *lvmcache_fmt(struct lvmcache_info *info) {
return info->fmt;
}
int lvmcache_lookup_mda(struct lvmcache_vgsummary *vgsummary)
{
struct lvmcache_vginfo *vginfo;
if (!vgsummary->mda_size)
return 0;
/* FIXME Index the checksums */
dm_list_iterate_items(vginfo, &_vginfos) {
if (vgsummary->mda_checksum == vginfo->mda_checksum &&
vgsummary->mda_size == vginfo->mda_size &&
!is_orphan_vg(vginfo->vgname)) {
vgsummary->vgname = vginfo->vgname;
vgsummary->creation_host = vginfo->creation_host;
vgsummary->vgstatus = vginfo->status;
memcpy((char *)&vgsummary->vgid, vginfo->vgid, sizeof(vginfo->vgid));
return 1;
}
}
return 0;
}

18
lib/cache/lvmcache.h vendored
View File

@@ -39,6 +39,15 @@ struct disk_locn;
struct lvmcache_vginfo;
struct lvmcache_vgsummary {
const char *vgname;
struct id vgid;
uint64_t vgstatus;
char *creation_host;
uint32_t mda_checksum;
size_t mda_size;
};
int lvmcache_init(void);
void lvmcache_allow_reads_with_lvmetad(void);
@@ -58,8 +67,7 @@ void lvmcache_del(struct lvmcache_info *info);
/* Update things */
int lvmcache_update_vgname_and_id(struct lvmcache_info *info,
const char *vgname, const char *vgid,
uint32_t vgstatus, const char *hostname);
struct lvmcache_vgsummary *vgsummary);
int lvmcache_update_vg(struct volume_group *vg, unsigned precommitted);
void lvmcache_lock_vgname(const char *vgname, int read_only);
@@ -68,6 +76,7 @@ int lvmcache_verify_lock_order(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);
@@ -157,4 +166,9 @@ 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);
void lvmcache_replace_dev(struct cmd_context *cmd, struct physical_volume *pv,
struct device *dev);
int lvmcache_found_duplicate_pvs(void);
#endif

76
lib/cache/lvmetad.c vendored
View File

@@ -136,6 +136,9 @@ void lvmetad_set_socket(const char *sock)
_lvmetad_socket = sock;
}
static int _lvmetad_pvscan_all_devs(struct cmd_context *cmd, activation_handler handler,
int ignore_obsolete);
static daemon_reply _lvmetad_send(const char *id, ...)
{
va_list ap;
@@ -183,7 +186,7 @@ retry:
max_remaining_sleep_times--; /* Sleep once before rescanning the first time, then 5 times each time after that. */
} else {
/* If the re-scan fails here, we try again later. */
(void) lvmetad_pvscan_all_devs(_lvmetad_cmd, NULL);
(void) _lvmetad_pvscan_all_devs(_lvmetad_cmd, NULL, 0);
num_rescans++;
max_remaining_sleep_times = 5;
}
@@ -264,15 +267,16 @@ static int _read_mda(struct lvmcache_info *info,
static struct lvmcache_info *_pv_populate_lvmcache(struct cmd_context *cmd,
struct dm_config_node *cn,
dev_t fallback)
struct format_type *fmt, dev_t fallback)
{
struct device *dev;
struct device *dev, *dev_alternate;
struct id pvid, vgid;
char mda_id[32];
char da_id[32];
int i = 0;
struct dm_config_node *mda = NULL;
struct dm_config_node *da = NULL;
struct dm_config_node *mda, *da;
struct dm_config_node *alt_devices = dm_config_find_node(cn->child, "devices_alternate");
struct dm_config_value *alt_device = NULL;
uint64_t offset, size;
struct lvmcache_info *info;
const char *pvid_txt = dm_config_find_str(cn->child, "id", NULL),
@@ -283,7 +287,8 @@ static struct lvmcache_info *_pv_populate_lvmcache(struct cmd_context *cmd,
uint64_t devsize = dm_config_find_int64(cn->child, "dev_size", 0),
label_sector = dm_config_find_int64(cn->child, "label_sector", 0);
struct format_type *fmt = fmt_name ? get_format_by_name(cmd, fmt_name) : NULL;
if (!fmt && fmt_name)
fmt = get_format_by_name(cmd, fmt_name);
if (!fmt) {
log_error("PV %s not recognised. Is the device missing?", pvid_txt);
@@ -356,6 +361,20 @@ static struct lvmcache_info *_pv_populate_lvmcache(struct cmd_context *cmd,
++i;
} while (da);
if (alt_devices)
alt_device = alt_devices->v;
while (alt_device) {
dev_alternate = dev_cache_get_by_devt(alt_device->v.i, cmd->filter);
if (dev_alternate)
lvmcache_add(fmt->labeller, (const char *)&pvid, dev_alternate,
vgname, (const char *)&vgid, 0);
else
log_warn("Duplicate of PV %s dev %s exists on unknown device %"PRId64 ":%" PRId64,
pvid_txt, dev_name(dev), MAJOR(alt_device->v.i), MINOR(alt_device->v.i));
alt_device = alt_device->next;
}
return info;
}
@@ -422,7 +441,7 @@ struct volume_group *lvmetad_vg_lookup(struct cmd_context *cmd, const char *vgna
if ((pvcn = dm_config_find_node(top, "metadata/physical_volumes")))
for (pvcn = pvcn->child; pvcn; pvcn = pvcn->sib)
_pv_populate_lvmcache(cmd, pvcn, 0);
_pv_populate_lvmcache(cmd, pvcn, fmt, 0);
top->key = name;
if (!(vg = import_vg_from_config_tree(reply.cft, fid)))
@@ -573,7 +592,7 @@ int lvmetad_pv_lookup(struct cmd_context *cmd, struct id pvid, int *found)
if (!(cn = dm_config_find_node(reply.cft->root, "physical_volume")))
goto_out;
else if (!_pv_populate_lvmcache(cmd, cn, 0))
else if (!_pv_populate_lvmcache(cmd, cn, NULL, 0))
goto_out;
out_success:
@@ -603,7 +622,7 @@ int lvmetad_pv_lookup_by_dev(struct cmd_context *cmd, struct device *dev, int *f
goto out_success;
cn = dm_config_find_node(reply.cft->root, "physical_volume");
if (!cn || !_pv_populate_lvmcache(cmd, cn, dev->dev))
if (!cn || !_pv_populate_lvmcache(cmd, cn, NULL, dev->dev))
goto_out;
out_success:
@@ -631,7 +650,7 @@ int lvmetad_pv_list_to_lvmcache(struct cmd_context *cmd)
if ((cn = dm_config_find_node(reply.cft->root, "physical_volumes")))
for (cn = cn->child; cn; cn = cn->sib)
_pv_populate_lvmcache(cmd, cn, 0);
_pv_populate_lvmcache(cmd, cn, NULL, 0);
daemon_reply_destroy(reply);
@@ -891,7 +910,9 @@ struct _lvmetad_pvscan_baton {
static int _lvmetad_pvscan_single(struct metadata_area *mda, void *baton)
{
struct _lvmetad_pvscan_baton *b = baton;
struct volume_group *this = mda->ops->vg_read(b->fid, "", mda, 1);
struct volume_group *this;
this = mda_is_ignored(mda) ? NULL : mda->ops->vg_read(b->fid, "", mda, NULL, NULL, 1);
/* FIXME Also ensure contents match etc. */
if (!b->vg || this->seqno > b->vg->seqno)
@@ -903,7 +924,7 @@ static int _lvmetad_pvscan_single(struct metadata_area *mda, void *baton)
}
int lvmetad_pvscan_single(struct cmd_context *cmd, struct device *dev,
activation_handler handler)
activation_handler handler, int ignore_obsolete)
{
struct label *label;
struct lvmcache_info *info;
@@ -932,9 +953,16 @@ int lvmetad_pvscan_single(struct cmd_context *cmd, struct device *dev,
goto_bad;
if (baton.fid->fmt->features & FMT_OBSOLETE) {
log_error("WARNING: Ignoring obsolete format of metadata (%s) on device %s when using lvmetad",
baton.fid->fmt->name, dev_name(dev));
if (ignore_obsolete)
log_warn("WARNING: Ignoring obsolete format of metadata (%s) on device %s when using lvmetad",
baton.fid->fmt->name, dev_name(dev));
else
log_error("WARNING: Ignoring obsolete format of metadata (%s) on device %s when using lvmetad",
baton.fid->fmt->name, dev_name(dev));
lvmcache_fmt(info)->ops->destroy_instance(baton.fid);
if (ignore_obsolete)
return 1;
return 0;
}
@@ -947,7 +975,7 @@ int lvmetad_pvscan_single(struct cmd_context *cmd, struct device *dev,
* can scan further devices.
*/
if (!baton.vg && !(baton.fid->fmt->features & FMT_MDAS))
baton.vg = ((struct metadata_area *) dm_list_first(&baton.fid->metadata_areas_in_use))->ops->vg_read(baton.fid, lvmcache_vgname_from_info(info), NULL, 1);
baton.vg = ((struct metadata_area *) dm_list_first(&baton.fid->metadata_areas_in_use))->ops->vg_read(baton.fid, lvmcache_vgname_from_info(info), NULL, NULL, NULL, 1);
if (!baton.vg)
lvmcache_fmt(info)->ops->destroy_instance(baton.fid);
@@ -973,7 +1001,8 @@ bad:
return 0;
}
int lvmetad_pvscan_all_devs(struct cmd_context *cmd, activation_handler handler)
static int _lvmetad_pvscan_all_devs(struct cmd_context *cmd, activation_handler handler,
int ignore_obsolete)
{
struct dev_iter *iter;
struct device *dev;
@@ -1015,7 +1044,7 @@ int lvmetad_pvscan_all_devs(struct cmd_context *cmd, activation_handler handler)
stack;
break;
}
if (!lvmetad_pvscan_single(cmd, dev, handler))
if (!lvmetad_pvscan_single(cmd, dev, handler, ignore_obsolete))
r = 0;
}
@@ -1030,3 +1059,16 @@ int lvmetad_pvscan_all_devs(struct cmd_context *cmd, activation_handler handler)
return r;
}
int lvmetad_pvscan_all_devs(struct cmd_context *cmd, activation_handler handler)
{
return _lvmetad_pvscan_all_devs(cmd, handler, 0);
}
/*
* FIXME Implement this function, skipping PVs known to belong to local or clustered,
* non-exported VGs.
*/
int lvmetad_pvscan_foreign_vgs(struct cmd_context *cmd, activation_handler handler)
{
return _lvmetad_pvscan_all_devs(cmd, handler, 1);
}

6
lib/cache/lvmetad.h vendored
View File

@@ -153,9 +153,10 @@ struct volume_group *lvmetad_vg_lookup(struct cmd_context *cmd,
* Scan a single device and update lvmetad with the result(s).
*/
int lvmetad_pvscan_single(struct cmd_context *cmd, struct device *dev,
activation_handler handler);
activation_handler handler, int ignore_obsolete);
int lvmetad_pvscan_all_devs(struct cmd_context *cmd, activation_handler handler);
int lvmetad_pvscan_foreign_vgs(struct cmd_context *cmd, activation_handler handler);
# else /* LVMETAD_SUPPORT */
@@ -179,8 +180,9 @@ int lvmetad_pvscan_all_devs(struct cmd_context *cmd, activation_handler handler)
# define lvmetad_pv_lookup_by_dev(cmd, dev, found) (0)
# define lvmetad_vg_list_to_lvmcache(cmd) (1)
# define lvmetad_vg_lookup(cmd, vgname, vgid) (NULL)
# define lvmetad_pvscan_single(cmd, dev, handler) (0)
# define lvmetad_pvscan_single(cmd, dev, handler, ignore_obsolete) (0)
# define lvmetad_pvscan_all_devs(cmd, handler) (0)
# define lvmetad_pvscan_foreign_vgs(cmd, handler) (0)
# endif /* LVMETAD_SUPPORT */

View File

@@ -19,7 +19,6 @@
#include "text_export.h"
#include "config.h"
#include "str_list.h"
#include "targets.h"
#include "lvm-string.h"
#include "activate.h"
#include "metadata.h"
@@ -69,7 +68,9 @@ static int _cache_pool_text_import(struct lv_segment *seg,
return SEG_LOG_ERROR("cache_mode must be a string in");
if (!set_cache_pool_feature(&seg->feature_flags, str))
return SEG_LOG_ERROR("Unknown cache_mode in");
}
} else
/* When missed in metadata, it's an old stuff - use writethrough */
seg->feature_flags |= DM_CACHE_FEATURE_WRITETHROUGH;
if (dm_config_has_node(sn, "policy")) {
if (!(str = dm_config_find_str(sn, "policy", NULL)))

View File

@@ -55,6 +55,128 @@
static const size_t linebuffer_size = 4096;
/*
* Copy the input string, removing invalid characters.
*/
const char *system_id_from_string(struct cmd_context *cmd, const char *str)
{
char *system_id;
if (!str || !*str) {
log_warn("WARNING: Empty system ID supplied.");
return "";
}
if (!(system_id = dm_pool_zalloc(cmd->libmem, strlen(str) + 1))) {
log_warn("WARNING: Failed to allocate system ID.");
return NULL;
}
copy_systemid_chars(str, system_id);
if (!*system_id) {
log_warn("WARNING: Invalid system ID format: %s", str);
return NULL;
}
if (!strncmp(system_id, "localhost", 9)) {
log_warn("WARNING: system ID may not begin with the string \"localhost\".");
return NULL;
}
return system_id;
}
static const char *_read_system_id_from_file(struct cmd_context *cmd, const char *file)
{
char *line = NULL;
size_t line_size;
char *start, *end;
const char *system_id = NULL;
FILE *fp;
if (!file || !strlen(file) || !file[0])
return_NULL;
if (!(fp = fopen(file, "r"))) {
log_warn("WARNING: %s: fopen failed: %s", file, strerror(errno));
return NULL;
}
while (getline(&line, &line_size, fp) > 0) {
start = line;
/* Ignore leading whitespace */
while (*start && isspace(*start))
start++;
/* Ignore rest of line after # */
if (!*start || *start == '#')
continue;
if (system_id && *system_id) {
log_warn("WARNING: Ignoring extra line(s) in system ID file %s.", file);
break;
}
/* Remove any comments from end of line */
for (end = start; *end; end++)
if (*end == '#') {
*end = '\0';
break;
}
system_id = system_id_from_string(cmd, start);
}
free(line);
if (fclose(fp))
stack;
return system_id;
}
static const char *_system_id_from_source(struct cmd_context *cmd, const char *source)
{
char filebuf[PATH_MAX];
const char *file;
const char *etc_str;
const char *str;
const char *system_id = NULL;
if (!strcasecmp(source, "uname")) {
if (cmd->hostname)
system_id = system_id_from_string(cmd, cmd->hostname);
goto out;
}
/* lvm.conf and lvmlocal.conf are merged into one config tree */
if (!strcasecmp(source, "lvmlocal")) {
if ((str = find_config_tree_str(cmd, local_system_id_CFG, NULL)))
system_id = system_id_from_string(cmd, str);
goto out;
}
if (!strcasecmp(source, "machineid") || !strcasecmp(source, "machine-id")) {
etc_str = find_config_tree_str(cmd, global_etc_CFG, NULL);
if (dm_snprintf(filebuf, sizeof(filebuf), "%s/machine-id", etc_str) != -1)
system_id = _read_system_id_from_file(cmd, filebuf);
goto out;
}
if (!strcasecmp(source, "file")) {
file = find_config_tree_str(cmd, global_system_id_file_CFG, NULL);
system_id = _read_system_id_from_file(cmd, file);
goto out;
}
log_warn("WARNING: Unrecognised system_id_source \"%s\".", source);
out:
return system_id;
}
static int _get_env_vars(struct cmd_context *cmd)
{
const char *e;
@@ -288,7 +410,8 @@ static int _check_config(struct cmd_context *cmd)
return 1;
}
int process_profilable_config(struct cmd_context *cmd) {
int process_profilable_config(struct cmd_context *cmd)
{
if (!(cmd->default_settings.unit_factor =
dm_units_to_factor(find_config_tree_str(cmd, global_units_CFG, NULL),
&cmd->default_settings.unit_type, 1, NULL))) {
@@ -304,9 +427,48 @@ int process_profilable_config(struct cmd_context *cmd) {
return 1;
}
static int _init_system_id(struct cmd_context *cmd)
{
const char *source, *system_id;
int local_set = 0;
cmd->system_id = NULL;
cmd->unknown_system_id = 0;
system_id = find_config_tree_str_allow_empty(cmd, local_system_id_CFG, NULL);
if (system_id && *system_id)
local_set = 1;
source = find_config_tree_str(cmd, global_system_id_source_CFG, NULL);
if (!source)
source = "none";
/* Defining local system_id but not using it is probably a config mistake. */
if (local_set && strcmp(source, "lvmlocal"))
log_warn("WARNING: local/system_id is set, so should global/system_id_source be \"lvmlocal\" not \"%s\"?", source);
if (!strcmp(source, "none"))
return 1;
if ((system_id = _system_id_from_source(cmd, source)) && *system_id) {
cmd->system_id = system_id;
return 1;
}
/*
* The source failed to resolve a system_id. In this case allow
* VGs with no system_id to be accessed, but not VGs with a system_id.
*/
log_warn("WARNING: No system ID found from system_id_source %s.", source);
cmd->unknown_system_id = 1;
return 1;
}
static int _process_config(struct cmd_context *cmd)
{
mode_t old_umask;
const char *dev_ext_info_src;
const char *read_ahead;
struct stat st;
const struct dm_config_node *cn;
@@ -340,6 +502,16 @@ static int _process_config(struct cmd_context *cmd)
return_0;
#endif
dev_ext_info_src = find_config_tree_str(cmd, devices_external_device_info_source_CFG, NULL);
if (!strcmp(dev_ext_info_src, "none"))
init_external_device_info_source(DEV_EXT_NONE);
else if (!strcmp(dev_ext_info_src, "udev"))
init_external_device_info_source(DEV_EXT_UDEV);
else {
log_error("Invalid external device info source specification.");
return 0;
}
/* proc dir */
if (dm_snprintf(cmd->proc_dir, sizeof(cmd->proc_dir), "%s",
find_config_tree_str(cmd, global_proc_CFG, NULL)) < 0) {
@@ -469,6 +641,9 @@ static int _process_config(struct cmd_context *cmd)
lvmetad_init(cmd);
if (!_init_system_id(cmd))
return_0;
return 1;
}
@@ -526,11 +701,12 @@ static int _init_tags(struct cmd_context *cmd, struct dm_config_tree *cft)
const char *tag;
int passes;
if (!(tn = find_config_tree_node(cmd, tags_CFG_SECTION, NULL)) || !tn->child)
/* Access tags section directly */
if (!(tn = find_config_node(cmd, cft, tags_CFG_SECTION)) || !tn->child)
return 1;
/* NB hosttags 0 when already 1 intentionally does not delete the tag */
if (!cmd->hosttags && find_config_tree_bool(cmd, tags_hosttags_CFG, NULL)) {
if (!cmd->hosttags && find_config_bool(cmd, cft, tags_hosttags_CFG)) {
/* FIXME Strip out invalid chars: only A-Za-z0-9_+.- */
if (!_set_tag(cmd, cmd->hostname))
return_0;
@@ -561,7 +737,7 @@ static int _init_tags(struct cmd_context *cmd, struct dm_config_tree *cft)
return 1;
}
static int _load_config_file(struct cmd_context *cmd, const char *tag)
static int _load_config_file(struct cmd_context *cmd, const char *tag, int local)
{
static char config_file[PATH_MAX] = "";
const char *filler = "";
@@ -569,6 +745,10 @@ static int _load_config_file(struct cmd_context *cmd, const char *tag)
if (*tag)
filler = "_";
else if (local) {
filler = "";
tag = "local";
}
if (dm_snprintf(config_file, sizeof(config_file), "%s/lvm%s%s.conf",
cmd->system_dir, filler, tag) < 0) {
@@ -596,7 +776,9 @@ static int _load_config_file(struct cmd_context *cmd, const char *tag)
return 1;
}
/* Find and read first config file */
/*
* Find and read lvm.conf.
*/
static int _init_lvm_conf(struct cmd_context *cmd)
{
/* No config file if LVM_SYSTEM_DIR is empty */
@@ -608,7 +790,7 @@ static int _init_lvm_conf(struct cmd_context *cmd)
return 1;
}
if (!_load_config_file(cmd, ""))
if (!_load_config_file(cmd, "", 0))
return_0;
return 1;
@@ -621,7 +803,7 @@ static int _init_tag_configs(struct cmd_context *cmd)
/* Tag list may grow while inside this loop */
dm_list_iterate_items(sl, &cmd->tags) {
if (!_load_config_file(cmd, sl->str))
if (!_load_config_file(cmd, sl->str, 0))
return_0;
}
@@ -835,7 +1017,7 @@ static int _init_dev_cache(struct cmd_context *cmd)
return 1;
}
#define MAX_FILTERS 7
#define MAX_FILTERS 8
static struct dev_filter *_init_lvmetad_filter_chain(struct cmd_context *cmd)
{
@@ -905,7 +1087,14 @@ static struct dev_filter *_init_lvmetad_filter_chain(struct cmd_context *cmd)
nr_filt++;
}
if (!(composite = composite_filter_create(nr_filt, filters)))
/* firmware raid filter. Optional, non-critical. */
if (find_config_tree_bool(cmd, devices_fw_raid_component_detection_CFG, NULL)) {
init_fwraid_filtering(1);
if ((filters[nr_filt] = fwraid_filter_create(cmd->dev_types)))
nr_filt++;
}
if (!(composite = composite_filter_create(nr_filt, 1, filters)))
goto_bad;
return composite;
@@ -926,7 +1115,7 @@ bad:
* sysfs filter -> global regex filter -> type filter ->
* usable device filter(FILTER_MODE_PRE_LVMETAD) ->
* mpath component filter -> partitioned filter ->
* md component filter
* md component filter -> fw raid filter
*
* - cmd->filter - the filter chain used for lvmetad responses:
* persistent filter -> usable device filter(FILTER_MODE_POST_LVMETAD) ->
@@ -942,7 +1131,7 @@ bad:
* global regex filter -> type filter ->
* usable device filter(FILTER_MODE_NO_LVMETAD) ->
* mpath component filter -> partitioned filter ->
* md component filter
* md component filter -> fw raid filter
*
*/
static int _init_filters(struct cmd_context *cmd, unsigned load_persistent_cache)
@@ -951,6 +1140,7 @@ static int _init_filters(struct cmd_context *cmd, unsigned load_persistent_cache
struct dev_filter *filter = NULL, *filter_components[2] = {0};
struct stat st;
const struct dm_config_node *cn;
struct timespec ts, cts;
cmd->dump_filter = 0;
@@ -985,7 +1175,7 @@ static int _init_filters(struct cmd_context *cmd, unsigned load_persistent_cache
if (!(filter_components[1] = regex_filter_create(cn->v)))
goto_bad;
/* we have two filter components - create composite filter */
if (!(filter = composite_filter_create(2, filter_components)))
if (!(filter = composite_filter_create(2, 0, filter_components)))
goto_bad;
} else
/* we have only one filter component - no need to create composite filter */
@@ -1004,7 +1194,7 @@ static int _init_filters(struct cmd_context *cmd, unsigned load_persistent_cache
if (lvmetad_used()) {
filter_components[0] = cmd->lvmetad_filter;
filter_components[1] = cmd->filter;
if (!(cmd->full_filter = composite_filter_create(2, filter_components)))
if (!(cmd->full_filter = composite_filter_create(2, 0, filter_components)))
goto_bad;
} else
cmd->full_filter = filter;
@@ -1023,11 +1213,14 @@ static int _init_filters(struct cmd_context *cmd, unsigned load_persistent_cache
*/
if (!find_config_tree_bool(cmd, global_use_lvmetad_CFG, NULL) &&
load_persistent_cache && !cmd->is_long_lived &&
!stat(dev_cache, &st) &&
(st.st_ctime > config_file_timestamp(cmd->cft)) &&
!persistent_filter_load(cmd->filter, NULL))
log_verbose("Failed to load existing device cache from %s",
dev_cache);
!stat(dev_cache, &st)) {
lvm_stat_ctim(&ts, &st);
cts = config_file_timestamp(cmd->cft);
if (timespeccmp(&ts, &cts, >) &&
!persistent_filter_load(cmd->filter, NULL))
log_verbose("Failed to load existing device cache from %s",
dev_cache);
}
return 1;
bad:
@@ -1550,6 +1743,10 @@ struct cmd_context *create_toolcontext(unsigned is_long_lived,
if (!_init_tags(cmd, cmd->cft))
goto_out;
/* Load lvmlocal.conf */
if (*cmd->system_dir && !_load_config_file(cmd, "", 1))
goto_out;
if (!_init_tag_configs(cmd))
goto_out;
@@ -1754,6 +1951,10 @@ int refresh_toolcontext(struct cmd_context *cmd)
if (!_init_tags(cmd, cft_tmp))
return_0;
/* Load lvmlocal.conf */
if (*cmd->system_dir && !_load_config_file(cmd, "", 1))
return_0;
/* Doesn't change cmd->cft */
if (!_init_tag_configs(cmd))
return_0;

View File

@@ -71,6 +71,7 @@ struct cmd_context {
struct dm_list formats; /* Available formats */
struct dm_list segtypes; /* Available segment types */
const char *system_id;
const char *hostname;
const char *kernel_vsn;
@@ -95,6 +96,10 @@ struct cmd_context {
unsigned threaded:1; /* Set if running within a thread e.g. clvmd */
unsigned independent_metadata_areas:1; /* Active formats have MDAs outside PVs */
unsigned unknown_system_id:1;
unsigned include_foreign_vgs:1;
unsigned include_active_foreign_vgs:1;
unsigned error_foreign_vgs:1;
struct dev_types *dev_types;
@@ -160,4 +165,6 @@ int init_lvmcache_orphans(struct cmd_context *cmd);
struct format_type *get_format_by_name(struct cmd_context *cmd, const char *format);
const char *system_id_from_string(struct cmd_context *cmd, const char *str);
#endif

View File

@@ -53,7 +53,7 @@ struct config_file {
struct config_source {
config_source_t type;
time_t timestamp;
struct timespec timestamp;
union {
struct config_file *file;
struct config_file *profile;
@@ -65,11 +65,11 @@ struct config_source {
* Map each ID to respective definition of the configuration item.
*/
static struct cfg_def_item _cfg_def_items[CFG_COUNT + 1] = {
#define cfg_section(id, name, parent, flags, since_version, comment) {id, parent, name, CFG_TYPE_SECTION, {0}, flags, since_version, comment},
#define cfg(id, name, parent, flags, type, default_value, since_version, comment) {id, parent, name, type, {.v_##type = default_value}, flags, since_version, comment},
#define cfg_runtime(id, name, parent, flags, type, since_version, comment) {id, parent, name, type, {.fn_##type = get_default_##id}, flags | CFG_DEFAULT_RUN_TIME, since_version, comment},
#define cfg_array(id, name, parent, flags, types, default_value, since_version, comment) {id, parent, name, CFG_TYPE_ARRAY | types, {.v_CFG_TYPE_STRING = default_value}, flags, since_version, comment},
#define cfg_array_runtime(id, name, parent, flags, types, since_version, comment) {id, parent, name, CFG_TYPE_ARRAY | types, {.fn_CFG_TYPE_STRING = get_default_##id}, flags | CFG_DEFAULT_RUN_TIME, since_version, comment},
#define cfg_section(id, name, parent, flags, since_version, unconfigured_path, comment) {id, parent, name, CFG_TYPE_SECTION, {0}, flags, since_version, unconfigured_path, comment},
#define cfg(id, name, parent, flags, type, default_value, since_version, unconfigured_path, comment) {id, parent, name, type, {.v_##type = default_value}, flags, since_version, unconfigured_path, comment},
#define cfg_runtime(id, name, parent, flags, type, since_version, unconfigured_path, comment) {id, parent, name, type, {.fn_##type = get_default_##id}, flags | CFG_DEFAULT_RUN_TIME, since_version, unconfigured_path, comment},
#define cfg_array(id, name, parent, flags, types, default_value, since_version, unconfigured_path, comment) {id, parent, name, CFG_TYPE_ARRAY | types, {.v_CFG_TYPE_STRING = default_value}, flags, since_version, unconfigured_path, comment},
#define cfg_array_runtime(id, name, parent, flags, types, since_version, unconfigured_path, comment) {id, parent, name, CFG_TYPE_ARRAY | types, {.fn_CFG_TYPE_STRING = get_default_##id}, flags | CFG_DEFAULT_RUN_TIME, since_version, unconfigured_path, comment},
#include "config_settings.h"
#undef cfg_section
#undef cfg
@@ -173,7 +173,7 @@ int config_file_check(struct dm_config_tree *cft, const char **filename, struct
return 0;
}
cs->timestamp = info->st_ctime;
lvm_stat_ctim(&cs->timestamp, info);
cf->exists = 1;
cf->st_size = info->st_size;
@@ -193,6 +193,7 @@ int config_file_changed(struct dm_config_tree *cft)
struct config_source *cs = dm_config_get_custom(cft);
struct config_file *cf;
struct stat info;
struct timespec ts;
if (cs->type != CONFIG_FILE) {
log_error(INTERNAL_ERROR "config_file_changed: expected file config source, "
@@ -226,7 +227,9 @@ int config_file_changed(struct dm_config_tree *cft)
}
/* Unchanged? */
if (cs->timestamp == info.st_ctime && cf->st_size == info.st_size)
lvm_stat_ctim(&ts, &info);
if ((timespeccmp(&cs->timestamp, &ts, ==)) &&
cf->st_size == info.st_size)
return 0;
reload:
@@ -478,9 +481,15 @@ int override_config_tree_from_profile(struct cmd_context *cmd,
return 0;
}
/*
* When checksum_only is set, the checksum of buffer is only matched
* and function avoids parsing of mda into config tree which
* remains unmodified and should not be used.
*/
int config_file_read_fd(struct dm_config_tree *cft, struct device *dev,
off_t offset, size_t size, off_t offset2, size_t size2,
checksum_fn_t checksum_fn, uint32_t checksum)
checksum_fn_t checksum_fn, uint32_t checksum,
int checksum_only)
{
char *fb, *fe;
int r = 0;
@@ -529,9 +538,11 @@ int config_file_read_fd(struct dm_config_tree *cft, struct device *dev,
goto out;
}
fe = fb + size + size2;
if (!dm_config_parse(cft, fb, fe))
goto_out;
if (!checksum_only) {
fe = fb + size + size2;
if (!dm_config_parse(cft, fb, fe))
goto_out;
}
r = 1;
@@ -575,7 +586,7 @@ int config_file_read(struct dm_config_tree *cft)
}
r = config_file_read_fd(cft, cf->dev, 0, (size_t) info.st_size, 0, 0,
(checksum_fn_t) NULL, 0);
(checksum_fn_t) NULL, 0, 0);
if (!cf->keep_open) {
if (!dev_close(cf->dev))
@@ -586,7 +597,7 @@ int config_file_read(struct dm_config_tree *cft)
return r;
}
time_t config_file_timestamp(struct dm_config_tree *cft)
struct timespec config_file_timestamp(struct dm_config_tree *cft)
{
struct config_source *cs = dm_config_get_custom(cft);
return cs->timestamp;
@@ -649,8 +660,8 @@ static void _log_type_error(const char *path, cfg_def_type_t actual,
_get_type_name(actual_type_name, sizeof(actual_type_name), actual);
_get_type_name(expected_type_name, sizeof(expected_type_name), expected);
log_warn_suppress(suppress_messages, "Configuration setting \"%s\" has invalid type. "
"Found%s, expected%s.", path,
log_warn_suppress(suppress_messages, "WARNING: Configuration setting \"%s\" has invalid type. "
"Found%s but expected%s.", path,
actual_type_name, expected_type_name);
}
@@ -790,6 +801,11 @@ static int _config_def_check_node_single_value(struct cft_check_handle *handle,
} else if (!(def->type & CFG_TYPE_STRING)) {
_log_type_error(rp, CFG_TYPE_STRING, def->type, handle->suppress_messages);
return 0;
} else if (!(def->flags & CFG_ALLOW_EMPTY) && !*v->v.str) {
log_warn_suppress(handle->suppress_messages,
"Configuration setting \"%s\" invalid. "
"It cannot be set to an empty value.", rp);
return 0;
}
break;
default: ;
@@ -1140,6 +1156,29 @@ static int _apply_local_profile(struct cmd_context *cmd, struct profile *profile
return override_config_tree_from_profile(cmd, profile);
}
static int _config_disabled(struct cmd_context *cmd, cfg_def_item_t *item, const char *path)
{
if ((item->flags & CFG_DISABLED) && dm_config_tree_find_node(cmd->cft, path)) {
log_warn("WARNING: Configuration setting %s is disabled. Using default value.", path);
return 1;
}
return 0;
}
const struct dm_config_node *find_config_node(struct cmd_context *cmd, struct dm_config_tree *cft, int id)
{
cfg_def_item_t *item = cfg_def_get_item_p(id);
char path[CFG_PATH_MAX_LEN];
const struct dm_config_node *cn;
_cfg_def_make_path(path, sizeof(path), item->id, item, 0);
cn = dm_config_tree_find_node(cft, path);
return cn;
}
const struct dm_config_node *find_config_tree_node(struct cmd_context *cmd, int id, struct profile *profile)
{
cfg_def_item_t *item = cfg_def_get_item_p(id);
@@ -1171,7 +1210,8 @@ const char *find_config_tree_str(struct cmd_context *cmd, int id, struct profile
if (item->type != CFG_TYPE_STRING)
log_error(INTERNAL_ERROR "%s cfg tree element not declared as string.", path);
str = dm_config_tree_find_str(cmd->cft, path, cfg_def_get_default_value(cmd, item, CFG_TYPE_STRING, profile));
str = _config_disabled(cmd, item, path) ? cfg_def_get_default_value(cmd, item, CFG_TYPE_STRING, profile)
: dm_config_tree_find_str(cmd->cft, path, cfg_def_get_default_value(cmd, item, CFG_TYPE_STRING, profile));
if (profile_applied)
remove_config_tree_by_source(cmd, profile->source);
@@ -1194,7 +1234,8 @@ const char *find_config_tree_str_allow_empty(struct cmd_context *cmd, int id, st
if (!(item->flags & CFG_ALLOW_EMPTY))
log_error(INTERNAL_ERROR "%s cfg tree element not declared to allow empty values.", path);
str = dm_config_tree_find_str_allow_empty(cmd->cft, path, cfg_def_get_default_value(cmd, item, CFG_TYPE_STRING, profile));
str = _config_disabled(cmd, item, path) ? cfg_def_get_default_value(cmd, item, CFG_TYPE_STRING, profile)
: dm_config_tree_find_str_allow_empty(cmd->cft, path, cfg_def_get_default_value(cmd, item, CFG_TYPE_STRING, profile));
if (profile_applied)
remove_config_tree_by_source(cmd, profile->source);
@@ -1215,7 +1256,8 @@ int find_config_tree_int(struct cmd_context *cmd, int id, struct profile *profil
if (item->type != CFG_TYPE_INT)
log_error(INTERNAL_ERROR "%s cfg tree element not declared as integer.", path);
i = dm_config_tree_find_int(cmd->cft, path, cfg_def_get_default_value(cmd, item, CFG_TYPE_INT, profile));
i = _config_disabled(cmd, item, path) ? cfg_def_get_default_value(cmd, item, CFG_TYPE_INT, profile)
: dm_config_tree_find_int(cmd->cft, path, cfg_def_get_default_value(cmd, item, CFG_TYPE_INT, profile));
if (profile_applied)
remove_config_tree_by_source(cmd, profile->source);
@@ -1236,7 +1278,8 @@ int64_t find_config_tree_int64(struct cmd_context *cmd, int id, struct profile *
if (item->type != CFG_TYPE_INT)
log_error(INTERNAL_ERROR "%s cfg tree element not declared as integer.", path);
i64 = dm_config_tree_find_int64(cmd->cft, path, cfg_def_get_default_value(cmd, item, CFG_TYPE_INT, profile));
i64 = _config_disabled(cmd, item, path) ? cfg_def_get_default_value(cmd, item, CFG_TYPE_INT, profile)
: dm_config_tree_find_int64(cmd->cft, path, cfg_def_get_default_value(cmd, item, CFG_TYPE_INT, profile));
if (profile_applied)
remove_config_tree_by_source(cmd, profile->source);
@@ -1257,7 +1300,8 @@ float find_config_tree_float(struct cmd_context *cmd, int id, struct profile *pr
if (item->type != CFG_TYPE_FLOAT)
log_error(INTERNAL_ERROR "%s cfg tree element not declared as float.", path);
f = dm_config_tree_find_float(cmd->cft, path, cfg_def_get_default_value(cmd, item, CFG_TYPE_FLOAT, profile));
f = _config_disabled(cmd, item, path) ? cfg_def_get_default_value(cmd, item, CFG_TYPE_FLOAT, profile)
: dm_config_tree_find_float(cmd->cft, path, cfg_def_get_default_value(cmd, item, CFG_TYPE_FLOAT, profile));
if (profile_applied)
remove_config_tree_by_source(cmd, profile->source);
@@ -1265,6 +1309,23 @@ float find_config_tree_float(struct cmd_context *cmd, int id, struct profile *pr
return f;
}
int find_config_bool(struct cmd_context *cmd, struct dm_config_tree *cft, int id)
{
cfg_def_item_t *item = cfg_def_get_item_p(id);
char path[CFG_PATH_MAX_LEN];
int b;
_cfg_def_make_path(path, sizeof(path), item->id, item, 0);
if (item->type != CFG_TYPE_BOOL)
log_error(INTERNAL_ERROR "%s cfg tree element not declared as boolean.", path);
b = _config_disabled(cmd, item, path) ? cfg_def_get_default_value(cmd, item, CFG_TYPE_BOOL, NULL)
: dm_config_tree_find_bool(cft, path, cfg_def_get_default_value(cmd, item, CFG_TYPE_BOOL, NULL));
return b;
}
int find_config_tree_bool(struct cmd_context *cmd, int id, struct profile *profile)
{
cfg_def_item_t *item = cfg_def_get_item_p(id);
@@ -1278,7 +1339,8 @@ int find_config_tree_bool(struct cmd_context *cmd, int id, struct profile *profi
if (item->type != CFG_TYPE_BOOL)
log_error(INTERNAL_ERROR "%s cfg tree element not declared as boolean.", path);
b = dm_config_tree_find_bool(cmd->cft, path, cfg_def_get_default_value(cmd, item, CFG_TYPE_BOOL, profile));
b = _config_disabled(cmd, item, path) ? cfg_def_get_default_value(cmd, item, CFG_TYPE_BOOL, profile)
: dm_config_tree_find_bool(cmd->cft, path, cfg_def_get_default_value(cmd, item, CFG_TYPE_BOOL, profile));
if (profile_applied)
remove_config_tree_by_source(cmd, profile->source);
@@ -1414,7 +1476,7 @@ int merge_config_tree(struct cmd_context *cmd, struct dm_config_tree *cft,
cs = dm_config_get_custom(cft);
csn = dm_config_get_custom(newdata);
if (cs && csn && (cs->timestamp < csn->timestamp))
if (cs && csn && timespeccmp(&cs->timestamp, &csn->timestamp, <))
cs->timestamp = csn->timestamp;
return 1;
@@ -1426,6 +1488,36 @@ struct out_baton {
struct dm_pool *mem;
};
#define MAX_COMMENT_LINE 512
static int _copy_one_line(const char *comment, char *line, int *pos, int len)
{
int p;
int i = 0;
char c;
if (*pos >= len)
return 0;
memset(line, 0, MAX_COMMENT_LINE+1);
for (p = *pos; ; p++) {
c = comment[p];
(*pos)++;
if (c == '\n' || c == '\0')
break;
line[i++] = c;
if (i == MAX_COMMENT_LINE)
break;
}
return i;
}
static int _out_prefix_fn(const struct dm_config_node *cn, const char *line, void *baton)
{
struct out_baton *out = baton;
@@ -1433,7 +1525,7 @@ static int _out_prefix_fn(const struct dm_config_node *cn, const char *line, voi
char version[9]; /* 8+1 chars for max version of 7.15.511 */
const char *node_type_name = cn->v ? "option" : "section";
char path[CFG_PATH_MAX_LEN];
char commentline[MAX_COMMENT_LINE+1];
if (cn->id < 0)
return 1;
@@ -1449,12 +1541,20 @@ static int _out_prefix_fn(const struct dm_config_node *cn, const char *line, voi
cfg_def = cfg_def_get_item_p(cn->id);
if (out->tree_spec->withcomments) {
if (out->tree_spec->withcomments || out->tree_spec->withfullcomments) {
_cfg_def_make_path(path, sizeof(path), cfg_def->id, cfg_def, 1);
fprintf(out->fp, "\n");
fprintf(out->fp, "%s# Configuration %s %s.\n", line, node_type_name, path);
if (cfg_def->comment)
fprintf(out->fp, "%s# %s\n", line, cfg_def->comment);
if (cfg_def->comment) {
int pos = 0;
while (_copy_one_line(cfg_def->comment, commentline, &pos, strlen(cfg_def->comment))) {
fprintf(out->fp, "%s# %s\n", line, commentline);
/* withcomments prints only the first comment line. */
if (!out->tree_spec->withfullcomments)
break;
}
}
if (cfg_def->flags & CFG_ADVANCED)
fprintf(out->fp, "%s# This configuration %s is advanced.\n", line, node_type_name);
@@ -1597,6 +1697,9 @@ static struct dm_config_node *_add_def_node(struct dm_config_tree *cft,
if (!(str = cfg_def_get_default_value_hint(spec->cmd, def, CFG_TYPE_STRING, NULL)))
str = "";
cn->v->v.str = str;
if (spec->unconfigured && def->unconfigured_path)
cn->v->v.str = def->unconfigured_path;
break;
default:
log_error(INTERNAL_ERROR "_add_def_node: unknown type");
@@ -1714,6 +1817,9 @@ struct dm_config_tree *config_def_create_tree(struct config_def_tree_spec *spec)
if (cfg_def_get_item_p(id)->parent != root_CFG_SECTION)
continue;
if (spec->ignorelocal && (id == local_CFG_SECTION))
continue;
if ((tmp = _add_def_section_subtree(cft, spec, root, relay, id))) {
relay = tmp;
if (!root)

View File

@@ -90,24 +90,27 @@ typedef union {
/* configuration definition item flags: */
/* whether the configuration item name is variable */
#define CFG_NAME_VARIABLE 0x01
#define CFG_NAME_VARIABLE 0x001
/* whether empty value is allowed */
#define CFG_ALLOW_EMPTY 0x02
#define CFG_ALLOW_EMPTY 0x002
/* whether the configuration item is for advanced use only */
#define CFG_ADVANCED 0x04
#define CFG_ADVANCED 0x004
/* whether the configuration item is not officially supported */
#define CFG_UNSUPPORTED 0x08
#define CFG_UNSUPPORTED 0x008
/* whether the configuration item is customizable by a profile */
#define CFG_PROFILABLE 0x10
#define CFG_PROFILABLE 0x010
/* whether the configuration item is customizable by a profile */
/* and whether it can be attached to VG/LV metadata at the same time
* The CFG_PROFILABLE_METADATA flag incorporates CFG_PROFILABLE flag!!! */
#define CFG_PROFILABLE_METADATA 0x30
#define CFG_PROFILABLE_METADATA 0x030
/* whether the default value is undefned */
#define CFG_DEFAULT_UNDEFINED 0x40
/* whether the defualt value is calculated during run time */
#define CFG_DEFAULT_RUN_TIME 0x80
#define CFG_DEFAULT_UNDEFINED 0x040
/* whether the default value is calculated during run time */
#define CFG_DEFAULT_RUN_TIME 0x080
/* whether the configuration setting is disabled (and hence defaults always used) */
#define CFG_DISABLED 0x100
/* configuration definition item structure */
typedef struct cfg_def_item {
@@ -118,6 +121,7 @@ typedef struct cfg_def_item {
cfg_def_value_t default_value; /* default value (only for settings) */
uint16_t flags; /* configuration item definition flags */
uint16_t since_version; /* version this item appeared in */
const char *unconfigured_path; /* path in terms of @FOO@, pre-configured */
const char *comment; /* brief comment */
} cfg_def_item_t;
@@ -141,8 +145,11 @@ struct config_def_tree_spec {
uint16_t version; /* tree at this LVM2 version */
unsigned ignoreadvanced:1; /* do not include advanced configs */
unsigned ignoreunsupported:1; /* do not include unsupported configs */
unsigned withcomments:1; /* include comments */
unsigned ignorelocal:1; /* do not include the local section */
unsigned withcomments:1; /* include first line of comment */
unsigned withfullcomments:1; /* include all comment lines */
unsigned withversions:1; /* include versions */
unsigned unconfigured:1; /* use unconfigured path strings */
uint8_t *check_status; /* status of last tree check (currently needed for CFG_DEF_TREE_MISSING only) */
};
@@ -158,11 +165,11 @@ struct config_def_tree_spec {
* Register ID for each possible item in the configuration tree.
*/
enum {
#define cfg_section(id, name, parent, flags, since_version, comment) id,
#define cfg(id, name, parent, flags, type, default_value, since_version, comment) id,
#define cfg_runtime(id, name, parent, flags, type, since_version, comment) id,
#define cfg_array(id, name, parent, flags, types, default_value, since_version, comment) id,
#define cfg_array_runtime(id, name, parent, flags, types, since_version, comment) id,
#define cfg_section(id, name, parent, flags, since_version, unconfigured_path, comment) id,
#define cfg(id, name, parent, flags, type, default_value, since_version, unconfigured_path, comment) id,
#define cfg_runtime(id, name, parent, flags, type, since_version, unconfigured_path, comment) id,
#define cfg_array(id, name, parent, flags, types, default_value, since_version, unconfigured_path, comment) id,
#define cfg_array_runtime(id, name, parent, flags, types, since_version, unconfigured_path, comment) id,
#include "config_settings.h"
#undef cfg_section
#undef cfg
@@ -202,7 +209,8 @@ typedef uint32_t (*checksum_fn_t) (uint32_t initial, const uint8_t *buf, uint32_
struct dm_config_tree *config_open(config_source_t source, const char *filename, int keep_open);
int config_file_read_fd(struct dm_config_tree *cft, struct device *dev,
off_t offset, size_t size, off_t offset2, size_t size2,
checksum_fn_t checksum_fn, uint32_t checksum);
checksum_fn_t checksum_fn, uint32_t checksum,
int skip_parse);
int config_file_read(struct dm_config_tree *cft);
struct dm_config_tree *config_file_open_and_read(const char *config_file, config_source_t source,
struct cmd_context *cmd);
@@ -211,7 +219,7 @@ int config_write(struct dm_config_tree *cft, struct config_def_tree_spec *tree_s
struct dm_config_tree *config_def_create_tree(struct config_def_tree_spec *spec);
void config_destroy(struct dm_config_tree *cft);
time_t config_file_timestamp(struct dm_config_tree *cft);
struct timespec config_file_timestamp(struct dm_config_tree *cft);
int config_file_changed(struct dm_config_tree *cft);
int config_file_check(struct dm_config_tree *cft, const char **filename, struct stat *info);
@@ -230,6 +238,12 @@ typedef enum {
int merge_config_tree(struct cmd_context *cmd, struct dm_config_tree *cft,
struct dm_config_tree *newdata, config_merge_t);
/*
* The next two do not check config overrides and must only be used for the tags section.
*/
const struct dm_config_node *find_config_node(struct cmd_context *cmd, struct dm_config_tree *cft, int id);
int find_config_bool(struct cmd_context *cmd, struct dm_config_tree *cft, int id);
/*
* These versions check an override tree, if present, first.
*/

File diff suppressed because it is too large Load Diff

View File

@@ -29,9 +29,12 @@
#define DEFAULT_DEV_DIR "/dev"
#define DEFAULT_PROC_DIR "/proc"
#define DEFAULT_SYSTEM_ID_SOURCE "none"
#define DEFAULT_OBTAIN_DEVICE_LIST_FROM_UDEV 1
#define DEFAULT_EXTERNAL_DEVICE_INFO_SOURCE "none"
#define DEFAULT_SYSFS_SCAN 1
#define DEFAULT_MD_COMPONENT_DETECTION 1
#define DEFAULT_FW_RAID_COMPONENT_DETECTION 0
#define DEFAULT_MD_CHUNK_ALIGNMENT 1
#define DEFAULT_IGNORE_LVM_MIRRORS 1
#define DEFAULT_MULTIPATH_COMPONENT_DETECTION 1
@@ -44,6 +47,7 @@
#define DEFAULT_PV_MIN_SIZE_KB 2048
#define DEFAULT_LOCKING_LIB "liblvm2clusterlock.so"
#define DEFAULT_ERROR_WHEN_FULL 0
#define DEFAULT_FALLBACK_TO_LOCAL_LOCKING 1
#define DEFAULT_FALLBACK_TO_CLUSTERED_LOCKING 1
#define DEFAULT_WAIT_FOR_LOCKS 1
@@ -72,9 +76,11 @@
#endif
#ifdef THIN_CHECK_NEEDS_CHECK
# define DEFAULT_THIN_CHECK_OPTIONS "-q --clear-needs-check-flag"
# define DEFAULT_THIN_CHECK_OPTION1 "-q"
# define DEFAULT_THIN_CHECK_OPTION2 "--clear-needs-check-flag"
#else
# define DEFAULT_THIN_CHECK_OPTIONS "-q"
# define DEFAULT_THIN_CHECK_OPTION1 "-q"
# define DEFAULT_THIN_CHECK_OPTION2 ""
#endif
#define DEFAULT_THIN_REPAIR_OPTIONS ""
@@ -89,7 +95,7 @@
#define DEFAULT_THIN_POOL_ZERO 1
#define DEFAULT_POOL_METADATA_SPARE 1 /* thin + cache */
#define DEFAULT_CACHE_CHECK_OPTIONS "-q"
#define DEFAULT_CACHE_CHECK_OPTION1 "-q"
#define DEFAULT_CACHE_REPAIR_OPTIONS ""
#define DEFAULT_CACHE_POOL_METADATA_REQUIRE_SEPARATE_PVS 0
#define DEFAULT_CACHE_POOL_CHUNK_SIZE 64 /* KB */
@@ -176,6 +182,7 @@
#define DEFAULT_MAX_ERROR_COUNT NO_DEV_ERROR_COUNT_LIMIT
#define DEFAULT_REP_COMPACT_OUTPUT 0
#define DEFAULT_REP_ALIGNED 1
#define DEFAULT_REP_BUFFERED 1
#define DEFAULT_REP_COLUMNS_AS_ROWS 0

View File

@@ -71,6 +71,21 @@ int str_list_add(struct dm_pool *mem, struct dm_list *sll, const char *str)
return str_list_add_no_dup_check(mem, sll, str);
}
/* Add contents of sll2 to sll */
int str_list_add_list(struct dm_pool *mem, struct dm_list *sll, struct dm_list *sll2)
{
struct dm_str_list *sl;
if (!sll2)
return_0;
dm_list_iterate_items(sl, sll2)
if (!str_list_add(mem, sll, sl->str))
return_0;
return 1;
}
void str_list_del(struct dm_list *sll, const char *str)
{
struct dm_list *slh, *slht;

View File

@@ -21,6 +21,7 @@ struct dm_pool;
struct dm_list *str_list_create(struct dm_pool *mem);
int str_list_add(struct dm_pool *mem, struct dm_list *sll, const char *str);
int str_list_add_list(struct dm_pool *mem, struct dm_list *sll, struct dm_list *sll2);
int str_list_add_no_dup_check(struct dm_pool *mem, struct dm_list *sll, const char *str);
int str_list_add_h_no_dup_check(struct dm_pool *mem, struct dm_list *sll, const char *str);
void str_list_del(struct dm_list *sll, const char *str);

View File

@@ -64,6 +64,9 @@ static void _dev_init(struct device *dev, int max_error_count)
dev->read_ahead = -1;
dev->max_error_count = max_error_count;
dev->ext.enabled = 0;
dev->ext.src = DEV_EXT_NONE;
dm_list_init(&dev->aliases);
dm_list_init(&dev->open_list);
}
@@ -983,12 +986,31 @@ static struct device *_dev_cache_seek_devt(dev_t dev)
*/
struct device *dev_cache_get_by_devt(dev_t dev, struct dev_filter *f)
{
char path[PATH_MAX];
const char *sysfs_dir;
struct stat info;
struct device *d = _dev_cache_seek_devt(dev);
if (d && (d->flags & DEV_REGULAR))
return d;
if (!d) {
sysfs_dir = dm_sysfs_dir();
if (sysfs_dir && *sysfs_dir) {
/* First check if dev is sysfs to avoid useless scan */
if (dm_snprintf(path, sizeof(path), "%s/dev/block/%d:%d",
sysfs_dir, (int)MAJOR(dev), (int)MINOR(dev)) < 0) {
log_error("dm_snprintf partition failed.");
return NULL;
}
if (lstat(path, &info)) {
log_debug("No sysfs entry for %d:%d.",
(int)MAJOR(dev), (int)MINOR(dev));
return NULL;
}
}
_full_scan(0);
d = _dev_cache_seek_devt(dev);
}

View File

@@ -0,0 +1,52 @@
/*
* Copyright (C) 2015 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*************************************************************************
* Properties saved in udev db and accesible via libudev and used by LVM *
*************************************************************************/
/*
* DEV_EXT_UDEV_BLKID_TYPE property with various DEV_EXT_UDEV_BLKID_TYPE_*
* values that is saved in udev db via blkid call in udev rules
*/
#define DEV_EXT_UDEV_BLKID_TYPE "ID_FS_TYPE"
/*
* mpath_member is forced by multipath - it's set in udev db via
* multipath call overwriting any existing ID_FS_TYPE value for
* a device which is a multipath component which prevents incorrect
* claim of the device by any other block device subsystem
*/
#define DEV_EXT_UDEV_BLKID_TYPE_MPATH "mpath_member"
/* FW RAIDs are all *_raid_member types except linux_raid_member which denotes SW RAID */
#define DEV_EXT_UDEV_BLKID_TYPE_RAID_SUFFIX "_raid_member"
#define DEV_EXT_UDEV_BLKID_TYPE_SW_RAID "linux_raid_member"
#define DEV_EXT_UDEV_BLKID_PART_TABLE_TYPE "ID_PART_TABLE_TYPE"
#define DEV_EXT_UDEV_BLKID_PART_ENTRY_DISK "ID_PART_ENTRY_DISK"
/*
* DEV_EXT_UDEV_MPATH_DEVICE_PATH is set by multipath in udev db
* with value either 0 or 1. The same functionality as
* DEV_EXT_UDEV_BLKID_TYPE_MPATH actually, but introduced later
* for some reason.
*/
#define DEV_EXT_UDEV_MPATH_DEVICE_PATH "DM_MULTIPATH_DEVICE_PATH"
/***********************************************************
* Sysfs attributes accessible via libudev and used by LVM *
***********************************************************/
/* the value of size sysfs attribute is size in bytes */
#define DEV_EXT_UDEV_SYSFS_ATTR_SIZE "size"

164
lib/device/dev-ext.c Normal file
View File

@@ -0,0 +1,164 @@
/*
* Copyright (C) 2014 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "lib.h"
#include "device.h"
#ifdef UDEV_SYNC_SUPPORT
#include <libudev.h>
#endif
struct ext_registry_item {
const char *name;
struct dev_ext *(* dev_ext_get) (struct device *dev);
int (*dev_ext_release) (struct device *dev);
};
#define EXT_REGISTER(id,name) [id] = { #name, &_dev_ext_get_ ## name, &_dev_ext_release_ ## name }
/*
* DEV_EXT_NONE
*/
static struct dev_ext *_dev_ext_get_none(struct device *dev)
{
dev->ext.handle = NULL;
return &dev->ext;
}
static int _dev_ext_release_none(struct device *dev)
{
dev->ext.handle = NULL;
return 1;
}
/*
* DEV_EXT_UDEV
*/
static struct dev_ext *_dev_ext_get_udev(struct device *dev)
{
#ifdef UDEV_SYNC_SUPPORT
struct udev *udev;
struct udev_device *udev_device;
if (dev->ext.handle)
return &dev->ext;
if (!(udev = udev_get_library_context()))
return_NULL;
if (!(udev_device = udev_device_new_from_devnum(udev, 'b', dev->dev)))
return_NULL;
dev->ext.handle = (void *) udev_device;
return &dev->ext;
#else
return NULL;
#endif
}
static int _dev_ext_release_udev(struct device *dev)
{
#ifdef UDEV_SYNC_SUPPORT
if (!dev->ext.handle)
return 1;
/* udev_device_unref can't fail - it has no return value */
udev_device_unref((struct udev_device *) dev->ext.handle);
dev->ext.handle = NULL;
return 1;
#else
return 0;
#endif
}
static struct ext_registry_item _ext_registry[DEV_EXT_NUM] = {
EXT_REGISTER(DEV_EXT_NONE, none),
EXT_REGISTER(DEV_EXT_UDEV, udev)
};
const char *dev_ext_name(struct device *dev)
{
return _ext_registry[dev->ext.src].name;
}
static const char *_ext_attached_msg = "External handle attached to device";
struct dev_ext *dev_ext_get(struct device *dev)
{
struct dev_ext *ext;
void *handle_ptr;
handle_ptr = dev->ext.handle;
if (!(ext = _ext_registry[dev->ext.src].dev_ext_get(dev)))
log_error("Failed to get external handle for device %s [%s].",
dev_name(dev), dev_ext_name(dev));
else if (handle_ptr != dev->ext.handle)
log_debug_devs("%s %s [%s:%p]", _ext_attached_msg, dev_name(dev),
dev_ext_name(dev), dev->ext.handle);
return ext;
}
int dev_ext_release(struct device *dev)
{
int r;
void *handle_ptr;
if (!dev->ext.enabled ||
!dev->ext.handle)
return 1;
handle_ptr = dev->ext.handle;
if (!(r = _ext_registry[dev->ext.src].dev_ext_release(dev)))
log_error("Failed to release external handle for device %s [%s:%p].",
dev_name(dev), dev_ext_name(dev), dev->ext.handle);
else
log_debug_devs("External handle detached from device %s [%s:%p]",
dev_name(dev), dev_ext_name(dev), handle_ptr);
return r;
}
int dev_ext_enable(struct device *dev, dev_ext_t src)
{
if (dev->ext.enabled && (dev->ext.src != src) && !dev_ext_release(dev)) {
log_error("Failed to enable external handle for device %s [%s].",
dev_name(dev), _ext_registry[src].name);
return 0;
}
dev->ext.src = src;
dev->ext.enabled = 1;
return 1;
}
int dev_ext_disable(struct device *dev)
{
if (!dev->ext.enabled)
return 1;
if (!dev_ext_release(dev)) {
log_error("Failed to disable external handle for device %s [%s].",
dev_name(dev), dev_ext_name(dev));
return 0;
}
dev->ext.enabled = 0;
dev->ext.src = DEV_EXT_NONE;
return 1;
}

View File

@@ -289,25 +289,22 @@ static int _dev_get_size_file(const struct device *dev, uint64_t *size)
return 1;
}
static int _dev_get_size_dev(const struct device *dev, uint64_t *size)
static int _dev_get_size_dev(struct device *dev, uint64_t *size)
{
int fd;
const char *name = dev_name(dev);
if ((fd = open(name, O_RDONLY)) < 0) {
log_sys_error("open", name);
return 0;
}
if (!dev_open_readonly(dev))
return_0;
if (ioctl(fd, BLKGETSIZE64, size) < 0) {
if (ioctl(dev_fd(dev), BLKGETSIZE64, size) < 0) {
log_sys_error("ioctl BLKGETSIZE64", name);
if (close(fd))
if (!dev_close(dev))
log_sys_error("close", name);
return 0;
}
*size >>= BLKSIZE_SHIFT; /* Convert to sectors */
if (close(fd))
if (!dev_close(dev))
log_sys_error("close", name);
log_very_verbose("%s: size is %" PRIu64 " sectors", name, *size);
@@ -377,7 +374,7 @@ static int _dev_discard_blocks(struct device *dev, uint64_t offset_bytes, uint64
* Public functions
*---------------------------------------------------------------*/
int dev_get_size(const struct device *dev, uint64_t *size)
int dev_get_size(struct device *dev, uint64_t *size)
{
if (!dev)
return 0;

View File

@@ -15,8 +15,11 @@
#include "lib.h"
#include "dev-type.h"
#include "metadata.h"
#include "xlate.h"
#ifdef UDEV_SYNC_SUPPORT
#include <libudev.h> /* for MD detection using udev db records */
#include "dev-ext-udev-constants.h"
#endif
#ifdef __linux__
@@ -82,10 +85,31 @@ static uint64_t _v1_sb_offset(uint64_t size, md_minor_version_t minor_version)
return sb_offset;
}
#ifdef UDEV_SYNC_SUPPORT
static int _udev_dev_is_md(struct device *dev)
{
const char *value;
struct dev_ext *ext;
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)))
return 0;
return !strcmp(value, DEV_EXT_UDEV_BLKID_TYPE_SW_RAID);
}
#else
static int _udev_dev_is_md(struct device *dev)
{
return 0;
}
#endif
/*
* Returns -1 on error
*/
int dev_is_md(struct device *dev, uint64_t *offset_found)
static int _native_dev_is_md(struct device *dev, uint64_t *offset_found)
{
int ret = 1;
md_minor_version_t minor;
@@ -130,6 +154,27 @@ out:
return ret;
}
int dev_is_md(struct device *dev, uint64_t *offset_found)
{
/*
* 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);
if (dev->ext.src == DEV_EXT_UDEV)
return _udev_dev_is_md(dev);
log_error(INTERNAL_ERROR "Missing hook for MD device recognition "
"using external device info source %s", dev_ext_name(dev));
return -1;
}
static int _md_sysfs_attribute_snprintf(char *path, size_t size,
struct dev_types *dt,
struct device *blkdev,

View File

@@ -25,6 +25,11 @@
#include <blkid.h>
#endif
#ifdef UDEV_SYNC_SUPPORT
#include <libudev.h>
#include "dev-ext-udev-constants.h"
#endif
#include "device-types.h"
struct dev_types *create_dev_types(const char *proc_dir,
@@ -112,6 +117,10 @@ struct dev_types *create_dev_types(const char *proc_dir,
if (!strncmp("drbd", line + i, 4) && isspace(*(line + i + 4)))
dt->drbd_major = line_maj;
/* Look for DASD */
if (!strncmp("dasd", line + i, 4) && isspace(*(line + i + 4)))
dt->dasd_major = line_maj;
/* Look for EMC powerpath */
if (!strncmp("emcpower", line + i, 8) && isspace(*(line + i + 8)))
dt->emcpower_major = line_maj;
@@ -222,6 +231,9 @@ const char *dev_subsystem_name(struct dev_types *dt, struct device *dev)
if (MAJOR(dev->dev) == dt->drbd_major)
return "DRBD";
if (MAJOR(dev->dev) == dt->dasd_major)
return "DASD";
if (MAJOR(dev->dev) == dt->emcpower_major)
return "EMCPOWER";
@@ -272,6 +284,9 @@ static int _is_partitionable(struct dev_types *dt, struct device *dev)
{
int parts = major_max_partitions(dt, MAJOR(dev->dev));
if (MAJOR(dev->dev) == dt->device_mapper_major)
return 1;
/* All MD devices are partitionable via blkext (as of 2.6.28) */
if (MAJOR(dev->dev) == dt->md_major)
return 1;
@@ -314,12 +329,66 @@ static int _has_partition_table(struct device *dev)
return ret;
}
int dev_is_partitioned(struct dev_types *dt, struct device *dev)
#ifdef UDEV_SYNC_SUPPORT
static int _udev_dev_is_partitioned(struct device *dev)
{
struct dev_ext *ext;
if (!(ext = dev_ext_get(dev)))
return_0;
if (!udev_device_get_property_value((struct udev_device *)ext->handle, DEV_EXT_UDEV_BLKID_PART_TABLE_TYPE))
return 0;
if (udev_device_get_property_value((struct udev_device *)ext->handle, DEV_EXT_UDEV_BLKID_PART_ENTRY_DISK))
return 0;
return 1;
}
#else
static int _udev_dev_is_partitioned(struct device *dev)
{
return 0;
}
#endif
static int _native_dev_is_partitioned(struct dev_types *dt, struct device *dev)
{
int r;
if (!_is_partitionable(dt, dev))
return 0;
return _has_partition_table(dev);
/* Unpartitioned DASD devices are not supported. */
if (MAJOR(dev->dev) == dt->dasd_major)
return 1;
if (!dev_open_readonly_quiet(dev)) {
log_debug_devs("%s: failed to open device, considering device "
"is partitioned", dev_name(dev));
return 1;
}
r = _has_partition_table(dev);
if (!dev_close(dev))
stack;
return r;
}
int dev_is_partitioned(struct dev_types *dt, struct device *dev)
{
if (dev->ext.src == DEV_EXT_NONE)
return _native_dev_is_partitioned(dt, dev);
if (dev->ext.src == DEV_EXT_UDEV)
return _udev_dev_is_partitioned(dev);
log_error(INTERNAL_ERROR "Missing hook for partition table recognition "
"using external device info source %s", dev_ext_name(dev));
return 0;
}
/*
@@ -470,7 +539,7 @@ static int _blkid_wipe(blkid_probe probe, struct device *dev, const char *name,
if (!blkid_probe_lookup_value(probe, "TYPE", &type, NULL)) {
if (_type_in_flag_list(type, types_to_exclude))
return 1;
return 2;
if (blkid_probe_lookup_value(probe, "SBMAGIC_OFFSET", &offset, NULL)) {
log_error(_msg_failed_offset, type, name);
return 0;
@@ -526,12 +595,17 @@ static int _blkid_wipe(blkid_probe probe, struct device *dev, const char *name,
static int _wipe_known_signatures_with_blkid(struct device *dev, const char *name,
uint32_t types_to_exclude,
uint32_t types_no_prompt,
int yes, force_t force)
int yes, force_t force, int *wiped)
{
blkid_probe probe = NULL;
int found = 0, wiped = 0, left = 0;
int found = 0, left = 0, wiped_tmp;
int r_wipe;
int r = 0;
if (!wiped)
wiped = &wiped_tmp;
*wiped = 0;
/* TODO: Should we check for valid dev - _dev_is_valid(dev)? */
if (!(probe = blkid_new_probe_from_filename(dev_name(dev)))) {
@@ -552,15 +626,17 @@ static int _wipe_known_signatures_with_blkid(struct device *dev, const char *nam
BLKID_SUBLKS_BADCSUM);
while (!blkid_do_probe(probe)) {
found++;
if (_blkid_wipe(probe, dev, name, types_to_exclude, types_no_prompt, yes, force))
wiped++;
if ((r_wipe = _blkid_wipe(probe, dev, name, types_to_exclude, types_no_prompt, yes, force)) == 1)
(*wiped)++;
/* do not count excluded types */
if (r_wipe != 2)
found++;
}
if (!found)
r = 1;
left = found - wiped;
left = found - *wiped;
if (!left)
r = 1;
else
@@ -575,7 +651,7 @@ out:
#endif /* BLKID_WIPING_SUPPORT */
static int _wipe_signature(struct device *dev, const char *type, const char *name,
int wipe_len, int yes, force_t force,
int wipe_len, int yes, force_t force, int *wiped,
int (*signature_detection_fn)(struct device *dev, uint64_t *offset_found))
{
int wipe;
@@ -605,17 +681,24 @@ static int _wipe_signature(struct device *dev, const char *type, const char *nam
return 0;
}
(*wiped)++;
return 1;
}
static int _wipe_known_signatures_with_lvm(struct device *dev, const char *name,
uint32_t types_to_exclude __attribute__((unused)),
uint32_t types_no_prompt __attribute__((unused)),
int yes, force_t force)
int yes, force_t force, int *wiped)
{
if (!_wipe_signature(dev, "software RAID md superblock", name, 4, yes, force, dev_is_md) ||
!_wipe_signature(dev, "swap signature", name, 10, yes, force, dev_is_swap) ||
!_wipe_signature(dev, "LUKS signature", name, 8, yes, force, dev_is_luks))
int wiped_tmp;
if (!wiped)
wiped = &wiped_tmp;
*wiped = 0;
if (!_wipe_signature(dev, "software RAID md superblock", name, 4, yes, force, wiped, dev_is_md) ||
!_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;
return 1;
@@ -623,19 +706,20 @@ static int _wipe_known_signatures_with_lvm(struct device *dev, const char *name,
int wipe_known_signatures(struct cmd_context *cmd, struct device *dev,
const char *name, uint32_t types_to_exclude,
uint32_t types_no_prompt, int yes, force_t force)
uint32_t types_no_prompt, int yes, force_t force,
int *wiped)
{
#ifdef BLKID_WIPING_SUPPORT
if (find_config_tree_bool(cmd, allocation_use_blkid_wiping_CFG, NULL))
return _wipe_known_signatures_with_blkid(dev, name,
types_to_exclude,
types_no_prompt,
yes, force);
yes, force, wiped);
#endif
return _wipe_known_signatures_with_lvm(dev, name,
types_to_exclude,
types_no_prompt,
yes, force);
yes, force, wiped);
}
#ifdef __linux__
@@ -715,7 +799,7 @@ static unsigned long _dev_topology_attribute(struct dev_types *dt,
}
log_very_verbose("Device %s: %s is %lu%s.",
dev_name(dev), attribute, result, default_value ? "" : " bytes");
dev_name(dev), attribute, value, default_value ? "" : " bytes");
result = value >> SECTOR_SHIFT;

View File

@@ -44,6 +44,7 @@ struct dev_types {
int device_mapper_major;
int emcpower_major;
int power2_major;
int dasd_major;
struct dev_type_def dev_type_array[NUMBER_OF_MAJORS];
};
@@ -65,7 +66,7 @@ int dev_is_luks(struct device *dev, uint64_t *signature);
#define TYPE_DM_SNAPSHOT_COW 0x004
int wipe_known_signatures(struct cmd_context *cmd, struct device *dev, const char *name,
uint32_t types_to_exclude, uint32_t types_no_prompt,
int yes, force_t force);
int yes, force_t force, int *wiped);
/* Type-specific device properties */
unsigned long dev_md_stripe_width(struct dev_types *dt, struct device *dev);

View File

@@ -28,6 +28,23 @@
#define DEV_O_DIRECT 0x00000020 /* Use O_DIRECT */
#define DEV_O_DIRECT_TESTED 0x00000040 /* DEV_O_DIRECT is reliable */
/*
* Support for external device info.
* Any new external device info source needs to be
* registered using EXT_REGISTER macro in dev-ext.c.
*/
typedef enum {
DEV_EXT_NONE,
DEV_EXT_UDEV,
DEV_EXT_NUM
} dev_ext_t;
struct dev_ext {
int enabled;
dev_ext_t src;
void *handle;
};
/*
* All devices in LVM will be represented by one of these.
* pointer comparisons are valid.
@@ -47,6 +64,7 @@ struct device {
uint32_t flags;
uint64_t end;
struct dm_list open_list;
struct dev_ext ext;
char pvid[ID_LEN + 1];
char _padding[7];
@@ -63,11 +81,20 @@ struct device_area {
uint64_t size; /* Bytes */
};
/*
* Support for external device info.
*/
const char *dev_ext_name(struct device *dev);
int dev_ext_enable(struct device *dev, dev_ext_t src);
int dev_ext_disable(struct device *dev);
struct dev_ext *dev_ext_get(struct device *dev);
int dev_ext_release(struct device *dev);
/*
* All io should use these routines.
*/
int dev_get_block_size(struct device *dev, unsigned int *phys_block_size, unsigned int *block_size);
int dev_get_size(const struct device *dev, uint64_t *size);
int dev_get_size(struct device *dev, uint64_t *size);
int dev_get_read_ahead(struct device *dev, uint32_t *read_ahead);
int dev_discard_blocks(struct device *dev, uint64_t offset_bytes, uint64_t size_bytes);

View File

@@ -385,7 +385,7 @@ int pvdisplay_short(const struct cmd_context *cmd __attribute__((unused)),
char uuid[64] __attribute__((aligned(8)));
if (!pv)
return 0;
return_0;
if (!id_write_format(&pv->id, uuid, sizeof(uuid)))
return_0;
@@ -399,7 +399,8 @@ int pvdisplay_short(const struct cmd_context *cmd __attribute__((unused)),
pv->pe_count, pv->pe_count - pv->pe_alloc_count);
log_print(" ");
return 0;
return 1; /* ECMD_PROCESSED */
}
void lvdisplay_colons(const struct logical_volume *lv)
@@ -623,7 +624,7 @@ int lvdisplay_full(struct cmd_context *cmd,
log_print(" ");
return 0;
return 1; /* ECMD_PROCESSED */
}
void display_stripe(const struct lv_segment *seg, uint32_t s, const char *pre)
@@ -695,7 +696,7 @@ void vgdisplay_full(const struct volume_group *vg)
log_print("--- Volume group ---");
log_print("VG Name %s", vg->name);
log_print("System ID %s", vg->system_id);
log_print("System ID %s", (vg->system_id && *vg->system_id) ? vg->system_id : vg->lvm1_system_id ? : "");
log_print("Format %s", vg->fid->fmt->name);
if (vg->fid->fmt->features & FMT_MDAS) {
log_print("Metadata Areas %d",
@@ -855,7 +856,7 @@ void display_name_error(name_error_t name_error)
case NAME_INVALID_EMPTY:
log_error("Name is zero length.");
break;
case NAME_INVALID_HYPEN:
case NAME_INVALID_HYPHEN:
log_error("Name cannot start with hyphen.");
break;
case NAME_INVALID_DOTS:

View File

@@ -27,6 +27,17 @@ static int _and_p(struct dev_filter *f, struct device *dev)
return 1;
}
static int _and_p_with_dev_ext_info(struct dev_filter *f, struct device *dev)
{
int r;
dev_ext_enable(dev, external_device_info_source());
r = _and_p(f, dev);
dev_ext_disable(dev);
return r;
}
static void _composite_destroy(struct dev_filter *f)
{
struct dev_filter **filters;
@@ -62,7 +73,7 @@ static void _wipe(struct dev_filter *f)
(*filters)->wipe(*filters);
}
struct dev_filter *composite_filter_create(int n, struct dev_filter **filters)
struct dev_filter *composite_filter_create(int n, int use_dev_ext_info, struct dev_filter **filters)
{
struct dev_filter **filters_copy, *cft;
@@ -83,7 +94,7 @@ struct dev_filter *composite_filter_create(int n, struct dev_filter **filters)
return NULL;
}
cft->passes_filter = _and_p;
cft->passes_filter = use_dev_ext_info ? _and_p_with_dev_ext_info : _and_p;
cft->destroy = _composite_destroy;
cft->dump = _dump;
cft->wipe = _wipe;

123
lib/filters/filter-fwraid.c Normal file
View File

@@ -0,0 +1,123 @@
/*
* Copyright (C) 2014 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "lib.h"
#include "filter.h"
#ifdef UDEV_SYNC_SUPPORT
#include <libudev.h>
#include "dev-ext-udev-constants.h"
#endif
#ifdef __linux__
#ifdef UDEV_SYNC_SUPPORT
static int _udev_dev_is_fwraid(struct device *dev)
{
const char *value;
value = udev_device_get_property_value((struct udev_device *)dev->ext.handle, DEV_EXT_UDEV_BLKID_TYPE);
if (value && strcmp(value, DEV_EXT_UDEV_BLKID_TYPE_SW_RAID) && strstr(value, DEV_EXT_UDEV_BLKID_TYPE_RAID_SUFFIX))
return 1;
return 0;
}
#else
static int _udev_dev_is_fwraid(struct device *dev)
{
return 0;
}
#endif
static int _native_dev_is_fwraid(struct device *dev)
{
log_verbose("%s: Firmware RAID detection is not supported by LVM natively. "
"Skipping firmware raid detection. ", dev_name(dev));
return 0;
}
static int _dev_is_fwraid(struct device *dev)
{
if (dev->ext.src == DEV_EXT_NONE)
return _native_dev_is_fwraid(dev);
if (dev->ext.src == DEV_EXT_UDEV)
return _udev_dev_is_fwraid(dev);
log_error(INTERNAL_ERROR "Missing hook for firmware RAID recognition "
"using external device info source %s", dev_ext_name(dev));
return 0;
}
static int _ignore_fwraid(struct dev_filter *f __attribute__((unused)),
struct device *dev)
{
int ret;
if (!fwraid_filtering())
return 1;
ret = _dev_is_fwraid(dev);
if (ret == 1) {
log_debug_devs("%s: Skipping firmware RAID component device [%s:%p]",
dev_name(dev), dev_ext_name(dev), dev->ext.handle);
return 0;
}
if (ret < 0) {
log_debug_devs("%s: Skipping: error in firmware RAID component detection",
dev_name(dev));
return 0;
}
return 1;
}
static void _destroy(struct dev_filter *f)
{
if (f->use_count)
log_error(INTERNAL_ERROR "Destroying firmware RAID filter while in use %u times.", f->use_count);
dm_free(f);
}
struct dev_filter *fwraid_filter_create(struct dev_types *dt __attribute__((unused)))
{
struct dev_filter *f;
if (!(f = dm_zalloc(sizeof(*f)))) {
log_error("Firmware RAID filter allocation failed");
return NULL;
}
f->passes_filter = _ignore_fwraid;
f->destroy = _destroy;
f->use_count = 0;
f->private = NULL;
log_debug_devs("Firmware RAID filter initialised.");
return f;
}
#else
struct dev_filter *fwraid_filter_create(struct dev_types *dt __attribute__((unused)))
{
return NULL;
}
#endif

View File

@@ -29,7 +29,8 @@ static int _ignore_md(struct dev_filter *f __attribute__((unused)),
ret = dev_is_md(dev, NULL);
if (ret == 1) {
log_debug_devs("%s: Skipping md component device", dev_name(dev));
log_debug_devs("%s: Skipping md component device [%s:%p]",
dev_name(dev), dev_ext_name(dev), dev->ext.handle);
return 0;
}

View File

@@ -15,6 +15,10 @@
#include "lib.h"
#include "filter.h"
#include "activate.h"
#ifdef UDEV_SYNC_SUPPORT
#include <libudev.h>
#include "dev-ext-udev-constants.h"
#endif
#ifdef __linux__
@@ -141,7 +145,33 @@ static int _get_parent_mpath(const char *dir, char *name, int max_size)
return r;
}
static int _dev_is_mpath(struct dev_filter *f, struct device *dev)
#ifdef UDEV_SYNC_SUPPORT
static int _udev_dev_is_mpath(struct device *dev)
{
const char *value;
struct dev_ext *ext;
if (!(ext = dev_ext_get(dev)))
return_0;
value = udev_device_get_property_value((struct udev_device *)ext->handle, DEV_EXT_UDEV_BLKID_TYPE);
if (value && !strcmp(value, DEV_EXT_UDEV_BLKID_TYPE_MPATH))
return 1;
value = udev_device_get_property_value((struct udev_device *)ext->handle, DEV_EXT_UDEV_MPATH_DEVICE_PATH);
if (value && !strcmp(value, "1"))
return 1;
return 0;
}
#else
static int _udev_dev_is_mpath(struct device *dev)
{
return 0;
}
#endif
static int _native_dev_is_mpath(struct dev_filter *f, struct device *dev)
{
struct dev_types *dt = (struct dev_types *) f->private;
const char *part_name, *name;
@@ -200,10 +230,25 @@ static int _dev_is_mpath(struct dev_filter *f, struct device *dev)
return lvm_dm_prefix_check(major, minor, MPATH_PREFIX);
}
static int _dev_is_mpath(struct dev_filter *f, struct device *dev)
{
if (dev->ext.src == DEV_EXT_NONE)
return _native_dev_is_mpath(f, dev);
if (dev->ext.src == DEV_EXT_UDEV)
return _udev_dev_is_mpath(dev);
log_error(INTERNAL_ERROR "Missing hook for mpath recognition "
"using external device info source %s", dev_ext_name(dev));
return 0;
}
static int _ignore_mpath(struct dev_filter *f, struct device *dev)
{
if (_dev_is_mpath(f, dev) == 1) {
log_debug_devs("%s: Skipping mpath component device", dev_name(dev));
log_debug_devs("%s: Skipping mpath component device [%s:%p]",
dev_name(dev), dev_ext_name(dev), dev->ext.handle);
return 0;
}

View File

@@ -19,40 +19,14 @@
static int _passes_partitioned_filter(struct dev_filter *f, struct device *dev)
{
struct dev_types *dt = (struct dev_types *) f->private;
const char *name = dev_name(dev);
int ret = 0;
uint64_t size;
/* Check it's accessible */
if (!dev_open_readonly_quiet(dev)) {
log_debug_devs("%s: Skipping: open failed", name);
if (dev_is_partitioned(dt, dev)) {
log_debug_devs("%s: Skipping: Partition table signature found [%s:%p]",
dev_name(dev), dev_ext_name(dev), dev->ext.handle);
return 0;
}
/* Check it's not too small */
if (!dev_get_size(dev, &size)) {
log_debug_devs("%s: Skipping: dev_get_size failed", name);
goto out;
}
if (size < pv_min_size()) {
log_debug_devs("%s: Skipping: Too small to hold a PV", name);
goto out;
}
if (dev_is_partitioned(dt, dev)) {
log_debug_devs("%s: Skipping: Partition table signature found",
name);
goto out;
}
ret = 1;
out:
if (!dev_close(dev))
stack;
return ret;
return 1;
}
static void _partitioned_filter_destroy(struct dev_filter *f)

View File

@@ -17,13 +17,12 @@
#include "filter.h"
#include "config.h"
#include "lvm-file.h"
#include "activate.h"
struct pfilter {
char *file;
struct dm_hash_table *devices;
struct dev_filter *real;
time_t ctime;
struct timespec ctime;
struct dev_types *dt;
};
@@ -107,7 +106,7 @@ int persistent_filter_load(struct dev_filter *f, struct dm_config_tree **cft_out
}
if (!stat(pf->file, &info))
pf->ctime = info.st_ctime;
lvm_stat_ctim(&pf->ctime, &info);
else {
log_very_verbose("%s: stat failed: %s", pf->file,
strerror(errno));
@@ -178,6 +177,7 @@ static int _persistent_filter_dump(struct dev_filter *f, int merge_existing)
struct pfilter *pf;
char *tmp_file;
struct stat info, info2;
struct timespec ts;
struct dm_config_tree *cft = NULL;
FILE *fp;
int lockfd;
@@ -228,7 +228,8 @@ static int _persistent_filter_dump(struct dev_filter *f, int merge_existing)
/*
* If file contents changed since we loaded it, merge new contents
*/
if (merge_existing && info.st_ctime != pf->ctime)
lvm_stat_ctim(&ts, &info);
if (merge_existing && timespeccmp(&ts, &pf->ctime, !=))
/* Keep cft open to avoid losing lock */
persistent_filter_load(f, &cft);
@@ -353,7 +354,7 @@ struct dev_filter *persistent_filter_create(struct dev_types *dt,
/* Only merge cache file before dumping it if it changed externally. */
if (!stat(pf->file, &info))
pf->ctime = info.st_ctime;
lvm_stat_ctim(&pf->ctime, &info);
f->passes_filter = _lookup_p;
f->destroy = _persistent_destroy;

View File

@@ -15,6 +15,101 @@
#include "lib.h"
#include "filter.h"
#include "activate.h" /* device_is_usable */
#ifdef UDEV_SYNC_SUPPORT
#include <libudev.h>
#include "dev-ext-udev-constants.h"
#endif
static const char *_too_small_to_hold_pv_msg = "Too small to hold a PV";
static int _native_check_pv_min_size(struct device *dev)
{
uint64_t size;
int ret = 0;
/* Check it's accessible */
if (!dev_open_readonly_quiet(dev)) {
log_debug_devs("%s: Skipping: open failed [%s:%p]",
dev_name(dev), dev_ext_name(dev), dev->ext.handle);
return 0;
}
/* Check it's not too small */
if (!dev_get_size(dev, &size)) {
log_debug_devs("%s: Skipping: dev_get_size failed [%s:%p]",
dev_name(dev), dev_ext_name(dev), dev->ext.handle);
goto out;
}
if (size < pv_min_size()) {
log_debug_devs("%s: Skipping: %s [%s:%p]", dev_name(dev),
_too_small_to_hold_pv_msg,
dev_ext_name(dev), dev->ext.handle);
goto out;
}
ret = 1;
out:
if (!dev_close(dev))
stack;
return ret;
}
#ifdef UDEV_SYNC_SUPPORT
static int _udev_check_pv_min_size(struct device *dev)
{
struct dev_ext *ext;
const char *size_str;
char *endp;
uint64_t size;
if (!(ext = dev_ext_get(dev)))
return_0;
if (!(size_str = udev_device_get_sysattr_value((struct udev_device *)ext->handle, DEV_EXT_UDEV_SYSFS_ATTR_SIZE))) {
log_debug_devs("%s: Skipping: failed to get size from sysfs [%s:%p]",
dev_name(dev), dev_ext_name(dev), dev->ext.handle);
return 0;
}
errno = 0;
size = strtoull(size_str, &endp, 10);
if (errno || !endp || *endp) {
log_debug_devs("%s: Skipping: failed to parse size from sysfs [%s:%p]",
dev_name(dev), dev_ext_name(dev), dev->ext.handle);
return 0;
}
if (size < pv_min_size()) {
log_debug_devs("%s: Skipping: %s [%s:%p]", dev_name(dev),
_too_small_to_hold_pv_msg,
dev_ext_name(dev), dev->ext.handle);
return 0;
}
return 1;
}
#else
static int _udev_check_pv_min_size(struct device *dev)
{
return 1;
}
#endif
static int _check_pv_min_size(struct device *dev)
{
if (dev->ext.src == DEV_EXT_NONE)
return _native_check_pv_min_size(dev);
if (dev->ext.src == DEV_EXT_UDEV)
return _udev_check_pv_min_size(dev);
log_error(INTERNAL_ERROR "Missing hook for PV min size check "
"using external device info source %s", dev_ext_name(dev));
return 0;
}
static int _passes_usable_filter(struct dev_filter *f, struct device *dev)
{
@@ -22,7 +117,20 @@ static int _passes_usable_filter(struct dev_filter *f, struct device *dev)
struct dev_usable_check_params ucp = {0};
int r;
/* filter only device-mapper devices */
/* check if the device is not too small to hold a PV */
switch (mode) {
case FILTER_MODE_NO_LVMETAD:
/* fall through */
case FILTER_MODE_PRE_LVMETAD:
if (!_check_pv_min_size(dev))
return 0;
break;
case FILTER_MODE_POST_LVMETAD:
/* nothing to do here */
break;
}
/* further checks are done on dm devices only */
if (!dm_is_dm_major(MAJOR(dev->dev)))
return 1;
@@ -86,6 +194,7 @@ struct dev_filter *usable_filter_create(struct dev_types *dt __attribute__((unus
f->use_count = 0;
if (!(f->private = dm_zalloc(sizeof(filter_mode_t)))) {
log_error("Usable device filter mode allocation failed");
dm_free(f);
return NULL;
}
*((filter_mode_t *) f->private) = mode;

View File

@@ -20,9 +20,11 @@
#include "dev-cache.h"
#include "dev-type.h"
struct dev_filter *composite_filter_create(int n, struct dev_filter **filters);
struct dev_filter *composite_filter_create(int n, int use_dev_ext_info, struct dev_filter **filters);
struct dev_filter *lvm_type_filter_create(struct dev_types *dt);
struct dev_filter *md_filter_create(struct dev_types *dt);
struct dev_filter *fwraid_filter_create(struct dev_types *dt);
struct dev_filter *mpath_filter_create(struct dev_types *dt);
struct dev_filter *partitioned_filter_create(struct dev_types *dt);
struct dev_filter *persistent_filter_create(struct dev_types *dt,

View File

@@ -245,4 +245,6 @@ int get_free_vg_number(struct format_instance *fid, struct dev_filter *filter,
int export_vg_number(struct format_instance *fid, struct dm_list *pvds,
const char *vg_name, struct dev_filter *filter);
int generate_lvm1_system_id(struct cmd_context *cmd, char *s, const char *prefix);
#endif

View File

@@ -180,6 +180,8 @@ out:
static struct volume_group *_format1_vg_read(struct format_instance *fid,
const char *vg_name,
struct metadata_area *mda __attribute__((unused)),
struct cached_vg_fmtdata **vg_fmtdata __attribute__((unused)),
unsigned *use_previous_vg __attribute__((unused)),
int single_device __attribute__((unused)))
{
struct volume_group *vg;
@@ -496,6 +498,11 @@ static int _format1_vg_setup(struct format_instance *fid, struct volume_group *v
if (!vg_check_new_extent_size(vg->fid->fmt, vg->extent_size))
return_0;
/* Generate lvm1_system_id if not yet set */
if (!*vg->lvm1_system_id &&
!generate_lvm1_system_id(vg->cmd, vg->lvm1_system_id, ""))
return_0;
return 1;
}
@@ -590,7 +597,8 @@ struct format_type *init_format(struct cmd_context *cmd)
fmt->alias = NULL;
fmt->orphan_vg_name = FMT_LVM1_ORPHAN_VG_NAME;
fmt->features = FMT_RESTRICTED_LVIDS | FMT_ORPHAN_ALLOCATABLE |
FMT_RESTRICTED_READAHEAD | FMT_OBSOLETE;
FMT_RESTRICTED_READAHEAD | FMT_OBSOLETE |
FMT_SYSTEMID_ON_PVS;
fmt->private = NULL;
dm_list_init(&fmt->mda_ops);

View File

@@ -69,14 +69,14 @@ int import_pv(const struct format_type *fmt, struct dm_pool *mem,
memcpy(&pv->vgid, vgd->vg_uuid, sizeof(vg->id));
/* Store system_id from first PV if PV belongs to a VG */
if (vg && !*vg->system_id)
strncpy(vg->system_id, (char *)pvd->system_id, NAME_LEN);
if (vg && !*vg->lvm1_system_id)
strncpy(vg->lvm1_system_id, (char *)pvd->system_id, NAME_LEN);
if (vg &&
strncmp(vg->system_id, (char *)pvd->system_id, sizeof(pvd->system_id)))
strncmp(vg->lvm1_system_id, (char *)pvd->system_id, sizeof(pvd->system_id)))
log_very_verbose("System ID %s on %s differs from %s for "
"volume group", pvd->system_id,
pv_dev_name(pv), vg->system_id);
pv_dev_name(pv), vg->lvm1_system_id);
/*
* If exported, we still need to flag in pv->status too because
@@ -125,12 +125,12 @@ int import_pv(const struct format_type *fmt, struct dm_pool *mem,
return 1;
}
static int _system_id(struct cmd_context *cmd, char *s, const char *prefix)
int generate_lvm1_system_id(struct cmd_context *cmd, char *s, const char *prefix)
{
if (dm_snprintf(s, NAME_LEN, "%s%s%lu",
prefix, cmd->hostname, time(NULL)) < 0) {
log_error("Generated system_id too long");
log_error("Generated LVM1 format system_id too long");
return 0;
}
@@ -156,16 +156,18 @@ int export_pv(struct cmd_context *cmd, struct dm_pool *mem __attribute__((unused
}
/* Preserve existing system_id if it exists */
if (vg && *vg->system_id)
if (vg && vg->lvm1_system_id && *vg->lvm1_system_id)
strncpy((char *)pvd->system_id, vg->lvm1_system_id, sizeof(pvd->system_id));
else if (vg && vg->system_id && *vg->system_id)
strncpy((char *)pvd->system_id, vg->system_id, sizeof(pvd->system_id));
/* Is VG already exported or being exported? */
if (vg && vg_is_exported(vg)) {
/* Does system_id need setting? */
if (!*vg->system_id ||
strncmp(vg->system_id, EXPORTED_TAG,
if (!*vg->lvm1_system_id ||
strncmp(vg->lvm1_system_id, EXPORTED_TAG,
sizeof(EXPORTED_TAG) - 1)) {
if (!_system_id(cmd, (char *)pvd->system_id, EXPORTED_TAG))
if (!generate_lvm1_system_id(cmd, (char *)pvd->system_id, EXPORTED_TAG))
return_0;
}
if (strlen((char *)pvd->vg_name) + sizeof(EXPORTED_TAG) >
@@ -178,22 +180,22 @@ int export_pv(struct cmd_context *cmd, struct dm_pool *mem __attribute__((unused
}
/* Is VG being imported? */
if (vg && !vg_is_exported(vg) && *vg->system_id &&
!strncmp(vg->system_id, EXPORTED_TAG, sizeof(EXPORTED_TAG) - 1)) {
if (!_system_id(cmd, (char *)pvd->system_id, IMPORTED_TAG))
if (vg && !vg_is_exported(vg) && *vg->lvm1_system_id &&
!strncmp(vg->lvm1_system_id, EXPORTED_TAG, sizeof(EXPORTED_TAG) - 1)) {
if (!generate_lvm1_system_id(cmd, (char *)pvd->system_id, IMPORTED_TAG))
return_0;
}
/* Generate system_id if PV is in VG */
if (!pvd->system_id[0])
if (!_system_id(cmd, (char *)pvd->system_id, ""))
if (!generate_lvm1_system_id(cmd, (char *)pvd->system_id, ""))
return_0;
/* Update internal system_id if we changed it */
if (vg &&
(!*vg->system_id ||
strncmp(vg->system_id, (char *)pvd->system_id, sizeof(pvd->system_id))))
strncpy(vg->system_id, (char *)pvd->system_id, NAME_LEN);
(!*vg->lvm1_system_id ||
strncmp(vg->lvm1_system_id, (char *)pvd->system_id, sizeof(pvd->system_id))))
strncpy(vg->lvm1_system_id, (char *)pvd->system_id, NAME_LEN);
//pvd->pv_major = MAJOR(pv->dev);
@@ -225,11 +227,9 @@ int import_vg(struct dm_pool *mem,
if (!(vg->name = dm_pool_strdup(mem, (char *)dl->pvd.vg_name)))
return_0;
if (!(vg->system_id = dm_pool_zalloc(mem, NAME_LEN + 1)))
if (!(vg->lvm1_system_id = dm_pool_zalloc(mem, NAME_LEN + 1)))
return_0;
*vg->system_id = '\0';
if (vgd->vg_status & VG_EXPORTED)
vg->status |= EXPORTED_VG;

View File

@@ -101,6 +101,8 @@ static int _check_usp(const char *vgname, struct user_subpool *usp, int sp_count
static struct volume_group *_pool_vg_read(struct format_instance *fid,
const char *vg_name,
struct metadata_area *mda __attribute__((unused)),
struct cached_vg_fmtdata **vg_fmtdata __attribute__((unused)),
unsigned *use_previous_vg __attribute__((unused)),
int single_device __attribute__((unused)))
{
struct volume_group *vg;

View File

@@ -308,7 +308,7 @@ struct volume_group *backup_read_vg(struct cmd_context *cmd,
}
dm_list_iterate_items(mda, &tf->metadata_areas_in_use) {
if (!(vg = mda->ops->vg_read(tf, vg_name, mda, 0)))
if (!(vg = mda->ops->vg_read(tf, vg_name, mda, NULL, NULL, 0)))
stack;
break;
}

View File

@@ -21,6 +21,7 @@
#include "segtype.h"
#include "text_export.h"
#include "lvm-version.h"
#include "toolcontext.h"
#include <stdarg.h>
#include <time.h>
@@ -327,7 +328,7 @@ int out_config_node(struct formatter *f, const struct dm_config_node *cn)
return dm_config_write_node(cn, _out_line, f);
}
static int _print_header(struct formatter *f,
static int _print_header(struct cmd_context *cmd, struct formatter *f,
const char *desc)
{
char *buf;
@@ -350,6 +351,8 @@ static int _print_header(struct formatter *f,
outf(f, "creation_host = \"%s\"\t# %s %s %s %s %s", _utsname.nodename,
_utsname.sysname, _utsname.nodename, _utsname.release,
_utsname.version, _utsname.machine);
if (cmd->system_id && *cmd->system_id)
outf(f, "creation_host_system_id = \"%s\"", cmd->system_id);
outf(f, "creation_time = %lu\t# %s", t, ctime(&t));
return 1;
@@ -390,6 +393,8 @@ static int _out_tags(struct formatter *f, struct dm_list *tagsl)
static int _print_vg(struct formatter *f, struct volume_group *vg)
{
char buffer[4096];
const struct format_type *fmt = NULL;
uint64_t status = vg->status;
if (!id_write_format(&vg->id, buffer, sizeof(buffer)))
return_0;
@@ -398,17 +403,35 @@ static int _print_vg(struct formatter *f, struct volume_group *vg)
outf(f, "seqno = %u", vg->seqno);
if (vg->fid && vg->fid->fmt)
outfc(f, "# informational", "format = \"%s\"", vg->fid->fmt->name);
if (vg->original_fmt)
fmt = vg->original_fmt;
else if (vg->fid)
fmt = vg->fid->fmt;
if (fmt)
outfc(f, "# informational", "format = \"%s\"", fmt->name);
if (!_print_flag_config(f, vg->status, VG_FLAGS))
/*
* Removing WRITE and adding LVM_WRITE_LOCKED makes it read-only
* to old versions of lvm that only look for LVM_WRITE.
*/
if ((status & LVM_WRITE) && vg_flag_write_locked(vg)) {
status &= ~LVM_WRITE;
status |= LVM_WRITE_LOCKED;
}
if (!_print_flag_config(f, status, VG_FLAGS))
return_0;
if (!_out_tags(f, &vg->tags))
return_0;
if (vg->system_id && *vg->system_id)
outf(f, "system_id = \"%s\"", vg->system_id);
else if (vg->lvm1_system_id && *vg->lvm1_system_id)
outf(f, "system_id = \"%s\"", vg->lvm1_system_id);
if (vg->lock_type)
outf(f, "lock_type = \"%s\"", vg->lock_type);
outsize(f, (uint64_t) vg->extent_size, "extent_size = %u",
vg->extent_size);
@@ -594,6 +617,7 @@ static int _print_lv(struct formatter *f, struct logical_volume *lv)
int seg_count;
struct tm *local_tm;
time_t ts;
uint64_t status = lv->status;
outnl(f);
outf(f, "%s {", lv->name);
@@ -605,7 +629,16 @@ static int _print_lv(struct formatter *f, struct logical_volume *lv)
outf(f, "id = \"%s\"", buffer);
if (!_print_flag_config(f, lv->status, LV_FLAGS))
/*
* Removing WRITE and adding LVM_WRITE_LOCKED makes it read-only
* to old versions of lvm that only look for LVM_WRITE.
*/
if ((status & LVM_WRITE) && vg_flag_write_locked(lv->vg)) {
status &= ~LVM_WRITE;
status |= LVM_WRITE_LOCKED;
}
if (!_print_flag_config(f, status, LV_FLAGS))
return_0;
if (!_out_tags(f, &lv->tags))
@@ -744,7 +777,7 @@ static int _text_vg_export(struct formatter *f,
if (!_build_pv_names(f, vg))
goto_out;
if (f->header && !_print_header(f, desc))
if (f->header && !_print_header(vg->cmd, f, desc))
goto_out;
if (!out_text(f, "%s {", vg->name))
@@ -767,7 +800,7 @@ static int _text_vg_export(struct formatter *f,
if (!out_text(f, "}"))
goto_out;
if (!f->header && !_print_header(f, desc))
if (!f->header && !_print_header(vg->cmd, f, desc))
goto_out;
r = 1;

View File

@@ -34,6 +34,7 @@ static const struct flag _vg_flags[] = {
{PVMOVE, "PVMOVE", STATUS_FLAG},
{LVM_READ, "READ", STATUS_FLAG},
{LVM_WRITE, "WRITE", STATUS_FLAG},
{LVM_WRITE_LOCKED, "WRITE_LOCKED", COMPATIBLE_FLAG},
{CLUSTERED, "CLUSTERED", STATUS_FLAG},
{SHARED, "SHARED", STATUS_FLAG},
{PARTIAL_VG, NULL, 0},
@@ -53,6 +54,7 @@ static const struct flag _pv_flags[] = {
static const struct flag _lv_flags[] = {
{LVM_READ, "READ", STATUS_FLAG},
{LVM_WRITE, "WRITE", STATUS_FLAG},
{LVM_WRITE_LOCKED, "WRITE_LOCKED", COMPATIBLE_FLAG},
{FIXED_MINOR, "FIXED_MINOR", STATUS_FLAG},
{VISIBLE_LV, "VISIBLE", STATUS_FLAG},
{PVMOVE, "PVMOVE", STATUS_FLAG},
@@ -61,6 +63,7 @@ static const struct flag _lv_flags[] = {
{LV_REBUILD, "REBUILD", STATUS_FLAG},
{LV_WRITEMOSTLY, "WRITEMOSTLY", STATUS_FLAG},
{LV_ACTIVATION_SKIP, "ACTIVATION_SKIP", COMPATIBLE_FLAG},
{LV_ERROR_WHEN_FULL, "ERROR_WHEN_FULL", COMPATIBLE_FLAG},
{LV_NOSCAN, NULL, 0},
{LV_TEMPORARY, NULL, 0},
{POOL_METADATA_SPARE, NULL, 0},
@@ -89,6 +92,7 @@ static const struct flag _lv_flags[] = {
{CACHE_POOL_DATA, NULL, 0},
{CACHE_POOL_METADATA, NULL, 0},
{LV_PENDING_DELETE, NULL, 0}, /* FIXME Display like COMPATIBLE_FLAG */
{LV_REMOVED, NULL, 0},
{0, NULL, 0}
};

View File

@@ -412,6 +412,11 @@ static struct raw_locn *_find_vg_rlocn(struct device_area *dev_area,
char vgnamebuf[NAME_LEN + 2] __attribute__((aligned(8)));
struct raw_locn *rlocn, *rlocn_precommitted;
struct lvmcache_info *info;
struct lvmcache_vgsummary vgsummary_orphan = {
.vgname = FMT_TEXT_ORPHAN_VG_NAME,
};
memcpy(&vgsummary_orphan.vgid, FMT_TEXT_ORPHAN_VG_NAME, sizeof(FMT_TEXT_ORPHAN_VG_NAME));
rlocn = mdah->raw_locns; /* Slot 0 */
rlocn_precommitted = rlocn + 1; /* Slot 1 */
@@ -449,8 +454,7 @@ static struct raw_locn *_find_vg_rlocn(struct device_area *dev_area,
bad:
if ((info = lvmcache_info_from_pvid(dev_area->dev->pvid, 0)))
lvmcache_update_vgname_and_id(info, FMT_TEXT_ORPHAN_VG_NAME,
FMT_TEXT_ORPHAN_VG_NAME, 0, NULL);
lvmcache_update_vgname_and_id(info, &vgsummary_orphan);
return NULL;
}
@@ -498,6 +502,8 @@ static int _raw_holds_vgname(struct format_instance *fid,
static struct volume_group *_vg_read_raw_area(struct format_instance *fid,
const char *vgname,
struct device_area *area,
struct cached_vg_fmtdata **vg_fmtdata,
unsigned *use_previous_vg,
int precommitted,
int single_device)
{
@@ -526,19 +532,26 @@ static struct volume_group *_vg_read_raw_area(struct format_instance *fid,
}
/* FIXME 64-bit */
if (!(vg = text_vg_import_fd(fid, NULL, single_device, area->dev,
if (!(vg = text_vg_import_fd(fid, NULL, vg_fmtdata, use_previous_vg, single_device, area->dev,
(off_t) (area->start + rlocn->offset),
(uint32_t) (rlocn->size - wrap),
(off_t) (area->start + MDA_HEADER_SIZE),
wrap, calc_crc, rlocn->checksum, &when,
&desc)))
&desc)) && (!use_previous_vg || !*use_previous_vg))
goto_out;
log_debug_metadata("Read %s %smetadata (%u) from %s at %" PRIu64 " size %"
PRIu64, vg->name, precommitted ? "pre-commit " : "",
vg->seqno, dev_name(area->dev),
area->start + rlocn->offset, rlocn->size);
if (precommitted)
if (vg)
log_debug_metadata("Read %s %smetadata (%u) from %s at %" PRIu64 " size %"
PRIu64, vg->name, precommitted ? "pre-commit " : "",
vg->seqno, dev_name(area->dev),
area->start + rlocn->offset, rlocn->size);
else
log_debug_metadata("Skipped reading %smetadata from %s at %" PRIu64 " size %"
PRIu64 " with matching checksum.", precommitted ? "pre-commit " : "",
dev_name(area->dev),
area->start + rlocn->offset, rlocn->size);
if (vg && precommitted)
vg->status |= PRECOMMITTED;
out:
@@ -548,6 +561,8 @@ static struct volume_group *_vg_read_raw_area(struct format_instance *fid,
static struct volume_group *_vg_read_raw(struct format_instance *fid,
const char *vgname,
struct metadata_area *mda,
struct cached_vg_fmtdata **vg_fmtdata,
unsigned *use_previous_vg,
int single_device)
{
struct mda_context *mdac = (struct mda_context *) mda->metadata_locn;
@@ -556,7 +571,7 @@ static struct volume_group *_vg_read_raw(struct format_instance *fid,
if (!dev_open_readonly(mdac->area.dev))
return_NULL;
vg = _vg_read_raw_area(fid, vgname, &mdac->area, 0, single_device);
vg = _vg_read_raw_area(fid, vgname, &mdac->area, vg_fmtdata, use_previous_vg, 0, single_device);
if (!dev_close(mdac->area.dev))
stack;
@@ -566,7 +581,9 @@ static struct volume_group *_vg_read_raw(struct format_instance *fid,
static struct volume_group *_vg_read_precommit_raw(struct format_instance *fid,
const char *vgname,
struct metadata_area *mda)
struct metadata_area *mda,
struct cached_vg_fmtdata **vg_fmtdata,
unsigned *use_previous_vg)
{
struct mda_context *mdac = (struct mda_context *) mda->metadata_locn;
struct volume_group *vg;
@@ -574,7 +591,7 @@ static struct volume_group *_vg_read_precommit_raw(struct format_instance *fid,
if (!dev_open_readonly(mdac->area.dev))
return_NULL;
vg = _vg_read_raw_area(fid, vgname, &mdac->area, 1, 0);
vg = _vg_read_raw_area(fid, vgname, &mdac->area, vg_fmtdata, use_previous_vg, 1, 0);
if (!dev_close(mdac->area.dev))
stack;
@@ -885,6 +902,8 @@ static struct volume_group *_vg_read_file_name(struct format_instance *fid,
static struct volume_group *_vg_read_file(struct format_instance *fid,
const char *vgname,
struct metadata_area *mda,
struct cached_vg_fmtdata **vg_fmtdata,
unsigned *use_previous_vg __attribute__((unused)),
int single_device __attribute__((unused)))
{
struct text_context *tc = (struct text_context *) mda->metadata_locn;
@@ -894,7 +913,9 @@ static struct volume_group *_vg_read_file(struct format_instance *fid,
static struct volume_group *_vg_read_precommit_file(struct format_instance *fid,
const char *vgname,
struct metadata_area *mda)
struct metadata_area *mda,
struct cached_vg_fmtdata **vg_fmtdata,
unsigned *use_previous_vg __attribute__((unused)))
{
struct text_context *tc = (struct text_context *) mda->metadata_locn;
struct volume_group *vg;
@@ -1123,26 +1144,24 @@ static int _scan_file(const struct format_type *fmt, const char *vgname)
return 1;
}
const char *vgname_from_mda(const struct format_type *fmt,
struct mda_header *mdah,
struct device_area *dev_area, struct id *vgid,
uint64_t *vgstatus, char **creation_host,
uint64_t *mda_free_sectors)
int vgname_from_mda(const struct format_type *fmt,
struct mda_header *mdah, struct device_area *dev_area,
struct lvmcache_vgsummary *vgsummary, uint64_t *mda_free_sectors)
{
struct raw_locn *rlocn;
uint32_t wrap = 0;
const char *vgname = NULL;
unsigned int len = 0;
char buf[NAME_LEN + 1] __attribute__((aligned(8)));
char uuid[64] __attribute__((aligned(8)));
uint64_t buffer_size, current_usage;
unsigned used_cached_metadata = 0;
if (mda_free_sectors)
*mda_free_sectors = ((dev_area->size - MDA_HEADER_SIZE) / 2) >> SECTOR_SHIFT;
if (!mdah) {
log_error(INTERNAL_ERROR "vgname_from_mda called with NULL pointer for mda_header");
goto_out;
return 0;
}
/* FIXME Cope with returning a list */
@@ -1151,13 +1170,16 @@ const char *vgname_from_mda(const struct format_type *fmt,
/*
* If no valid offset, do not try to search for vgname
*/
if (!rlocn->offset)
goto out;
if (!rlocn->offset) {
log_debug("%s: found metadata with offset 0.",
dev_name(dev_area->dev));
return 0;
}
/* Do quick check for a vgname */
if (!dev_read(dev_area->dev, dev_area->start + rlocn->offset,
NAME_LEN, buf))
goto_out;
return_0;
while (buf[len] && !isspace(buf[len]) && buf[len] != '{' &&
len < (NAME_LEN - 1))
@@ -1167,7 +1189,7 @@ const char *vgname_from_mda(const struct format_type *fmt,
/* Ignore this entry if the characters aren't permissible */
if (!validate_name(buf))
goto_out;
return_0;
/* We found a VG - now check the metadata */
if (rlocn->offset + rlocn->size > mdah->size)
@@ -1176,36 +1198,39 @@ const char *vgname_from_mda(const struct format_type *fmt,
if (wrap > rlocn->offset) {
log_error("%s: metadata too large for circular buffer",
dev_name(dev_area->dev));
goto out;
return 0;
}
/* Did we see this metadata before? */
vgsummary->mda_checksum = rlocn->checksum;
vgsummary->mda_size = rlocn->size;
if (lvmcache_lookup_mda(vgsummary))
used_cached_metadata = 1;
/* FIXME 64-bit */
if (!(vgname = text_vgname_import(fmt, dev_area->dev,
(off_t) (dev_area->start +
rlocn->offset),
(uint32_t) (rlocn->size - wrap),
(off_t) (dev_area->start +
MDA_HEADER_SIZE),
wrap, calc_crc, rlocn->checksum,
vgid, vgstatus, creation_host)))
goto_out;
if (!text_vgname_import(fmt, dev_area->dev,
(off_t) (dev_area->start + rlocn->offset),
(uint32_t) (rlocn->size - wrap),
(off_t) (dev_area->start + MDA_HEADER_SIZE),
wrap, calc_crc, vgsummary->vgname ? 1 : 0,
vgsummary))
return_0;
/* Ignore this entry if the characters aren't permissible */
if (!validate_name(vgname)) {
vgname = NULL;
goto_out;
}
if (!validate_name(vgsummary->vgname))
return_0;
if (!id_write_format(vgid, uuid, sizeof(uuid))) {
vgname = NULL;
goto_out;
}
if (!id_write_format((struct id *)&vgsummary->vgid, uuid, sizeof(uuid)))
return_0;
log_debug_metadata("%s: Found metadata at %" PRIu64 " size %" PRIu64
log_debug_metadata("%s: %s metadata at %" PRIu64 " size %" PRIu64
" (in area at %" PRIu64 " size %" PRIu64
") for %s (%s)",
dev_name(dev_area->dev), dev_area->start + rlocn->offset,
rlocn->size, dev_area->start, dev_area->size, vgname, uuid);
dev_name(dev_area->dev),
used_cached_metadata ? "Using cached" : "Found",
dev_area->start + rlocn->offset,
rlocn->size, dev_area->start, dev_area->size, vgsummary->vgname, uuid);
if (mda_free_sectors) {
current_usage = (rlocn->size + SECTOR_SIZE - UINT64_C(1)) -
@@ -1218,19 +1243,16 @@ const char *vgname_from_mda(const struct format_type *fmt,
*mda_free_sectors = ((buffer_size - 2 * current_usage) / 2) >> SECTOR_SHIFT;
}
out:
return vgname;
return 1;
}
static int _scan_raw(const struct format_type *fmt, const char *vgname __attribute__((unused)))
{
struct raw_list *rl;
struct dm_list *raw_list;
const char *scanned_vgname;
struct volume_group *vg;
struct format_instance fid;
struct id vgid;
uint64_t vgstatus;
struct lvmcache_vgsummary vgsummary = { 0 };
struct mda_header *mdah;
raw_list = &((struct mda_lists *) fmt->private)->raws;
@@ -1251,13 +1273,11 @@ static int _scan_raw(const struct format_type *fmt, const char *vgname __attribu
goto close_dev;
}
if ((scanned_vgname = vgname_from_mda(fmt, mdah,
&rl->dev_area, &vgid, &vgstatus,
NULL, NULL))) {
vg = _vg_read_raw_area(&fid, scanned_vgname, &rl->dev_area, 0, 0);
/* TODO: caching as in vgname_from_mda() (trigger this code?) */
if (vgname_from_mda(fmt, mdah, &rl->dev_area, &vgsummary, NULL)) {
vg = _vg_read_raw_area(&fid, vgsummary.vgname, &rl->dev_area, NULL, NULL, 0, 0);
if (vg)
lvmcache_update_vg(vg, 0);
}
close_dev:
if (!dev_close(rl->dev_area.dev))
@@ -1298,7 +1318,7 @@ static int _write_single_mda(struct metadata_area *mda, void *baton)
return 1;
}
/* Only for orphans */
/* Only for orphans - FIXME That's not true any more */
static int _text_pv_write(const struct format_type *fmt, struct physical_volume *pv)
{
struct format_instance *fid = pv->fid;
@@ -1312,7 +1332,8 @@ static int _text_pv_write(const struct format_type *fmt, struct physical_volume
/* Add a new cache entry with PV info or update existing one. */
if (!(info = lvmcache_add(fmt->labeller, (const char *) &pv->id,
pv->dev, pv->vg_name, NULL, 0)))
pv->dev, pv->vg_name,
is_orphan_vg(pv->vg_name) ? pv->vg_name : pv->vg ? (const char *) &pv->vg->id : NULL, 0)))
return_0;
label = lvmcache_get_label(info);

View File

@@ -18,6 +18,7 @@
#include "config.h"
#include "metadata.h"
#include "lvmcache.h"
#include <stdio.h>
@@ -49,10 +50,9 @@ struct text_vg_version_ops {
unsigned use_cached_pvs);
void (*read_desc) (struct dm_pool * mem, const struct dm_config_tree *cf,
time_t *when, char **desc);
const char *(*read_vgname) (const struct format_type *fmt,
const struct dm_config_tree *cft,
struct id *vgid, uint64_t *vgstatus,
char **creation_host);
int (*read_vgname) (const struct format_type *fmt,
const struct dm_config_tree *cft,
struct lvmcache_vgsummary *vgsummary);
};
struct text_vg_version_ops *text_vg_vsn1_init(void);
@@ -70,6 +70,8 @@ struct volume_group *text_vg_import_file(struct format_instance *fid,
time_t *when, char **desc);
struct volume_group *text_vg_import_fd(struct format_instance *fid,
const char *file,
struct cached_vg_fmtdata **vg_fmtdata,
unsigned *use_previous_vg,
int single_device,
struct device *dev,
off_t offset, uint32_t size,
@@ -77,12 +79,13 @@ struct volume_group *text_vg_import_fd(struct format_instance *fid,
checksum_fn_t checksum_fn,
uint32_t checksum,
time_t *when, char **desc);
const char *text_vgname_import(const struct format_type *fmt,
struct device *dev,
off_t offset, uint32_t size,
off_t offset2, uint32_t size2,
checksum_fn_t checksum_fn, uint32_t checksum,
struct id *vgid, uint64_t *vgstatus,
char **creation_host);
int text_vgname_import(const struct format_type *fmt,
struct device *dev,
off_t offset, uint32_t size,
off_t offset2, uint32_t size2,
checksum_fn_t checksum_fn,
int checksum_only,
struct lvmcache_vgsummary *vgsummary);
#endif

View File

@@ -32,30 +32,41 @@ static void _init_text_import(void)
_text_import_initialised = 1;
}
const char *text_vgname_import(const struct format_type *fmt,
struct device *dev,
off_t offset, uint32_t size,
off_t offset2, uint32_t size2,
checksum_fn_t checksum_fn, uint32_t checksum,
struct id *vgid, uint64_t *vgstatus,
char **creation_host)
/*
* Find out vgname on a given device.
*/
int text_vgname_import(const struct format_type *fmt,
struct device *dev,
off_t offset, uint32_t size,
off_t offset2, uint32_t size2,
checksum_fn_t checksum_fn,
int checksum_only,
struct lvmcache_vgsummary *vgsummary)
{
struct dm_config_tree *cft;
struct text_vg_version_ops **vsn;
const char *vgname = NULL;
int r = 0;
_init_text_import();
if (!(cft = config_open(CONFIG_FILE_SPECIAL, NULL, 0)))
return_NULL;
return_0;
if ((!dev && !config_file_read(cft)) ||
(dev && !config_file_read_fd(cft, dev, offset, size,
offset2, size2, checksum_fn, checksum))) {
offset2, size2, checksum_fn,
vgsummary->mda_checksum,
checksum_only))) {
log_error("Couldn't read volume group metadata.");
goto out;
}
if (checksum_only) {
/* Checksum matches already-cached content - no need to reparse. */
r = 1;
goto out;
}
/*
* Find a set of version functions that can read this file
*/
@@ -63,20 +74,27 @@ const char *text_vgname_import(const struct format_type *fmt,
if (!(*vsn)->check_version(cft))
continue;
if (!(vgname = (*vsn)->read_vgname(fmt, cft, vgid, vgstatus,
creation_host)))
if (!(*vsn)->read_vgname(fmt, cft, vgsummary))
goto_out;
r = 1;
break;
}
out:
config_destroy(cft);
return vgname;
return r;
}
struct cached_vg_fmtdata {
uint32_t cached_mda_checksum;
size_t cached_mda_size;
};
struct volume_group *text_vg_import_fd(struct format_instance *fid,
const char *file,
struct cached_vg_fmtdata **vg_fmtdata,
unsigned *use_previous_vg,
int single_device,
struct device *dev,
off_t offset, uint32_t size,
@@ -88,6 +106,13 @@ struct volume_group *text_vg_import_fd(struct format_instance *fid,
struct volume_group *vg = NULL;
struct dm_config_tree *cft;
struct text_vg_version_ops **vsn;
int skip_parse;
if (vg_fmtdata && !*vg_fmtdata &&
!(*vg_fmtdata = dm_pool_zalloc(fid->mem, sizeof(**vg_fmtdata)))) {
log_error("Failed to allocate VG fmtdata for text format.");
return NULL;
}
_init_text_import();
@@ -97,10 +122,22 @@ struct volume_group *text_vg_import_fd(struct format_instance *fid,
if (!(cft = config_open(CONFIG_FILE_SPECIAL, file, 0)))
return_NULL;
/* Does the metadata match the already-cached VG? */
skip_parse = vg_fmtdata &&
((*vg_fmtdata)->cached_mda_checksum == checksum) &&
((*vg_fmtdata)->cached_mda_size == (size + size2));
if ((!dev && !config_file_read(cft)) ||
(dev && !config_file_read_fd(cft, dev, offset, size,
offset2, size2, checksum_fn, checksum)))
offset2, size2, checksum_fn, checksum,
skip_parse)))
goto_out;
if (skip_parse) {
if (use_previous_vg)
*use_previous_vg = 1;
goto out;
}
/*
* Find a set of version functions that can read this file
@@ -116,6 +153,14 @@ struct volume_group *text_vg_import_fd(struct format_instance *fid,
break;
}
if (vg && vg_fmtdata && *vg_fmtdata) {
(*vg_fmtdata)->cached_mda_size = (size + size2);
(*vg_fmtdata)->cached_mda_checksum = checksum;
}
if (use_previous_vg)
*use_previous_vg = 0;
out:
config_destroy(cft);
return vg;
@@ -125,7 +170,7 @@ struct volume_group *text_vg_import_file(struct format_instance *fid,
const char *file,
time_t *when, char **desc)
{
return text_vg_import_fd(fid, file, 0, NULL, (off_t)0, 0, (off_t)0, 0, NULL, 0,
return text_vg_import_fd(fid, file, NULL, NULL, 0, NULL, (off_t)0, 0, (off_t)0, 0, NULL, 0,
when, desc);
}

View File

@@ -531,7 +531,7 @@ static int _read_lvnames(struct format_instance *fid __attribute__((unused)),
const char *str;
const struct dm_config_value *cv;
const char *hostname;
uint64_t timestamp = 0;
uint64_t timestamp = 0, lvstatus;
if (!(lv = alloc_lv(mem)))
return_0;
@@ -544,12 +544,18 @@ static int _read_lvnames(struct format_instance *fid __attribute__((unused)),
return 0;
}
if (!_read_flag_config(lvn, &lv->status, LV_FLAGS)) {
if (!_read_flag_config(lvn, &lvstatus, LV_FLAGS)) {
log_error("Couldn't read status flags for logical volume %s.",
lv->name);
return 0;
}
if (lvstatus & LVM_WRITE_LOCKED) {
lvstatus |= LVM_WRITE;
lvstatus &= ~LVM_WRITE_LOCKED;
}
lv->status = lvstatus;
if (dm_config_has_node(lvn, "creation_time")) {
if (!_read_uint64(lvn, "creation_time", &timestamp)) {
log_error("Invalid creation_time for logical volume %s.",
@@ -733,10 +739,11 @@ static struct volume_group *_read_vg(struct format_instance *fid,
{
const struct dm_config_node *vgn;
const struct dm_config_value *cv;
const char *str;
const char *str, *format_str, *system_id;
struct volume_group *vg;
struct dm_hash_table *pv_hash = NULL, *lv_hash = NULL;
unsigned scan_done_once = use_cached_pvs;
uint64_t vgstatus;
/* skip any top-level values */
for (vgn = cft->root; (vgn && vgn->v); vgn = vgn->sib)
@@ -750,9 +757,6 @@ static struct volume_group *_read_vg(struct format_instance *fid,
if (!(vg = alloc_vg("read_vg", fid->fmt->cmd, vgn->key)))
return_NULL;
if (!(vg->system_id = dm_pool_zalloc(vg->vgmem, NAME_LEN + 1)))
goto_bad;
/*
* The pv hash memorises the pv section names -> pv
* structures.
@@ -773,8 +777,16 @@ static struct volume_group *_read_vg(struct format_instance *fid,
vgn = vgn->child;
if (dm_config_get_str(vgn, "system_id", &str)) {
strncpy(vg->system_id, str, NAME_LEN);
/* A backup file might be a backup of a different format */
if (dm_config_get_str(vgn, "format", &format_str) &&
!(vg->original_fmt = get_format_by_name(fid->fmt->cmd, format_str))) {
log_error("Unrecognised format %s for volume group %s.", format_str, vg->name);
goto bad;
}
if (dm_config_get_str(vgn, "lock_type", &str)) {
if (!(vg->lock_type = dm_pool_strdup(vg->vgmem, str)))
goto bad;
}
if (!_read_id(&vg->id, vgn, "id")) {
@@ -788,12 +800,32 @@ static struct volume_group *_read_vg(struct format_instance *fid,
goto bad;
}
if (!_read_flag_config(vgn, &vg->status, VG_FLAGS)) {
if (!_read_flag_config(vgn, &vgstatus, VG_FLAGS)) {
log_error("Error reading flags of volume group %s.",
vg->name);
goto bad;
}
/*
* A system id without WRITE_LOCKED is an old lvm1 system id.
*/
if (dm_config_get_str(vgn, "system_id", &system_id)) {
if (!(vgstatus & LVM_WRITE_LOCKED)) {
if (!(vg->lvm1_system_id = dm_pool_zalloc(vg->vgmem, NAME_LEN + 1)))
goto_bad;
strncpy(vg->lvm1_system_id, system_id, NAME_LEN);
} else if (!(vg->system_id = dm_pool_strdup(vg->vgmem, system_id))) {
log_error("Failed to allocate memory for system_id in _read_vg.");
goto bad;
}
}
if (vgstatus & LVM_WRITE_LOCKED) {
vgstatus |= LVM_WRITE;
vgstatus &= ~LVM_WRITE_LOCKED;
}
vg->status = vgstatus;
if (!_read_int32(vgn, "extent_size", &vg->extent_size)) {
log_error("Couldn't read extent size for volume group %s.",
vg->name);
@@ -875,8 +907,6 @@ static struct volume_group *_read_vg(struct format_instance *fid,
dm_hash_destroy(pv_hash);
dm_hash_destroy(lv_hash);
/* FIXME Determine format type from file contents */
/* eg Set to instance of fmt1 here if reading a format1 backup? */
vg_set_fid(vg, fid);
/*
@@ -911,19 +941,16 @@ static void _read_desc(struct dm_pool *mem,
*when = u;
}
static const char *_read_vgname(const struct format_type *fmt,
const struct dm_config_tree *cft, struct id *vgid,
uint64_t *vgstatus, char **creation_host)
static int _read_vgname(const struct format_type *fmt, const struct dm_config_tree *cft,
struct lvmcache_vgsummary *vgsummary)
{
const struct dm_config_node *vgn;
struct dm_pool *mem = fmt->cmd->mem;
char *vgname;
int old_suppress;
old_suppress = log_suppress(2);
*creation_host = dm_pool_strdup(mem,
dm_config_find_str_allow_empty(cft->root,
"creation_host", ""));
vgsummary->creation_host =
dm_pool_strdup(mem, dm_config_find_str_allow_empty(cft->root, "creation_host", ""));
log_suppress(old_suppress);
/* skip any top-level values */
@@ -934,23 +961,23 @@ static const char *_read_vgname(const struct format_type *fmt,
return 0;
}
if (!(vgname = dm_pool_strdup(mem, vgn->key)))
if (!(vgsummary->vgname = dm_pool_strdup(mem, vgn->key)))
return_0;
vgn = vgn->child;
if (!_read_id(vgid, vgn, "id")) {
log_error("Couldn't read uuid for volume group %s.", vgname);
if (!_read_id(&vgsummary->vgid, vgn, "id")) {
log_error("Couldn't read uuid for volume group %s.", vgsummary->vgname);
return 0;
}
if (!_read_flag_config(vgn, vgstatus, VG_FLAGS)) {
if (!_read_flag_config(vgn, &vgsummary->vgstatus, VG_FLAGS)) {
log_error("Couldn't find status flags for volume group %s.",
vgname);
vgsummary->vgname);
return 0;
}
return vgname;
return 1;
}
static struct text_vg_version_ops _vsn1_ops = {

View File

@@ -18,6 +18,7 @@
#include "config.h"
#include "metadata.h"
#include "lvmcache.h"
#include "uuid.h"
/* disk_locn and data_area_list are defined in format-text.h */
@@ -97,11 +98,8 @@ struct mda_context {
#define LVM2_LABEL "LVM2 001"
#define MDA_SIZE_MIN (8 * (unsigned) lvm_getpagesize())
const char *vgname_from_mda(const struct format_type *fmt,
struct mda_header *mdah,
struct device_area *dev_area, struct id *vgid,
uint64_t *vgstatus, char **creation_host,
uint64_t *mda_free_sectors);
int vgname_from_mda(const struct format_type *fmt, struct mda_header *mdah,
struct device_area *dev_area, struct lvmcache_vgsummary *vgsummary,
uint64_t *mda_free_sectors);
#endif

View File

@@ -319,10 +319,14 @@ static int _update_mda(struct metadata_area *mda, void *baton)
const struct format_type *fmt = p->label->labeller->fmt;
struct mda_context *mdac = (struct mda_context *) mda->metadata_locn;
struct mda_header *mdah;
const char *vgname = NULL;
struct id vgid;
uint64_t vgstatus;
char *creation_host;
struct lvmcache_vgsummary vgsummary = { 0 };
/*
* Using the labeller struct to preserve info about
* the last parsed vgname, vgid, creation host
*
* TODO: make lvmcache smarter and move this cache logic there
*/
if (!dev_open_readonly(mdac->area.dev)) {
mda_set_ignored(mda, 1);
@@ -346,17 +350,14 @@ static int _update_mda(struct metadata_area *mda, void *baton)
return 1;
}
if ((vgname = vgname_from_mda(fmt, mdah,
&mdac->area,
&vgid, &vgstatus, &creation_host,
&mdac->free_sectors)) &&
!lvmcache_update_vgname_and_id(p->info, vgname,
(char *) &vgid, vgstatus,
creation_host)) {
if (vgname_from_mda(fmt, mdah, &mdac->area, &vgsummary,
&mdac->free_sectors) &&
!lvmcache_update_vgname_and_id(p->info, &vgsummary)) {
if (!dev_close(mdac->area.dev))
stack;
return_0;
}
close_dev:
if (!dev_close(mdac->area.dev))
stack;
@@ -465,7 +466,7 @@ struct labeller *text_labeller_create(const struct format_type *fmt)
{
struct labeller *l;
if (!(l = dm_malloc(sizeof(*l)))) {
if (!(l = dm_zalloc(sizeof(*l)))) {
log_error("Couldn't allocate labeller object.");
return NULL;
}

View File

@@ -97,6 +97,17 @@ struct labeller *label_get_handler(const char *name)
return NULL;
}
static void _update_lvmcache_orphan(struct lvmcache_info *info)
{
struct lvmcache_vgsummary vgsummary_orphan = {
.vgname = lvmcache_fmt(info)->orphan_vg_name,
};
memcpy(&vgsummary_orphan.vgid, lvmcache_fmt(info)->orphan_vg_name, strlen(lvmcache_fmt(info)->orphan_vg_name));
lvmcache_update_vgname_and_id(info, &vgsummary_orphan);
}
static struct labeller *_find_labeller(struct device *dev, char *buf,
uint64_t *label_sector,
uint64_t scan_sector)
@@ -173,9 +184,7 @@ static struct labeller *_find_labeller(struct device *dev, char *buf,
out:
if (!found) {
if ((info = lvmcache_info_from_pvid(dev->pvid, 0)))
lvmcache_update_vgname_and_id(info, lvmcache_fmt(info)->orphan_vg_name,
lvmcache_fmt(info)->orphan_vg_name,
0, NULL);
_update_lvmcache_orphan(info);
log_very_verbose("%s: No label detected", dev_name(dev));
}
@@ -271,9 +280,7 @@ int label_read(struct device *dev, struct label **result,
stack;
if ((info = lvmcache_info_from_pvid(dev->pvid, 0)))
lvmcache_update_vgname_and_id(info, lvmcache_fmt(info)->orphan_vg_name,
lvmcache_fmt(info)->orphan_vg_name,
0, NULL);
_update_lvmcache_orphan(info);
return r;
}
@@ -348,10 +355,7 @@ int label_verify(struct device *dev)
if (!dev_open_readonly(dev)) {
if ((info = lvmcache_info_from_pvid(dev->pvid, 0)))
lvmcache_update_vgname_and_id(info, lvmcache_fmt(info)->orphan_vg_name,
lvmcache_fmt(info)->orphan_vg_name,
0, NULL);
_update_lvmcache_orphan(info);
return_0;
}

View File

@@ -114,7 +114,7 @@ int check_lvm1_vg_inactive(struct cmd_context *cmd, const char *vgname);
#define LCK_DMEVENTD_MONITOR_MODE 0x04 /* Register with dmeventd */
/* Not yet used. */
#define LCK_CONVERT 0x08 /* Convert existing lock */
#define LCK_CONVERT_MODE 0x08 /* Convert existing lock */
#define LCK_TEST_MODE 0x10 /* Test mode: No activation */
#define LCK_ORIGIN_ONLY_MODE 0x20 /* Same as above */

View File

@@ -18,10 +18,13 @@
#include "memlock.h"
#include "defaults.h"
#include <stdio.h>
#include <stdarg.h>
#include <syslog.h>
#include <ctype.h>
static FILE *_log_file;
static char _log_file_path[PATH_MAX];
static struct device _log_dev;
static struct dm_str_list _log_dev_alias;
@@ -52,11 +55,58 @@ void init_log_fn(lvm2_log_fn_t log_fn)
_lvm2_log_fn = NULL;
}
/*
* Support envvar LVM_LOG_FILE_EPOCH and allow to attach
* extra keyword (consist of upto 32 alpha chars) to
* opened log file. After this 'epoch' word pid and starttime
* (in kernel units, read from /proc/self/stat)
* is automatically attached.
* If command/daemon forks multiple times, it could create multiple
* log files ensuring, there are no overwrites.
*/
void init_log_file(const char *log_file, int append)
{
const char *open_mode = append ? "a" : "w";
static const char statfile[] = "/proc/self/stat";
const char *env;
int pid;
long long starttime;
FILE *st;
int i = 0;
if (!(_log_file = fopen(log_file, open_mode))) {
_log_file_path[0] = '\0';
if ((env = getenv("LVM_LOG_FILE_EPOCH"))) {
while (isalpha(env[i]) && i < 32) /* Up to 32 alphas */
i++;
if (env[i]) {
if (i)
log_warn("WARNING: Ignoring invalid LVM_LOG_FILE_EPOCH envvar \"%s\".", env);
goto no_epoch;
}
if (!(st = fopen(statfile, "r")))
log_sys_error("fopen", statfile);
else if (fscanf(st, "%d %*s %*c %*d %*d %*d %*d " /* tty_nr */
"%*d %*u %*u %*u %*u " /* mjflt */
"%*u %*u %*u %*d %*d " /* cstim */
"%*d %*d %*d %*d " /* itrealvalue */
"%llu", &pid, &starttime) != 2) {
log_warn("WARNING: Cannot parse content of %s.", statfile);
} else {
if (fclose(st))
log_sys_debug("fclose", statfile);
if (dm_snprintf(_log_file_path, sizeof(_log_file_path),
"%s_%s_%d_%lld", log_file, env, pid, starttime) < 0) {
log_warn("WARNING: Debug log file path is too long for epoch.");
_log_file_path[0] = '\0';
} else {
log_file = _log_file_path;
append = 1; /* force */
}
}
}
no_epoch:
if (!(_log_file = fopen(log_file, append ? "a" : "w"))) {
log_sys_error("fopen", log_file);
return;
}
@@ -64,6 +114,31 @@ void init_log_file(const char *log_file, int append)
_log_to_file = 1;
}
/*
* Unlink the log file depeding on command's return value
*
* When envvar LVM_EXPECTED_EXIT_STATUS is set, compare
* resulting status with this string.
*
* It's possible to specify 2 variants - having it equal to
* a single number or having it different from a single number.
*
* i.e. LVM_EXPECTED_EXIT_STATUS=">1" # delete when ret > 1.
*/
void unlink_log_file(int ret)
{
const char *env;
if (_log_file_path[0] &&
(env = getenv("LVM_EXPECTED_EXIT_STATUS")) &&
((env[0] == '>' && ret > atoi(env + 1)) ||
(atoi(env) == ret))) {
if (unlink(_log_file_path))
log_sys_error("unlink", _log_file_path);
_log_file_path[0] = '\0';
}
}
void init_log_direct(const char *log_file, int append)
{
int open_flags = append ? 0 : O_TRUNC;
@@ -299,13 +374,13 @@ void print_log(int level, const char *file, int line, int dm_errno_or_class,
va_start(ap, format);
switch (level) {
case _LOG_DEBUG:
if ((verbose_level() == level) &&
(strcmp("<backtrace>", format) == 0))
break;
if (verbose_level() < _LOG_DEBUG)
break;
if (!debug_class_is_logged(dm_errno_or_class))
break;
if ((verbose_level() == level) &&
(strcmp("<backtrace>", format) == 0))
break;
/* fall through */
default:
/* Typically only log_warn goes to stdout */
@@ -333,7 +408,7 @@ void print_log(int level, const char *file, int line, int dm_errno_or_class,
vfprintf(_log_file, trformat, ap);
va_end(ap);
fprintf(_log_file, "\n");
fputc('\n', _log_file);
fflush(_log_file);
}

View File

@@ -109,6 +109,8 @@
#define return_0 do { stack; return 0; } while (0)
#define return_NULL do { stack; return NULL; } while (0)
#define return_EINVALID_CMD_LINE \
do { stack; return EINVALID_CMD_LINE; } while (0)
#define return_ECMD_FAILED do { stack; return ECMD_FAILED; } while (0)
#define goto_out do { stack; goto out; } while (0)
#define goto_bad do { stack; goto bad; } while (0)

View File

@@ -40,6 +40,7 @@ void init_indent(int indent);
void init_msg_prefix(const char *prefix);
void init_log_file(const char *log_file, int append);
void unlink_log_file(int ret);
void init_log_direct(const char *log_file, int append);
void init_log_while_suspended(int log_while_suspended);
void init_abort_on_internal_errors(int fatal);

View File

@@ -40,7 +40,7 @@ const char *get_cache_pool_cachemode_name(const struct lv_segment *seg)
if (seg->feature_flags & DM_CACHE_FEATURE_PASSTHROUGH)
return "passthrough";
log_error("LV %s has uknown feature flags %" PRIu64,
log_error(INTERNAL_ERROR "LV %s has uknown feature flags %" PRIu64 ".",
display_lvname(seg->lv), seg->feature_flags);
return NULL;
@@ -70,7 +70,7 @@ int update_cache_pool_params(const struct segment_type *segtype,
{
uint64_t min_meta_size;
uint32_t extent_size = vg->extent_size;
uint64_t pool_metadata_size = *pool_metadata_extents * vg->extent_size;
uint64_t pool_metadata_size = (uint64_t) *pool_metadata_extents * vg->extent_size;
if (!(passed_args & PASS_ARG_CHUNK_SIZE))
*chunk_size = DEFAULT_CACHE_POOL_CHUNK_SIZE * 2;
@@ -395,6 +395,59 @@ int lv_is_cache_origin(const struct logical_volume *lv)
return seg && lv_is_cache(seg->lv) && !lv_is_pending_delete(seg->lv) && (seg_lv(seg, 0) == lv);
}
int lv_cache_setpolicy(struct logical_volume *lv, struct dm_config_tree *policy)
{
struct lv_segment *seg = first_seg(lv);
const char *name;
struct dm_config_node *cn;
struct dm_config_tree *old = NULL, *new = NULL, *tmp = NULL;
int r = 0;
if (lv_is_cache(lv))
seg = first_seg(seg->pool_lv);
if (seg->policy_settings) {
if (!(old = dm_config_create()))
goto_out;
if (!(new = dm_config_create()))
goto_out;
new->root = policy->root;
old->root = seg->policy_settings;
new->cascade = old;
if (!(tmp = policy = dm_config_flatten(new)))
goto_out;
}
if ((cn = dm_config_find_node(policy->root, "policy_settings")) &&
!(seg->policy_settings = dm_config_clone_node_with_mem(lv->vg->vgmem, cn, 0)))
goto_out;
if ((name = dm_config_find_str(policy->root, "policy", NULL)) &&
!(seg->policy_name = dm_pool_strdup(lv->vg->vgmem, name)))
goto_out;
restart: /* remove any 'default" nodes */
cn = seg->policy_settings ? seg->policy_settings->child : NULL;
while (cn) {
if (cn->v->type == DM_CFG_STRING && !strcmp(cn->v->v.str, "default")) {
dm_config_remove_node(seg->policy_settings, cn);
goto restart;
}
cn = cn->sib;
}
r = 1;
out:
if (old)
dm_config_destroy(old);
if (new)
dm_config_destroy(new);
if (tmp)
dm_config_destroy(tmp);
return r;
}
/*
* Wipe cache pool metadata area before use.
*

View File

@@ -130,7 +130,12 @@ char *lvseg_discards_dup(struct dm_pool *mem, const struct lv_segment *seg)
char *lvseg_cachemode_dup(struct dm_pool *mem, const struct lv_segment *seg)
{
return dm_pool_strdup(mem, get_cache_pool_cachemode_name(seg));
const char *name = get_cache_pool_cachemode_name(seg);
if (!name)
return_NULL;
return dm_pool_strdup(mem, name);
}
#ifdef DMEVENTD
@@ -147,11 +152,10 @@ char *lvseg_monitor_dup(struct dm_pool *mem, const struct lv_segment *seg)
if (lv_is_cow(seg->lv) && !lv_is_merging_cow(seg->lv))
segm = first_seg(seg->lv->snapshot->lv);
else if (seg->log_lv)
segm = first_seg(seg->log_lv);
// log_debug("Query LV:%s mon:%s segm:%s tgtm:%p segmon:%d statusm:%d", seg->lv->name, segm->lv->name, segm->segtype->name, segm->segtype->ops->target_monitored, seg_monitored(segm), (int)(segm->status & PVMOVE));
if ((dmeventd_monitor_mode() != 1) ||
!segm->segtype->ops ||
!segm->segtype->ops->target_monitored)
/* Nothing to do, monitoring not supported */;
else if (lv_is_cow_covering_origin(seg->lv))
@@ -634,10 +638,10 @@ int lv_raid_healthy(const struct logical_volume *lv)
return 1;
}
char *lv_attr_dup(struct dm_pool *mem, const struct logical_volume *lv)
char *lv_attr_dup_with_info_and_seg_status(struct dm_pool *mem, const struct lv_with_info_and_seg_status *lvdm)
{
dm_percent_t snap_percent;
struct lvinfo info;
const struct logical_volume *lv = lvdm->lv;
struct lv_segment *seg;
char *repstr;
@@ -711,30 +715,30 @@ char *lv_attr_dup(struct dm_pool *mem, const struct logical_volume *lv)
repstr[3] = (lv->status & FIXED_MINOR) ? 'm' : '-';
if (!activation() || !lv_info(lv->vg->cmd, lv, 0, &info, 1, 0)) {
if (!activation() || !lvdm->info_ok) {
repstr[4] = 'X'; /* Unknown */
repstr[5] = 'X'; /* Unknown */
} else if (info.exists) {
if (info.suspended)
} else if (lvdm->info.exists) {
if (lvdm->info.suspended)
repstr[4] = 's'; /* Suspended */
else if (info.live_table)
else if (lvdm->info.live_table)
repstr[4] = 'a'; /* Active */
else if (info.inactive_table)
else if (lvdm->info.inactive_table)
repstr[4] = 'i'; /* Inactive with table */
else
repstr[4] = 'd'; /* Inactive without table */
/* Snapshot dropped? */
if (info.live_table && lv_is_cow(lv)) {
if (lvdm->info.live_table && lv_is_cow(lv)) {
if (!lv_snapshot_percent(lv, &snap_percent) ||
snap_percent == DM_PERCENT_INVALID) {
if (info.suspended)
if (lvdm->info.suspended)
repstr[4] = 'S'; /* Susp Inv snapshot */
else
repstr[4] = 'I'; /* Invalid snapshot */
}
else if (snap_percent == LVM_PERCENT_MERGE_FAILED) {
if (info.suspended)
if (lvdm->info.suspended)
repstr[4] = 'M'; /* Susp snapshot merge failed */
else
repstr[4] = 'm'; /* snapshot merge failed */
@@ -745,10 +749,10 @@ char *lv_attr_dup(struct dm_pool *mem, const struct logical_volume *lv)
* 'R' indicates read-only activation of a device that
* does not have metadata flagging it as read-only.
*/
if (repstr[1] != 'r' && info.read_only)
if (repstr[1] != 'r' && lvdm->info.read_only)
repstr[1] = 'R';
repstr[5] = (info.open_count) ? 'o' : '-';
repstr[5] = (lvdm->info.open_count) ? 'o' : '-';
} else {
repstr[4] = '-';
repstr[5] = '-';
@@ -792,6 +796,16 @@ char *lv_attr_dup(struct dm_pool *mem, const struct logical_volume *lv)
repstr[8] = 'm'; /* RAID has 'm'ismatches */
} else if (lv->status & LV_WRITEMOSTLY)
repstr[8] = 'w'; /* sub-LV has 'w'ritemostly */
} else if (lv_is_thin_pool(lv) &&
(lvdm->seg_status.type != SEG_STATUS_NONE)) {
if (lvdm->seg_status.type == SEG_STATUS_UNKNOWN)
repstr[8] = 'X'; /* Unknown */
else if (lvdm->seg_status.thin_pool->fail)
repstr[8] = 'F';
else if (lvdm->seg_status.thin_pool->out_of_data_space)
repstr[8] = 'D';
else if (lvdm->seg_status.thin_pool->read_only)
repstr[8] = 'M';
}
if (lv->status & LV_ACTIVATION_SKIP)
@@ -803,6 +817,28 @@ out:
return repstr;
}
/* backward compatible internal API for lvm2api, TODO improve it */
char *lv_attr_dup(struct dm_pool *mem, const struct logical_volume *lv)
{
char *ret = NULL;
struct lv_with_info_and_seg_status status = {
.seg_status.type = SEG_STATUS_NONE,
.lv = lv
};
if (!(status.seg_status.mem = dm_pool_create("reporter_pool", 1024)))
return_0;
if (!(status.info_ok = lv_info_with_seg_status(lv->vg->cmd, lv, first_seg(lv), 1, &status, 1, 1)))
goto_bad;
ret = lv_attr_dup_with_info_and_seg_status(mem, &status);
bad:
dm_pool_destroy(status.seg_status.mem);
return ret;
}
int lv_set_creation(struct logical_volume *lv,
const char *hostname, uint64_t timestamp)
{
@@ -980,6 +1016,10 @@ const struct logical_volume *lv_lock_holder(const struct logical_volume *lv)
return sl->seg->lv;
}
/* RAID changes visibility of splitted LVs but references them still as leg/meta */
if ((lv_is_raid_image(lv) || lv_is_raid_metadata(lv)) && lv_is_visible(lv))
return lv;
/* For other types, by default look for the first user */
dm_list_iterate_items(sl, &lv->segs_using_this_lv) {
/* FIXME: complete this exception list */

View File

@@ -54,8 +54,11 @@ struct logical_volume {
const char *hostname;
};
struct lv_with_info_and_seg_status;
uint64_t lv_size(const struct logical_volume *lv);
uint64_t lv_metadata_size(const struct logical_volume *lv);
char *lv_attr_dup_with_info_and_seg_status(struct dm_pool *mem, const struct lv_with_info_and_seg_status *lvdm);
char *lv_attr_dup(struct dm_pool *mem, const struct logical_volume *lv);
char *lv_uuid_dup(const struct logical_volume *lv);
char *lv_tags_dup(const struct logical_volume *lv);

File diff suppressed because it is too large Load Diff

View File

@@ -147,6 +147,13 @@ int check_lv_segments(struct logical_volume *lv, int complete_vg)
inc_error_count;
}
if (lv_is_error_when_full(lv) &&
!seg_can_error_when_full(seg)) {
log_error("LV %s: segment %u (%s) does not support flag "
"ERROR_WHEN_FULL.", lv->name, seg_count, seg->segtype->name);
inc_error_count;
}
if (complete_vg && seg->log_lv &&
!seg_is_mirrored(seg) && !(seg->status & RAID_IMAGE)) {
log_error("LV %s: segment %u log LV %s is not a "

View File

@@ -58,6 +58,7 @@
#define LVM_READ UINT64_C(0x0000000000000100) /* LV, VG */
#define LVM_WRITE UINT64_C(0x0000000000000200) /* LV, VG */
#define LVM_WRITE_LOCKED UINT64_C(0x0020000000000000) /* LV, VG */
#define CLUSTERED UINT64_C(0x0000000000000400) /* VG */
//#define SHARED UINT64_C(0x0000000000000800) /* VG */
@@ -118,8 +119,20 @@
#define CACHE UINT64_C(0x0001000000000000) /* LV - Internal use only */
#define LV_PENDING_DELETE UINT64_C(0x0004000000000000) /* LV - Internal use only */
/* Next unused flag: UINT64_C(0x0008000000000000) */
#define LV_REMOVED UINT64_C(0x0040000000000000) /* LV - Internal use only
This flag is used to mark an LV once it has
been removed from the VG. It might still
be referenced on internal lists of LVs.
Any remaining references should check for
this flag and ignore the LV is set.
FIXME: Remove this flag once we have indexed
vg->removed_lvs for quick lookup.
*/
#define LV_ERROR_WHEN_FULL UINT64_C(0x0008000000000000) /* LV - error when full */
#define PV_ALLOCATION_PROHIBITED UINT64_C(0x0010000000000000) /* PV - internal use only - allocation prohibited
e.g. to prohibit allocation of a RAID image
on a PV already holing an image of the RAID set */
/* Next unused flag: UINT64_C(0x0080000000000000) */
/* Format features flags */
#define FMT_SEGMENTS 0x00000001U /* Arbitrary segment params? */
@@ -136,6 +149,9 @@
#define FMT_CONFIG_PROFILE 0x000000800U /* Supports configuration profiles? */
#define FMT_OBSOLETE 0x000001000U /* Obsolete format? */
#define FMT_NON_POWER2_EXTENTS 0x000002000U /* Non-power-of-2 extent sizes? */
#define FMT_SYSTEMID_ON_PVS 0x000004000U /* System ID is stored on PVs not VG */
#define systemid_on_pvs(vg) ((vg)->fid->fmt->features & FMT_SYSTEMID_ON_PVS)
/* Mirror conversion type flags */
#define MIRROR_BY_SEG 0x00000001U /* segment-by-segment mirror */
@@ -162,6 +178,9 @@
#define FAILED_CLUSTERED 0x00000040U
#define FAILED_ALLOCATION 0x00000080U
#define FAILED_EXIST 0x00000100U
#define FAILED_RECOVERY 0x00000200U
#define FAILED_SYSTEMID 0x00000400U
#define FAILED_LOCK_TYPE 0x00000800U
#define SUCCESS 0x00000000U
#define VGMETADATACOPIES_ALL UINT32_MAX
@@ -191,6 +210,7 @@
#define lv_is_mirror_type(lv) (((lv)->status & (MIRROR | MIRROR_LOG | MIRROR_IMAGE)) ? 1 : 0)
#define lv_is_pending_delete(lv) (((lv)->status & LV_PENDING_DELETE) ? 1 : 0)
#define lv_is_error_when_full(lv) (((lv)->status & LV_ERROR_WHEN_FULL) ? 1 : 0)
#define lv_is_pvmove(lv) (((lv)->status & PVMOVE) ? 1 : 0)
#define lv_is_raid(lv) (((lv)->status & RAID) ? 1 : 0)
@@ -211,6 +231,8 @@
#define lv_is_rlog(lv) (((lv)->status & REPLICATOR_LOG) ? 1 : 0)
#define lv_is_removed(lv) (((lv)->status & LV_REMOVED) ? 1 : 0)
int lv_layout_and_role(struct dm_pool *mem, const struct logical_volume *lv,
struct dm_list **layout, struct dm_list **role);
@@ -634,7 +656,9 @@ struct physical_volume *pv_create(const struct cmd_context *cmd,
int pvremove_single(struct cmd_context *cmd, const char *pv_name,
void *handle __attribute__((unused)), unsigned force_count,
unsigned prompt);
unsigned prompt, struct dm_list *pvslist);
int pvremove_many(struct cmd_context *cmd, struct dm_list *pv_names,
unsigned force_count, unsigned prompt);
int pv_resize_single(struct cmd_context *cmd,
struct volume_group *vg,
@@ -853,6 +877,7 @@ struct lvcreate_params {
uint32_t max_recovery_rate; /* RAID */
uint64_t feature_flags; /* cache */
struct dm_config_tree *cache_policy; /* cache */
const struct segment_type *segtype; /* all */
unsigned target_attr; /* all */
@@ -867,6 +892,7 @@ struct lvcreate_params {
struct dm_list *pvh; /* all */
uint64_t permission; /* all */
unsigned error_when_full; /* when segment supports it */
uint32_t read_ahead; /* all */
int approx_alloc; /* all */
alloc_policy_t alloc; /* all */
@@ -1015,11 +1041,16 @@ int lv_remove_mirrors(struct cmd_context *cmd, struct logical_volume *lv,
const char *get_mirror_log_name(int log_count);
int set_mirror_log_count(int *log_count, const char *mirrorlog);
int cluster_mirror_is_available(struct cmd_context *cmd);
int is_temporary_mirror_layer(const struct logical_volume *lv);
struct logical_volume * find_temporary_mirror(const struct logical_volume *lv);
uint32_t lv_mirror_count(const struct logical_volume *lv);
/* Remove CMIRROR_REGION_COUNT_LIMIT when http://bugzilla.redhat.com/682771 is fixed */
#define CMIRROR_REGION_COUNT_LIMIT (256*1024 * 8)
uint32_t adjusted_mirror_region_size(uint32_t extent_size, uint32_t extents,
uint32_t region_size, int internal);
uint32_t region_size, int internal, int clustered);
int remove_mirrors_from_segments(struct logical_volume *lv,
uint32_t new_mirrors, uint64_t status_mask);
int add_mirrors_to_segments(struct cmd_context *cmd, struct logical_volume *lv,
@@ -1108,6 +1139,7 @@ int validate_lv_cache_create_origin(const struct logical_volume *origin_lv);
struct logical_volume *lv_cache_create(struct logical_volume *pool,
struct logical_volume *origin);
int lv_cache_remove(struct logical_volume *cache_lv);
int lv_cache_setpolicy(struct logical_volume *cache_lv, struct dm_config_tree *pol);
int wipe_cache_pool(struct logical_volume *cache_pool_lv);
/* -- metadata/cache_manip.c */
@@ -1148,6 +1180,7 @@ char *generate_lv_name(struct volume_group *vg, const char *format,
int pv_change_metadataignore(struct physical_volume *pv, uint32_t mda_ignore);
int vg_flag_write_locked(struct volume_group *vg);
int vg_check_write_mode(struct volume_group *vg);
#define vg_is_clustered(vg) (vg_status((vg)) & CLUSTERED)
#define vg_is_exported(vg) (vg_status((vg)) & EXPORTED_VG)
@@ -1166,6 +1199,7 @@ struct vgcreate_params {
alloc_policy_t alloc;
int clustered; /* FIXME: put this into a 'status' variable instead? */
uint32_t vgmetadatacopies;
const char *system_id;
};
int validate_major_minor(const struct cmd_context *cmd,

View File

@@ -1009,7 +1009,6 @@ struct volume_group *vg_create(struct cmd_context *cmd, const char *vg_name)
.context.vg_ref.vg_name = vg_name
};
struct format_instance *fid;
int consistent = 0;
uint32_t rc;
if (!validate_name(vg_name)) {
@@ -1023,15 +1022,6 @@ struct volume_group *vg_create(struct cmd_context *cmd, const char *vg_name)
/* NOTE: let caller decide - this may be check for existence */
return _vg_make_handle(cmd, NULL, rc);
/* FIXME: Is this vg_read_internal necessary? Move it inside
vg_lock_newname? */
/* is this vg name already in use ? */
if ((vg = vg_read_internal(cmd, vg_name, NULL, WARN_PV_READ, &consistent))) {
log_error("A volume group called '%s' already exists.", vg_name);
unlock_and_release_vg(cmd, vg, vg_name);
return _vg_make_handle(cmd, NULL, FAILED_EXIST);
}
/* Strip dev_dir if present */
vg_name = strip_dir(vg_name, cmd->dev_dir);
@@ -1045,10 +1035,10 @@ struct volume_group *vg_create(struct cmd_context *cmd, const char *vg_name)
}
vg->status = (RESIZEABLE_VG | LVM_READ | LVM_WRITE);
if (!(vg->system_id = dm_pool_zalloc(vg->vgmem, NAME_LEN + 1)))
vg->system_id = NULL;
if (!(vg->lvm1_system_id = dm_pool_zalloc(vg->vgmem, NAME_LEN + 1)))
goto_bad;
*vg->system_id = '\0';
vg->extent_size = DEFAULT_EXTENT_SIZE * 2;
vg->max_lv = DEFAULT_MAX_LV;
vg->max_pv = DEFAULT_MAX_PV;
@@ -1416,7 +1406,7 @@ int vg_split_mdas(struct cmd_context *cmd __attribute__((unused)),
* 0 indicates we may not.
*/
static int _pvcreate_check(struct cmd_context *cmd, const char *name,
struct pvcreate_params *pp)
struct pvcreate_params *pp, int *wiped)
{
struct physical_volume *pv;
struct device *dev;
@@ -1426,6 +1416,8 @@ static int _pvcreate_check(struct cmd_context *cmd, const char *name,
/* FIXME Check partition type is LVM unless --force is given */
*wiped = 0;
/* Is there a pv here already? */
pv = find_pv_by_name(cmd, name, 1, 1);
@@ -1450,6 +1442,33 @@ static int _pvcreate_check(struct cmd_context *cmd, const char *name,
dev = dev_cache_get(name, cmd->full_filter);
/*
* Refresh+rescan at the end is needed if:
* - we don't obtain device list from udev,
* hence persistent cache file is used
* and we need to trash it and reevaluate
* for any changes done outside - adding
* any new foreign signature which may affect
* filtering - before we do pvcreate, we
* need to be sure that we have up-to-date
* view for filters
*
* - we have wiped existing foreign signatures
* from dev as this may affect what's filtered
* as well
*
*
* Only rescan at the end is needed if:
* - we've just checked whether dev is fileterd
* by MD filter. We do the refresh in-situ,
* so no need to require the refresh at the
* end of this fn. This is to allow for
* wiping MD signature during pvcreate for
* the dev - the dev would normally be
* filtered because of MD filter.
* This is an exception.
*/
/* Is there an md superblock here? */
if (!dev && md_filtering()) {
if (!refresh_filters(cmd))
@@ -1460,7 +1479,8 @@ static int _pvcreate_check(struct cmd_context *cmd, const char *name,
init_md_filtering(1);
scan_needed = 1;
}
} else if (!obtain_device_list_from_udev())
filter_refresh_needed = scan_needed = 1;
if (!dev) {
log_error("Device %s not found (or ignored by filtering).", name);
@@ -1479,12 +1499,13 @@ static int _pvcreate_check(struct cmd_context *cmd, const char *name,
if (!wipe_known_signatures(cmd, dev, name,
TYPE_LVM1_MEMBER | TYPE_LVM2_MEMBER,
0, pp->yes, pp->force)) {
0, pp->yes, pp->force, wiped)) {
log_error("Aborting pvcreate on %s.", name);
goto out;
} else
}
if (wiped)
filter_refresh_needed = scan_needed = 1;
if (sigint_caught())
goto_out;
@@ -1505,11 +1526,12 @@ out:
r = 0;
}
if (scan_needed)
if (scan_needed) {
if (!lvmcache_label_scan(cmd, 2)) {
stack;
r = 0;
}
}
free_pv_fid(pv);
return r;
@@ -1620,9 +1642,11 @@ struct physical_volume *pvcreate_vol(struct cmd_context *cmd, const char *pv_nam
{
struct physical_volume *pv = NULL;
struct device *dev;
int wiped = 0;
struct dm_list mdas;
struct pvcreate_params default_pp;
char buffer[64] __attribute__((aligned(8)));
dev_ext_t dev_ext_src;
pvcreate_params_set_defaults(&default_pp);
if (!pp)
@@ -1644,13 +1668,32 @@ struct physical_volume *pvcreate_vol(struct cmd_context *cmd, const char *pv_nam
}
}
if (!_pvcreate_check(cmd, pv_name, pp))
if (!_pvcreate_check(cmd, pv_name, pp, &wiped))
goto_bad;
if (sigint_caught())
goto_bad;
if (!(dev = dev_cache_get(pv_name, cmd->full_filter))) {
/*
* wipe_known_signatures called in _pvcreate_check fires
* WATCH event to update udev database. But at the moment,
* we have no way to synchronize with such event - we may
* end up still seeing the old info in udev db and pvcreate
* can fail to proceed because of the device still being
* filtered (because of the stale info in udev db).
* Disable udev dev-ext source temporarily here for
* this reason and rescan with DEV_EXT_NONE dev-ext
* source (so filters use DEV_EXT_NONE source).
*/
dev_ext_src = external_device_info_source();
if (wiped && (dev_ext_src == DEV_EXT_UDEV))
init_external_device_info_source(DEV_EXT_NONE);
dev = dev_cache_get(pv_name, cmd->full_filter);
init_external_device_info_source(dev_ext_src);
if (!dev) {
log_error("%s: Couldn't find device. Check your filters?",
pv_name);
goto bad;
@@ -2452,6 +2495,12 @@ int vg_validate(struct volume_group *vg)
r = 0;
}
if (vg->status & LVM_WRITE_LOCKED) {
log_error(INTERNAL_ERROR "VG %s has external flag LVM_WRITE_LOCKED set internally.",
vg->name);
r = 0;
}
/* FIXME Also check there's no data/metadata overlap */
if (!(vhash.pvid = dm_hash_create(vg->pv_count))) {
log_error("Failed to allocate pvid hash.");
@@ -2519,12 +2568,32 @@ int vg_validate(struct volume_group *vg)
r = 0;
}
dm_list_iterate_items(lvl, &vg->removed_lvs) {
if (!(lvl->lv->status & LV_REMOVED)) {
log_error(INTERNAL_ERROR "LV %s is not marked as removed while it's part "
"of removed LV list for VG %s", lvl->lv->name, vg->name);
r = 0;
}
}
/*
* Count all non-snapshot invisible LVs
*/
dm_list_iterate_items(lvl, &vg->lvs) {
lv_count++;
if (lvl->lv->status & LV_REMOVED) {
log_error(INTERNAL_ERROR "LV %s is marked as removed while it's "
"still part of the VG %s", lvl->lv->name, vg->name);
r = 0;
}
if (lvl->lv->status & LVM_WRITE_LOCKED) {
log_error(INTERNAL_ERROR "LV %s has external flag LVM_WRITE_LOCKED set internally.",
lvl->lv->name);
r = 0;
}
dev_name_len = strlen(lvl->lv->name) + vg_name_len + 3;
if (dev_name_len >= NAME_LEN) {
log_error(INTERNAL_ERROR "LV name \"%s/%s\" length %"
@@ -2807,6 +2876,7 @@ int vg_write(struct volume_group *vg)
}
if (revert || !wrote) {
log_error("Failed to write VG %s.", vg->name);
dm_list_uniterate(mdah, &vg->fid->metadata_areas_in_use, &mda->list) {
mda = dm_list_item(mdah, struct metadata_area);
@@ -3192,6 +3262,8 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
char uuid[64] __attribute__((aligned(8)));
unsigned seqno = 0;
int reappeared = 0;
struct cached_vg_fmtdata *vg_fmtdata = NULL; /* Additional format-specific data about the vg */
unsigned use_previous_vg;
if (is_orphan_vg(vgname)) {
if (use_precommitted) {
@@ -3278,12 +3350,20 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
/* Ensure contents of all metadata areas match - else do recovery */
inconsistent_mda_count=0;
dm_list_iterate_items(mda, &fid->metadata_areas_in_use) {
use_previous_vg = 0;
if ((use_precommitted &&
!(vg = mda->ops->vg_read_precommit(fid, vgname, mda))) ||
!(vg = mda->ops->vg_read_precommit(fid, vgname, mda, &vg_fmtdata, &use_previous_vg)) && !use_previous_vg) ||
(!use_precommitted &&
!(vg = mda->ops->vg_read(fid, vgname, mda, 0)))) {
!(vg = mda->ops->vg_read(fid, vgname, mda, &vg_fmtdata, &use_previous_vg, 0)) && !use_previous_vg)) {
inconsistent = 1;
vg_fmtdata = NULL;
continue;
}
/* Use previous VG because checksum matches */
if (!vg) {
vg = correct_vg;
continue;
}
@@ -3310,8 +3390,10 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
}
}
if (vg != correct_vg)
if (vg != correct_vg) {
release_vg(vg);
vg_fmtdata = NULL;
}
}
fid->ref_count--;
@@ -3427,6 +3509,7 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
* but we failed to do so (so there's a dangling fid now).
*/
_destroy_fid(&fid);
vg_fmtdata = NULL;
inconsistent = 0;
@@ -3457,14 +3540,23 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
/* Ensure contents of all metadata areas match - else recover */
inconsistent_mda_count=0;
dm_list_iterate_items(mda, &fid->metadata_areas_in_use) {
use_previous_vg = 0;
if ((use_precommitted &&
!(vg = mda->ops->vg_read_precommit(fid, vgname,
mda))) ||
!(vg = mda->ops->vg_read_precommit(fid, vgname, mda, &vg_fmtdata, &use_previous_vg)) && !use_previous_vg) ||
(!use_precommitted &&
!(vg = mda->ops->vg_read(fid, vgname, mda, 0)))) {
!(vg = mda->ops->vg_read(fid, vgname, mda, &vg_fmtdata, &use_previous_vg, 0)) && !use_previous_vg)) {
inconsistent = 1;
vg_fmtdata = NULL;
continue;
}
/* Use previous VG because checksum matches */
if (!vg) {
vg = correct_vg;
continue;
}
if (!correct_vg) {
correct_vg = vg;
if (!_update_pv_list(cmd->mem, &all_pvs, correct_vg)) {
@@ -3507,8 +3599,10 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
}
}
if (vg != correct_vg)
if (vg != correct_vg) {
release_vg(vg);
vg_fmtdata = NULL;
}
}
fid->ref_count--;
@@ -3567,8 +3661,8 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
/* Don't touch if vgids didn't match */
if (inconsistent_vgid) {
log_error("Inconsistent metadata UUIDs found for "
"volume group %s", vgname);
log_warn("WARNING: Inconsistent metadata UUIDs found for "
"volume group %s.", vgname);
*consistent = 0;
_free_pv_list(&all_pvs);
return correct_vg;
@@ -3600,8 +3694,8 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
release_vg(correct_vg);
return_NULL;
}
log_error("Removing PV %s (%s) that no longer belongs to VG %s",
pv_dev_name(pvl->pv), uuid, correct_vg->name);
log_warn("WARNING: Removing PV %s (%s) that no longer belongs to VG %s",
pv_dev_name(pvl->pv), uuid, correct_vg->name);
if (!pv_write_orphan(cmd, pvl->pv)) {
_free_pv_list(&all_pvs);
release_vg(correct_vg);
@@ -3624,10 +3718,9 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
}
if ((correct_vg->status & PVMOVE) && !pvmove_mode()) {
log_error("WARNING: Interrupted pvmove detected in "
"volume group %s", correct_vg->name);
log_error("Please restore the metadata by running "
"vgcfgrestore.");
log_error("Interrupted pvmove detected in volume group %s.",
correct_vg->name);
log_print("Please restore the metadata by running vgcfgrestore.");
release_vg(correct_vg);
return NULL;
}
@@ -3678,7 +3771,7 @@ struct volume_group *vg_read_internal(struct cmd_context *cmd, const char *vgnam
out:
if (!*consistent && (warn_flags & WARN_INCONSISTENT))
log_warn("WARNING: Volume Group %s is not consistent", vgname);
log_warn("WARNING: Volume Group %s is not consistent.", vgname);
return vg;
}
@@ -4203,6 +4296,37 @@ int vg_check_write_mode(struct volume_group *vg)
return 1;
}
/*
* Return 1 if the VG metadata should be written
* *without* the LVM_WRITE flag in the status line, and
* *with* the LVM_WRITE_LOCKED flag in the flags line.
*
* If this is done for a VG, it forces previous versions
* of lvm (before the LVM_WRITE_LOCKED flag was added), to view
* the VG and its LVs as read-only (because the LVM_WRITE flag
* is missing). Versions of lvm that understand the
* LVM_WRITE_LOCKED flag know to check the other methods of
* access control for the VG, specifically system_id and lock_type.
*
* So, if a VG has a system_id or lock_type, then the
* system_id and lock_type control access to the VG in
* addition to its basic writable status. Because previous
* lvm versions do not know about system_id or lock_type,
* VGs depending on either of these should have LVM_WRITE_LOCKED
* instead of LVM_WRITE to prevent the previous lvm versions from
* assuming they can write the VG and its LVs.
*/
int vg_flag_write_locked(struct volume_group *vg)
{
if (vg->system_id && vg->system_id[0])
return 1;
if (vg->lock_type && vg->lock_type[0] && strcmp(vg->lock_type, "none"))
return 1;
return 0;
}
/*
* Performs a set of checks against a VG according to bits set in status
* and returns FAILED_* bits for those that aren't acceptable.
@@ -4285,6 +4409,166 @@ static struct volume_group *_recover_vg(struct cmd_context *cmd,
return (struct volume_group *)vg;
}
static int _allow_system_id(struct cmd_context *cmd, const char *system_id)
{
const struct dm_config_node *cn;
const struct dm_config_value *cv;
const char *str;
if (!(cn = find_config_tree_node(cmd, local_extra_system_ids_CFG, NULL)))
return 0;
for (cv = cn->v; cv; cv = cv->next) {
if (cv->type == DM_CFG_EMPTY_ARRAY)
break;
/* Ignore invalid data: Warning message already issued by config.c */
if (cv->type != DM_CFG_STRING)
continue;
str = cv->v.str;
if (!*str)
continue;
if (!strcmp(str, system_id))
return 1;
}
return 0;
}
static int _access_vg_clustered(struct cmd_context *cmd, struct volume_group *vg)
{
if (vg_is_clustered(vg) && !locking_is_clustered()) {
if (!cmd->ignore_clustered_vgs)
log_error("Skipping clustered volume group %s", vg->name);
else
log_verbose("Skipping clustered volume group %s", vg->name);
return 0;
}
return 1;
}
static int _access_vg_lock_type(struct cmd_context *cmd, struct volume_group *vg)
{
if (!is_real_vg(vg->name))
return 1;
/*
* Until lock_type support is added, reject any VG that has a lock_type.
*/
if (vg->lock_type && vg->lock_type[0] && strcmp(vg->lock_type, "none")) {
log_error("Cannot access VG %s with unsupported lock_type %s.",
vg->name, vg->lock_type);
return 0;
}
return 1;
}
static int _access_vg_systemid(struct cmd_context *cmd, struct volume_group *vg)
{
/*
* LVM1 VGs must not be accessed if a new-style LVM2 system ID is set.
*/
if (cmd->system_id && systemid_on_pvs(vg)) {
log_error("Cannot access VG %s with LVM1 system ID %s when host system ID is set.",
vg->name, vg->lvm1_system_id);
return 0;
}
/*
* A VG without a system_id can be accessed by anyone.
*/
if (!vg->system_id || !vg->system_id[0])
return 1;
/*
* A few commands allow read-only access to foreign VGs.
*/
if (cmd->include_foreign_vgs)
return 1;
/*
* A host can access a VG with a matching system_id.
*/
if (cmd->system_id && !strcmp(vg->system_id, cmd->system_id))
return 1;
/*
* A host can access a VG if the VG's system_id is in extra_system_ids list.
*/
if (cmd->system_id && _allow_system_id(cmd, vg->system_id))
return 1;
/*
* Allow VG access if the local host has active LVs in it.
*/
if (lvs_in_vg_activated(vg)) {
log_warn("WARNING: Found LVs active in VG %s with foreign system ID %s. Possible data corruption.",
vg->name, vg->system_id);
if (cmd->include_active_foreign_vgs)
return 1;
return 0;
}
/*
* A host without a system_id cannot access a VG with a system_id.
*/
if (!cmd->system_id || cmd->unknown_system_id) {
log_error("Cannot access VG %s with system ID %s with unknown local system ID.",
vg->name, vg->system_id);
return 0;
}
/*
* Some commands always produce an error when accessing foreign VG.
*/
if (cmd->error_foreign_vgs) {
log_error("Cannot access VG %s with system ID %s with local system ID %s.",
vg->name, vg->system_id, cmd->system_id);
return 0;
}
/*
* When include_foreign_vgs is 0 and error_foreign_vgs is 0,
* the result is to silently ignore foreign vgs.
*/
return 0;
}
/*
* FIXME: move _vg_bad_status_bits() checks in here.
*/
static int _vg_access_permitted(struct cmd_context *cmd, struct volume_group *vg, uint32_t *failure)
{
if (!is_real_vg(vg->name)) {
/* Disallow use of LVM1 orphans when a host system ID is set. */
if (cmd->system_id && *cmd->system_id && systemid_on_pvs(vg)) {
*failure |= FAILED_SYSTEMID;
return_0;
}
return 1;
}
if (!_access_vg_clustered(cmd, vg)) {
*failure |= FAILED_CLUSTERED;
return 0;
}
if (!_access_vg_lock_type(cmd, vg)) {
*failure |= FAILED_LOCK_TYPE;
return 0;
}
if (!_access_vg_systemid(cmd, vg)) {
*failure |= FAILED_SYSTEMID;
return 0;
}
return 1;
}
/*
* Consolidated locking, reading, and status flag checking.
*
@@ -4344,14 +4628,8 @@ static struct volume_group *_vg_lock_and_read(struct cmd_context *cmd, const cha
goto bad;
}
if (vg_is_clustered(vg) && !locking_is_clustered()) {
if (!cmd->ignore_clustered_vgs)
log_error("Skipping clustered volume group %s", vg->name);
else
log_verbose("Skipping clustered volume group %s", vg->name);
failure |= FAILED_CLUSTERED;
if (!_vg_access_permitted(cmd, vg, &failure))
goto bad;
}
/* consistent == 0 when VG is not found, but failed == FAILED_NOTFOUND */
if (!consistent && !failure) {
@@ -4359,7 +4637,7 @@ static struct volume_group *_vg_lock_and_read(struct cmd_context *cmd, const cha
if (!(vg = _recover_vg(cmd, vg_name, vgid))) {
log_error("Recovery of volume group \"%s\" failed.",
vg_name);
failure |= FAILED_INCONSISTENT;
failure |= FAILED_RECOVERY;
goto bad_no_unlock;
}
}

View File

@@ -72,6 +72,7 @@ struct dm_config_tree;
struct metadata_area;
struct alloc_handle;
struct lvmcache_info;
struct cached_vg_fmtdata;
/* Per-format per-metadata area operations */
struct metadata_area_ops {
@@ -79,10 +80,14 @@ struct metadata_area_ops {
struct volume_group *(*vg_read) (struct format_instance * fi,
const char *vg_name,
struct metadata_area * mda,
struct cached_vg_fmtdata **vg_fmtdata,
unsigned *use_previous_vg,
int single_device);
struct volume_group *(*vg_read_precommit) (struct format_instance * fi,
const char *vg_name,
struct metadata_area * mda);
struct metadata_area * mda,
struct cached_vg_fmtdata **vg_fmtdata,
unsigned *use_previous_vg);
/*
* Write out complete VG metadata. You must ensure internal
* consistency before calling. eg. PEs can't refer to PVs not
@@ -430,9 +435,13 @@ int lv_split_segment(struct logical_volume *lv, uint32_t le);
int add_seg_to_segs_using_this_lv(struct logical_volume *lv, struct lv_segment *seg);
int remove_seg_from_segs_using_this_lv(struct logical_volume *lv, struct lv_segment *seg);
int for_each_sub_lv_except_pools(struct logical_volume *lv,
int (*fn)(struct logical_volume *lv, void *data),
void *data);
int for_each_sub_lv(struct logical_volume *lv,
int (*fn)(struct logical_volume *lv, void *data),
void *data);
int (*fn)(struct logical_volume *lv, void *data),
void *data);
int move_lv_segments(struct logical_volume *lv_to,
struct logical_volume *lv_from,
uint64_t set_status, uint64_t reset_status);

View File

@@ -78,10 +78,9 @@ struct logical_volume *find_temporary_mirror(const struct logical_volume *lv)
*
* Returns: 1 if available, 0 otherwise
*/
static int _cluster_mirror_is_available(struct logical_volume *lv)
int cluster_mirror_is_available(struct cmd_context *cmd)
{
unsigned attr = 0;
struct cmd_context *cmd = lv->vg->cmd;
const struct segment_type *segtype;
if (!(segtype = get_segtype_from_string(cmd, "mirror")))
@@ -90,7 +89,7 @@ static int _cluster_mirror_is_available(struct logical_volume *lv)
if (!segtype->ops->target_present)
return_0;
if (!segtype->ops->target_present(lv->vg->cmd, NULL, &attr))
if (!segtype->ops->target_present(cmd, NULL, &attr))
return_0;
if (!(attr & MIRROR_LOG_CLUSTERED))
@@ -160,11 +159,12 @@ struct lv_segment *find_mirror_seg(struct lv_segment *seg)
* For internal use only log only in verbose mode
*/
uint32_t adjusted_mirror_region_size(uint32_t extent_size, uint32_t extents,
uint32_t region_size, int internal)
uint32_t region_size, int internal, int clustered)
{
uint64_t region_max;
uint64_t region_min, region_min_pow2;
region_max = (1 << (ffs((int)extents) - 1)) * (uint64_t) extent_size;
region_max = (1 << (ffs((int)extents) - 1)) * (uint64_t) (1 << (ffs((int)extent_size) - 1));
if (region_max < UINT32_MAX && region_size > region_max) {
region_size = (uint32_t) region_max;
@@ -176,6 +176,42 @@ uint32_t adjusted_mirror_region_size(uint32_t extent_size, uint32_t extents,
PRIu32 " sectors.", region_size);
}
#ifdef CMIRROR_REGION_COUNT_LIMIT
if (clustered) {
/*
* The CPG code used by cluster mirrors can only handle a
* payload of < 1MB currently. (This deficiency is tracked by
* http://bugzilla.redhat.com/682771.) The region size for cluster
* mirrors must be restricted in such a way as to limit the
* size of the bitmap to < 512kB, because there are two bitmaps
* which get sent around during checkpointing while a cluster
* mirror starts up. Ergo, the number of regions must not
* exceed 512k * 8. We also need some room for the other
* checkpointing structures as well, so we reduce by another
* factor of two.
*
* This code should be removed when the CPG restriction is
* lifted.
*/
region_min = (uint64_t) extents * extent_size / CMIRROR_REGION_COUNT_LIMIT;
region_min_pow2 = 1;
while (region_min_pow2 < region_min)
region_min_pow2 *= 2;
if (region_size < region_min_pow2) {
if (internal)
log_print_unless_silent("Increasing mirror region size from %"
PRIu32 " to %" PRIu64 " sectors.",
region_size, region_min_pow2);
else
log_verbose("Increasing mirror region size from %"
PRIu32 " to %" PRIu64 " sectors.",
region_size, region_min_pow2);
region_size = region_min_pow2;
}
}
#endif /* CMIRROR_REGION_COUNT_LIMIT */
return region_size;
}
@@ -421,7 +457,8 @@ static int _activate_lv_like_model(struct logical_volume *model,
/*
* Delete independent/orphan LV, it must acquire lock.
*/
static int _delete_lv(struct logical_volume *mirror_lv, struct logical_volume *lv)
static int _delete_lv(struct logical_volume *mirror_lv, struct logical_volume *lv,
int reactivate)
{
struct cmd_context *cmd = mirror_lv->vg->cmd;
struct dm_str_list *sl;
@@ -441,15 +478,17 @@ static int _delete_lv(struct logical_volume *mirror_lv, struct logical_volume *l
}
}
/* FIXME: the 'model' should be 'mirror_lv' not 'lv', I think. */
if (!_activate_lv_like_model(lv, lv))
return_0;
if (reactivate) {
/* FIXME: the 'model' should be 'mirror_lv' not 'lv', I think. */
if (!_activate_lv_like_model(lv, lv))
return_0;
/* FIXME Is this superfluous now? */
sync_local_dev_names(cmd);
/* FIXME Is this superfluous now? */
sync_local_dev_names(cmd);
if (!deactivate_lv(cmd, lv))
return_0;
if (!deactivate_lv(cmd, lv))
return_0;
}
if (!lv_remove(lv))
return_0;
@@ -800,11 +839,11 @@ static int _split_mirror_images(struct logical_volume *lv,
}
/* Remove original mirror layer if it has been converted to linear */
if (sub_lv && !_delete_lv(lv, sub_lv))
if (sub_lv && !_delete_lv(lv, sub_lv, 1))
return_0;
/* Remove the log if it has been converted to linear */
if (detached_log_lv && !_delete_lv(lv, detached_log_lv))
if (detached_log_lv && !_delete_lv(lv, detached_log_lv, 1))
return_0;
return 1;
@@ -853,6 +892,7 @@ static int _remove_mirror_images(struct logical_volume *lv,
struct lv_list *lvl;
struct dm_list tmp_orphan_lvs;
uint32_t orig_removed = num_removed;
int reactivate;
if (removed)
*removed = 0;
@@ -865,6 +905,7 @@ static int _remove_mirror_images(struct logical_volume *lv,
if (collapse && (old_area_count - num_removed != 1)) {
log_error("Incompatible parameters to _remove_mirror_images");
return 0;
}
num_removed = 0;
@@ -1094,16 +1135,17 @@ static int _remove_mirror_images(struct logical_volume *lv,
}
/* Save or delete the 'orphan' LVs */
reactivate = lv_is_active(lv_lock_holder(lv));
if (!collapse) {
dm_list_iterate_items(lvl, &tmp_orphan_lvs)
if (!_delete_lv(lv, lvl->lv))
if (!_delete_lv(lv, lvl->lv, reactivate))
return_0;
}
if (temp_layer_lv && !_delete_lv(lv, temp_layer_lv))
if (temp_layer_lv && !_delete_lv(lv, temp_layer_lv, reactivate))
return_0;
if (detached_log_lv && !_delete_lv(lv, detached_log_lv))
if (detached_log_lv && !_delete_lv(lv, detached_log_lv, reactivate))
return_0;
/* Mirror with only 1 area is 'in sync'. */
@@ -1703,7 +1745,8 @@ static int _add_mirrors_that_preserve_segments(struct logical_volume *lv,
adjusted_region_size = adjusted_mirror_region_size(lv->vg->extent_size,
lv->le_count,
region_size, 1);
region_size, 1,
vg_is_clustered(lv->vg));
if (!(ah = allocate_extents(lv->vg, NULL, segtype, 1, mirrors, 0, 0,
lv->le_count, allocatable_pvs, alloc, 0,
@@ -2127,7 +2170,7 @@ int lv_add_mirrors(struct cmd_context *cmd, struct logical_volume *lv,
if (!lv_is_pvmove(lv) && !lv_is_locked(lv) &&
lv_is_active(lv) &&
!lv_is_active_exclusive_locally(lv) && /* lv_is_active_remotely */
!_cluster_mirror_is_available(lv)) {
!cluster_mirror_is_available(lv->vg->cmd)) {
log_error("Shared cluster mirrors are not available.");
return 0;
}

View File

@@ -235,6 +235,11 @@ struct lv_segment *find_pool_seg(const struct lv_segment *seg)
pool_seg = sl->seg;
}
if (!pool_seg) {
log_error("Pool segment not found for %s.", display_lvname(seg->lv));
return NULL;
}
if ((lv_is_thin_type(seg->lv) && !seg_is_pool(pool_seg))) {
log_error("%s on %s is not a %s pool segment",
pool_seg->lv->name, seg->lv->name,
@@ -397,7 +402,7 @@ int update_pool_params(const struct segment_type *segtype,
return_0;
if ((uint64_t) *chunk_size > (uint64_t) pool_data_extents * vg->extent_size) {
log_error("Size of %s data volume cannot be smaller then chunk size %s.",
log_error("Size of %s data volume cannot be smaller than chunk size %s.",
segtype->name, display_size(vg->cmd, *chunk_size));
return 0;
}

View File

@@ -24,6 +24,7 @@
#include "display.h"
#include "label.h"
#include "archiver.h"
#include "lvm-signal.h"
static struct pv_segment *_alloc_pv_segment(struct dm_pool *mem,
struct physical_volume *pv,
@@ -650,7 +651,7 @@ int pv_resize_single(struct cmd_context *cmd,
}
log_verbose("Resizing volume \"%s\" to %" PRIu64 " sectors.",
pv_name, pv_size(pv));
pv_name, size);
if (!pv_resize(pv, vg, size))
goto_out;
@@ -694,12 +695,11 @@ const char _really_wipe[] =
* 0 indicates we may not.
*/
static int pvremove_check(struct cmd_context *cmd, const char *name,
unsigned force_count, unsigned prompt)
unsigned force_count, unsigned prompt, struct dm_list *pvslist)
{
struct device *dev;
struct label *label;
struct pv_list *pvl;
struct dm_list *pvslist;
struct physical_volume *pv = NULL;
int r = 0;
@@ -720,10 +720,6 @@ static int pvremove_check(struct cmd_context *cmd, const char *name,
return 0;
}
lvmcache_seed_infos_from_lvmetad(cmd);
if (!(pvslist = get_pvs(cmd)))
return_0;
dm_list_iterate_items(pvl, pvslist)
if (pvl->pv->dev == dev)
pv = pvl->pv;
@@ -765,26 +761,18 @@ static int pvremove_check(struct cmd_context *cmd, const char *name,
r = 1;
out:
if (pvslist)
dm_list_iterate_items(pvl, pvslist)
free_pv_fid(pvl->pv);
return r;
}
int pvremove_single(struct cmd_context *cmd, const char *pv_name,
void *handle __attribute__((unused)), unsigned force_count,
unsigned prompt)
unsigned prompt, struct dm_list *pvslist)
{
struct device *dev;
struct lvmcache_info *info;
int r = 0;
if (!lock_vol(cmd, VG_ORPHANS, LCK_VG_WRITE, NULL)) {
log_error("Can't get lock for orphan PVs");
return 0;
}
if (!pvremove_check(cmd, pv_name, force_count, prompt))
if (!pvremove_check(cmd, pv_name, force_count, prompt, pvslist))
goto out;
if (!(dev = dev_cache_get(pv_name, cmd->filter))) {
@@ -819,10 +807,49 @@ int pvremove_single(struct cmd_context *cmd, const char *pv_name,
r = 1;
out:
return r;
}
int pvremove_many(struct cmd_context *cmd, struct dm_list *pv_names,
unsigned force_count, unsigned prompt)
{
int ret = 1;
struct dm_list *pvslist = NULL;
struct pv_list *pvl;
const struct dm_str_list *pv_name;
if (!lock_vol(cmd, VG_ORPHANS, LCK_VG_WRITE, NULL)) {
log_error("Can't get lock for orphan PVs");
return 0;
}
lvmcache_seed_infos_from_lvmetad(cmd);
if (!(pvslist = get_pvs(cmd))) {
ret = 0;
goto_out;
}
dm_list_iterate_items(pv_name, pv_names) {
if (!pvremove_single(cmd, pv_name->str, NULL, force_count, prompt, pvslist)) {
stack;
ret = 0;
}
if (sigint_caught()) {
ret = 0;
goto_out;
}
}
out:
unlock_vg(cmd, VG_ORPHANS);
return r;
if (pvslist)
dm_list_iterate_items(pvl, pvslist)
free_pv_fid(pvl->pv);
return ret;
}
int pvcreate_single(struct cmd_context *cmd, const char *pv_name,

View File

@@ -133,8 +133,11 @@ static int _create_maps(struct dm_pool *mem, struct dm_list *pvs, struct dm_list
struct pv_list *pvl;
dm_list_iterate_items(pvl, pvs) {
if (!(pvl->pv->status & ALLOCATABLE_PV))
if (!(pvl->pv->status & ALLOCATABLE_PV) ||
(pvl->pv->status & PV_ALLOCATION_PROHIBITED)) {
pvl->pv->status &= ~PV_ALLOCATION_PROHIBITED;
continue;
}
if (is_missing_pv(pvl->pv))
continue;
assert(pvl->pv->dev);

View File

@@ -1040,8 +1040,8 @@ int lv_raid_change_image_count(struct logical_volume *lv,
/*
* LV must be either in-active or exclusively active
*/
if (lv_is_active(lv) && vg_is_clustered(lv->vg) &&
!lv_is_active_exclusive_locally(lv)) {
if (lv_is_active(lv_lock_holder(lv)) && vg_is_clustered(lv->vg) &&
!lv_is_active_exclusive_locally(lv_lock_holder(lv))) {
log_error("%s/%s must be active exclusive locally to"
" perform this operation.", lv->vg->name, lv->name);
return 0;
@@ -1149,12 +1149,6 @@ int lv_raid_split(struct logical_volume *lv, const char *split_name,
return 0;
}
if (!resume_lv(lv->vg->cmd, lv_lock_holder(lv))) {
log_error("Failed to resume %s/%s after committing changes",
lv->vg->name, lv->name);
return 0;
}
/*
* First activate the newly split LV and LVs on the removal list.
* This is necessary so that there are no name collisions due to
@@ -1168,6 +1162,18 @@ int lv_raid_split(struct logical_volume *lv, const char *split_name,
if (!activate_lv_excl_local(cmd, lvl->lv))
return_0;
if (!resume_lv(cmd, lv_lock_holder(lv))) {
log_error("Failed to resume %s/%s after committing changes",
lv->vg->name, lv->name);
return 0;
}
/*
* Since newly split LV is typically already active - we need to call
* suspend() and resume() to also rename it.
*
* TODO: activate should recognize it and avoid these 2 calls
*/
/*
* Eliminate the residual LVs
@@ -1393,7 +1399,7 @@ static int _convert_mirror_to_raid1(struct logical_volume *lv,
}
for (s = 0; s < seg->area_count; ++s) {
if (!(new_name = _generate_raid_name(seg_lv(seg, s), "rimage", s)))
if (!(new_name = _generate_raid_name(lv, "rimage", s)))
return_0;
log_debug_metadata("Renaming %s to %s", seg_lv(seg, s)->name, new_name);
seg_lv(seg, s)->name = new_name;
@@ -1529,6 +1535,29 @@ has_enough_space:
return 1;
}
static int _avoid_pvs_of_lv(struct logical_volume *lv, void *data)
{
struct dm_list *allocate_pvs = (struct dm_list *) data;
struct pv_list *pvl;
dm_list_iterate_items(pvl, allocate_pvs)
if (!(lv->status & PARTIAL_LV) &&
lv_is_on_pv(lv, pvl->pv))
pvl->pv->status |= PV_ALLOCATION_PROHIBITED;
return 1;
}
/*
* Prevent any PVs holding other image components of @lv from being used for allocation
* by setting the internal PV_ALLOCATION_PROHIBITED flag to use it to avoid generating
* pv maps for those PVs.
*/
static int _avoid_pvs_with_other_images_of_lv(struct logical_volume *lv, struct dm_list *allocate_pvs)
{
return for_each_sub_lv(lv, _avoid_pvs_of_lv, allocate_pvs);
}
/*
* lv_raid_replace
* @lv
@@ -1627,6 +1656,13 @@ int lv_raid_replace(struct logical_volume *lv,
}
}
/* Prevent any PVs holding image components from being used for allocation */
if (!_avoid_pvs_with_other_images_of_lv(lv, allocate_pvs)) {
log_error("Failed to prevent PVs holding image components "
"from being used for allocation.");
return 0;
}
/*
* Allocate the new image components first
* - This makes it easy to avoid all currently used devs

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