1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-08-24 09:49:27 +03:00

Compare commits

..

341 Commits

Author SHA1 Message Date
d60364c634 libdm: use uint64_t where possible in filemap routines
Use uint64_t where possible and eplicit casts elsewhere to avoid
compiler warnings when converting between int, int64_t and
uint64_t.
2017-03-29 20:57:04 +01:00
b5ac2c458a libdm: use size_t for buflen in _stats_group_file_regions() 2017-03-29 20:46:21 +01:00
181975e635 libdm: make _stats_resize_group() num_regions argument uint64_t 2017-03-29 20:42:36 +01:00
820843fcb6 libdm: make _find_extent() nr_extents argument uint64_t 2017-03-29 20:41:33 +01:00
d487fcfb0e dmfilemapd: cast return value of strto* functions when needed 2017-03-29 20:32:55 +01:00
f1e42e2186 dmfilemapd: use log_sys_error in _filemap_monitor_set_notify
Since _filemap_monitor_set_notify() is only called after daemon
start up it should not use the _early_log() macros. Use
log_sys_error to log errors from the two syscalls in the function.
2017-03-29 20:29:20 +01:00
3c69a7248a dmfilemapd: cast sysconf() return value to int 2017-03-29 20:28:43 +01:00
00e716b037 dmfilemapd: fix len type in _filemap_monitor_check_file_unlinked()
Make 'len' a size_t to match the return type of readlink(2).
2017-03-29 20:26:39 +01:00
926ce7e279 dmfilemapd: make filemap_monitor->nr_regions uint64_t 2017-03-29 20:23:57 +01:00
6582cc4ff2 libdm: use DM_STATS_GROUP_* constants in dm_stats_create_regions_from_fd 2017-03-29 20:02:26 +01:00
618f9ab04b dmsetup: simplify branching in _stats_update_file()
The fallback branch in _stats_update_file() is redundant (since the
branch taken when the daemon starts successfully must jump to the
'out' label anyway): remove it and re-order the conditions to
improve readability.
2017-03-29 18:35:27 +01:00
5994ed9df2 dmsetup: always close fd when leaving _stats_update_file() (coverity) 2017-03-29 18:34:57 +01:00
11749e7adb dmsetup: do not start dmfilemapd if region creation fails (coverity) 2017-03-29 18:34:51 +01:00
6740eb1c2b libdm: do not attempt filemap cleanup if dm_stats_list() fails (coverity) 2017-03-29 18:34:43 +01:00
f86c1f5d0a libdm: abort filemap update if pool allocation fails (coverity) 2017-03-29 18:34:38 +01:00
bc5d67884f libdm: do not leak FIEMAP extent buffer if pool allocation fails (coverity) 2017-03-29 18:34:30 +01:00
13426092e9 dmfilemapd: free region table at end of _update_regions() (coverity) 2017-03-29 18:34:24 +01:00
f66bc3dab0 dmfilemapd: fix off-by-one in fd comparison (coverity)
The function _filemap_monitor_check_file_unlinked() attempts to
test whether a fd value should be closed by comparison to zero:

        if ((fd > 0) && close(fd))
                log_error("Error closing fd %d", fd);

The test should be '>=' since 0 is a valid file descriptor.
2017-03-29 18:34:19 +01:00
8658bbe3ee dmfilemapd: always close link check file descriptor (coverity)
Similar to 40fb91a, but for the file descriptor opened using the
link path reported by /proc/<self>/fd/<fd>.

The daemon opens a new file descriptor from /proc/<self>/fd when
checking for an unlinked file with mode=inode. Ensure that it is
always closed even if the same file test fails.
2017-03-29 18:34:11 +01:00
7db51a6bed dmfilemapd: always terminate link buffer after readlink(2) (coverity) 2017-03-29 18:34:05 +01:00
70bb726678 dmfilemapd: always close check file descriptor (coverity)
The daemon opens a new file descriptor from fm->path when checking
for an unlinked file with mode=inode. Ensure that it is always
closed even if the same file test fails.
2017-03-29 18:33:53 +01:00
43fdbb8aeb dmfilemapd: use *argv[0] when testing for absolute path (coverity)
The path argument check in dmfilemapd incorrectly tests for:

  if (argv[0] == '/')

Rather than testing the 1st character in the string pointed to by
argv[0].
2017-03-29 18:33:42 +01:00
b5252a51a5 dmfilemapd: pass correct dirp to closedir() 2017-03-29 16:54:44 +01:00
481a522dd7 dmfilemapd: do not closdir(pid_d) unless it is open 2017-03-29 16:48:32 +01:00
d71071a1af dmfilemapd: log closedir errors with log_sys_error() 2017-03-29 16:04:15 +01:00
5dfd35f2f8 dmstats: Fix path to static dmstats 2017-03-29 09:04:56 +02:00
5012be326d man: ranges/LV names/symbolic use regexp 2017-03-29 02:27:10 +02:00
4af09a94bd man: simplify by avoiding different headers on de-duplication of lvmconfig, lvm-config and lvm-dumpconfig 2017-03-29 01:44:09 +02:00
6742137964 man: de-duplicate lvmconfig, lvm-config and lvm-dumpconfig manuals 2017-03-29 00:22:15 +02:00
162552041f spec: Add dmfilemapd 2017-03-28 21:52:50 +02:00
a41d5b6491 dmfilemapd: Fix install target 2017-03-28 21:52:30 +02:00
3aab873199 man: regexp readability / use $(SED) 2017-03-28 17:51:22 +02:00
0c2f7ed49a post-release 2017-03-28 16:14:03 +01:00
396377bc03 pre-release
Removing some unused new lines and changing some incorrect "can't
release until this is fixed" comments.  Rename license.txt to make
it clear its merely an included file, not itself a licence.
2017-03-28 16:11:35 +01:00
b9399f2148 man: pre-generated files weren't committed 2017-03-28 01:32:59 +01:00
19a72e601f man: fix / typo 2017-03-28 00:27:04 +02:00
7f31261844 man: enhance man postprocessing regexp 2017-03-28 00:17:43 +02:00
88e408b8ed tests: update to better fit
Die is automatic on 'error' result
Cleanup everything on 'regular' code path.
2017-03-27 20:50:19 +02:00
e3a3cf01eb cleanup: use more common FMTd64 type
We use 'd' for plain singed integers.
2017-03-27 20:50:19 +02:00
78d004efa8 build: fix x32 arch
This patch fixed lvm2 compilation running on x32 arch.
(Using 64bit x86 cpu features but running on 32b address space,
so consuming less mem in VM).

On x32 arch 'time_t' is 64bit while 'long' is 32bit.
2017-03-27 20:50:19 +02:00
36cac41115 man-generator/man/help: simplify hyphen escaping
Commits a29bb6a14b
    ... 5c199d99f4
narrowed down on addressing the escaping of hyphens
in the dynamic creation of manuals whilst avoiding
them in creating help texts.  This lead to a sequence
of slipping through hyphens adrressed by additional
patches in aforementioned commit series.

On the other hand, postprocessing dynamically man-generator
created and statically provided manuals catches all hyphens
in need of escaping.

Changes:
- revert the above commits whilst keeping man-generator
  streamlining and the detection of any '\' when generating
  help texts in order to avoid escapes to slip in

- Dynamically escape hyphens in manaual pages using sed(1)
  in the respective Makefile targets

- remove any manually added escaping on hyphens from any
  static manual sources or headers
2017-03-27 16:49:39 +02:00
6165e09221 lvchange: reject setting all raid1 images to writemostly
raid1 doesn't allow to set all images to writemostly because at
least one image is required to receive any written data immediately.

The dm-raid target will detect such invalid request and
fail it iwith a kernel error message.

Reject such request in uspace displaying a respective error message.
2017-03-26 20:28:04 +02:00
5c199d99f4 man: a few more missed '-' to escape 2017-03-25 03:40:02 +01:00
66b2084b96 man-generator: more escaped '-' 2017-03-24 18:57:45 +01:00
d823c65d50 man-generator: fix buffer length calculation 2017-03-24 18:33:03 +01:00
25c841af00 make: Don't hard-code SHELL as /bin/sh 2017-03-24 15:29:17 +00:00
4046f9bd95 man/help: avoid escaping of '-' with --help 2017-03-24 15:14:21 +01:00
e9433a9de9 WHATS_NEW: man-generator escape '-' 2017-03-24 14:31:19 +01:00
9354ce6045 man-generator: cleanup escape '-' 2017-03-24 14:27:59 +01:00
10e0a5066e man-generator: emit escaped '-' 2017-03-24 04:00:47 +01:00
5eec3de41f man: escape all single '-' 2017-03-24 02:46:11 +01:00
93467f0d9f man: revert erouneous '-' escapes in Makefine.in 2017-03-24 01:39:50 +01:00
a29bb6a14b man: escape all double '-' 2017-03-24 01:03:58 +01:00
2eaca7ab63 tools: Reinstate lvm script processing.
We check for a script if the command isn't recognised (ENO_SUCH_CMD).
(Also added a few comments and fixed some whitespace.)
2017-03-23 23:20:53 +00:00
fe3b9bb7d4 libdm: typo 2017-03-24 00:12:41 +01:00
6471bb2c41 commands: improve error message for unknown command
when running "lvm foo".
2017-03-23 03:35:06 -05:00
0dabe7237c commands: fix commands with run with path basename
The recent command definitions commit took the command
name from argv[0] without applying basename to the value,
so a pathname, e.g. /usr/sbin, would cause lvm to not
recognize the command name.
2017-03-23 03:06:07 -05:00
e8362b4cb7 tools: Show configuration command line in lvm version.
Also update configure.in with some items recently added to the tree.
2017-03-23 01:01:35 +00:00
b84bf3e8cd raid: adjust to misordered raid table line output
This commit supersedes reverted 1e4462dbfb
to avoid changes to liblvm and the libdm API completely.

The libdevmapper interface compares existing table line retrieved from
the kernel to new table line created to decide if it can suppress a reload.
Any difference between input and output of the table line is taken to be a
change thus causing a table reload.

The dm-raid target started to misorder the raid parameters (e.g. 'raid10_copies')
starting with dm-raid target version 1.9.0 up to (excluding) 1.11.0.  This causes
runtime failures (limited to raid10 as of tests) and needs to be reversed to allow
e.g. old lvm2 uspace to run properly.

Check for the aforementioned version range in libdm and adjust creation of the table line
to the respective (mis)ordered sequence inside and correct order outside the range
(as described for the raid target in the kernels Documentation/device-mapper/dm-raid.txt).
2017-03-23 01:20:00 +01:00
1bf90dac77 Revert "raid: adjust to misordered raid table line output"
This reverts commit 1e4462dbfb
in favour of an enhanced solution avoiding changes in liblvm
completetly by checking the target versions in libdm and emitting
the respective parameter lines.
2017-03-23 01:19:41 +01:00
14c4d32247 commands: fix combined thin pool and vol create defs
Fixes command defs related to creating a new thin pool and
then a new thin lv in the new pool.

1. lvcreate --size --virtualsize --thinpool
   Needs a cmd def, it was missing.
   The def is unique by the three required
   options: size, virtualsize and thinpool.

2. lvcreate --size --virtualsize --thinpool VG
   Needs a cmd def, it was missing.
   The def is unique by the three required
   options: size, virtualsize and thinpool,
   and one required positional arg: VG.

3. lvcreate --thin --virtualsize --size LV_new|VG
   This existing def should not accept an optional
   --type thin, which if used makes it indistinct
   from another def.

4. lvcreate --size --virtualsize VG
   This existing def should not accept an optional
   --type thin or --thin, which if used makes it
   indistinct from other defs (e.g. 3)
2017-03-21 22:04:01 -05:00
3be2e61c9f Revert "lvcreate: continue to accept --thinpool with -L and -V but not -T"
This reverts commit 642d682d8d.

Using the thinpool option with this cmd def makes it
indistinct from other cmd defs where thinpool is a
required option.
2017-03-21 22:01:19 -05:00
7126fb13e7 metadata: cleanup flags definition to be consistent
Use shift bitops throughout segtype.h.
2017-03-22 00:29:49 +01:00
1810162b51 WHATS_NEW: adjust to misordered raid parameters 2017-03-21 18:18:58 +01:00
1e4462dbfb raid: adjust to misordered raid table line output
The libdevmapper interface compares existing table line retrieved from
the kernel to new table line created to decide if it can suppress a reload.
Any difference between input and output of the table line is taken to be a
change thus causing a table reload.

The dm-raid target started to misorder the raid parameters (e.g. 'raid10_copies')
starting with dm-raid target version 1.9.0 up to (excluding) 1.11.0.  This causes
runtime failures (limited to raid10 as of tests) and needs to be reversed to allow
e.g. old lvm2 uspace to run properly.

Check for the aforementioned version range and adjust creation of the table line
to the respective (mis)ordered sequence inside and correct order outside the range
(as described for the raid target in the kernels Documentation/device-mapper/dm-raid.txt).
2017-03-21 18:17:42 +01:00
642d682d8d lvcreate: continue to accept --thinpool with -L and -V but not -T
lvcreate --thinpool POOL1 -L 100M --virtualsize 100M snapper_thinp

https://bugzilla.redhat.com/1434027

(The general rule is that a command is accepted if it is unambiguous.
The combination -L -V --thinpool uniquely identifies the operation.)
2017-03-20 22:04:37 +00:00
b3e833c777 man-generator: Remove unused variable.
man-generator.c:2976:6: warning: variable "sep" set but not used
2017-03-20 16:55:30 +00:00
862ca6e8b7 lvmdbusd: Rename ee to got_external_event
This variable is global, make it more descriptive.
2017-03-20 10:08:39 -05:00
b65a9230a3 lvmdbusd: Update state during pv move
Periodically update the state during pv move so that all the different
dbus objects reflect something close to reality during the process.
2017-03-20 10:08:39 -05:00
3ead4fb7ac lvmdbusd: Limit state refreshes for udev events
Udev events can come in like a flood when something changes.  It really
doesn't do us any good to refresh the state of the service numerous times
when 1 would suffice.  We had something like this before, but it was
removed when we added the refresh thread.  However, we have since learned
that we need to sequence events in the correct order and block dbus
operations if we believe the state has been affected, thus udev events are
being processed on the main work queue.  This change limits spurious
work items from getting to the queue.
2017-03-20 10:08:39 -05:00
7eeb093fdd lvmdbusd: Call add_no_notify for *move commands
Missed this in change when "add_no_notify" was added.  This was causing
extra external events to process when we did moves.
2017-03-20 10:08:38 -05:00
2dc71fc291 lvmdbusd: Only disable notify_dbus after getting external event
If we always disable the sending of notify dbus events then in the case
where all the users are lvm dbus users we will be in udev handling mode
until at least 1 external lvm command occurs.  Instead we will not disable
notify dbus until after we get at least 1 external event.  This makes the
service get into the correct mode of operation faster.
2017-03-20 10:08:38 -05:00
17b56a4aed tests: early detect leaking error dev
lvconvert should not leak 'error' device.

(This patch is not fix the problem, just makes it more easily visible
instead of more confusing 'clvmd' trace).
2017-03-20 14:18:50 +01:00
07040942ed man: advise against mirrored mirror log 2017-03-17 11:54:39 -05:00
8d7be8f5df help: align option list in pv/lv/vgchange cases
Align one-required options like is done for
optional options.
2017-03-17 11:23:38 -05:00
fec2ea76cf raid: check target version for shrink support
Starting with dm-raid target version 1.9.0 shrinking of mapped devices is supported.
Check for support being present in lvresize and lvreduce.

Related: rhbz1394048
2017-03-17 16:46:33 +01:00
17a8f3d6f0 raid: conditionally reject convert to striped/raid; fix
Fix a logic flaw introduced in commit 17bee733d1
preventing e.g. striped -> raid5 conversions.

Related: rhbz1191935
Related: rhbz1366296
2017-03-17 16:03:35 +01:00
6ebf39da91 WHATS_NEW: conditionally reject raid convert 2017-03-17 14:51:10 +01:00
76709aaf39 raid: cleanup; remove unused function
Remove unused function (lv_has_constant_stripes() is used instead).
2017-03-17 14:24:44 +01:00
07ea9887d3 tests: raise min dm cache version
Since we want to test different cache policies with profiles mq&smq
raise version to 1.8.

TODO: maybe split in more tests so older targets can test here as well.
N.B.: passthrough is also not supported with version 1.3
2017-03-17 14:22:33 +01:00
4a271e7ee7 properties: only thin-pool provides discards
Quering non-thin-pool segment for discard property may lead
to intenal error if the segment had set 'out-of-range' value,
so only thin-pool is allowed, for other it returns NULL.
2017-03-17 14:22:33 +01:00
d211c98581 lvm2app: correct internal API changes
Internal library gets more strict about setting discard and
zero_new_blocks parameter.
2017-03-17 14:22:33 +01:00
e0ea569045 raid: cleanup
Move function _raid45_to_raid54_wrapper() to avoid superfluous declaration.
2017-03-17 14:14:42 +01:00
1520fec3e8 raid: name variables consistently
Related: rhbz1191935
Related: rhbz1366296
2017-03-17 14:04:03 +01:00
17bee733d1 raid: conditionally reject convert to striped/raid0*
If SubLVs to be removed still exist after an image removing
conversion (i.e. "lvconvert --yes --force --stripes N "
with N < total stripes) any request to convert to a different
striped/raid* level has to be rejected until after those freed
SubLVs got removed by running the aforementioned lvconvert again.

Add tests to check conversion to striped/raid* gets rejected.
Enhance a test comment.

Related: rhbz1191935
Related: rhbz1366296
2017-03-17 13:58:54 +01:00
5e7bc8d854 man: Build man-generator in tools dir.
Use ln to make a copy of command.c for compilation with different DEFS
then handle dependencies the normal way.
2017-03-16 23:10:40 +00:00
270ed9bc90 man: Preserve template variables in pre-generated pages. 2017-03-16 23:08:59 +00:00
0c74afa1c6 make.tmpl: Support per-object DEFS.
Same as CFLAGS.
2017-03-16 23:03:03 +00:00
2d00767394 tools: Avoid man-generator compilation warnings.
Unused variables and make fns with missing prototypes static.
2017-03-16 22:39:04 +00:00
ad4158bac7 man: lvmraid(7) clarifications 2017-03-16 23:10:57 +01:00
4a3e30d102 WHATS_NEW: ensure raid6 upconversion restrictions 2017-03-16 22:33:08 +01:00
b917b12e2c WHATS_NEW: adjust mirror+raid DSOs to lvconvert --repair 2017-03-16 22:27:30 +01:00
b0336e8b3c lvconvert: ensure upconversion restrictions
Ensure minimum number of 3 data stripes on conversions to raid6.

Add test for it.

Resolves: rhbz1432675
2017-03-16 22:10:32 +01:00
76b843a4bf test: adjust to proper dm-raid target version
Adjust to final target version 1.10.1 supporting reshape
properly and to recently changed report field specifications
(e.g. rehape_len_le) to allow these tests to run.

Lower mirror region size to suite the tiny test VG.
2017-03-16 21:17:58 +01:00
a37bb7b2a5 dmeventd: adjust mirror/raid DSOs to new repair design
Previous commit 506d88a2ec introduced disabling lvmetad on repairs.

Avoid calling lvscan and use of any --config options altogether
in the mirror and raid DSOs.

Related: rhbz1380521
2017-03-16 21:05:05 +01:00
73d028023a lvmetad: fix bug in snprintf of disable reason 2017-03-16 12:15:40 -05:00
c8719d4e94 WHATS_NEW: disable lvmetad for repair 2017-03-16 11:56:19 -05:00
506d88a2ec lvconvert: disable lvmetad for repair
Repairing missing devices does not work reliably
with lvmetad, so disable lvmetad before repair.
A standard lvmetad refresh (pvscan --cache) will
enable lvmetad again.
2017-03-16 11:50:36 -05:00
e5b6f2685a dmeventd: reintroduce fix mirror DSO to work with lvmetad
Commit 07ded8059c assumed that the mirror is blocked which is not the case.

It is accessible, degraded and in need of repair because some of its legs
(partially) failed.  Any auto-repair via dmeventd fails though because
of lvmetad not providing proper data about the failed PV(s).  That's why
this workaround got introduced in commit 76f6951c3e until we get to
the lvmetad interaction core issue.

Mind any mirror auto-repair failure is caused by such lvmetad interaction
problems not yet solved so disabling lvmetad works as a resort as elaborated
on in the related bz.

Reintroducing the interim solution.

Resolves: rhbz1380521
2017-03-16 14:19:06 +01:00
a87715b6fd spec: Disable sanlock only, keep lockd_dlm enabled 2017-03-16 13:03:25 +01:00
19b65a3d76 spec: Replace remaining %define by %global 2017-03-16 13:03:24 +01:00
7067514c9b spec: Use %global instead of %define for constants
Using %define is now discouraged by Fedora Packaging Guidelines
2017-03-16 13:03:24 +01:00
5ba82a16db spec: Update requirements for lockd
lockd requires sanlock >= 3.3.0
2017-03-16 13:03:24 +01:00
cf0bf4b314 spec: Profiles are not %config(noreplace)
These files are just examples and should not be edited by user.
2017-03-16 13:02:24 +01:00
a4a6a7a526 man: Make dmfilemapd.8 optional 2017-03-16 12:26:51 +01:00
2fd5c8e908 spec: lvmchange is built-in command 2017-03-16 11:44:10 +01:00
affe055462 man: Handle empty MAN8GENERATED 2017-03-16 11:35:08 +01:00
51b9de7249 tests: better disk delay
Delay only writable extents.
Skip zeroing for earlier lvcreate finish.
2017-03-16 08:49:52 +01:00
7fa08ae4e8 tests: add missing --yes 2017-03-16 08:44:44 +01:00
e9b5a455e1 tools: Drop unused e2fsadm refs (replaced by fsadm). 2017-03-16 02:24:39 +00:00
8ef93c756e man: Include lvmchange/lvmsar/lvmsadc content in lvm.8
Remove separate lvmchange man page as the external command has also been
removed.
2017-03-16 02:09:51 +00:00
b0430b975b man: Reinstate previous lvmsar and lvmsadc pages.
Avoid listing all the common options for obsolete commands.
2017-03-16 01:49:40 +00:00
1cdaa8144d lvmsar/lvmsadc: Mention dmstats when run. 2017-03-16 01:36:02 +00:00
4f86519845 lvmchange: Move to a built-in command.
Has been obsolete since LVM1 and it's clear we'll never implement this.
2017-03-16 01:09:29 +00:00
9729fc4f8c man: Remove blank lines from pregenerated files 2017-03-16 00:50:27 +00:00
6d6ab310e5 man: reinstate lvmchange man page for now 2017-03-16 00:46:35 +00:00
07ded8059c mirror: revert 76f6951c3e
Effectively revert whole  76f6951c3e.
We need to figure out some other solution.

At this moment usage of --config  with 'repair' of blocked mirror
is 'freezing' combination.
2017-03-16 01:17:57 +01:00
4a727a3ccd raid: use 64bit arithmetic
Coverity - keep  multiplication for size cals in 64bit
(otherwise it's just 32b x 32b)
2017-03-16 01:02:10 +01:00
e3a51537c5 coverity: make sure segtype pointer is valid 2017-03-16 01:02:10 +01:00
42b970d4f3 libdm: fix endless loop
Coverity noticed endless loop (i not being changed).

TODO: test coverage
2017-03-16 01:02:10 +01:00
2a139993b4 thin: remove unneeed test for NULL
In this API NULL is not valid parameter so do not check for it.
2017-03-16 01:02:10 +01:00
0dcb928d1e coverity: update models
Latest versions do get quite  strange - so let's use suggestions
from their authors...
2017-03-16 01:02:10 +01:00
115fd205de mirror: avoid scanning
While mirror is blocked we can't try to scan device.
Regression introduce by previous commit
76f6951c3e.
2017-03-16 01:02:10 +01:00
849ab38e3c man: Minor clarifications and grammar corrections for lvmraid.7 2017-03-15 18:19:29 -05:00
7b6ee130cc man: remove blank lines from end/des files
which produce unwanted blank lines in some output
formats.
2017-03-15 15:59:43 -05:00
5c5df43ea3 help: fix missing newlines
Recent commits to remove newlines from man output
accidentally removed some newlines from help output.
2017-03-15 11:40:59 -05:00
60eb74a27a man: remove blank lines in included files 2017-03-15 11:30:34 -05:00
7e9bc77865 man: remove blank lines
Blank lines in the man source sometimes appear as extra
blank lines in the output, so remove them.
2017-03-15 11:05:31 -05:00
f536c53aee man: specify man-generator path 2017-03-15 01:36:12 +00:00
1dc1a1cedb make: Support for 'make -R'.
Aim to be self-sufficient.
2017-03-15 01:31:11 +00:00
531d7c97e7 man: remove more unnecessary line breaks
in case they cause extra blank lines in some output formats.
2017-03-14 16:28:20 -05:00
23d59c6fc1 man: remove redundant line breaks
unecessary .br and .P
2017-03-14 15:04:58 -05:00
5942fd18db args: clarify repeated --options lists 2017-03-14 13:52:09 -05:00
88b05391ff man clvmd: mention attempt for deactivate
attempt is always the case, but mention it again
2017-03-14 10:17:46 -05:00
c891918174 man: Adjust some wording and update examples style. 2017-03-14 14:55:36 +00:00
ca905681cc man: Revise internal man page generation process.
For each section 8 man page, a .8_gen file is created from one of:
  .8_main            - Old-style man page - content used directly
  .8_des and .8_end  - Description and end section of a generated page
  .8_pregen	     - Pre-generated page used if the generator fails

Other man sections are not generated and use the suffix .5_main or .7_main.

Developers should use 'make generate' to regenerate the .8_pregen files.
2017-03-14 00:47:46 +00:00
38292ca1d0 commands: fix command matching for unused options
When a given command:

- matches command definition A based on required options,
  but uses optional options that are not accepted by A.

- matches command definition B based on required options,
  (but fewer required items than A), and uses no
  unaccepted optional options.

then B is the correct choice.  Command A would fail because
of the unaccepted optional options.  The logic was mistakenly
letting A win because it had a greater number of required option
matches, without accounting for the optional option mismatches.
2017-03-13 13:37:07 -05:00
49cd54fc3a commands: fix lvcreate mirrors/stripes options
Systematically outline every combination of:
--type striped, --type mirror, --type raid, --mirrors, --stripes
and make sure each is assigned to one specific cmd def.

This revealed that a new command def is needed for
lvcreate that uses both --mirrors and --stripes
but no --type option.

The use of LVCREATE_RAID shortcut for an option set
resulted in mirrors/stripes being included in optional
opts set when they were already in the required list.
2017-03-13 13:37:07 -05:00
46b735c937 lvmetad: fix segfault on i386
Sending %d as format argument in lvmetad_vg_remove_pending() will cause
segfaults in config_make_nodes_v() when va_arg() casts to int64_t. Also, it is
clearly advertised in the lvm source code that using plain %d is prohibited, so
let's switch to FMTd64.

Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
2017-03-13 13:37:07 -05:00
5f2c942000 raid: check more cautious on region size changes
Add additional checks to avoid calling _region_size_change_requested()
with bogus actual arguments.
2017-03-13 17:46:56 +01:00
77a7ed065f dmfilemapd: ensure path argument is absolute
Require that the path argument to dmfilemapd be an absolute path
and document this in tool output, libdevmapper.h and dmfilemapd.8.

The check is also enforced by dm_stats_start_filemapd() to avoid
forking a new process with an invalid path argument.
2017-03-13 11:44:05 +00:00
9b0aba5fe9 dmfilemapd: return error for wrong number of args
The initial check on argc incorrectly returns 1 when the wrong
number of arguments are present, causing a segfault in main()
when no arguments are given:

  # dmfilemapd
  Wrong number of arguments.
  usage: dmfilemapd <fd> <group_id> <path> <mode> [<foreground>[<log_level>]]
  Segmentation fault (core dumped)
2017-03-13 11:09:11 +00:00
66760f9673 man: fix typo 2017-03-10 22:48:16 +01:00
09ad36fb9b report: fix lv_size with reshape space allocated
Commit f4b30b0dae was about displaying visible LV size
when reshape space is allocated.  Take parity devices
into account when displaying the user visible LV size.
2017-03-10 22:46:20 +01:00
c8671f6f79 commands: use correct relative signs with mirror option
As was recently done with relative signes for sizes/extents,
limit the signs used with the mirrors option, e.g.
lvcreate --mirrors now does not accept or advertise an
optional minus sign with the value.  lvconvert --mirrors
accepts +|-.
2017-03-10 15:41:29 -06:00
164d4a309c man: add more info/examples to lvmraid(7)
Add a warning about maximum supported numbers of stripes
with striped LVs realtive to RAID conversions.

Add examples for a more elaborate, multi-step conversion
from linear to striped (and vice versa).

Shrink lvs examples output.

Related: rhbz834579
Related: rhbz1191935
Related: rhbz1191978
2017-03-10 22:40:22 +01:00
15682270f4 commands: fix lvconvert options for mirrors/stripes
The LVCONVERT_RAID shortcut for including options ended
up including mirrors/stripes as optional opts in defs where
they were already required, or in defs where they would
not be used.  Remove the option set and specify in each
case only the options wanted.
2017-03-10 14:05:15 -06:00
5d3e870946 raid: fix compile time warning 2017-03-10 20:38:16 +01:00
53f5cf0af0 tests: cache profile and metadata2
New tests trying to cover support syntax variants.
A lot it still missing...
2017-03-10 19:33:02 +01:00
a11b875074 cleanup: use FMTu
Replace some PRIu with FMTu for formating strings.
2017-03-10 19:33:01 +01:00
d11b8eef89 cleanup: easier code 2017-03-10 19:33:01 +01:00
52935b5834 cache: enhance lvdisplay for cache volumes
Better support for lvdisplay.
By default info about running (in kernel) cache status is printed.
To get 'segtype' info, user runs: 'lvdisplay -m',  example:

  --- Logical volume ---
  LV Path                /dev/vg/lvol0
  LV Name                lvol0
  VG Name                vg
  LV UUID                Y4uWuN-TBGk-duer-aPWl-yBWn-iFFR-RU1gg1
  LV Write Access        read/write
  LV Creation host, time linux, 2017-03-01 20:52:39 +0100
  LV Cache pool name     lvol2
  LV Cache origin name   lvol0_corig
  LV Status              available
  # open                 0
  LV Size                12,00 MiB
  Cache used blocks      10,42%
  Cache metadata blocks  0,49%
  Cache dirty blocks     0,00%
  Cache read hits/misses 112 / 34
  Cache wrt hits/misses  133 / 0
  Cache demotions        0
  Cache promotions       20
  Current LE             3
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     256
  Block device           253:0

  --- Segments ---
  Logical extents 0 to 2:
    Type		cache
    Chunk size		64,00 KiB
    Metadata format	1
    Mode		writethrough
    Policy		smq
      Setting		migration_threshold=100000
2017-03-10 19:33:01 +01:00
4d2b1a0660 cache: enable usage of --cachemetadataformat
lvcreate and lvconvert may select cache metadata format when caching LV.
By default lvm2 picks best available format.
2017-03-10 19:33:01 +01:00
7b748b7cb8 cache: allow to specify cachemetadataformat
OO_LVCREATE_CACHE accepts --cachemetadataformat.

Support new option --cachemetadataformat auto|1|2 for caching.
Word 'auto' can be also be given as '0'.
2017-03-10 19:33:01 +01:00
0a9b52f7a4 cache: reporting cache metadata format
Report CMFmt column with cache metadata format version.

Report KMFmt column with 'kernel cache metadata format version' for device.
(a value reported from status).

(Update 'CacheMode' to name 'Cache' as primary segtype).
2017-03-10 19:33:01 +01:00
64d3f05aa1 cache: validation for cache_metadata_format
Only  cache-pool segtype may store cache_metadata_format.
Only supported values are 0,1,2
Format 2 requires LV status uses LV_METADATA_FORMAT.
Format 0 (unselected) or 1 shall not set this 'incompatible' status.
2017-03-10 19:33:01 +01:00
825c16e57e cache: use DM_CACHE_FEATURE_METADATA2 with libdm
Call libdm  with new feature flag when metadata format 2 is selected
and available in kernel cache target.
2017-03-10 19:33:01 +01:00
518b814cdb cache: LV supports cache segs with metadata format
Cache pool read/writes metadata_format within its segment type..

For CachePoolLV unselected metadata format is NOT stored in metadata.

For CacheLV when metadata format is not present/selected in lvm2 metadata,
it's automatically assumed to be the version 1 (backward compatible).

To ensure older lvm2 will not 'miss-read' metadata with new version 2,
such LV is marked with METADATA_FORMAT status flag (segment is
specifying metadata format). So when cache uses metadata format 2,
it will become inaccesible on older system without such support.
(kernel dm cache < 1.10,  lvm2 < 2.02.169).
2017-03-10 19:33:01 +01:00
4a394f410d cache: introduce allocation/cache_metadata_format
Add new profilable configation setting to let user select
which metadata format of a created cache pool he wish to use.

By default the 'best' available format is autodetected at runtime,
but user may enforce format 1 or 2 ATM.

Code also detects availability for metadata2 supporting cache target.

In case of troubles user may easily Disable usage of this feature
by placing 'metadata2' into global/cache_disabled_features list.
2017-03-10 19:33:01 +01:00
bb20fac4ab libdm: maintain binary interface for new FEATURE flag
Older library version was not detecting unknown 'feature' bits
and could let start target without needed option.

New versioned symbol now checks for supported feature bits.
_Base version keeps accepting only previously known features and
mask/ignores unknown bits.

NB: if the older binary passed in 'random' bits, it will not get
metadata2 by chance. New linked binary get new validation function.
Library user is required to not pass 'trash' for unsupported bits,
as such calls will be rejected.
2017-03-10 19:33:01 +01:00
ddd5a76801 libdm: support cache metadata2 feature flag
Dm cache target version 1.10 introduces new cache metadata format
(upstream kernel >=4.11).

New format is enable by passing new target feature flag metadata2.
Interace side on libdm uses DM_CACHE_FEATURE_METADATA2.
This feature bit is now also recognized on status
and set in 'feature_flags' field of dm_status_cache structure.

Code also adds check for 'highest' supported feature flag bit.
So it rejects properly any 'unknown' feature bit set by application.
2017-03-10 19:33:01 +01:00
bf79fb1a33 libdm: better code to enforce writethrough
Better code to enforce writethrough caching for cleaner policy.
Only check for cleaner when DM_CACHE_FEATURE_PASSTHROUGH or
DM_CACHE_FEATURE_WRITEBACK is set.
2017-03-10 19:33:01 +01:00
edf5e43f9a libdm: passthrough checks traling space char
When checking for passthrough length, check also for extra ' ' char
just like with other feature strings.
2017-03-10 19:33:01 +01:00
c717011f8e tests: use LVM_SYSTEM_DIR for etc
Instead of hardcoding etc/ dir  use $LVM_SYSTEM_DIR.
2017-03-10 19:33:01 +01:00
a9b78d26b1 cleanup: minor cosmetics
Update some return value to match return type.
Drop unused function and declaration.
2017-03-10 19:33:01 +01:00
21c265adcf cache: improve profile support for cache_set_policy 2017-03-10 19:33:01 +01:00
4d0793f0ec pool: rework handling of passed args
As now we can properly recognize all paramerters for pool creation,
we may drop PASS_ARG_  defines and rely on '_UNSELECTED' or 0 entries
as being those without user given args.

When setting are not given on command line - 'update' function
fill them from profiles or configuration. For this  'profile' arg
was needed to be passed around and since  'VG' itself is not needed,
it's been all replaced with 'cmd, profile, extents_size' args.
2017-03-10 19:33:01 +01:00
7c52d550e9 thin: single formula for estimation
Share the same formula for estimation chunk size or metadata size.
Use uint32_t matching type.
2017-03-10 19:33:00 +01:00
1cfc1be85d parser: enable --metadataprofile for pool lvconvert
Lvconvert can use values from profile when caching.
2017-03-10 19:33:00 +01:00
07c24736e0 parser: allow --zero for pool conversion 2017-03-10 19:33:00 +01:00
46820bfff3 lvconvert: share function for cache params
Reuse same code for getting/setting cache parameters with lvcreate.

So there is single one place how to get vars from profiles and configs.

Variables declarations are moved to start of function and
there is no need to initialize them as they are always
defined by functions get_cache_params() and get_pool_params().
2017-03-10 19:33:00 +01:00
298d12c459 lvcreate: do not round cache volumes on cache chunks
Since cache chunk might be huge and there is no technical need
to enforce rounding and there is actually more 'real' VG space
used then necessary - keep rounding on 'chunk' bounrary only
for thin volumes - where it's the space used anyway.

NB: we support conversion of any-size 'existing' LV into cached LV.
2017-03-10 19:33:00 +01:00
f24a1f06b2 lvcreate: respecting profile settings 2017-03-10 19:33:00 +01:00
36003df7e3 cache: extend usability of cache_set_params
Fix missing reset of '*settings' pointer when no args were given.

Handle cache_chunk settings like all other settings, so it is properly
updated only with non-zero settings and the existing cache-pool
chunk_size is not being reconfigured.
2017-03-10 19:33:00 +01:00
dcf038c7a6 cache: improve support for profile for cache settings
User can specify metadata profile which stores important cache
geometry data for easy configuration.

Fix missing support for getting chunk_size, cache_mode, cache_policy
for a cache/cache pools volumes from configuration or metadata profile.
2017-03-10 19:33:00 +01:00
c598e65de9 cache: get and set cache params 2017-03-10 19:33:00 +01:00
861992d874 lvconvert: replacing with goto
Split-off patch that just replaces returns with 'goto bad'
so there is single place to release  policy_settings.

In the next patch we will start to use some shared
function call between lvconvert and lvcreate
(effectively restoring previous logic which has got lost).
2017-03-10 19:33:00 +01:00
2d11fc695e cache: set chunk_size as first param 2017-03-10 19:33:00 +01:00
4184331965 cache: use UNSELECTED enum
Switch from _UNDEFINED to _UNSELECTED which is more describing
its value 0, while value -1 is better match for UNDEFINED.
2017-03-10 19:33:00 +01:00
b8cd0f4808 thin: add new ZERO/DISCARDS_UNSELECTED
To more easily recognize unselected state from select '0' state
add new 'THIN_ZERO_UNSELECTED' enum.
Same applies to THIN_DISCARDS_UNSELECTED.

For those we no longer need to use PASS_ARG_ZERO or PASS_ARG_DISCARDS.
2017-03-10 19:33:00 +01:00
8c72878cf2 pool: drop duplicated sign test
Avoid duplicate testing of '-' sign.
Already checked with arg_from_list_is_negative().
2017-03-10 19:33:00 +01:00
acfc82ae29 pool: split chunk size validation
Move cache and thin bits into their respective manipulation files.
When possible directly call respective chunk_size validator.
2017-03-10 19:33:00 +01:00
375e4bb3da thin: getting default chunk_size from single place
Basically code moving operation to have a single place resolving
thin_pool_chunk_size_policy.

Supported are generic & performance profiles.

Function is now shared between thin manipulation code and configuration
_CFG logic to obtain defaults and handle correct reporting upward coding
stack.
2017-03-10 19:33:00 +01:00
50441f2433 cache: properly translate DM_THIN_DISCARDS
DM status uses DM defines which need to be translated to LVM enum.
2017-03-10 19:33:00 +01:00
f221ba97c9 lvcreate: avoid rejecting --metadataprofile
Likely user normaly have used 'shortcut' --profile option which
is (for lvcreate) decoded as metadataprofile.

However full option was rejected.
2017-03-10 19:33:00 +01:00
fb38426d28 lvconvert: validate name before prompt
Before prompting make sure name fits.
2017-03-10 19:33:00 +01:00
7ad57d55af lvconvert: indent and code simplification
Simple modifications to existing  _lvconvert_to_pool().
2017-03-10 19:33:00 +01:00
dd2881f277 raid: enhance lv_raid_convert() header relative to reshaping 2017-03-10 19:26:02 +01:00
2fcbe34fe8 lvcreate: fix "striped" limit
Fix regression limiting number of stripes to 8.
Raise back to 128 as before.

Resolves: rhbz1389546
2017-03-10 18:57:06 +01:00
43388f1220 commands: fix missing skip condition in coverity fixes
Fix for commit 5e6ea4b7
2017-03-10 11:50:00 -06:00
a9341b18ef daemons: use DEFAULT_PROC_DIR in dmfilemapd
Include defaults.h and use it to obtain the default procfs mount
point in dmfilemapd.
2017-03-10 17:26:47 +00:00
b17eb054cd daemons: cleanup dmeventd references from dmfilemapd/Makefile.in 2017-03-10 17:26:47 +00:00
5e6ea4b784 commands: coverity fixes 2017-03-10 10:54:42 -06:00
8c6b8e90e3 libdm: use correct value for NR_FILEMAPD_ARGS
The argument count for the file mapping daemon needs to account
for the program's name in argv[0] to avoid indexing off the end
of the argument array.
2017-03-10 16:52:27 +00:00
c713745314 dmsetup: always initialise 'dms' in _stats_update_file() 2017-03-10 16:44:08 +00:00
d28a50ec76 libdm: make dm_stats_destroy(NULL) a no-op
Test for NULL in dm_stats_destroy() and return immediately if
the struct dm_stats pointer is NULL (similar to free(NULL)).

This simplifies cleanup code which otherwise needs to:

  out:
    if (dms)
        dm_stats_destroy(dms);
    return;
2017-03-10 16:41:28 +00:00
93644be44b libdm: dm_stats_start_filemapd() mode can never be < 0 2017-03-10 14:42:23 +00:00
bc3bec6c54 raid: fix compile time warning 2017-03-10 14:43:37 +01:00
59e57be54f man: add man-generator and build artefacts to .gitignore 2017-03-10 13:14:02 +00:00
1f7ac54bc4 tools: add generated headers to .gitignore 2017-03-10 13:13:41 +00:00
6a0f597727 dmsetup: always initialise 'mode' in filemap create functions
Older compilers cannot tell that the 'mode' variable is only
used in branches in which it is assigned:

dmsetup.c:5651: warning: "mode" may be used uninitialized in this function
dmsetup.c:5023: warning: "mode" may be used uninitialized in this function

Avoid this by always assigning the variable a value.
2017-03-10 12:17:25 +00:00
146b2582b0 libdm: move initialisation of group_id in _aggregate_histogram()
Older compilers are not able to determine that although group_id
is only assigned in one branch of a conditional, it is never used
used when the other branch is taken:

  libdm-stats.c:3319: warning: "group_id" may be used uninitialized in this function

Avoid this by always initialising the variable when it is
declared.
2017-03-10 11:45:08 +00:00
97b6486b27 lvmdbustest.py: Correct debug & assert order
If we do the assert first we won't get to the print statement.
2017-03-09 16:39:47 -06:00
ee7946ed82 lvmdbustest.py: Correct call_lvm doc 2017-03-09 16:39:47 -06:00
957e283de8 lvmdbusd: Simplify add_no_notify for loop 2017-03-09 16:39:47 -06:00
075f8e658c lvmdbusd: Correct utils.add_no_notify doc 2017-03-09 16:39:47 -06:00
00143753ee lvmdbusd: Add debug message to lvm ID lookup 2017-03-09 16:39:47 -06:00
28754145d8 lvmdbustest.py: Add unit test for external PV create
Ensure a PV created outside of the dbus service is immediately found by
service user.
2017-03-09 16:39:47 -06:00
e06e4d9355 lvmdbustest.py: Add unit test for external LV create
Ensure a LV created outside of the dbus service is immediately found by
service user.
2017-03-09 16:39:47 -06:00
43d0fbeba2 lvmdbustest.py: Add unit test for external VG create
Ensure a VG created outside of the dbus service is immediately found by
service user.
2017-03-09 16:39:47 -06:00
92b7c329ee lvmdbustest.py: Remove un-used import time 2017-03-09 16:39:47 -06:00
0c0002d765 lvmdbusd: Correct src doc for Manager.UseLvmShell
It returns a boolean.
2017-03-09 16:39:47 -06:00
11cfc58976 lvmdbusd: Disable notify_dbus for service command use
Utilizing the --config option  we will utilize global/notify_dbus=0 so
that the service itself doesn't generate change events which it then needs to
process.
2017-03-09 16:39:47 -06:00
e53454d6de lvmdbusd: Use work queue for queries too
We need to place query operations in the queue to prevent the case where
a client knows of something before the service does.  For example if a
client creates a PV/VG/LV outside of the dbus API and then immediately
tries to lookup and use that resource in the lvm dbus service it should
be present.  By placing the queries in the work queue any previous
refresh operation will complete before we process the query.
2017-03-09 16:39:47 -06:00
470a1f1c50 lvmdbusd: Add FlightRecorderDump
Diagnostic method for dumping flight recorder to syslog.
2017-03-09 16:39:47 -06:00
f2d7a48418 lvconvert: add raid1 <-> raid4 conversion
In addition to the already supported conversion between 2-legged
raid1 and raid5, raid1 and raid4 can be also converted into each
other with 2 legs (raid4/5 are limited to map a 2-legged raid1).

This patch supports the missing raid4 conversion in the sequence
linear -> 2-legged raid1 -> raid4/5, then restripe to more than one
data stripes for performance and resilience reasons and optionally
convert to striped/raid0.

The other conversion sequence is also possible by converting N-way
striped/raid0 to raid4/5, then restripe to 2 legs followed by a
conversion to raid1 and optionally to linear (loosing all resilience).
2017-03-09 23:18:13 +01:00
d2aae8cff4 man: add more examples to lvmraid(7)
Add examples for reshaping number of stripes
and converting from raid6 to striped to raid10.

Remove trailing spaces.

Related: rhbz834579
Related: rhbz1191935
Related: rhbz1191978
2017-03-09 23:18:13 +01:00
1ba11aa7ee dmfilemapd: always set the program_id after listing regions
The filemap daemon takes its program_id from the regions it is
managing: use DM_STATS_ALL_PROGRAMS when retrieving an initial
listing and then obtain the correct program_id from the group
leader.
2017-03-09 21:20:27 +00:00
0104fd6c66 libdm: don't nest FIEMAP and DMFILEMAPD ifdefs 2017-03-09 21:20:27 +00:00
af7a11bc57 configure: make --enable-dmfilemapd require fiemap.h 2017-03-09 21:20:27 +00:00
66fff1d774 raid: add missing lv_merge_segments() call
On conversion from striped to raid0, data LVs are created
and all segments and their respective areas of the striped
LV are moved across to new segments allocated for the raid0
image LVs.  This can cause non-canonical segments to be added
to the image LVs.

Add a call to lv_merge_segments() once all segments have been
added to an image LV to compensate for that.  This avoids
unsafe table loads on activation.

Fix comments.
2017-03-09 22:18:34 +01:00
76f6951c3e dmeventd: (workaround) fix mirror DSO to work with lvmetad
Automatic dmeventd repair of mirrors with active lvmetad configured
(mirror_image_fault_policy = "allocate") fails because the lvscan
run before the repair in the mirror DSO does not update the
lvmetad cache properly thus "lvconvert --repair ..." fails.

Need to scan the mirror LV before and after the repair
to have proper cache content after the repair finished.
The cache can't be relied on or the repair will fail.

Resolves: rhbz1380521
2017-03-09 20:41:07 +01:00
67ddc0c292 man: add FILE MAPPING section to dmstats.8.in
Add a section to explain file mapping, outside of the individual
command descriptions, and to describe the limitations of the
current update strategy.
2017-03-09 18:50:15 +00:00
b5c8accdf2 man: add dmfilemapd options to dmstats.8.in
Add descriptions of --follow and --nomonitor, and the behaviour
of create and update_filemap when starting dmfilemapd.
2017-03-09 18:50:15 +00:00
baa8a9be4a dmstats: start dmfilemapd when creating or updating file maps
Launch an instance of the filemap monitoring daemon when creating,
or updating, a file mapped group, unless the --nomonitor switch is
given.

Unless --foreground is given the daemon will detach from the
terminal and run in the background until it is signaled or the
daemon termination conditions are met.

The --follow={inode|path} switch is added to control the daemon
behaviour when files are moved, unlinked, or renamed while they
are being monitored.

The daemon runs with the same verbosity as the dmstats command
that starts it.
2017-03-09 18:50:15 +00:00
044f92e466 man: add dmfilemapd.8 2017-03-09 18:50:15 +00:00
8b78982297 daemons: add dmfilemapd
Add a daemon that can be launched to monitor a group of regions
corresponding to the extents of a file, and to update the regions as the
file's allocation changes.

The daemon is intended to be started from a library interface, but can
also be run from the command line:

  dmfilemapd <fd> <group_id> <path> <mode> [<foreground>[<log_level>]]

Where fd is a file descriptor open on the mapped file, group_id is the
group identifier of the mapped group and mode is either "inode" or
"path". E.g.:

  # dmfilemapd 3 0 vm.img inode 1 3 3<vm.img
  ...

If foreground is non-zero, the daemon will not fork to run in the
background. If verbose is non-zero, libdm and daemon log messages will
be printed.

It is possible for the group identifier to change when regions are
re-mapped: this occurs when the group leader is deleted (regroup=1 in
dm_stats_update_regions_from_fd()), and another region is created before
the daemon has a chance to recreate the leader region.

The operation is inherently racey since there is currently no way to
atomically move or resize a dm_stats region while retaining its
region_id.

Detect this condition and update the group_id value stored in the
filemap monitor.

A function is also provided in the the stats API to launch the filemap
monitoring daemon:

  int dm_stats_start_filemapd(int fd, uint64_t group_id, const char *path,
                              dm_filemapd_mode_t mode, unsigned foreground,
                              unsigned verbose);

This carries out the first fork and execs dmfilemapd with the arguments
specified.

A dm_filemapd_mode_t value is specified by the mode argument: either
DM_FILEMAPD_FOLLOW_INODE, or DM_FILEMAPD_FOLLOW_PATH. A helper function,
dm_filemapd_mode_from_string(), is provided to parse a string containing
a valid mode name into the appropriate dm_filemapd_mode_t value.
2017-03-09 18:50:15 +00:00
c98868181f libdm: remove unnecessary backtrace in _stats_group_id_present()
It's not an error to call dm_stats_group_present() on a handle
that contains no regions.

This causes dmfilemap to log a false backtrace during shutdown
if all regions are removed from the corresponding device:

  exiting _filemap_monitor_get_events() with deleted=0, check=0
  waiting for FILEMAPD_WAIT
  dm message   (253:1) [ opencount flush ]  @stats_list dmstats [32768] (*1)
  <backtrace>
  Filemap group removed: exiting.

Change this to only emit a backtrace if the handle is NULL.
2017-03-09 17:53:15 +00:00
fab088cbc7 man lvmraid: remove fixmes, use consistent example name 2017-03-09 11:48:30 -06:00
716c345334 tests relative-sign-options: only skip thin part 2017-03-09 11:29:54 -06:00
43bcd7393c tests relative-sign-options.sh: skip without thin 2017-03-09 10:43:41 -06:00
aa31272223 lvresize: poolmetadatasize cannot use minus 2017-03-09 09:51:24 -06:00
6dfe1ce251 lvconvert: prompt when splitting off LV of a 2-legged raid1 LV
Splitting off an image LV of a 2-legged
raid1 LV causes loss of resilience.

Ask user to avoid uninformed loss of all resilience.

Don't ask for N > 2 legged raid1 LVs.

Adjust tests.
2017-03-09 13:59:47 +01:00
6b1b66c266 test: raid1 down convert to linear
Missed one test in last commit.
2017-03-09 13:21:21 +01:00
4b0ae266c2 test: raid1 down convert to linear
Add/adjust more tests for commit 7fbe6ef16b.
2017-03-09 13:16:08 +01:00
413164765f lvconvert: remove superfluous compile time conditonal code 2017-03-09 12:16:11 +01:00
3d1df10af3 test: raid1 down convert to linear / split and track tests
Add/adjust tests for commits d250aa7208 and 7fbe6ef16b.
2017-03-09 04:01:47 +01:00
d250aa7208 lvconvert: prompt when splitting off a tracked LV of a 2-legged raid1 LV
Splitting off an image LV of a 2-legged raid1 LV tracking changes
causes loosing partial resilience for any newly written data set.
Full resilience will be provided again after the split off image LV
got merged back in and the new data set got fully synchronized.
Reason being that the data is only stored on the remaining single
writable image during the split.

Ask user to avoid uninformed loss of such partial resilience.

Don't ask for N > 2 legged raid1 LVs.
2017-03-09 03:22:55 +01:00
7fbe6ef16b lvconvert: prompt when converting raid1 to linear
Ask user when converting raid1 to linear to avoid
uninformed loss of all resilience.
2017-03-09 02:39:49 +01:00
8daad11666 test: "lvconvert --repair" after vgreduce
Add test for commit 921b496fff.
2017-03-09 02:35:57 +01:00
90ed3d5e8c raid: fix function description 2017-03-09 02:16:03 +01:00
921b496fff lvconvert: fix --repair after vgreduce
In case N images fail (N <= parity chunks) _and_
a "vgreduce --removemissing --force VG" was applied
a following repair of the RaidLV fails:

  Unable to remove N images:  Only 0 devices given.
  Failed to remove the specified images from tb/r.
  Failed to replace faulty devices in tb/r.

Fix as of this commit results in correct repair:

  Faulty devices in tb/r successfully replaced.
2017-03-09 02:11:52 +01:00
00b8c2bebc test: Copyright 2017-03-09 00:10:55 +01:00
b4e78b26f5 help: fix missing required option
Fix for previous commit 4d0172ff15.
2017-03-08 15:00:27 -06:00
4d0172ff15 man/help: use order of required options from cmd def
Follow the same as written in command-lines.in
2017-03-08 14:51:08 -06:00
3d5182c819 man: add more references to topical man pages 2017-03-08 14:43:30 -06:00
14c7912f45 tests: add test for relative option values
Combinations of: lvcreate/lvresize/lvextend/lvreduce,
--size/--extents/--poolmetadatasize, +/-/nosign.
2017-03-08 13:51:33 -06:00
a6a2788e7c commands: clean up and unify signed option value handling
Add new values for different sign variations, resulting in:

size_VAL      no sign accepted
ssize_VAL     accepts + or -
psize_VAL     accepts +
nsize_VAL     accpets -

extents_VAL   no sign accepted
sextents_VAL  accepts + or -
pextents_VAL  accepts +
nextents_VAL  accepts -

Depending on the command being run, change the option
values for --size, --extents, --poolmetadatasize to
use the appropriate value from above.

lvcreate uses no sign (but accepts + and ignores it).
lvresize accepts +|- for a relative change.
lvextend accepts + for a relative change.
lvreduce accepts - for a relative change.
2017-03-08 12:54:43 -06:00
7f25fbe154 report: fix segfault
Commit f4b30b0dae which was about displaying visible
LV size when reshape space is allocated did not account
for undefined first lv segment.
2017-03-08 18:32:01 +01:00
11f1556d5d commands: combine duplicate arrays for lv types and props
Like opt and val arrays in previous commit, combine duplicate
arrays for lv types and props in command.c and lvmcmdline.c.
Also move the command_names array to be defined in command.c
so it's consistent with the others.
2017-03-08 11:03:02 -06:00
690f604733 commands: combine duplicate arrays for opt and val
command.c and lvmcmdline.c each had a full array defining
all options and values.  This duplication was not removed
when the command.c code was merged into the run time.
2017-03-08 11:03:02 -06:00
f48e6b2690 help: avoid end notes repetition in lvm help all 2017-03-08 11:03:02 -06:00
ed58672029 metadata: comments
log_count,nosync,stripes,stripe_size,,...  are also used for raid.
2017-03-08 15:13:59 +01:00
3a5561e5ab raid: define seg->extents_copied
seg->extents_copied has to be defined properly on reducing
the size of a raid LV or conversion from raid5 with 1 stripe
to raid1 will fail.

Related: rhbz834579
Related: rhbz1191935
Related: rhbz1191978
2017-03-07 23:28:09 +01:00
aedac100f9 report: correct lv_size for 2-legged raid5
Reshaping a raid5 LV to one stripe aiming to convert it to
raid1 (and optionally to linear) reports the wrong LV size
when still having reshape space allocated.
2017-03-07 22:36:50 +01:00
18bbeec825 raid: fix raid LV resizing
The lv_extend/_lv_reduce API doesn't cope with resizing RaidLVs
with allocated reshape space and ongoing conversions.  Prohibit
resizing during conversions and remove the reshape space before
processing resize.  Add missing seg->data_copies initialisation.

Fix typo/comment.
2017-03-07 22:05:23 +01:00
9ed11e9191 raid: cleanup _lv_set_image_lvs_start_les()
Avoid second loop.
2017-03-07 21:55:19 +01:00
05aceaffbd lvconvert: adjust --stripes on raid10 convert
For the time being raid10 is limited to even number of total stripes
as is and 2 data copies.  The number of stripes provided on creation
of a raid10(_near) LV with -i/--stripes gets doubled to define
that even total number of stripes (i.e. images).

Apply the same on disk adding conversions (reshapes) with
"lvconvert --stripes RaidLV" (e.g. 2 stripes = 4 images
total converted to 3 stripes = 6 images total).

Related: rhbz834579
Related: rhbz1191935
Related: rhbz1191978
2017-03-07 21:36:03 +01:00
f4b30b0dae report: display proper LV size for reshapable RaidLVs
Subtract reshape space when reporting visible lv_size on RaidLV.

Related: rhbz834579
Related: rhbz1191935
Related: rhbz1191978
2017-03-07 18:47:20 +01:00
43fb4aa69b test: add delay to lvchange-raid1-writemostly.sh
Commit 8ab0725077 introduced this new test.

Add a read delay to the PVs to avoid a race
in the script causing the test to fail.

Correct comment.
2017-03-07 15:18:13 +01:00
872932a0fb man lvs: describe new 'R' volume health character 2017-03-06 19:33:10 +01:00
0b019c5406 man/help: improve stripes option wording 2017-03-06 12:20:33 -06:00
ef97360866 man lvextend: mention segment type 2017-03-06 11:27:56 -06:00
17838e6439 test: fix typo 2017-03-03 23:22:29 +01:00
11589891d7 man: move the full UNIT description
Part of the UNIT description was still living in the
--size description.  Move it to the Size[UNIT] description
since it is used by other options, not just --size.
2017-03-03 16:12:02 -06:00
b6c4b7cfb0 man/help: poolmetadatasize option can take relative value
In lvcreate/lvconvert, --poolmetdatasize can only be an
absolute value, but in lvresize/lvextend, --poolmetadatasize
can be given a + relative value.

The val types only currently support relative values that
go in both directions +|-.  Further work is needed to add
val types that can be relative in only one direction, and
switching various option values to one those depending on
the command name.  Then poolmetdatasize will not appear
with a +|- option in lvcreate/lvconvert, and will
appear with only the + option in lvresize/lvextend.
2017-03-03 16:12:02 -06:00
c5b6c9ad44 report: raid enhancements for --select
Enhance the raid report functions for the recently added LV fields
reshape_len, reshape_len_le, data_offset, new_data_offset, data_copies,
data_stripes and parity_chunks to cope with "lvs --select".

Related: rhbz834579
Related: rhbz1191935
Related: rhbz1191978
2017-03-03 22:29:50 +01:00
6dea1ed5ae man: fix term in lvmraid(7)
Adjust commit af7c8e7106 to use "image/leg".

Related: rhbz834579
Related: rhbz1191935
Related: rhbz1191978
2017-03-03 22:24:53 +01:00
e4ef3d04ad help: show short opt with long opt
e.g. show -n|--name instead of just --name
2017-03-03 15:14:18 -06:00
547bdb63e1 dev_manager: remove reshape message
The dm-raid target doesn't support a "reshape" message.
2017-03-03 22:10:21 +01:00
9a50df291a man/help: rework extents and size output
Clean up and correct the details around --extents and --size.

lvcreate/lvresize/lvreduce/lvextend all now display the
extents option in usages.

The Size and Number value variables for --size and --extents
are now displayed without the [+|-] prefix for lvcreate.
2017-03-03 14:23:50 -06:00
e7ee89d80b man/help: improve the PV range description 2017-03-03 11:15:27 -06:00
2a5e24580a args: in cachemode option fix passthrough value 2017-03-03 10:53:18 -06:00
191a2517be args: update select description
mention --select help and --options help.
2017-03-03 09:53:11 -06:00
1a0d57f895 man lvcreate: show extents option
Display --extents as an option in each cmd def,
in addition to the special notes about how
--size and --extents are alternatives.
2017-03-02 16:58:19 -06:00
9a62767f2d man lvcreate: remove the extents prefix
This applies the same hack to --extents (dropping
the [+|-] prefix), as commit b7831fc14a did for --size.
2017-03-02 16:58:19 -06:00
5d39927f22 help: show extents option for lvcreate
A special case is needed to display
--extents for lvcreate since the cmd defs
treat --extents as an automatic alternative
to --size (to avoid duplicating every cmd def).
2017-03-02 16:58:19 -06:00
9b23d9bfe4 help: print info about special options and variables
when --longhelp is used
2017-03-02 16:58:19 -06:00
f350283398 lvcreate: munge size value in help output
Add hack to omit the [+|-] from the --size
value.  Same hack exists in man generator.
2017-03-02 16:58:19 -06:00
af7c8e7106 man: cover reshaping
Related: rhbz834579
Related: rhbz1191935
Related: rhbz1191978
2017-03-02 22:24:19 +01:00
ca859b5149 lvs: enhance stripes and region size field descriptions
Now that we got the "data_stripes" field key, adjust the "stripes" field description.
Enhance the "regionsize" field description to cover raids as well.
2017-03-02 22:22:16 +01:00
d3bcec5993 man: change the synopsis option style
Remove the required/optional words because it
should already be evident from the use of [ ].
2017-03-02 14:08:59 -06:00
910918d1c2 lvcreate: allow chunksize option when creating cache 2017-03-02 13:58:27 -06:00
6360ba3d2d commands: handle including an optional opt multiple times
When a cmd def includes multiple sets of options (OO_FOO),
allow multiple OO_FOO sets to contain the same option and
avoid repeating it in the cmd def.
2017-03-02 13:52:06 -06:00
b7831fc14a lvcreate/lvresize: the --size option accepts signed values
There was confusion in the code about whether or not the
--size option accepted a sign.  Make it consistent and clear
that it does.

This exposes a new problem in that an option can only
accept one value type, e.g. --size can only accept a
signed number, it cannot accept a positive or negative
number for some commands and reject negative numbers for
others.

In practice, lvcreate accepts only positive --size
values and lvresize accepts positive or negative --size
values.  There is currently no way to encode this
difference.  Until that is fixed, the man page output
is hacked to avoid printing the [+|-] prefix for sizes
in lvcreate.
2017-03-02 12:53:01 -06:00
70c1fa3764 tools: Fix overriding of current_settings.
Settings specified in other command line args take precedence over
profiles and --config, which takes precedence over settings in actual
config files.

Since commit 1e2420bca8 ('commands: new
method for defining commands') commands like this:
  lvchange --config 'global/test=1' -ay vg
have been printing the 'TEST MODE' message, but nevertheless making
real changes.
2017-03-02 16:41:41 +00:00
8df3f300ba commands: adjust syntax error message 2017-03-02 09:46:41 -06:00
b76852bf35 man lvchange: mention special activation vals
used by lvmlockd and clvmd.
2017-03-02 09:31:06 -06:00
26ca308ba9 lvmdbustest.py: Remove un-used variable
Not needed with new validation function.
2017-03-01 17:47:04 -06:00
7b0371e74e lvmdbustest.py: Validate LV lookups
Ensure that the LV lookups work as expected for newly created LVs.
2017-03-01 17:47:04 -06:00
83249f3327 lvmdbustest.py: Validate PV device
Validate device lookup after PV creation.
2017-03-01 17:47:04 -06:00
4c89d3794c lvmdbustest.py: Re-name validation function
Make this name generic as we can use for different types.
2017-03-01 17:47:04 -06:00
10c3d94159 lvmdbustest.py: Verify lookups work immediately after vg create 2017-03-01 17:47:04 -06:00
157948b5a5 lvmdbustest.py: Use _lookup function
Be consistent in using this helper function for dbus object lookups.
2017-03-01 17:47:04 -06:00
c25b95e2ef man: fix typo 2017-03-01 16:59:51 -06:00
51dfbf1fb3 commands: tweak some descriptions 2017-03-01 16:59:51 -06:00
daf1d4cadc lvconvert: add new reporting fields for reshaping
Commit 48778bc503 introduced new RAID reshaping related report fields.

The inclusioon of segtype.h in properties.c isn't mandatory, remove it.

Related: rhbz834579
Related: rhbz1191935
Related: rhbz1191978
2017-03-01 19:30:52 +01:00
fb42874a4f lvconvert: libdm RAID API compatibility versioning; remove new function
Commit 80a6de616a versioned the dm_tree_node_add_raid_target_with_params()
and dm_tree_node_add_raid_target() APIs for compatibility reasons.

There's no user of the latter function, remove it.

Related: rhbz834579
Related: rhbz1191935
Related: rhbz1191978
2017-03-01 18:58:48 +01:00
48778bc503 lvconvert: add new reporting fields for reshaping
During an ongoing reshape, the MD kernel runtime reads stripes relative
to data_offset and starts storing the reshaped stripes (with new raid
layout and/or new stripesize  and/or new number of stripes) relative
to new_data_offset.  This is to avoid writing over any data in place
which is non-atomic by nature and thus be recoverable without data loss
in the transition.  MD uses the term out-of-place reshaping for it.

There's 2 other areas we don't have report capability for:
- number of data stripes vs. total stripes
  (e.g. raid6 with 7 stripes toal has 5 data stripes)
- number of (rotating) parity/syndrome chunks
  (e.g. raid6 with 7 stripes toal has 2 parity chunks; one
   per stripe for P-Syndrome and another one for Q-Syndrome)

Thus, add the following reportable keys:

- reshape_len      (in current units)
- reshape_len_le   (in logical extents)
- data_offset      (in sectors)
- new_data_offset  (     "    )
- data_stripes
- parity_chunks

Enhance lvchange-raid.sh, lvconvert-raid-reshape-linear_to_striped.sh,
lvconvert-raid-reshape-striped_to_linear.sh, lvconvert-raid-reshape.sh
and lvconvert-raid-takeover.sh to make use of new keys.

Related: rhbz834579
Related: rhbz1191935
Related: rhbz1191978
2017-03-01 18:50:35 +01:00
62abae1525 man: put some commands into advanced usage section
and separate commands with --
2017-03-01 10:22:48 -06:00
eb9586bd3b commands: SECONDARY flag changes in cmd defs
Add/remove the SECONDARY_SYNTAX flag to cmd defs.
cmd defs with this flag will be listed under the
ADVANCED USAGE man page section, so that the main
USAGE section contains the most common commands
without distraction.

- When multiple cmd defs do the same thing, one variant
  can be displayed in the first list.
- Very advanced, unusual or uncommon commands should be
  in the second list.
2017-03-01 10:22:48 -06:00
d6dd700bf7 raid: rework _raid_target_present()
Recently added check for reshaping in this function called for
a cleanup to avoid proliferating it with more explicit conditionals.

Base the reshaping check on the given _features array.

Related: rhbz834579
Related: rhbz1191935
Related: rhbz1191978
2017-03-01 14:52:23 +01:00
7a064303fe lvconvert: add missing reshape_len initialization
An initialization was missing when converting striped to raid0(_meta)
causing unitialized reshape_len in the new component LVs first segment.

Related: rhbz834579
Related: rhbz1191935
Related: rhbz1191978
2017-02-28 23:29:03 +01:00
964114950c lvconvert: adjust mininum region size check
The imposed minimum region size can cause rejection on
disk removing reshapes.  Lower it to avoid that.

Related: rhbz834579
Related: rhbz1191935
Related: rhbz1191978
2017-02-28 23:10:37 +01:00
1828822bd8 help: print full usage for lvm help all 2017-02-28 15:58:14 -06:00
ce1e5b9991 lvconvert: adjust reshaping check to target version
https://git.kernel.org/cgit/linux/kernel/git/device-mapper/linux-dm.git/commit/?h=dm-4.11&id=b08c6076782
sets the dm-raid target version to 1.10.1.

Adjust the condition to set RAID_RESHAPE_FEATURE to it.

Related: rhbz834579
Related: rhbz1191935
Related: rhbz1191978
2017-02-28 22:46:25 +01:00
80a6de616a lvconvert: libdm RAID API compatibility versioning
Commit 27384c52cf lowered the maximum number of devices
back to 64 for compatibility.

Because more members have been added to the API in
'struct dm_tree_node_raid_params *', we have to version
the public libdm RAID API to not break any existing users.

Changes:

- keep the previous 'struct dm_tree_node_raid_params' and
  dm_tree_node_add_raid_target_with_params()/dm_tree_node_add_raid_target()
  in order to expose the already released public RAID API

- introduce 'struct dm_tree_node_raid_params_v2' and additional functions
  dm_tree_node_add_raid_target_with_params_v2()/dm_tree_node_add_raid_target_v2()
  to be used by the new lvm2 lib reshape extentions

With this new API, the bitfields for rebuild/writemostly legs in
'struct dm_tree_node_raid_params_v2' can be raised to 256 bits
again (253 legs maximum supported in MD kernel).

Mind that we can limit the maximum usable number via the
DEFAULT_RAID{1}_MAX_IMAGES definition in defaults.h.

Related: rhbz834579
Related: rhbz1191935
Related: rhbz1191978
2017-02-28 22:34:00 +01:00
21456dcf7f commands: include lvconvert cache options as group 2017-02-28 13:47:46 -06:00
89661981e8 man: fix syntax for PV ranges 2017-02-28 12:22:12 -06:00
4a14617dc4 commands: remove lvconvert raid rule
A raid0 LV also needs to be converted to other
raid levels, so this rule should be removed entirely.
2017-02-27 17:06:08 -06:00
f9d28f1aec man: mention regionsize default is in lvm.conf 2017-02-27 17:05:20 -06:00
998151e83e commands: fix lvconvert raid rule
Recent rule change was incorrect.
We want to allow 'lvconvert --type raid' on raid1 LVs.
2017-02-27 16:33:38 -06:00
8d0df0c011 commands: fixes for recent raid changes
- Combine the equivalent lvconvert --type raid defs.
  (Two cmd defs must be different without relying
  on LV type, which are not known at the time the
  cmd def is matched.)

- Remove unused optional options from lvconvert --stripes,
  and lvconvert --stripesize.

- Use Number for --stripes_long val type.

- Combine the cmd def for raid reshape cleanup into the
  existing start_poll cmd def (they were duplicate defs).
  Calls into the raid code from a poll opertion will be
  added.
2017-02-27 14:44:00 -06:00
27384c52cf lvconvert: limit libdm to maximum of 64 RAID devices
Commit 64a2fad5d6 raised the maximum number of RAID devices to 64.

Commit e2354ea344 introduced RAID_BITMAP_SIZE as 4 to have
256 bits (4 * 64 bit array members), thus changing the libdm API
unnecessarilly for the time being.

To not change the API, reduce RAID_BITMAP_SIZE to 1.
Remove an unneeded definition of it from libdm-common.h.

If we ever decide to raise past 64, we'll version the API.

Related: rhbz834579
Related: rhbz1191935
Related: rhbz1191978
2017-02-27 21:42:15 +01:00
c41e999488 git: Upstream repository moved to sourceware.org
The fedorahosted git repository shuts down tomorrow:
  https://communityblog.fedoraproject.org/fedorahosted-sunset-2017-02-28/

Our upstream git repository has moved back to sourceware.org.
Mailing list hosting is not changing.

Gitweb:
  https://www.sourceware.org/git/?p=lvm2

Git:
  git://sourceware.org/git/lvm2.git
  ssh://sourceware.org/git/lvm2.git
  http://sourceware.org/git/lvm2.git

Example command to change the origin of a repository clone:
  Public:
    git remote set-url origin git://sourceware.org/git/lvm2.git
  Committers:
    git remote set-url origin git+ssh://sourceware.org/git/lvm2.git
2017-02-27 14:05:50 +00:00
4f7631b4ad man: change option sorting in synopsis
The options list was sorted as:
- options with both long and short forms, alphabetically
- options with only long form, alphabetically

This was done only for the visual effect.  Change to
sort alphabetically by long opt, without regard to
short forms.
2017-02-24 15:11:18 -06:00
5f6bdf707d man: add ENVIRONMENT VARIABLES section 2017-02-24 15:05:17 -06:00
84cceaf9b9 lvconvert: fix handling args in combining snapshots
Fixes commit 286d39ee3c, which was correct except
for a reversed strstr.  Now uses strchr, and modifies
a copy of the name so the original argv is preserved.
2017-02-24 14:17:58 -06:00
74ba326007 man: use Size variable for a number with unit
Define a separate variable type Size to represent
a number that takes an optional UNIT.
2017-02-24 13:44:05 -06:00
189fa64793 lvconvert: impose region size constraints
When requesting a regionsize change during conversions, check
for constraints or the command may fail in the kernel n case
the region size is too smalle or too large thus leaving any
new SubLVs behind.

Related: rhbz834579
Related: rhbz1191935
Related: rhbz1191978
2017-02-24 07:27:43 +01:00
3bdc4045c2 lvconvert: fix 2 issues identified in intesting
Allow regionsize on upconvert from linear:
fix related commit 2574d3257a to actually work

Related: rhbz1394427

Remove setting raid5_n on conversions from raid1
as of commit 932db3db53 because any raid5 mapping
may be requested.

Related: rhbz834579
Related: rhbz1191935
Related: rhbz1191978
2017-02-24 05:58:45 +01:00
d768fbe010 WHATS_NEW: add entry 2017-02-24 05:24:59 +01:00
76f60cc430 lvconvert: add missed new test scripts for reshaping
Add aforementioned but forgotten new test scripts
lvconvert-raid-reshape-linear_to_striped.sh,
lvconvert-raid-reshape-striped_to_linear.sh and
lvconvert-raid-reshape.sh

Those presume dm-raid target version 1.10.2
provided by a following kernel patch.

Related: rhbz834579
Related: rhbz1191935
Related: rhbz1191978
2017-02-24 05:20:59 +01:00
2574d3257a lvconvert: allow regionsize on upconvert from linear
Allow to provide regionsize with "lvconvert -m1 -R N " on
upconverts from linear and on N -> M raid1 leg conversions.

Resolves: rhbz1394427
2017-02-24 05:20:58 +01:00
64a2fad5d6 lvconvert/lvcreate: raise maximum number of raid images
Because of contraints in renaming shifted rimage/rmeta LV names
the current RaidLV limit is a maximum of 10 SubLV pairs.

With the previous introduction of reshaping infratructure that
constriant got removed.

Kernel supports 253 since dm-raid target 1.9.0, older kernels 64.

Raise the maximum number of RaidLV rimage/rmeta pairs to 64.
If we want to raise past 64, we have to introdce a check for
the kernel supporting it in lvcreate/lvconvert.

Related: rhbz834579
Related: rhbz1191935
Related: rhbz1191978
2017-02-24 05:20:58 +01:00
34caf83172 lvconvert: add infrastructure for RaidLV reshaping support
In order to support striped raid5/6/10 LV reshaping (change
of LV type, stripesize or number of legs), this patch
introduces the changes to call the reshaping infratructure
from lv_raid_convert().

Changes:
- add reshaping calls from lv_raid_convert()
- add command definitons for reshaping to tools/command-lines.in
- fix raid_rimage_extents()
- add 2 new test scripts lvconvert-raid-reshape-linear_to_striped.sh
  and lvconvert-raid-reshape-striped_to_linear.sh to test
  the linear <-> striped multi-step conversions
- add lvconvert-raid-reshape.sh reshaping tests
- enhance lvconvert-raid-takeover.sh with new raid10 tests

Related: rhbz834579
Related: rhbz1191935
Related: rhbz1191978
2017-02-24 05:20:58 +01:00
f79bd30a8b lvconvert: add infrastructure for RaidLV reshaping support
In order to support striped raid5/6/10 LV reshaping (change
of LV type, stripesize or number of legs), this patch
introduces more local infrastructure to raid_manip.c
used by followup patches.

Change:
- allow raid_rimage_extents() to calculate raid10
- remove an __unused__ attribute

Related: rhbz834579
Related: rhbz1191935
Related: rhbz1191978
2017-02-24 05:20:58 +01:00
1784cc990e lvconvert: add infrastructure for RaidLV reshaping support
In order to support striped raid5/6/10 LV reshaping (change
of LV type, stripesize or number of legs), this patch
introduces more local infrastructure to raid_manip.c
used by followup patches.

Change:
- add missing raid1 <-> raid5 conversions to support
  linear <-> raid5 <-> raid0(_meta)/striped conversions
- rename related new takeover functions to
  _takeover_from_raid1_to_raid5 and _takeover_from_raid5_to_raid1,
  because a reshape to > 2 legs is only possible with
  raid5 layout

Related: rhbz834579
Related: rhbz1191935
Related: rhbz1191978
2017-02-24 05:20:58 +01:00
2d74de3f05 lvconvert: add infrastructure for RaidLV reshaping support
In order to support striped raid5/6/10 LV reshaping (change
of LV type, stripesize or number of legs), this patch
introduces more local infrastructure to raid_manip.c
used by followup patches.

Change:
- enhance _clear_meta_lvs() to support raid0 allowing
  raid0_meta -> raid10 conversions to succeed by clearing
  the raid0 rmeta images or the kernel will fail because
  of discovering reordered raid devices

Related: rhbz834579
Related: rhbz1191935
Related: rhbz1191978
2017-02-24 05:20:58 +01:00
34a8d3c2fd lvconvert: add infrastructure for RaidLV reshaping support
In order to support striped raid5/6/10 LV reshaping (change
of LV type, stripesize or number of legs), this patch
introduces more local infrastructure to raid_manip.c
used by followup patches.

Changes:
- enhance _raid45610_to_raid0_or_striped_wrapper() to support
  raid5_n with 2 areas to raid1 conversion to allow for
  striped/raid0(_meta)/raid4/5/6 -> raid1/linear conversions;
  rename it to _takeover_downconvert_wrapper to discontinue the
  illegible function name
- enhance _striped_or_raid0_to_raid45610_wrapper()  to support
  raid1 with 2 areas to raid5* conversions to allow for
  linear/raid1 -> striped/raid0(_meta)/raid4/5/6 conversions;
  rename it to _takeover_upconvert_wrapper for the same reason

Related: rhbz834579
Related: rhbz1191935
Related: rhbz1191978
2017-02-24 05:20:58 +01:00
932db3db53 lvconvert: add infrastructure for RaidLV reshaping support
In order to support striped raid5/6/10 LV reshaping (change
of LV type, stripesize or number of legs), this patch
introduces more local infrastructure to raid_manip.c
used by followup patches.

Changes:
- add missing possible reshape conversions and conversion options
  to allow/prohibit changing stripesize or number fo stripes
- enhance setting convenient riad types in reshape conversions
  (e.g. raid1 with 2 legs -> radi5_n)

Related: rhbz834579
Related: rhbz1191935
Related: rhbz1191978
2017-02-24 05:20:58 +01:00
fe18e5e77a lvconvert: add infrastructure for RaidLV reshaping support
In order to support striped raid5/6/10 LV reshaping (change
of LV type, stripesize or number of legs), this patch
introduces more local infrastructure to raid_manip.c
used by followup patches.

Changes:
- add _raid_reshape() using the pre/post callbacks and
  the stripes add/remove reshape functions introduced before
- and _reshape_requested function checking if a reshape
  was requested

Related: rhbz834579
Related: rhbz1191935
Related: rhbz1191978
2017-02-24 05:20:58 +01:00
929cf4b73c lvconvert: add infrastructure for RaidLV reshaping support
In order to support striped raid5/6/10 LV reshaping (change
of LV type, stripesize or number of legs), this patch
introduces more local infrastructure to raid_manip.c
used by followup patches.

Changes:
- add vg metadata update functions
- add pre and post activation callback functions for
  proper sequencing of sub lv activations during reshaping
- move and enhance _lv_update_reload_fns_reset_eliminate_lvs()
  to support pre and post activation callbacks
- add _reset_flags_passed_to_kernel() which resets anyxi
  rebuild/reshape flags after they have been passed into the kernel
  and sets the SubLV remove after reshape flags on legs to be removed

Related: rhbz834579
Related: rhbz1191935
Related: rhbz1191978
2017-02-24 05:20:58 +01:00
4de0e692db lvconvert: add infrastructure for RaidLV reshaping support
In order to support striped raid5/6/10 LV reshaping (change
of LV type, stripesize or number of legs), this patch
introduces more local infrastructure to raid_manip.c
used by followup patches.

Changes:
- add function to support disk adding reshapes
- add function to support disk removing reshapes
- add function to support layout (e.g. raid5ls -> raid5_rs)
  or stripesize reshaping

Related: rhbz834579
Related: rhbz1191935
Related: rhbz1191978
2017-02-24 05:20:58 +01:00
7d39b4d5e7 lvconvert: add infrastructure for RaidLV reshaping support
In order to support striped raid5/6/10 LV reshaping (change
of LV type, stripesize or number of legs), this patch
introduces more local infrastructure to raid_manip.c
used by followup patches.

Changes:
- add function providing state of a reshaped RaidLV
- add function to adjust the size of a RaidLV was
  reshaped to add/remove stripes

Related: rhbz834579
Related: rhbz1191935
Related: rhbz1191978
2017-02-24 05:20:58 +01:00
92691e345d lvconvert: add infrastructure for RaidLV reshaping support
In order to support striped raid5/6/10 LV reshaping (change
of LV type, stripesize or number of legs), this patch
introduces more local infrastructure to raid_manip.c
used by followup patches.

Changes:
- add lv_raid_data_copies returning raid type specific number;
  needed for raid10 with more than 2 data copies
- remove _shift_and_rename_image_components() constraint
  to support more than 10 raid legs
- add function to calculate total rimage length used by out-of-place
  reshape space allocation
- add out-of-place reshape space alloc/relocate/free functions
- move _data_rimages_count() used by reshape space alloc/realocate functions

Related: rhbz834579
Related: rhbz1191935
Related: rhbz1191978
2017-02-24 05:20:58 +01:00
c1865b0a86 raid: typo 2017-02-24 05:20:58 +01:00
b499d96215 lvconvert: add infrastructure for RaidLV reshaping support
In order to support striped raid5/6/10 LV reshaping (change
of LV type, stripesize or number of legs), this patch
introduces local infrastructure to raid_manip.c
used by followup patches.

Add functions:
- to check reshaping is supported in target attibute
- to return device health string needed to check
  the raid device is ready to reshape

Related: rhbz834579
Related: rhbz1191935
Related: rhbz1191978
2017-02-24 05:20:58 +01:00
e2354ea344 lvconvert: add infrastructure for RaidLV reshaping support
In order to support striped raid5/6/10 LV reshaping (change
of LV type, stripesize or number of legs), this patch
introduces infrastructure prerequisites to be used
by raid_manip.c extensions in followup patches.

This base is needed for allocation of out-of-place
reshape space required by the MD raid personalities to
avoid writing over data in-place when reading off the
current RAID layout or number of legs and writing out
the new layout or to a different number of legs
(i.e. restripe)

Changes:
- add members reshape_len to 'struct lv_segment' to store
  out-of-place reshape length per component rimage
- add member data_copies to struct lv_segment
  to support more than 2 raid10 data copies
- make alloc_lv_segment() aware of both reshape_len and data_copies
- adjust all alloc_lv_segment() callers to the new API
- add functions to retrieve the current data offset (needed for
  out-of-place reshaping space allocation) and the devices count
  from the kernel
- make libdm deptree code aware of reshape_len
- add LV flags for disk add/remove reshaping
- support import/export of the new 'struct lv_segment' members
- enhance lv_extend/_lv_reduce to cope with reshape_len
- add seg_is_*/segtype_is_* macros related to reshaping
- add target version check for reshaping
- grow rebuilds/writemostly bitmaps to 246 bit to support kernel maximal
- enhance libdm deptree code to support data_offset (out-of-place reshaping)
  and delta_disk (legs add/remove reshaping) target arguments

Related: rhbz834579
Related: rhbz1191935
Related: rhbz1191978
2017-02-24 05:20:58 +01:00
ffe3ca26e0 man: improve line breaks
Borrow tricks from dmsetup man page to improve
the line break and indentation using .ad l, .ad b,
and soft break \%.
2017-02-23 17:06:42 -06:00
3fd3c9430d man/help: change syntax to UNIT
(Change to recent commit 3f4ecaf8c2.)

Use --foo Number[k|UNIT] to indicate that
the default units of the number is k, but other
units listed below are also accepted.

Previously, underlined/italic Unit was used,
like other of variables, but this UNIT is more
like a shortcut than an actual variable.
2017-02-23 14:24:28 -06:00
285 changed files with 33704 additions and 3653 deletions

View File

@ -100,7 +100,7 @@ CLEAN_DIRS += autom4te.cache
check check_system check_cluster check_local check_lvmetad check_lvmpolld check_lvmlockd_test check_lvmlockd_dlm check_lvmlockd_sanlock unit: all check check_system check_cluster check_local check_lvmetad check_lvmpolld check_lvmlockd_test check_lvmlockd_dlm check_lvmlockd_sanlock unit: all
$(MAKE) -C test $(@) $(MAKE) -C test $(@)
conf.generate: tools conf.generate man.generate: tools
# how to use parenthesis in makefiles # how to use parenthesis in makefiles
leftparen:=( leftparen:=(
@ -130,8 +130,9 @@ rpm: dist
$(top_srcdir)/spec/source.inc >$(rpmbuilddir)/SOURCES/source.inc $(top_srcdir)/spec/source.inc >$(rpmbuilddir)/SOURCES/source.inc
rpmbuild -v --define "_topdir $(rpmbuilddir)" -ba $(top_srcdir)/spec/lvm2.spec rpmbuild -v --define "_topdir $(rpmbuilddir)" -ba $(top_srcdir)/spec/lvm2.spec
generate: conf.generate generate: conf.generate man.generate
$(MAKE) -C conf generate $(MAKE) -C conf generate
$(MAKE) -C man generate
all_man: all_man:
$(MAKE) -C man all_man $(MAKE) -C man all_man

5
README
View File

@ -6,11 +6,12 @@ Installation instructions are in INSTALL.
There is no warranty - see COPYING and COPYING.LIB. There is no warranty - see COPYING and COPYING.LIB.
Tarballs are available from: Tarballs are available from:
ftp://sourceware.org/pub/lvm2/
ftp://sources.redhat.com/pub/lvm2/ ftp://sources.redhat.com/pub/lvm2/
The source code is stored in git: The source code is stored in git:
http://git.fedorahosted.org/git/lvm2.git https://sourceware.org/git/?p=lvm2.git
git clone git://git.fedorahosted.org/git/lvm2.git git clone git://sourceware.org/git/lvm2.git
Mailing list for general discussion related to LVM2: Mailing list for general discussion related to LVM2:
linux-lvm@redhat.com linux-lvm@redhat.com

View File

@ -1 +1 @@
2.02.169(2)-git (2016-11-30) 2.02.170(2)-git (2017-03-28)

View File

@ -1 +1 @@
1.02.138-git (2016-11-30) 1.02.139-git (2017-03-28)

View File

@ -1,8 +1,30 @@
Version 2.02.169 - Version 2.02.170 -
===================================== ==================================
Version 2.02.169 - 28th March 2017
==================================
Automatically decide whether '-' in a man page is a hyphen or a minus sign.
Add build-time configuration command line to 'lvm version' output.
Handle known table line parameter order change in specific raid target vsns.
Conditionally reject raid convert to striped/raid0* after reshape.
Ensure raid6 upconversion restrictions.
Adjust mirror & raid dmeventd plugins for new lvconvert --repair behaviour.
Disable lvmetad when lvconvert --repair is run.
Remove obsolete lvmchange binary - convert to built-in command.
Show more information for cached volumes in lvdisplay [-m].
Add option for lvcreate/lvconvert --cachemetadataformat auto|1|2.
Support cache segment with configurable metadata format.
Add allocation/cache_metadata_format profilable settings.
Use function cache_set_params() for both lvcreate and lvconvert.
Skip rounding on cache chunk size boudary when create cache LV.
Improve cache_set_params support for chunk_size selection.
Fix metadata profile allocation/cache_[mode|policy] setting.
Fix missing support for using allocation/cache_pool_chunk_size setting.
Upstream git moved to https://sourceware.org/git/?p=lvm2
Support conversion of raid type, stripesize and number of disks
Reject writemostly/writebehind in lvchange during resynchronization. Reject writemostly/writebehind in lvchange during resynchronization.
Deactivate active origin first before removal for improved workflow. Deactivate active origin first before removal for improved workflow.
Fix regression of accepting options --type and -m with lvresize (2.02.158). Fix regression of accepting both --type and -m with lvresize. (2.02.158)
Add lvconvert --swapmetadata, new specific way to swap pool metadata LVs. Add lvconvert --swapmetadata, new specific way to swap pool metadata LVs.
Add lvconvert --startpoll, new specific way to start polling conversions. Add lvconvert --startpoll, new specific way to start polling conversions.
Add lvconvert --mergethin, new specific way to merge thin snapshots. Add lvconvert --mergethin, new specific way to merge thin snapshots.
@ -15,9 +37,9 @@ Version 2.02.169 -
Match every command run to one command definition. Match every command run to one command definition.
Specify every allowed command definition/syntax in command-lines.in. Specify every allowed command definition/syntax in command-lines.in.
Add extra memory page when limiting pthread stack size in clvmd. Add extra memory page when limiting pthread stack size in clvmd.
Support striped/raid0* <-> raid10_near conversions Support striped/raid0* <-> raid10_near conversions.
Support shrinking of RaidLvs Support shrinking of RaidLVs.
Support region size changes on existing RaidLVs Support region size changes on existing RaidLVs.
Avoid parallel usage of cpg_mcast_joined() in clvmd with corosync. Avoid parallel usage of cpg_mcast_joined() in clvmd with corosync.
Support raid6_{ls,rs,la,ra}_6 segment types and conversions from/to it. Support raid6_{ls,rs,la,ra}_6 segment types and conversions from/to it.
Support raid6_n_6 segment type and conversions from/to it. Support raid6_n_6 segment type and conversions from/to it.

View File

@ -1,19 +1,27 @@
Version 1.02.138 - Version 1.02.139 -
===================================== ==================================
Version 1.02.138 - 28th March 2017
==================================
Support additional raid5/6 configurations.
Provide dm_tree_node_add_cache_target@base compatible symbol.
Support DM_CACHE_FEATURE_METADATA2, new cache metadata format 2.
Improve code to handle mode mask for cache nodes.
Cache status check for passthrough also require trailing space.
Add extra memory page when limiting pthread stack size in dmeventd. Add extra memory page when limiting pthread stack size in dmeventd.
Avoids immediate resume when preloaded device is smaller. Avoids immediate resume when preloaded device is smaller.
Do not suppress kernel key description in dmsetup table output. Do not suppress kernel key description in dmsetup table output for dm-crypt.
Support configurable command executed from dmeventd thin plugin. Support configurable command executed from dmeventd thin plugin.
Support new R|r human readable units output format. Support new R|r human readable units output format.
Thin dmeventd plugin reacts faster on lvextend failure path with umount. Thin dmeventd plugin reacts faster on lvextend failure path with umount.
Add dm_stats_bind_from_fd() to bind a stats handle from a file descriptor. Add dm_stats_bind_from_fd() to bind a stats handle from a file descriptor.
Do not try call callback when reverting activation on error path. Do not try call callback when reverting activation on error path.
Fix file mapping for extents with physically adjacent extents. Fix file mapping for extents with physically adjacent extents in dmstats.
Validation vsnprintf result in runtime translate of dm_log (1.02.136). Validation vsnprintf result in runtime translate of dm_log (1.02.136).
Separate filemap extent allocation from region table. Separate filemap extent allocation from region table in dmstats.
Fix segmentation fault when filemap region creation fails. Fix segmentation fault when filemap region creation fails in dmstats.
Fix performance of region cleanup for failed filemap creation. Fix performance of region cleanup for failed filemap creation in dmstats.
Fix very slow region deletion with many regions. Fix very slow region deletion with many regions in dmstats.
Version 1.02.137 - 30th November 2016 Version 1.02.137 - 30th November 2016
===================================== =====================================

View File

@ -9,6 +9,6 @@ allocation {
cache_mode = "writethrough" cache_mode = "writethrough"
cache_policy = "smq" cache_policy = "smq"
cache_settings { cache_settings {
# currently no settins for "smq" policy # currently no settings for "smq" policy
} }
} }

View File

@ -403,9 +403,20 @@ allocation {
# This configuration option has an automatic default value. # This configuration option has an automatic default value.
# cache_mode = "writethrough" # cache_mode = "writethrough"
# Configuration option allocation/cache_metadata_format.
# Sets default metadata format for new cache.
#
# Accepted values:
# 0 Automatically detected best available format
# 1 Original format
# 2 Improved 2nd. generation format
#
# This configuration option has an automatic default value.
# cache_metadata_format = 0
# Configuration option allocation/cache_policy. # Configuration option allocation/cache_policy.
# The default cache policy used for new cache volume. # The default cache policy used for new cache volume.
# Since kernel 4.2 the default policy is smq (Stochastic multique), # Since kernel 4.2 the default policy is smq (Stochastic multiqueue),
# otherwise the older mq (Multiqueue) policy is selected. # otherwise the older mq (Multiqueue) policy is selected.
# This configuration option does not have a default value defined. # This configuration option does not have a default value defined.
@ -1013,7 +1024,7 @@ global {
# Configuration option global/cache_disabled_features. # Configuration option global/cache_disabled_features.
# Features to not use in the cache driver. # Features to not use in the cache driver.
# This can be helpful for testing, or to avoid using a feature that is # This can be helpful for testing, or to avoid using a feature that is
# causing problems. Features include: policy_mq, policy_smq. # causing problems. Features include: policy_mq, policy_smq, metadata2.
# #
# Example # Example
# cache_disabled_features = [ "policy_smq" ] # cache_disabled_features = [ "policy_smq" ]
@ -1277,8 +1288,9 @@ activation {
# Configuration option activation/raid_region_size. # Configuration option activation/raid_region_size.
# Size in KiB of each raid or mirror synchronization region. # Size in KiB of each raid or mirror synchronization region.
# For raid or mirror segment types, this is the amount of data that is # The clean/dirty state of data is tracked for each region.
# copied at once when initializing, or moved at once by pvmove. # The value is rounded down to a power of two if necessary, and
# is ignored if it is not a multiple of the machine memory page size.
raid_region_size = 512 raid_region_size = 512
# Configuration option activation/error_when_full. # Configuration option activation/error_when_full.

81
configure vendored
View File

@ -702,6 +702,7 @@ BLKDEACTIVATE
FSADM FSADM
ELDFLAGS ELDFLAGS
DM_LIB_PATCHLEVEL DM_LIB_PATCHLEVEL
DMFILEMAPD
DMEVENTD_PATH DMEVENTD_PATH
DMEVENTD DMEVENTD
DL_LIBS DL_LIBS
@ -737,6 +738,7 @@ CLDNOWHOLEARCHIVE
CLDFLAGS CLDFLAGS
CACHE CACHE
BUILD_NOTIFYDBUS BUILD_NOTIFYDBUS
BUILD_DMFILEMAPD
BUILD_LOCKDDLM BUILD_LOCKDDLM
BUILD_LOCKDSANLOCK BUILD_LOCKDSANLOCK
BUILD_LVMLOCKD BUILD_LVMLOCKD
@ -960,6 +962,7 @@ enable_use_lvmetad
with_lvmetad_pidfile with_lvmetad_pidfile
enable_use_lvmpolld enable_use_lvmpolld
with_lvmpolld_pidfile with_lvmpolld_pidfile
enable_dmfilemapd
enable_notify_dbus enable_notify_dbus
enable_blkid_wiping enable_blkid_wiping
enable_udev_systemd_background_jobs enable_udev_systemd_background_jobs
@ -1694,6 +1697,7 @@ Optional Features:
--disable-use-lvmlockd disable usage of LVM lock daemon --disable-use-lvmlockd disable usage of LVM lock daemon
--disable-use-lvmetad disable usage of LVM Metadata Daemon --disable-use-lvmetad disable usage of LVM Metadata Daemon
--disable-use-lvmpolld disable usage of LVM Poll Daemon --disable-use-lvmpolld disable usage of LVM Poll Daemon
--enable-dmfilemapd enable the dmstats filemap daemon
--enable-notify-dbus enable LVM notification using dbus --enable-notify-dbus enable LVM notification using dbus
--disable-blkid_wiping disable libblkid detection of signatures when wiping --disable-blkid_wiping disable libblkid detection of signatures when wiping
and use native code instead and use native code instead
@ -3011,6 +3015,7 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $
ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_compiler_gnu=$ac_cv_c_compiler_gnu
CONFIGURE_LINE="$0 $@"
ac_config_headers="$ac_config_headers include/configure.h" ac_config_headers="$ac_config_headers include/configure.h"
@ -6074,7 +6079,7 @@ fi
done done
for ac_header in termios.h sys/statvfs.h sys/timerfd.h linux/magic.h linux/fiemap.h for ac_header in termios.h sys/statvfs.h sys/timerfd.h sys/vfs.h linux/magic.h linux/fiemap.h
do : do :
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
@ -6267,6 +6272,26 @@ _ACEOF
fi fi
ac_fn_c_check_member "$LINENO" "struct stat" "st_blocks" "ac_cv_member_struct_stat_st_blocks" "$ac_includes_default"
if test "x$ac_cv_member_struct_stat_st_blocks" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_STRUCT_STAT_ST_BLOCKS 1
_ACEOF
$as_echo "#define HAVE_ST_BLOCKS 1" >>confdefs.h
else
case " $LIBOBJS " in
*" fileblocks.$ac_objext "* ) ;;
*) LIBOBJS="$LIBOBJS fileblocks.$ac_objext"
;;
esac
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether struct tm is in sys/time.h or time.h" >&5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether struct tm is in sys/time.h or time.h" >&5
$as_echo_n "checking whether struct tm is in sys/time.h or time.h... " >&6; } $as_echo_n "checking whether struct tm is in sys/time.h or time.h... " >&6; }
if ${ac_cv_struct_tm+:} false; then : if ${ac_cv_struct_tm+:} false; then :
@ -12074,6 +12099,32 @@ cat >>confdefs.h <<_ACEOF
_ACEOF _ACEOF
################################################################################
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build dmfilemapd" >&5
$as_echo_n "checking whether to build dmfilemapd... " >&6; }
# Check whether --enable-dmfilemapd was given.
if test "${enable_dmfilemapd+set}" = set; then :
enableval=$enable_dmfilemapd; DMFILEMAPD=$enableval
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $DMFILEMAPD" >&5
$as_echo "$DMFILEMAPD" >&6; }
BUILD_DMFILEMAPD=$DMFILEMAPD
$as_echo "#define DMFILEMAPD 1" >>confdefs.h
if test "$DMFILEMAPD" = yes; then
ac_fn_c_check_header_mongrel "$LINENO" "linux/fiemap.h" "ac_cv_header_linux_fiemap_h" "$ac_includes_default"
if test "x$ac_cv_header_linux_fiemap_h" = xyes; then :
else
as_fn_error $? "--enable-dmfilemapd requires fiemap.h" "$LINENO" 5
fi
fi
################################################################################ ################################################################################
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build notifydbus" >&5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build notifydbus" >&5
$as_echo_n "checking whether to build notifydbus... " >&6; } $as_echo_n "checking whether to build notifydbus... " >&6; }
@ -15123,6 +15174,23 @@ done
fi fi
if test "$DMFILEMAPD" = yes; then
for ac_header in sys/inotify.h
do :
ac_fn_c_check_header_mongrel "$LINENO" "sys/inotify.h" "ac_cv_header_sys_inotify_h" "$ac_includes_default"
if test "x$ac_cv_header_sys_inotify_h" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_SYS_INOTIFY_H 1
_ACEOF
else
hard_bailout
fi
done
fi
################################################################################ ################################################################################
if test -n "$ac_tool_prefix"; then if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}modprobe", so it can be a program name with args. # Extract the first word of "${ac_tool_prefix}modprobe", so it can be a program name with args.
@ -15426,6 +15494,12 @@ LVM_MINOR=`echo "$VER" | $AWK -F '.' '{print $2}'`
LVM_PATCHLEVEL=`echo "$VER" | $AWK -F '[(.]' '{print $3}'` LVM_PATCHLEVEL=`echo "$VER" | $AWK -F '[(.]' '{print $3}'`
LVM_LIBAPI=`echo "$VER" | $AWK -F '[()]' '{print $2}'` LVM_LIBAPI=`echo "$VER" | $AWK -F '[()]' '{print $2}'`
cat >>confdefs.h <<_ACEOF
#define LVM_CONFIGURE_LINE "$CONFIGURE_LINE"
_ACEOF
################################################################################ ################################################################################
@ -15582,11 +15656,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/lvmdbusd/Makefile daemons/lvmdbusd/path.py daemons/lvmetad/Makefile daemons/lvmpolld/Makefile daemons/lvmlockd/Makefile conf/Makefile conf/example.conf conf/lvmlocal.conf conf/command_profile_template.profile conf/metadata_profile_template.profile include/.symlinks include/Makefile lib/Makefile lib/format1/Makefile lib/format_pool/Makefile lib/locking/Makefile lib/mirror/Makefile lib/replicator/Makefile include/lvm-version.h lib/raid/Makefile lib/snapshot/Makefile lib/thin/Makefile lib/cache_segtype/Makefile libdaemon/Makefile libdaemon/client/Makefile libdaemon/server/Makefile libdm/Makefile libdm/libdevmapper.pc liblvm/Makefile liblvm/liblvm2app.pc man/Makefile po/Makefile python/Makefile python/setup.py scripts/blkdeactivate.sh scripts/blk_availability_init_red_hat scripts/blk_availability_systemd_red_hat.service scripts/clvmd_init_red_hat scripts/cmirrord_init_red_hat scripts/com.redhat.lvmdbus1.service scripts/dm_event_systemd_red_hat.service scripts/dm_event_systemd_red_hat.socket scripts/lvm2_cluster_activation_red_hat.sh scripts/lvm2_cluster_activation_systemd_red_hat.service scripts/lvm2_clvmd_systemd_red_hat.service scripts/lvm2_cmirrord_systemd_red_hat.service scripts/lvm2_lvmdbusd_systemd_red_hat.service scripts/lvm2_lvmetad_init_red_hat scripts/lvm2_lvmetad_systemd_red_hat.service scripts/lvm2_lvmetad_systemd_red_hat.socket scripts/lvm2_lvmpolld_init_red_hat scripts/lvm2_lvmpolld_systemd_red_hat.service scripts/lvm2_lvmpolld_systemd_red_hat.socket scripts/lvm2_lvmlockd_systemd_red_hat.service scripts/lvm2_lvmlocking_systemd_red_hat.service scripts/lvm2_monitoring_init_red_hat scripts/lvm2_monitoring_systemd_red_hat.service scripts/lvm2_pvscan_systemd_red_hat@.service scripts/lvm2_tmpfiles_red_hat.conf scripts/lvmdump.sh scripts/Makefile test/Makefile test/api/Makefile test/unit/Makefile tools/Makefile udev/Makefile unit-tests/datastruct/Makefile unit-tests/regex/Makefile unit-tests/mm/Makefile" ac_config_files="$ac_config_files Makefile make.tmpl daemons/Makefile daemons/clvmd/Makefile daemons/cmirrord/Makefile daemons/dmeventd/Makefile daemons/dmeventd/libdevmapper-event.pc daemons/dmeventd/plugins/Makefile daemons/dmeventd/plugins/lvm2/Makefile daemons/dmeventd/plugins/raid/Makefile daemons/dmeventd/plugins/mirror/Makefile daemons/dmeventd/plugins/snapshot/Makefile daemons/dmeventd/plugins/thin/Makefile daemons/dmfilemapd/Makefile daemons/lvmdbusd/Makefile daemons/lvmdbusd/path.py daemons/lvmetad/Makefile daemons/lvmpolld/Makefile daemons/lvmlockd/Makefile conf/Makefile conf/example.conf conf/lvmlocal.conf conf/command_profile_template.profile conf/metadata_profile_template.profile include/.symlinks include/Makefile lib/Makefile lib/format1/Makefile lib/format_pool/Makefile lib/locking/Makefile lib/mirror/Makefile lib/replicator/Makefile include/lvm-version.h lib/raid/Makefile lib/snapshot/Makefile lib/thin/Makefile lib/cache_segtype/Makefile libdaemon/Makefile libdaemon/client/Makefile libdaemon/server/Makefile libdm/Makefile libdm/libdevmapper.pc liblvm/Makefile liblvm/liblvm2app.pc man/Makefile po/Makefile python/Makefile python/setup.py scripts/blkdeactivate.sh scripts/blk_availability_init_red_hat scripts/blk_availability_systemd_red_hat.service scripts/clvmd_init_red_hat scripts/cmirrord_init_red_hat scripts/com.redhat.lvmdbus1.service scripts/dm_event_systemd_red_hat.service scripts/dm_event_systemd_red_hat.socket scripts/lvm2_cluster_activation_red_hat.sh scripts/lvm2_cluster_activation_systemd_red_hat.service scripts/lvm2_clvmd_systemd_red_hat.service scripts/lvm2_cmirrord_systemd_red_hat.service scripts/lvm2_lvmdbusd_systemd_red_hat.service scripts/lvm2_lvmetad_init_red_hat scripts/lvm2_lvmetad_systemd_red_hat.service scripts/lvm2_lvmetad_systemd_red_hat.socket scripts/lvm2_lvmpolld_init_red_hat scripts/lvm2_lvmpolld_systemd_red_hat.service scripts/lvm2_lvmpolld_systemd_red_hat.socket scripts/lvm2_lvmlockd_systemd_red_hat.service scripts/lvm2_lvmlocking_systemd_red_hat.service scripts/lvm2_monitoring_init_red_hat scripts/lvm2_monitoring_systemd_red_hat.service scripts/lvm2_pvscan_systemd_red_hat@.service scripts/lvm2_tmpfiles_red_hat.conf scripts/lvmdump.sh scripts/Makefile test/Makefile test/api/Makefile test/unit/Makefile tools/Makefile udev/Makefile unit-tests/datastruct/Makefile unit-tests/regex/Makefile unit-tests/mm/Makefile"
cat >confcache <<\_ACEOF cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure # This file is a shell script that caches the results of configure
@ -16294,6 +16370,7 @@ do
"daemons/dmeventd/plugins/mirror/Makefile") CONFIG_FILES="$CONFIG_FILES daemons/dmeventd/plugins/mirror/Makefile" ;; "daemons/dmeventd/plugins/mirror/Makefile") CONFIG_FILES="$CONFIG_FILES daemons/dmeventd/plugins/mirror/Makefile" ;;
"daemons/dmeventd/plugins/snapshot/Makefile") CONFIG_FILES="$CONFIG_FILES daemons/dmeventd/plugins/snapshot/Makefile" ;; "daemons/dmeventd/plugins/snapshot/Makefile") CONFIG_FILES="$CONFIG_FILES daemons/dmeventd/plugins/snapshot/Makefile" ;;
"daemons/dmeventd/plugins/thin/Makefile") CONFIG_FILES="$CONFIG_FILES daemons/dmeventd/plugins/thin/Makefile" ;; "daemons/dmeventd/plugins/thin/Makefile") CONFIG_FILES="$CONFIG_FILES daemons/dmeventd/plugins/thin/Makefile" ;;
"daemons/dmfilemapd/Makefile") CONFIG_FILES="$CONFIG_FILES daemons/dmfilemapd/Makefile" ;;
"daemons/lvmdbusd/Makefile") CONFIG_FILES="$CONFIG_FILES daemons/lvmdbusd/Makefile" ;; "daemons/lvmdbusd/Makefile") CONFIG_FILES="$CONFIG_FILES daemons/lvmdbusd/Makefile" ;;
"daemons/lvmdbusd/path.py") CONFIG_FILES="$CONFIG_FILES daemons/lvmdbusd/path.py" ;; "daemons/lvmdbusd/path.py") CONFIG_FILES="$CONFIG_FILES daemons/lvmdbusd/path.py" ;;
"daemons/lvmetad/Makefile") CONFIG_FILES="$CONFIG_FILES daemons/lvmetad/Makefile" ;; "daemons/lvmetad/Makefile") CONFIG_FILES="$CONFIG_FILES daemons/lvmetad/Makefile" ;;

View File

@ -15,6 +15,7 @@ AC_PREREQ(2.69)
################################################################################ ################################################################################
dnl -- Process this file with autoconf to produce a configure script. dnl -- Process this file with autoconf to produce a configure script.
AC_INIT AC_INIT
CONFIGURE_LINE="$0 $@"
AC_CONFIG_SRCDIR([lib/device/dev-cache.h]) AC_CONFIG_SRCDIR([lib/device/dev-cache.h])
AC_CONFIG_HEADERS([include/configure.h]) AC_CONFIG_HEADERS([include/configure.h])
@ -105,7 +106,7 @@ AC_CHECK_HEADERS([assert.h ctype.h dirent.h errno.h fcntl.h float.h \
sys/time.h sys/types.h sys/utsname.h sys/wait.h time.h \ sys/time.h sys/types.h sys/utsname.h sys/wait.h time.h \
unistd.h], , [AC_MSG_ERROR(bailing out)]) unistd.h], , [AC_MSG_ERROR(bailing out)])
AC_CHECK_HEADERS(termios.h sys/statvfs.h sys/timerfd.h linux/magic.h linux/fiemap.h) AC_CHECK_HEADERS(termios.h sys/statvfs.h sys/timerfd.h sys/vfs.h linux/magic.h linux/fiemap.h)
case "$host_os" in case "$host_os" in
linux*) linux*)
@ -120,6 +121,7 @@ AC_C_CONST
AC_C_INLINE AC_C_INLINE
AC_CHECK_MEMBERS([struct stat.st_rdev]) AC_CHECK_MEMBERS([struct stat.st_rdev])
AC_CHECK_TYPES([ptrdiff_t]) AC_CHECK_TYPES([ptrdiff_t])
AC_STRUCT_ST_BLOCKS
AC_STRUCT_TM AC_STRUCT_TM
AC_TYPE_OFF_T AC_TYPE_OFF_T
AC_TYPE_PID_T AC_TYPE_PID_T
@ -1271,6 +1273,21 @@ fi
AC_DEFINE_UNQUOTED(DEFAULT_USE_LVMPOLLD, [$DEFAULT_USE_LVMPOLLD], AC_DEFINE_UNQUOTED(DEFAULT_USE_LVMPOLLD, [$DEFAULT_USE_LVMPOLLD],
[Use lvmpolld by default.]) [Use lvmpolld by default.])
################################################################################
dnl -- Check dmfilemapd
AC_MSG_CHECKING(whether to build dmfilemapd)
AC_ARG_ENABLE(dmfilemapd, AC_HELP_STRING([--enable-dmfilemapd],
[enable the dmstats filemap daemon]),
DMFILEMAPD=$enableval)
AC_MSG_RESULT($DMFILEMAPD)
BUILD_DMFILEMAPD=$DMFILEMAPD
AC_DEFINE([DMFILEMAPD], 1, [Define to 1 to enable the device-mapper filemap daemon.])
dnl -- dmfilemapd requires FIEMAP
if test "$DMFILEMAPD" = yes; then
AC_CHECK_HEADER([linux/fiemap.h], , [AC_MSG_ERROR(--enable-dmfilemapd requires fiemap.h)])
fi
################################################################################ ################################################################################
dnl -- Build notifydbus dnl -- Build notifydbus
AC_MSG_CHECKING(whether to build notifydbus) AC_MSG_CHECKING(whether to build notifydbus)
@ -1855,6 +1872,10 @@ if test "$UDEV_SYNC" = yes; then
AC_CHECK_HEADERS(sys/ipc.h sys/sem.h,,hard_bailout) AC_CHECK_HEADERS(sys/ipc.h sys/sem.h,,hard_bailout)
fi fi
if test "$DMFILEMAPD" = yes; then
AC_CHECK_HEADERS([sys/inotify.h],,hard_bailout)
fi
################################################################################ ################################################################################
AC_PATH_TOOL(MODPROBE_CMD, modprobe) AC_PATH_TOOL(MODPROBE_CMD, modprobe)
@ -1982,6 +2003,8 @@ LVM_MINOR=`echo "$VER" | $AWK -F '.' '{print $2}'`
LVM_PATCHLEVEL=`echo "$VER" | $AWK -F '[[(.]]' '{print $3}'` LVM_PATCHLEVEL=`echo "$VER" | $AWK -F '[[(.]]' '{print $3}'`
LVM_LIBAPI=`echo "$VER" | $AWK -F '[[()]]' '{print $2}'` LVM_LIBAPI=`echo "$VER" | $AWK -F '[[()]]' '{print $2}'`
AC_DEFINE_UNQUOTED(LVM_CONFIGURE_LINE, "$CONFIGURE_LINE", [configure command line used])
################################################################################ ################################################################################
AC_SUBST(APPLIB) AC_SUBST(APPLIB)
AC_SUBST(AWK) AC_SUBST(AWK)
@ -1994,6 +2017,7 @@ AC_SUBST(BUILD_LVMPOLLD)
AC_SUBST(BUILD_LVMLOCKD) AC_SUBST(BUILD_LVMLOCKD)
AC_SUBST(BUILD_LOCKDSANLOCK) AC_SUBST(BUILD_LOCKDSANLOCK)
AC_SUBST(BUILD_LOCKDDLM) AC_SUBST(BUILD_LOCKDDLM)
AC_SUBST(BUILD_DMFILEMAPD)
AC_SUBST(BUILD_NOTIFYDBUS) AC_SUBST(BUILD_NOTIFYDBUS)
AC_SUBST(CACHE) AC_SUBST(CACHE)
AC_SUBST(CFLAGS) AC_SUBST(CFLAGS)
@ -2043,6 +2067,7 @@ AC_SUBST(DLM_LIBS)
AC_SUBST(DL_LIBS) AC_SUBST(DL_LIBS)
AC_SUBST(DMEVENTD) AC_SUBST(DMEVENTD)
AC_SUBST(DMEVENTD_PATH) AC_SUBST(DMEVENTD_PATH)
AC_SUBST(DMFILEMAPD)
AC_SUBST(DM_LIB_PATCHLEVEL) AC_SUBST(DM_LIB_PATCHLEVEL)
AC_SUBST(ELDFLAGS) AC_SUBST(ELDFLAGS)
AC_SUBST(FSADM) AC_SUBST(FSADM)
@ -2158,6 +2183,7 @@ daemons/dmeventd/plugins/raid/Makefile
daemons/dmeventd/plugins/mirror/Makefile daemons/dmeventd/plugins/mirror/Makefile
daemons/dmeventd/plugins/snapshot/Makefile daemons/dmeventd/plugins/snapshot/Makefile
daemons/dmeventd/plugins/thin/Makefile daemons/dmeventd/plugins/thin/Makefile
daemons/dmfilemapd/Makefile
daemons/lvmdbusd/Makefile daemons/lvmdbusd/Makefile
daemons/lvmdbusd/path.py daemons/lvmdbusd/path.py
daemons/lvmetad/Makefile daemons/lvmetad/Makefile

View File

@ -71,6 +71,17 @@ void model_FD_ZERO(void *fdset)
((long*)fdset)[i] = 0; ((long*)fdset)[i] = 0;
} }
/* Resent Coverity reports quite weird errors... */
int *__errno_location(void)
{
}
const unsigned short **__ctype_b_loc (void)
{
}
/* /*
* Added extra pointer check to not need these models, * Added extra pointer check to not need these models,
* for now just keep then in file * for now just keep then in file

View File

@ -48,8 +48,12 @@ ifeq ("@BUILD_LVMDBUSD@", "yes")
SUBDIRS += lvmdbusd SUBDIRS += lvmdbusd
endif endif
ifeq ("@BUILD_DMFILEMAPD@", "yes")
SUBDIRS += dmfilemapd
endif
ifeq ($(MAKECMDGOALS),distclean) ifeq ($(MAKECMDGOALS),distclean)
SUBDIRS = clvmd cmirrord dmeventd lvmetad lvmpolld lvmlockd lvmdbusd SUBDIRS = clvmd cmirrord dmeventd lvmetad lvmpolld lvmlockd lvmdbusd dmfilemapd
endif endif
include $(top_builddir)/make.tmpl include $(top_builddir)/make.tmpl

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2005-2015 Red Hat, Inc. All rights reserved. * Copyright (C) 2005-2017 Red Hat, Inc. All rights reserved.
* *
* This file is part of LVM2. * This file is part of LVM2.
* *
@ -25,7 +25,6 @@
struct dso_state { struct dso_state {
struct dm_pool *mem; struct dm_pool *mem;
char cmd_lvscan[512];
char cmd_lvconvert[512]; char cmd_lvconvert[512];
}; };
@ -99,12 +98,8 @@ static int _get_mirror_event(struct dso_state *state, char *params)
return r; return r;
} }
static int _remove_failed_devices(const char *cmd_lvscan, const char *cmd_lvconvert, static int _remove_failed_devices(const char *cmd_lvconvert, const char *device)
const char *device)
{ {
if (!dmeventd_lvm2_run_with_lock(cmd_lvscan))
log_warn("WARNING: Re-scan of mirrored device %s failed.", device);
/* if repair goes OK, report success even if lvscan has failed */ /* if repair goes OK, report success even if lvscan has failed */
if (!dmeventd_lvm2_run_with_lock(cmd_lvconvert)) { if (!dmeventd_lvm2_run_with_lock(cmd_lvconvert)) {
log_error("Repair of mirrored device %s failed.", device); log_error("Repair of mirrored device %s failed.", device);
@ -151,9 +146,7 @@ void process_event(struct dm_task *dmt,
break; break;
case ME_FAILURE: case ME_FAILURE:
log_error("Device failure in %s.", device); log_error("Device failure in %s.", device);
if (!_remove_failed_devices(state->cmd_lvscan, if (!_remove_failed_devices(state->cmd_lvconvert, device))
state->cmd_lvconvert,
device))
/* FIXME Why are all the error return codes unused? Get rid of them? */ /* FIXME Why are all the error return codes unused? Get rid of them? */
log_error("Failed to remove faulty devices in %s.", log_error("Failed to remove faulty devices in %s.",
device); device);
@ -183,10 +176,7 @@ int register_device(const char *device,
if (!dmeventd_lvm2_init_with_pool("mirror_state", state)) if (!dmeventd_lvm2_init_with_pool("mirror_state", state))
goto_bad; goto_bad;
if (!dmeventd_lvm2_command(state->mem, state->cmd_lvscan, sizeof(state->cmd_lvscan), /* CANNOT use --config as this disables cached content */
"lvscan --cache", device))
goto_bad;
if (!dmeventd_lvm2_command(state->mem, state->cmd_lvconvert, sizeof(state->cmd_lvconvert), if (!dmeventd_lvm2_command(state->mem, state->cmd_lvconvert, sizeof(state->cmd_lvconvert),
"lvconvert --repair --use-policies", device)) "lvconvert --repair --use-policies", device))
goto_bad; goto_bad;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2005-2016 Red Hat, Inc. All rights reserved. * Copyright (C) 2005-2017 Red Hat, Inc. All rights reserved.
* *
* This file is part of LVM2. * This file is part of LVM2.
* *
@ -22,7 +22,6 @@
struct dso_state { struct dso_state {
struct dm_pool *mem; struct dm_pool *mem;
char cmd_lvscan[512];
char cmd_lvconvert[512]; char cmd_lvconvert[512];
uint64_t raid_devs[RAID_DEVS_ELEMS]; uint64_t raid_devs[RAID_DEVS_ELEMS];
int failed; int failed;
@ -74,8 +73,6 @@ static int _process_raid_event(struct dso_state *state, char *params, const char
goto out; /* already reported */ goto out; /* already reported */
state->failed = 1; state->failed = 1;
if (!dmeventd_lvm2_run_with_lock(state->cmd_lvscan))
log_warn("WARNING: Re-scan of RAID device %s failed.", device);
/* if repair goes OK, report success even if lvscan has failed */ /* if repair goes OK, report success even if lvscan has failed */
if (!dmeventd_lvm2_run_with_lock(state->cmd_lvconvert)) { if (!dmeventd_lvm2_run_with_lock(state->cmd_lvconvert)) {
@ -136,9 +133,7 @@ int register_device(const char *device,
if (!dmeventd_lvm2_init_with_pool("raid_state", state)) if (!dmeventd_lvm2_init_with_pool("raid_state", state))
goto_bad; goto_bad;
if (!dmeventd_lvm2_command(state->mem, state->cmd_lvscan, sizeof(state->cmd_lvscan), if (!dmeventd_lvm2_command(state->mem, state->cmd_lvconvert, sizeof(state->cmd_lvconvert),
"lvscan --cache", device) ||
!dmeventd_lvm2_command(state->mem, state->cmd_lvconvert, sizeof(state->cmd_lvconvert),
"lvconvert --config devices{ignore_suspended_devices=1} " "lvconvert --config devices{ignore_suspended_devices=1} "
"--repair --use-policies", device)) "--repair --use-policies", device))
goto_bad; goto_bad;

1
daemons/dmfilemapd/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
dmfilemapd

View File

@ -0,0 +1,68 @@
#
# Copyright (C) 2016 Red Hat, Inc. All rights reserved.
#
# This file is part of the device-mapper userspace tools.
#
# This copyrighted material is made available to anyone wishing to use,
# modify, copy, or redistribute it subject to the terms and conditions
# of the GNU Lesser General Public License v.2.1.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
srcdir = @srcdir@
top_srcdir = @top_srcdir@
top_builddir = @top_builddir@
SOURCES = dmfilemapd.c
TARGETS = dmfilemapd
.PHONY: install_dmfilemapd install_dmfilemapd_static
INSTALL_DMFILEMAPD_TARGETS = install_dmfilemapd_dynamic
CLEAN_TARGETS = dmfilemapd.static
CFLOW_LIST = $(SOURCES)
CFLOW_LIST_TARGET = $(LIB_NAME).cflow
CFLOW_TARGET = dmfilemapd
include $(top_builddir)/make.tmpl
all: device-mapper
device-mapper: $(TARGETS)
LIBS += -ldevmapper
CFLAGS_dmfilemapd.o += $(EXTRA_EXEC_CFLAGS)
dmfilemapd: $(LIB_SHARED) dmfilemapd.o
$(CC) $(CFLAGS) $(LDFLAGS) $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS) -L. -o $@ dmfilemapd.o \
$(DL_LIBS) $(LVMLIBS) $(LIBS) -rdynamic
dmfilemapd.static: $(LIB_STATIC) dmfilemapd.o $(interfacebuilddir)/libdevmapper.a
$(CC) $(CFLAGS) $(LDFLAGS) $(ELDFLAGS) -static -L. -L$(interfacebuilddir) -o $@ \
dmfilemapd.o $(DL_LIBS) $(LVMLIBS) $(LIBS) $(STATIC_LIBS)
ifneq ("$(CFLOW_CMD)", "")
CFLOW_SOURCES = $(addprefix $(srcdir)/, $(SOURCES))
-include $(top_builddir)/libdm/libdevmapper.cflow
-include $(top_builddir)/lib/liblvm-internal.cflow
-include $(top_builddir)/lib/liblvm2cmd.cflow
-include $(top_builddir)/daemons/dmfilemapd/$(LIB_NAME).cflow
endif
install_dmfilemapd_dynamic: dmfilemapd
$(INSTALL_PROGRAM) -D $< $(sbindir)/$(<F)
install_dmfilemapd_static: dmfilemapd.static
$(INSTALL_PROGRAM) -D $< $(staticdir)/$(<F)
install_dmfilemapd: $(INSTALL_DMFILEMAPD_TARGETS)
install: install_dmfilemapd
install_device-mapper: install_dmfilemapd

View File

@ -0,0 +1,816 @@
/*
* Copyright (C) 2016 Red Hat, Inc. All rights reserved.
*
* This file is part of the device-mapper userspace tools.
*
* It includes tree drawing code based on pstree: http://psmisc.sourceforge.net/
*
* 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 General Public License v.2.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "tool.h"
#include "dm-logging.h"
#include "defaults.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/inotify.h>
#include <dirent.h>
#include <ctype.h>
#ifdef __linux__
# include "kdev_t.h"
#else
# define MAJOR(x) major((x))
# define MINOR(x) minor((x))
# define MKDEV(x,y) makedev((x),(y))
#endif
/* limit to two updates/sec */
#define FILEMAPD_WAIT_USECS 500000
/* how long to wait for unlinked files */
#define FILEMAPD_NOFILE_WAIT_USECS 100000
#define FILEMAPD_NOFILE_WAIT_TRIES 10
struct filemap_monitor {
dm_filemapd_mode_t mode;
const char *program_id;
uint64_t group_id;
char *path;
int fd;
int inotify_fd;
int inotify_watch_fd;
/* monitoring heuristics */
int64_t blocks; /* allocated blocks, from stat.st_blocks */
uint64_t nr_regions;
int deleted;
};
static int _foreground;
static int _verbose;
const char *const _usage = "dmfilemapd <fd> <group_id> <abs_path> <mode> "
"[<foreground>[<log_level>]]";
/*
* Daemon logging. By default, all messages are thrown away: messages
* are only written to the terminal if the daemon is run in the foreground.
*/
__attribute__((format(printf, 5, 0)))
static void _dmfilemapd_log_line(int level,
const char *file __attribute__((unused)),
int line __attribute__((unused)),
int dm_errno_or_class,
const char *f, va_list ap)
{
static int _abort_on_internal_errors = -1;
FILE *out = log_stderr(level) ? stderr : stdout;
level = log_level(level);
if (level <= _LOG_WARN || _verbose) {
if (level < _LOG_WARN)
out = stderr;
vfprintf(out, f, ap);
fputc('\n', out);
}
if (_abort_on_internal_errors < 0)
/* Set when env DM_ABORT_ON_INTERNAL_ERRORS is not "0" */
_abort_on_internal_errors =
strcmp(getenv("DM_ABORT_ON_INTERNAL_ERRORS") ? : "0", "0");
if (_abort_on_internal_errors &&
!strncmp(f, INTERNAL_ERROR, sizeof(INTERNAL_ERROR) - 1))
abort();
}
__attribute__((format(printf, 5, 6)))
static void _dmfilemapd_log_with_errno(int level,
const char *file, int line,
int dm_errno_or_class,
const char *f, ...)
{
va_list ap;
va_start(ap, f);
_dmfilemapd_log_line(level, file, line, dm_errno_or_class, f, ap);
va_end(ap);
}
/*
* Only used for reporting errors before daemonise().
*/
__attribute__((format(printf, 1, 2)))
static void _early_log(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
fputc('\n', stderr);
va_end(ap);
}
static void _setup_logging(void)
{
dm_log_init_verbose(_verbose - 1);
dm_log_with_errno_init(_dmfilemapd_log_with_errno);
}
#define PROC_FD_DELETED_STR "(deleted)"
/*
* Scan the /proc/<pid>/fd directory for pid and check for an fd
* symlink whose contents match path.
*/
static int _is_open_in_pid(pid_t pid, const char *path)
{
char deleted_path[PATH_MAX + sizeof(PROC_FD_DELETED_STR)];
struct dirent *pid_dp = NULL;
char path_buf[PATH_MAX];
char link_buf[PATH_MAX];
DIR *pid_d = NULL;
ssize_t len;
if (pid == getpid())
return 0;
if (dm_snprintf(path_buf, sizeof(path_buf),
DEFAULT_PROC_DIR "%d/fd", pid) < 0) {
log_error("Could not format pid path.");
return 0;
}
/*
* Test for the kernel 'file (deleted)' form when scanning.
*/
if (dm_snprintf(deleted_path, sizeof(deleted_path), "%s %s",
path, PROC_FD_DELETED_STR) < 0) {
log_error("Could not format check path.");
return 0;
}
pid_d = opendir(path_buf);
if (!pid_d) {
log_error("Could not open proc path: %s.", path_buf);
return 0;
}
while ((pid_dp = readdir(pid_d)) != NULL) {
if (pid_dp->d_name[0] == '.')
continue;
if ((len = readlinkat(dirfd(pid_d), pid_dp->d_name, link_buf,
sizeof(link_buf))) < 0) {
log_error("readlink failed for " DEFAULT_PROC_DIR
"/%d/fd/.", pid);
goto bad;
}
link_buf[len] = '\0';
if (!strcmp(deleted_path, link_buf)) {
if (closedir(pid_d))
log_sys_error("closedir", path_buf);
return 1;
}
}
bad:
if (closedir(pid_d))
log_sys_error("closedir", path_buf);
return 0;
}
/*
* Attempt to determine whether a file is open by any process by
* scanning symbolic links in /proc/<pid>/fd.
*
* This is a heuristic since it cannot guarantee to detect brief
* access in all cases: a process that opens and then closes the
* file rapidly may never be seen by the scan.
*
* The method will also give false-positives if a process exists
* that has a deleted file open that had the same path, but a
* different inode number, to the file being monitored.
*
* For this reason the daemon only uses _is_open() for unlinked
* files when the mode is DM_FILEMAPD_FOLLOW_INODE, since these
* files can no longer be newly opened by processes.
*
* In this situation !is_open(path) provides an indication that
* the daemon should shut down: the file has been unlinked from
* the file system and we appear to hold the final reference.
*/
static int _is_open(const char *path)
{
struct dirent *proc_dp = NULL;
DIR *proc_d = NULL;
pid_t pid;
proc_d = opendir(DEFAULT_PROC_DIR);
if (!proc_d)
return 0;
while ((proc_dp = readdir(proc_d)) != NULL) {
if (!isdigit(proc_dp->d_name[0]))
continue;
pid = (pid_t) strtol(proc_dp->d_name, NULL, 10);
if (!pid)
continue;
if (_is_open_in_pid(pid, path)) {
if (closedir(proc_d))
log_sys_error("closedir", DEFAULT_PROC_DIR);
return 1;
}
}
if (closedir(proc_d))
log_sys_error("closedir", DEFAULT_PROC_DIR);
return 0;
}
static void _filemap_monitor_wait(uint64_t usecs)
{
if (_verbose) {
if (usecs == FILEMAPD_WAIT_USECS)
log_very_verbose("Waiting for check interval");
if (usecs == FILEMAPD_NOFILE_WAIT_USECS)
log_very_verbose("Waiting for unlinked path");
}
usleep((useconds_t) usecs);
}
static int _parse_args(int argc, char **argv, struct filemap_monitor *fm)
{
char *endptr;
/* we don't care what is in argv[0]. */
argc--;
argv++;
if (argc < 5) {
_early_log("Wrong number of arguments.");
_early_log("usage: %s", _usage);
return 0;
}
memset(fm, 0, sizeof(*fm));
/*
* We don't know the true nr_regions at daemon start time,
* and it is not worth a dm_stats_list()/group walk to count:
* we can assume that there is at least one region or the
* daemon would not have been started.
*
* A correct value will be obtained following the first update
* of the group's regions.
*/
fm->nr_regions = 1;
/* parse <fd> */
fm->fd = (int) strtol(argv[0], &endptr, 10);
if (*endptr) {
_early_log("Could not parse file descriptor: %s", argv[0]);
return 0;
}
argc--;
argv++;
/* parse <group_id> */
fm->group_id = strtoull(argv[0], &endptr, 10);
if (*endptr) {
_early_log("Could not parse group identifier: %s", argv[0]);
return 0;
}
argc--;
argv++;
/* parse <path> */
if (!argv[0] || !strlen(argv[0])) {
_early_log("Path argument is required.");
return 0;
}
if (*argv[0] != '/') {
_early_log("Path argument must specify an absolute path.");
return 0;
}
fm->path = dm_strdup(argv[0]);
if (!fm->path) {
_early_log("Could not allocate memory for path argument.");
return 0;
}
argc--;
argv++;
/* parse <mode> */
if (!argv[0] || !strlen(argv[0])) {
_early_log("Mode argument is required.");
return 0;
}
fm->mode = dm_filemapd_mode_from_string(argv[0]);
if (fm->mode == DM_FILEMAPD_FOLLOW_NONE)
return 0;
argc--;
argv++;
/* parse [<foreground>[<verbose>]] */
if (argc) {
_foreground = (int) strtol(argv[0], &endptr, 10);
if (*endptr) {
_early_log("Could not parse debug argument: %s.",
argv[0]);
return 0;
}
argc--;
argv++;
if (argc) {
_verbose = (int) strtol(argv[0], &endptr, 10);
if (*endptr) {
_early_log("Could not parse verbose "
"argument: %s", argv[0]);
return 0;
}
if (_verbose < 0 || _verbose > 3) {
_early_log("Verbose argument out of range: %d.",
_verbose);
return 0;
}
}
}
return 1;
}
static int _filemap_fd_check_changed(struct filemap_monitor *fm)
{
int64_t blocks, old_blocks;
struct stat buf;
if (fm->fd < 0) {
log_error("Filemap fd is not open.");
return -1;
}
if (fstat(fm->fd, &buf)) {
log_error("Failed to fstat filemap file descriptor.");
return -1;
}
blocks = buf.st_blocks;
/* first check? */
if (fm->blocks < 0)
old_blocks = buf.st_blocks;
else
old_blocks = fm->blocks;
fm->blocks = blocks;
return (fm->blocks != old_blocks);
}
static void _filemap_monitor_close_fd(struct filemap_monitor *fm)
{
if (close(fm->fd))
log_error("Error closing file descriptor.");
fm->fd = -1;
}
static void _filemap_monitor_end_notify(struct filemap_monitor *fm)
{
inotify_rm_watch(fm->inotify_fd, fm->inotify_watch_fd);
}
static int _filemap_monitor_set_notify(struct filemap_monitor *fm)
{
int inotify_fd, watch_fd;
/*
* Set IN_NONBLOCK since we do not want to block in event read()
* calls. Do not set IN_CLOEXEC as dmfilemapd is single-threaded
* and does not fork or exec.
*/
if ((inotify_fd = inotify_init1(IN_NONBLOCK)) < 0) {
log_sys_error("inotify_init1", "IN_NONBLOCK");
return 0;
}
if ((watch_fd = inotify_add_watch(inotify_fd, fm->path,
IN_MODIFY | IN_DELETE_SELF)) < 0) {
log_sys_error("inotify_add_watch", fm->path);
return 0;
}
fm->inotify_fd = inotify_fd;
fm->inotify_watch_fd = watch_fd;
return 1;
}
static int _filemap_monitor_reopen_fd(struct filemap_monitor *fm)
{
int tries = FILEMAPD_NOFILE_WAIT_TRIES;
/*
* In DM_FILEMAPD_FOLLOW_PATH mode, inotify watches must be
* re-established whenever the file at the watched path is
* changed.
*
* FIXME: stat file and skip if inode is unchanged.
*/
if (fm->fd > 0)
log_error("Filemap file descriptor already open.");
while ((fm->fd < 0) && --tries)
if (((fm->fd = open(fm->path, O_RDONLY)) < 0) && tries)
_filemap_monitor_wait(FILEMAPD_NOFILE_WAIT_USECS);
if (!tries && (fm->fd < 0)) {
log_error("Could not re-open file descriptor.");
return 0;
}
return _filemap_monitor_set_notify(fm);
}
static int _filemap_monitor_get_events(struct filemap_monitor *fm)
{
/* alignment as per man(7) inotify */
char buf[sizeof(struct inotify_event) + NAME_MAX + 1]
__attribute__ ((aligned(__alignof__(struct inotify_event))));
struct inotify_event *event;
int check = 0;
ssize_t len;
char *ptr;
/*
* Close the file descriptor for the file being monitored here
* when mode=path: this will allow the inode to be de-allocated,
* and an IN_DELETE_SELF event generated in the case that the
* daemon is holding the last open reference to the file.
*/
if (fm->mode == DM_FILEMAPD_FOLLOW_PATH) {
_filemap_monitor_end_notify(fm);
_filemap_monitor_close_fd(fm);
}
len = read(fm->inotify_fd, (void *) &buf, sizeof(buf));
/* no events to read? */
if (len < 0 && (errno == EAGAIN))
goto out;
/* interrupted by signal? */
if (len < 0 && (errno == EINTR))
goto out;
if (len < 0)
return -1;
if (!len)
goto out;
for (ptr = buf; ptr < buf + len; ptr += sizeof(*event) + event->len) {
event = (struct inotify_event *) ptr;
if (event->mask & IN_DELETE_SELF)
fm->deleted = 1;
if (event->mask & IN_MODIFY)
check = 1;
/*
* Event IN_IGNORED is generated when a file has been deleted
* and IN_DELETE_SELF generated, and indicates that the file
* watch has been automatically removed.
*
* This can only happen for the DM_FILEMAPD_FOLLOW_PATH mode,
* since inotify IN_DELETE events are generated at the time
* the inode is destroyed: DM_FILEMAPD_FOLLOW_INODE will hold
* the file descriptor open, meaning that the event will not
* be generated until after the daemon closes the file.
*
* The event is ignored here since inotify monitoring will
* be reestablished (or the daemon will terminate) following
* deletion of a DM_FILEMAPD_FOLLOW_PATH monitored file.
*/
if (event->mask & IN_IGNORED)
log_very_verbose("Inotify watch removed: IN_IGNORED "
"in event->mask");
}
out:
/*
* Re-open file descriptor if required and log disposition.
*/
if (fm->mode == DM_FILEMAPD_FOLLOW_PATH)
if (!_filemap_monitor_reopen_fd(fm))
return -1;
log_very_verbose("exiting _filemap_monitor_get_events() with "
"deleted=%d, check=%d", fm->deleted, check);
return check;
}
static void _filemap_monitor_destroy(struct filemap_monitor *fm)
{
if (fm->fd > 0) {
_filemap_monitor_end_notify(fm);
_filemap_monitor_close_fd(fm);
}
dm_free((void *) fm->program_id);
}
static int _filemap_monitor_check_same_file(int fd1, int fd2)
{
struct stat buf1, buf2;
if ((fd1 < 0) || (fd2 < 0))
return 0;
if (fstat(fd1, &buf1)) {
log_error("Failed to fstat file descriptor %d", fd1);
return -1;
}
if (fstat(fd2, &buf2)) {
log_error("Failed to fstat file descriptor %d", fd2);
return -1;
}
return ((buf1.st_dev == buf2.st_dev) && (buf1.st_ino == buf2.st_ino));
}
static int _filemap_monitor_check_file_unlinked(struct filemap_monitor *fm)
{
char path_buf[PATH_MAX];
char link_buf[PATH_MAX];
int same, fd;
ssize_t len;
fm->deleted = 0;
if ((fd = open(fm->path, O_RDONLY)) < 0)
goto check_unlinked;
same = _filemap_monitor_check_same_file(fm->fd, fd);
if (close(fd))
log_error("Error closing fd %d", fd);
if (same < 0)
return 0;
if (same)
return 1;
check_unlinked:
/*
* The file has been unlinked from its original location: test
* whether it is still reachable in the filesystem, or if it is
* unlinked and anonymous.
*/
if (dm_snprintf(path_buf, sizeof(path_buf), DEFAULT_PROC_DIR
"/%d/fd/%d", getpid(), fm->fd) < 0) {
log_error("Could not format pid path.");
return 0;
}
if ((len = readlink(path_buf, link_buf, sizeof(link_buf))) < 0) {
log_error("readlink failed for " DEFAULT_PROC_DIR "/%d/fd/%d.",
getpid(), fm->fd);
return 0;
}
link_buf[len] = '\0';
/*
* Try to re-open the file, from the path now reported in /proc/pid/fd.
*/
if ((fd = open(link_buf, O_RDONLY)) < 0)
fm->deleted = 1;
else
same = _filemap_monitor_check_same_file(fm->fd, fd);
if ((fd >= 0) && close(fd))
log_error("Error closing fd %d", fd);
if (same < 0)
return 0;
/* Should not happen with normal /proc. */
if ((fd > 0) && !same) {
log_error("File descriptor mismatch: %d and %s (read from %s) "
"are not the same file!", fm->fd, link_buf, path_buf);
return 0;
}
return 1;
}
static int _daemonise(struct filemap_monitor *fm)
{
pid_t pid = 0, sid;
int fd;
if (!(sid = setsid())) {
_early_log("setsid failed.");
return 0;
}
if ((pid = fork()) < 0) {
_early_log("Failed to fork daemon process.");
return 0;
}
if (pid > 0) {
if (_verbose)
_early_log("Started dmfilemapd with pid=%d", pid);
exit(0);
}
if (chdir("/")) {
_early_log("Failed to change directory.");
return 0;
}
if (!_verbose) {
if (close(STDIN_FILENO))
_early_log("Error closing stdin");
if (close(STDOUT_FILENO))
_early_log("Error closing stdout");
if (close(STDERR_FILENO))
_early_log("Error closing stderr");
if ((open("/dev/null", O_RDONLY) < 0) ||
(open("/dev/null", O_WRONLY) < 0) ||
(open("/dev/null", O_WRONLY) < 0)) {
_early_log("Error opening stdio streams.");
return 0;
}
}
for (fd = (int) sysconf(_SC_OPEN_MAX) - 1; fd > STDERR_FILENO; fd--) {
if (fd == fm->fd)
continue;
close(fd);
}
return 1;
}
static int _update_regions(struct dm_stats *dms, struct filemap_monitor *fm)
{
uint64_t *regions = NULL, *region, nr_regions = 0;
regions = dm_stats_update_regions_from_fd(dms, fm->fd, fm->group_id);
if (!regions) {
log_error("Failed to update filemap regions for group_id="
FMTu64 ".", fm->group_id);
return 0;
}
for (region = regions; *region != DM_STATS_REGIONS_ALL; region++)
nr_regions++;
if (regions[0] != fm->group_id) {
log_warn("group_id changed from " FMTu64 " to " FMTu64,
fm->group_id, regions[0]);
fm->group_id = regions[0];
}
dm_free(regions);
fm->nr_regions = nr_regions;
return 1;
}
static int _dmfilemapd(struct filemap_monitor *fm)
{
int running = 1, check = 0, open = 0;
const char *program_id;
struct dm_stats *dms;
/*
* The correct program_id is retrieved from the group leader
* following the call to dm_stats_list().
*/
dms = dm_stats_create(NULL);
if (!dm_stats_bind_from_fd(dms, fm->fd)) {
log_error("Could not bind dm_stats handle to file descriptor "
"%d", fm->fd);
goto bad;
}
if (!_filemap_monitor_set_notify(fm))
goto bad;
if (!dm_stats_list(dms, DM_STATS_ALL_PROGRAMS)) {
log_error("Failed to list stats handle.");
goto bad;
}
/*
* Take the program_id for new regions (created by calls to
* dm_stats_update_regions_from_fd()) from the value used by
* the group leader.
*/
program_id = dm_stats_get_region_program_id(dms, fm->group_id);
if (program_id)
fm->program_id = dm_strdup(program_id);
else
fm->program_id = NULL;
dm_stats_set_program_id(dms, 1, program_id);
do {
if (!dm_stats_group_present(dms, fm->group_id)) {
log_info("Filemap group removed: exiting.");
running = 0;
continue;
}
if ((check = _filemap_monitor_get_events(fm)) < 0)
goto bad;
if (!check)
goto wait;
if ((check = _filemap_fd_check_changed(fm)) < 0)
goto bad;
if (!check)
goto wait;
if (!_update_regions(dms, fm))
goto bad;
wait:
_filemap_monitor_wait(FILEMAPD_WAIT_USECS);
running = !!fm->nr_regions;
/* mode=inode termination condions */
if (fm->mode == DM_FILEMAPD_FOLLOW_INODE) {
if (!_filemap_monitor_check_file_unlinked(fm))
goto bad;
if (fm->deleted && !(open = _is_open(fm->path))) {
log_info("File unlinked and closed: exiting.");
running = 0;
} else if (fm->deleted && open)
log_verbose("File unlinked and open: "
"continuing.");
}
if (!dm_stats_list(dms, NULL)) {
log_error("Failed to list stats handle.");
goto bad;
}
} while (running);
_filemap_monitor_destroy(fm);
dm_stats_destroy(dms);
return 0;
bad:
_filemap_monitor_destroy(fm);
dm_stats_destroy(dms);
log_error("Exiting");
return 1;
}
static const char * _mode_names[] = {
"inode",
"path"
};
/*
* dmfilemapd <fd> <group_id> <path> <mode> [<foreground>[<log_level>]]
*/
int main(int argc, char **argv)
{
struct filemap_monitor fm;
if (!_parse_args(argc, argv, &fm))
return 1;
_setup_logging();
log_info("Starting dmfilemapd with fd=%d, group_id=" FMTu64 " "
"mode=%s, path=%s", fm.fd, fm.group_id,
_mode_names[fm.mode], fm.path);
if (!_foreground && !_daemonise(&fm))
return 1;
return _dmfilemapd(&fm);
}

View File

@ -38,7 +38,7 @@ class AutomatedProperties(dbus.service.Object):
props = {} props = {}
for i in self.interface(): for i in self.interface():
props[i] = self.GetAll(i) props[i] = AutomatedProperties._get_all_prop(self, i)
return self._ap_o_path, props return self._ap_o_path, props
@ -65,32 +65,53 @@ class AutomatedProperties(dbus.service.Object):
return self._ap_interface return self._ap_interface
# Properties @staticmethod
# noinspection PyUnusedLocal def _get_prop(obj, interface_name, property_name):
@dbus.service.method(dbus_interface=dbus.PROPERTIES_IFACE, value = getattr(obj, property_name)
in_signature='ss', out_signature='v')
def Get(self, interface_name, property_name):
value = getattr(self, property_name)
# Note: If we get an exception in this handler we won't know about it, # Note: If we get an exception in this handler we won't know about it,
# only the side effect of no returned value! # only the side effect of no returned value!
log_debug('Get (%s), type (%s), value(%s)' % log_debug('Get (%s), type (%s), value(%s)' %
(property_name, str(type(value)), str(value))) (property_name, str(type(value)), str(value)))
return value return value
# Properties
# noinspection PyUnusedLocal
@dbus.service.method(dbus_interface=dbus.PROPERTIES_IFACE, @dbus.service.method(dbus_interface=dbus.PROPERTIES_IFACE,
in_signature='s', out_signature='a{sv}') in_signature='ss', out_signature='v',
def GetAll(self, interface_name): async_callbacks=('cb', 'cbe'))
if interface_name in self.interface(True): def Get(self, interface_name, property_name, cb, cbe):
# Note: If we get an exception in this handler we won't know about it,
# only the side effect of no returned value!
r = cfg.create_request_entry(
-1, AutomatedProperties._get_prop,
(self, interface_name, property_name),
cb, cbe, False)
cfg.worker_q.put(r)
@staticmethod
def _get_all_prop(obj, interface_name):
if interface_name in obj.interface(True):
# Using introspection, lets build this dynamically # Using introspection, lets build this dynamically
properties = get_properties(self) properties = get_properties(obj)
if interface_name in properties: if interface_name in properties:
return properties[interface_name][1] return properties[interface_name][1]
return {} return {}
raise dbus.exceptions.DBusException( raise dbus.exceptions.DBusException(
self._ap_interface, obj._ap_interface,
'The object %s does not implement the %s interface' 'The object %s does not implement the %s interface'
% (self.__class__, interface_name)) % (self.__class__, interface_name))
@dbus.service.method(dbus_interface=dbus.PROPERTIES_IFACE,
in_signature='s', out_signature='a{sv}',
async_callbacks=('cb', 'cbe'))
def GetAll(self, interface_name, cb, cbe):
r = cfg.create_request_entry(
-1, AutomatedProperties._get_all_prop,
(self, interface_name),
cb, cbe, False)
cfg.worker_q.put(r)
@dbus.service.method(dbus_interface=dbus.PROPERTIES_IFACE, @dbus.service.method(dbus_interface=dbus.PROPERTIES_IFACE,
in_signature='ssv') in_signature='ssv')
def Set(self, interface_name, property_name, new_value): def Set(self, interface_name, property_name, new_value):

View File

@ -11,7 +11,8 @@ import subprocess
from . import cfg from . import cfg
from .cmdhandler import options_to_cli_args from .cmdhandler import options_to_cli_args
import dbus import dbus
from .utils import pv_range_append, pv_dest_ranges, log_error, log_debug from .utils import pv_range_append, pv_dest_ranges, log_error, log_debug,\
add_no_notify
import os import os
import threading import threading
@ -42,6 +43,10 @@ def _move_merge(interface_name, command, job_state):
# the command always as we will be getting periodic output from them on # the command always as we will be getting periodic output from them on
# the status of the long running operation. # the status of the long running operation.
command.insert(0, cfg.LVM_CMD) command.insert(0, cfg.LVM_CMD)
# Instruct lvm to not register an event with us
command = add_no_notify(command)
process = subprocess.Popen(command, stdout=subprocess.PIPE, process = subprocess.Popen(command, stdout=subprocess.PIPE,
env=os.environ, env=os.environ,
stderr=subprocess.PIPE, close_fds=True) stderr=subprocess.PIPE, close_fds=True)
@ -59,6 +64,10 @@ def _move_merge(interface_name, command, job_state):
(device, ignore, percentage) = line_str.split(':') (device, ignore, percentage) = line_str.split(':')
job_state.Percent = round( job_state.Percent = round(
float(percentage.strip()[:-1]), 1) float(percentage.strip()[:-1]), 1)
# While the move is in progress we need to periodically update
# the state to reflect where everything is at.
cfg.load()
except ValueError: except ValueError:
log_error("Trying to parse percentage which failed for %s" % log_error("Trying to parse percentage which failed for %s" %
line_str) line_str)

View File

@ -26,7 +26,7 @@ bus = None
args = None args = None
# Set to true if we are depending on external events for updates # Set to true if we are depending on external events for updates
ee = False got_external_event = False
# Shared state variable across all processes # Shared state variable across all processes
run = multiprocessing.Value('i', 1) run = multiprocessing.Value('i', 1)
@ -84,3 +84,6 @@ db = None
# lvm flight recorder # lvm flight recorder
blackbox = None blackbox = None
# RequestEntry ctor
create_request_entry = None

View File

@ -16,7 +16,7 @@ import traceback
import os import os
from lvmdbusd import cfg from lvmdbusd import cfg
from lvmdbusd.utils import pv_dest_ranges, log_debug, log_error from lvmdbusd.utils import pv_dest_ranges, log_debug, log_error, add_no_notify
from lvmdbusd.lvm_shell_proxy import LVMShellProxy from lvmdbusd.lvm_shell_proxy import LVMShellProxy
try: try:
@ -93,6 +93,7 @@ def call_lvm(command, debug=False):
# Prepend the full lvm executable so that we can run different versions # Prepend the full lvm executable so that we can run different versions
# in different locations on the same box # in different locations on the same box
command.insert(0, cfg.LVM_CMD) command.insert(0, cfg.LVM_CMD)
command = add_no_notify(command)
process = Popen(command, stdout=PIPE, stderr=PIPE, close_fds=True, process = Popen(command, stdout=PIPE, stderr=PIPE, close_fds=True,
env=os.environ) env=os.environ)

View File

@ -29,7 +29,7 @@ except ImportError:
from lvmdbusd.cfg import LVM_CMD from lvmdbusd.cfg import LVM_CMD
from lvmdbusd.utils import log_debug, log_error from lvmdbusd.utils import log_debug, log_error, add_no_notify
SHELL_PROMPT = "lvm> " SHELL_PROMPT = "lvm> "
@ -206,6 +206,8 @@ class LVMShellProxy(object):
self.lvm_shell.returncode, self.lvm_shell.returncode,
"Underlying lvm shell process is not present!") "Underlying lvm shell process is not present!")
argv = add_no_notify(argv)
# create the command string # create the command string
cmd = " ".join(_quote_arg(arg) for arg in argv) cmd = " ".join(_quote_arg(arg) for arg in argv)
cmd += "\n" cmd += "\n"

View File

@ -30,6 +30,7 @@ import argparse
import os import os
import sys import sys
from .cmdhandler import LvmFlightRecorder from .cmdhandler import LvmFlightRecorder
from .request import RequestEntry
class Lvm(objectmanager.ObjectManager): class Lvm(objectmanager.ObjectManager):
@ -97,6 +98,7 @@ def main():
os.environ["LC_ALL"] = "C" os.environ["LC_ALL"] = "C"
cfg.args = parser.parse_args() cfg.args = parser.parse_args()
cfg.create_request_entry = RequestEntry
# We create a flight recorder in cmdhandler too, but we replace it here # We create a flight recorder in cmdhandler too, but we replace it here
# as the user may be specifying a different size. The default one in # as the user may be specifying a different size. The default one in
@ -144,7 +146,6 @@ def main():
thread_list.append(updater.thread) thread_list.append(updater.thread)
cfg.load = updater.load cfg.load = updater.load
cfg.event = updater.event
cfg.loop = GLib.MainLoop() cfg.loop = GLib.MainLoop()

View File

@ -6,7 +6,7 @@
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
from utils import log_debug
from .automatedproperties import AutomatedProperties from .automatedproperties import AutomatedProperties
from . import utils from . import utils
@ -132,11 +132,28 @@ class Manager(AutomatedProperties):
r = RequestEntry(-1, Manager._refresh, (), cb, cbe, False) r = RequestEntry(-1, Manager._refresh, (), cb, cbe, False)
cfg.worker_q.put(r) cfg.worker_q.put(r)
@dbus.service.method(
dbus_interface=MANAGER_INTERFACE)
def FlightRecorderDump(self):
"""
Dump the flight recorder to syslog
"""
cfg.blackbox.dump()
@staticmethod
def _lookup_by_lvm_id(key):
p = cfg.om.get_object_path_by_uuid_lvm_id(key, key)
if not p:
p = '/'
log_debug('LookUpByLvmId: key = %s, result = %s' % (key, p))
return p
@dbus.service.method( @dbus.service.method(
dbus_interface=MANAGER_INTERFACE, dbus_interface=MANAGER_INTERFACE,
in_signature='s', in_signature='s',
out_signature='o') out_signature='o',
def LookUpByLvmId(self, key): async_callbacks=('cb', 'cbe'))
def LookUpByLvmId(self, key, cb, cbe):
""" """
Given a lvm id in one of the forms: Given a lvm id in one of the forms:
@ -150,10 +167,8 @@ class Manager(AutomatedProperties):
:param key: The lookup value :param key: The lookup value
:return: Return the object path. If object not found you will get '/' :return: Return the object path. If object not found you will get '/'
""" """
p = cfg.om.get_object_path_by_uuid_lvm_id(key, key) r = RequestEntry(-1, Manager._lookup_by_lvm_id, (key,), cb, cbe, False)
if p: cfg.worker_q.put(r)
return p
return '/'
@staticmethod @staticmethod
def _use_lvm_shell(yes_no): def _use_lvm_shell(yes_no):
@ -169,25 +184,33 @@ class Manager(AutomatedProperties):
:param yes_no: :param yes_no:
:param cb: dbus python call back parameter, not client visible :param cb: dbus python call back parameter, not client visible
:param cbe: dbus python error call back parameter, not client visible :param cbe: dbus python error call back parameter, not client visible
:return: Nothing :return: Boolean
""" """
r = RequestEntry(-1, Manager._use_lvm_shell, (yes_no,), cb, cbe, False) r = RequestEntry(-1, Manager._use_lvm_shell, (yes_no,), cb, cbe, False)
cfg.worker_q.put(r) cfg.worker_q.put(r)
@staticmethod
def _external_event(command):
utils.log_debug("Processing _external_event= %s" % command,
'bg_black', 'fg_orange')
cfg.load()
@dbus.service.method( @dbus.service.method(
dbus_interface=MANAGER_INTERFACE, dbus_interface=MANAGER_INTERFACE,
in_signature='s', out_signature='i') in_signature='s', out_signature='i')
def ExternalEvent(self, command): def ExternalEvent(self, command):
utils.log_debug("ExternalEvent %s" % command)
# If a user didn't explicitly specify udev, we will turn it off now. # If a user didn't explicitly specify udev, we will turn it off now.
if not cfg.args.use_udev: if not cfg.args.use_udev:
if udevwatch.remove(): if udevwatch.remove():
utils.log_debug("ExternalEvent received, disabling " utils.log_debug("ExternalEvent received, disabling "
"udev monitoring") "udev monitoring")
# We are dependent on external events now to stay current! # We are dependent on external events now to stay current!
cfg.ee = True cfg.got_external_event = True
utils.log_debug("ExternalEvent %s" % command)
cfg.event() r = RequestEntry(
-1, Manager._external_event, (command,), None, None, False)
cfg.worker_q.put(r)
return dbus.Int32(0) return dbus.Int32(0)
@staticmethod @staticmethod

View File

@ -32,14 +32,12 @@ class ObjectManager(AutomatedProperties):
self._id_to_object_path = {} self._id_to_object_path = {}
self.rlock = threading.RLock() self.rlock = threading.RLock()
@dbus.service.method( @staticmethod
dbus_interface="org.freedesktop.DBus.ObjectManager", def _get_managed_objects(obj):
out_signature='a{oa{sa{sv}}}') with obj.rlock:
def GetManagedObjects(self):
with self.rlock:
rc = {} rc = {}
try: try:
for k, v in list(self._objects.items()): for k, v in list(obj._objects.items()):
path, props = v[0].emit_data() path, props = v[0].emit_data()
rc[path] = props rc[path] = props
except Exception: except Exception:
@ -47,6 +45,14 @@ class ObjectManager(AutomatedProperties):
sys.exit(1) sys.exit(1)
return rc return rc
@dbus.service.method(
dbus_interface="org.freedesktop.DBus.ObjectManager",
out_signature='a{oa{sa{sv}}}', async_callbacks=('cb', 'cbe'))
def GetManagedObjects(self, cb, cbe):
r = cfg.create_request_entry(-1, ObjectManager._get_managed_objects,
(self, ), cb, cbe, False)
cfg.worker_q.put(r)
def locked(self): def locked(self):
""" """
If some external code need to run across a number of different If some external code need to run across a number of different

View File

@ -10,10 +10,41 @@
import pyudev import pyudev
import threading import threading
from . import cfg from . import cfg
from .request import RequestEntry
from . import utils
observer = None observer = None
observer_lock = threading.RLock() observer_lock = threading.RLock()
_udev_lock = threading.RLock()
_udev_count = 0
def udev_add():
global _udev_count
with _udev_lock:
if _udev_count == 0:
_udev_count += 1
# Place this on the queue so any other operations will sequence
# behind it
r = RequestEntry(
-1, _udev_event, (), None, None, False)
cfg.worker_q.put(r)
def udev_complete():
global _udev_count
with _udev_lock:
if _udev_count > 0:
_udev_count -= 1
def _udev_event():
utils.log_debug("Processing udev event")
udev_complete()
cfg.load()
# noinspection PyUnusedLocal # noinspection PyUnusedLocal
def filter_event(action, device): def filter_event(action, device):
@ -37,7 +68,7 @@ def filter_event(action, device):
refresh = True refresh = True
if refresh: if refresh:
cfg.event() udev_add()
def add(): def add():

View File

@ -499,6 +499,33 @@ def validate_tag(interface, tag):
% (tag, _ALLOWABLE_TAG_CH)) % (tag, _ALLOWABLE_TAG_CH))
def add_no_notify(cmdline):
"""
Given a command line to execute we will see if `--config` is present, if it
is we will add the global/notify_dbus=0 to it, otherwise we will append it
to the end of the list.
:param: cmdline: The command line to inspect
:type: cmdline: list
:return: cmdline with notify_dbus config option present
:rtype: list
"""
# Only after we have seen an external event will be disable lvm from sending
# us one when we call lvm
if cfg.got_external_event:
if 'help' in cmdline:
return cmdline
if '--config' in cmdline:
for i, arg in enumerate(cmdline):
if arg == '--config':
cmdline[i] += "global/notify_dbus=0"
break
else:
cmdline.extend(['--config', 'global/notify_dbus=0'])
return cmdline
# The methods below which start with mt_* are used to execute the desired code # The methods below which start with mt_* are used to execute the desired code
# on the the main thread of execution to alleviate any issues the dbus-python # on the the main thread of execution to alleviate any issues the dbus-python
# library with regards to multi-threaded access. Essentially, we are trying to # library with regards to multi-threaded access. Essentially, we are trying to

View File

@ -25,6 +25,7 @@
#define LVMETAD_DISABLE_REASON_LVM1 "LVM1" #define LVMETAD_DISABLE_REASON_LVM1 "LVM1"
#define LVMETAD_DISABLE_REASON_DUPLICATES "DUPLICATES" #define LVMETAD_DISABLE_REASON_DUPLICATES "DUPLICATES"
#define LVMETAD_DISABLE_REASON_VGRESTORE "VGRESTORE" #define LVMETAD_DISABLE_REASON_VGRESTORE "VGRESTORE"
#define LVMETAD_DISABLE_REASON_REPAIR "REPAIR"
struct volume_group; struct volume_group;

View File

@ -203,8 +203,9 @@ struct vg_info {
#define GLFL_DISABLE_REASON_LVM1 0x00000008 #define GLFL_DISABLE_REASON_LVM1 0x00000008
#define GLFL_DISABLE_REASON_DUPLICATES 0x00000010 #define GLFL_DISABLE_REASON_DUPLICATES 0x00000010
#define GLFL_DISABLE_REASON_VGRESTORE 0x00000020 #define GLFL_DISABLE_REASON_VGRESTORE 0x00000020
#define GLFL_DISABLE_REASON_REPAIR 0x00000040
#define GLFL_DISABLE_REASON_ALL (GLFL_DISABLE_REASON_DIRECT | GLFL_DISABLE_REASON_LVM1 | GLFL_DISABLE_REASON_DUPLICATES | GLFL_DISABLE_REASON_VGRESTORE) #define GLFL_DISABLE_REASON_ALL (GLFL_DISABLE_REASON_DIRECT | GLFL_DISABLE_REASON_REPAIR | GLFL_DISABLE_REASON_LVM1 | GLFL_DISABLE_REASON_DUPLICATES | GLFL_DISABLE_REASON_VGRESTORE)
#define VGFL_INVALID 0x00000001 #define VGFL_INVALID 0x00000001
@ -2355,6 +2356,8 @@ static response set_global_info(lvmetad_state *s, request r)
if ((reason = daemon_request_str(r, "disable_reason", NULL))) { if ((reason = daemon_request_str(r, "disable_reason", NULL))) {
if (strstr(reason, LVMETAD_DISABLE_REASON_DIRECT)) if (strstr(reason, LVMETAD_DISABLE_REASON_DIRECT))
reason_flags |= GLFL_DISABLE_REASON_DIRECT; reason_flags |= GLFL_DISABLE_REASON_DIRECT;
if (strstr(reason, LVMETAD_DISABLE_REASON_REPAIR))
reason_flags |= GLFL_DISABLE_REASON_REPAIR;
if (strstr(reason, LVMETAD_DISABLE_REASON_LVM1)) if (strstr(reason, LVMETAD_DISABLE_REASON_LVM1))
reason_flags |= GLFL_DISABLE_REASON_LVM1; reason_flags |= GLFL_DISABLE_REASON_LVM1;
if (strstr(reason, LVMETAD_DISABLE_REASON_DUPLICATES)) if (strstr(reason, LVMETAD_DISABLE_REASON_DUPLICATES))
@ -2418,8 +2421,9 @@ static response get_global_info(lvmetad_state *s, request r)
pid = (int)daemon_request_int(r, "pid", 0); pid = (int)daemon_request_int(r, "pid", 0);
if (s->flags & GLFL_DISABLE) { if (s->flags & GLFL_DISABLE) {
snprintf(reason, REASON_BUF_SIZE - 1, "%s%s%s%s", snprintf(reason, REASON_BUF_SIZE - 1, "%s%s%s%s%s",
(s->flags & GLFL_DISABLE_REASON_DIRECT) ? LVMETAD_DISABLE_REASON_DIRECT "," : "", (s->flags & GLFL_DISABLE_REASON_DIRECT) ? LVMETAD_DISABLE_REASON_DIRECT "," : "",
(s->flags & GLFL_DISABLE_REASON_REPAIR) ? LVMETAD_DISABLE_REASON_REPAIR "," : "",
(s->flags & GLFL_DISABLE_REASON_LVM1) ? LVMETAD_DISABLE_REASON_LVM1 "," : "", (s->flags & GLFL_DISABLE_REASON_LVM1) ? LVMETAD_DISABLE_REASON_LVM1 "," : "",
(s->flags & GLFL_DISABLE_REASON_DUPLICATES) ? LVMETAD_DISABLE_REASON_DUPLICATES "," : "", (s->flags & GLFL_DISABLE_REASON_DUPLICATES) ? LVMETAD_DISABLE_REASON_DUPLICATES "," : "",
(s->flags & GLFL_DISABLE_REASON_VGRESTORE) ? LVMETAD_DISABLE_REASON_VGRESTORE "," : ""); (s->flags & GLFL_DISABLE_REASON_VGRESTORE) ? LVMETAD_DISABLE_REASON_VGRESTORE "," : "");

View File

@ -127,6 +127,9 @@
/* Path to dmeventd pidfile. */ /* Path to dmeventd pidfile. */
#undef DMEVENTD_PIDFILE #undef DMEVENTD_PIDFILE
/* Define to 1 to enable the device-mapper filemap daemon. */
#undef DMFILEMAPD
/* Define to enable compat protocol */ /* Define to enable compat protocol */
#undef DM_COMPAT #undef DM_COMPAT
@ -488,6 +491,9 @@
/* Define to 1 if you have the <sys/file.h> header file. */ /* Define to 1 if you have the <sys/file.h> header file. */
#undef HAVE_SYS_FILE_H #undef HAVE_SYS_FILE_H
/* Define to 1 if you have the <sys/inotify.h> header file. */
#undef HAVE_SYS_INOTIFY_H
/* Define to 1 if you have the <sys/ioctl.h> header file. */ /* Define to 1 if you have the <sys/ioctl.h> header file. */
#undef HAVE_SYS_IOCTL_H #undef HAVE_SYS_IOCTL_H
@ -623,6 +629,9 @@
/* Define to 1 to include code that uses lvmpolld. */ /* Define to 1 to include code that uses lvmpolld. */
#undef LVMPOLLD_SUPPORT #undef LVMPOLLD_SUPPORT
/* configure command line used */
#undef LVM_CONFIGURE_LINE
/* Path to lvm binary. */ /* Path to lvm binary. */
#undef LVM_PATH #undef LVM_PATH

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004-2016 Red Hat, Inc. All rights reserved. * Copyright (C) 2004-2017 Red Hat, Inc. All rights reserved.
* *
* This file is part of LVM2. * This file is part of LVM2.
* *
@ -272,10 +272,18 @@ int lv_raid_percent(const struct logical_volume *lv, dm_percent_t *percent)
{ {
return 0; return 0;
} }
int lv_raid_data_offset(const struct logical_volume *lv, uint64_t *data_offset)
{
return 0;
}
int lv_raid_dev_health(const struct logical_volume *lv, char **dev_health) int lv_raid_dev_health(const struct logical_volume *lv, char **dev_health)
{ {
return 0; return 0;
} }
int lv_raid_dev_count(const struct logical_volume *lv, uint32_t *dev_cnt)
{
return 0;
}
int lv_raid_mismatch_count(const struct logical_volume *lv, uint64_t *cnt) int lv_raid_mismatch_count(const struct logical_volume *lv, uint64_t *cnt)
{ {
return 0; return 0;
@ -984,6 +992,30 @@ int lv_raid_percent(const struct logical_volume *lv, dm_percent_t *percent)
return lv_mirror_percent(lv->vg->cmd, lv, 0, percent, NULL); return lv_mirror_percent(lv->vg->cmd, lv, 0, percent, NULL);
} }
int lv_raid_data_offset(const struct logical_volume *lv, uint64_t *data_offset)
{
int r;
struct dev_manager *dm;
struct dm_status_raid *status;
if (!lv_info(lv->vg->cmd, lv, 0, NULL, 0, 0))
return 0;
log_debug_activation("Checking raid data offset and dev sectors for LV %s/%s",
lv->vg->name, lv->name);
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1)))
return_0;
if (!(r = dev_manager_raid_status(dm, lv, &status)))
stack;
*data_offset = status->data_offset;
dev_manager_destroy(dm);
return r;
}
int lv_raid_dev_health(const struct logical_volume *lv, char **dev_health) int lv_raid_dev_health(const struct logical_volume *lv, char **dev_health)
{ {
int r; int r;
@ -1013,6 +1045,32 @@ int lv_raid_dev_health(const struct logical_volume *lv, char **dev_health)
return r; return r;
} }
int lv_raid_dev_count(const struct logical_volume *lv, uint32_t *dev_cnt)
{
struct dev_manager *dm;
struct dm_status_raid *status;
*dev_cnt = 0;
if (!lv_info(lv->vg->cmd, lv, 0, NULL, 0, 0))
return 0;
log_debug_activation("Checking raid device count for LV %s/%s",
lv->vg->name, lv->name);
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1)))
return_0;
if (!dev_manager_raid_status(dm, lv, &status)) {
dev_manager_destroy(dm);
return_0;
}
*dev_cnt = status->dev_count;
dev_manager_destroy(dm);
return 1;
}
int lv_raid_mismatch_count(const struct logical_volume *lv, uint64_t *cnt) int lv_raid_mismatch_count(const struct logical_volume *lv, uint64_t *cnt)
{ {
struct dev_manager *dm; struct dev_manager *dm;

View File

@ -168,6 +168,8 @@ int lv_snapshot_percent(const struct logical_volume *lv, dm_percent_t *percent);
int lv_mirror_percent(struct cmd_context *cmd, const struct logical_volume *lv, int lv_mirror_percent(struct cmd_context *cmd, const struct logical_volume *lv,
int wait, dm_percent_t *percent, uint32_t *event_nr); int wait, dm_percent_t *percent, uint32_t *event_nr);
int lv_raid_percent(const struct logical_volume *lv, dm_percent_t *percent); int lv_raid_percent(const struct logical_volume *lv, dm_percent_t *percent);
int lv_raid_dev_count(const struct logical_volume *lv, uint32_t *dev_cnt);
int lv_raid_data_offset(const struct logical_volume *lv, uint64_t *data_offset);
int lv_raid_dev_health(const struct logical_volume *lv, char **dev_health); int lv_raid_dev_health(const struct logical_volume *lv, char **dev_health);
int lv_raid_mismatch_count(const struct logical_volume *lv, uint64_t *cnt); int lv_raid_mismatch_count(const struct logical_volume *lv, uint64_t *cnt);
int lv_raid_sync_action(const struct logical_volume *lv, char **sync_action); int lv_raid_sync_action(const struct logical_volume *lv, char **sync_action);

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved. * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004-2016 Red Hat, Inc. All rights reserved. * Copyright (C) 2004-2017 Red Hat, Inc. All rights reserved.
* *
* This file is part of LVM2. * This file is part of LVM2.
* *
@ -214,6 +214,14 @@ typedef enum {
STATUS, /* DM_DEVICE_STATUS ioctl */ STATUS, /* DM_DEVICE_STATUS ioctl */
} info_type_t; } info_type_t;
/* Return length of segment depending on type and reshape_len */
static uint32_t _seg_len(const struct lv_segment *seg)
{
uint32_t reshape_len = seg_is_raid(seg) ? ((seg->area_count - seg->segtype->parity_devs) * seg->reshape_len) : 0;
return seg->len - reshape_len;
}
static int _info_run(const char *dlid, struct dm_info *dminfo, static int _info_run(const char *dlid, struct dm_info *dminfo,
uint32_t *read_ahead, uint32_t *read_ahead,
struct lv_seg_status *seg_status, struct lv_seg_status *seg_status,
@ -250,7 +258,7 @@ static int _info_run(const char *dlid, struct dm_info *dminfo,
if (seg_status && dminfo->exists) { if (seg_status && dminfo->exists) {
start = length = seg_status->seg->lv->vg->extent_size; start = length = seg_status->seg->lv->vg->extent_size;
start *= seg_status->seg->le; start *= seg_status->seg->le;
length *= seg_status->seg->len; length *= _seg_len(seg_status->seg);
do { do {
target = dm_get_next_target(dmt, target, &target_start, target = dm_get_next_target(dmt, target, &target_start,
@ -1308,14 +1316,13 @@ int dev_manager_raid_message(struct dev_manager *dm,
return 0; return 0;
} }
/* These are the supported RAID messages for dm-raid v1.5.0 */ /* These are the supported RAID messages for dm-raid v1.9.0 */
if (strcmp(msg, "idle") && if (strcmp(msg, "idle") &&
strcmp(msg, "frozen") && strcmp(msg, "frozen") &&
strcmp(msg, "resync") && strcmp(msg, "resync") &&
strcmp(msg, "recover") && strcmp(msg, "recover") &&
strcmp(msg, "check") && strcmp(msg, "check") &&
strcmp(msg, "repair") && strcmp(msg, "repair")) {
strcmp(msg, "reshape")) {
log_error(INTERNAL_ERROR "Unknown RAID message: %s.", msg); log_error(INTERNAL_ERROR "Unknown RAID message: %s.", msg);
return 0; return 0;
} }
@ -2214,7 +2221,7 @@ static char *_add_error_or_zero_device(struct dev_manager *dm, struct dm_tree *d
struct lv_segment *seg_i; struct lv_segment *seg_i;
struct dm_info info; struct dm_info info;
int segno = -1, i = 0; int segno = -1, i = 0;
uint64_t size = (uint64_t) seg->len * seg->lv->vg->extent_size; uint64_t size = (uint64_t) _seg_len(seg) * seg->lv->vg->extent_size;
dm_list_iterate_items(seg_i, &seg->lv->segments) { dm_list_iterate_items(seg_i, &seg->lv->segments) {
if (seg == seg_i) { if (seg == seg_i) {
@ -2500,7 +2507,7 @@ static int _add_target_to_dtree(struct dev_manager *dm,
return seg->segtype->ops->add_target_line(dm, dm->mem, dm->cmd, return seg->segtype->ops->add_target_line(dm, dm->mem, dm->cmd,
&dm->target_state, seg, &dm->target_state, seg,
laopts, dnode, laopts, dnode,
extent_size * seg->len, extent_size * _seg_len(seg),
&dm->pvmove_mirror_count); &dm->pvmove_mirror_count);
} }
@ -2693,7 +2700,7 @@ static int _add_segment_to_dtree(struct dev_manager *dm,
/* Replace target and all its used devs with error mapping */ /* Replace target and all its used devs with error mapping */
log_debug_activation("Using error for pending delete %s.", log_debug_activation("Using error for pending delete %s.",
display_lvname(seg->lv)); display_lvname(seg->lv));
if (!dm_tree_node_add_error_target(dnode, (uint64_t)seg->lv->vg->extent_size * seg->len)) if (!dm_tree_node_add_error_target(dnode, (uint64_t)seg->lv->vg->extent_size * _seg_len(seg)))
return_0; return_0;
} else if (!_add_target_to_dtree(dm, dnode, seg, laopts)) } else if (!_add_target_to_dtree(dm, dnode, seg, laopts))
return_0; return_0;
@ -3165,7 +3172,6 @@ static int _tree_action(struct dev_manager *dm, const struct logical_volume *lv,
log_error(INTERNAL_ERROR "_tree_action: Action %u not supported.", action); log_error(INTERNAL_ERROR "_tree_action: Action %u not supported.", action);
goto out; goto out;
} }
r = 1; r = 1;
out: out:

7
lib/cache/lvmetad.c vendored
View File

@ -66,7 +66,7 @@ static int _log_debug_inequality(const char *name, struct dm_config_node *a, str
log_debug_lvmetad("VG %s metadata inequality at %s / %s: %s / %s", log_debug_lvmetad("VG %s metadata inequality at %s / %s: %s / %s",
name, a->key, b->key, av->v.str, bv->v.str); name, a->key, b->key, av->v.str, bv->v.str);
else if (a->v->type == DM_CFG_INT && b->v->type == DM_CFG_INT) else if (a->v->type == DM_CFG_INT && b->v->type == DM_CFG_INT)
log_debug_lvmetad("VG %s metadata inequality at %s / %s: " FMTi64 " / " FMTi64, log_debug_lvmetad("VG %s metadata inequality at %s / %s: " FMTd64 " / " FMTd64,
name, a->key, b->key, av->v.i, bv->v.i); name, a->key, b->key, av->v.i, bv->v.i);
else else
log_debug_lvmetad("VG %s metadata inequality at %s / %s: type %d / type %d", log_debug_lvmetad("VG %s metadata inequality at %s / %s: type %d / type %d",
@ -1304,7 +1304,7 @@ int lvmetad_vg_remove_pending(struct volume_group *vg)
reply = _lvmetad_send(vg->cmd, "set_vg_info", reply = _lvmetad_send(vg->cmd, "set_vg_info",
"name = %s", vg->name, "name = %s", vg->name,
"uuid = %s", uuid, "uuid = %s", uuid,
"version = %d", 0, "version = %"PRId64, (int64_t)0,
NULL); NULL);
if (!_lvmetad_handle_reply(reply, "set_vg_info", vg->name, NULL)) { if (!_lvmetad_handle_reply(reply, "set_vg_info", vg->name, NULL)) {
@ -2874,6 +2874,9 @@ int lvmetad_is_disabled(struct cmd_context *cmd, const char **reason)
} else if (strstr(reply_reason, LVMETAD_DISABLE_REASON_DIRECT)) { } else if (strstr(reply_reason, LVMETAD_DISABLE_REASON_DIRECT)) {
*reason = "the disable flag was set directly"; *reason = "the disable flag was set directly";
} else if (strstr(reply_reason, LVMETAD_DISABLE_REASON_REPAIR)) {
*reason = "a repair command was run";
} else if (strstr(reply_reason, LVMETAD_DISABLE_REASON_LVM1)) { } else if (strstr(reply_reason, LVMETAD_DISABLE_REASON_LVM1)) {
*reason = "LVM1 metadata was found"; *reason = "LVM1 metadata was found";

View File

@ -36,6 +36,31 @@ static unsigned _feature_mask;
log_error(t " segment %s of logical volume %s.", ## p, \ log_error(t " segment %s of logical volume %s.", ## p, \
dm_config_parent_name(sn), seg->lv->name), 0; dm_config_parent_name(sn), seg->lv->name), 0;
static int _cache_out_line(const char *line, void *_f)
{
log_print(" Setting\t\t%s", line);
return 1;
}
static void _cache_display(const struct lv_segment *seg)
{
const struct dm_config_node *n;
const struct lv_segment *pool_seg =
seg_is_cache_pool(seg) ? seg : first_seg(seg->pool_lv);
log_print(" Chunk size\t\t%s",
display_size(seg->lv->vg->cmd, pool_seg->chunk_size));
log_print(" Metadata format\t%u", pool_seg->cache_metadata_format);
log_print(" Mode\t\t%s", get_cache_mode_name(pool_seg));
log_print(" Policy\t\t%s", pool_seg->policy_name);
if ((n = pool_seg->policy_settings->child))
dm_config_write_node(n, _cache_out_line, NULL);
log_print(" ");
}
/* /*
* When older metadata are loaded without newer settings, * When older metadata are loaded without newer settings,
* set then to default settings (the one that could have been * set then to default settings (the one that could have been
@ -52,7 +77,13 @@ static void _fix_missing_defaults(struct lv_segment *cpool_seg)
cpool_seg->policy_name); cpool_seg->policy_name);
} }
if (cpool_seg->cache_mode == CACHE_MODE_UNDEFINED) { if (cpool_seg->cache_metadata_format == CACHE_METADATA_FORMAT_UNSELECTED) {
cpool_seg->cache_metadata_format = CACHE_METADATA_FORMAT_1;
log_verbose("Cache pool %s uses implicit metadata format %u.",
display_lvname(cpool_seg->lv), cpool_seg->cache_metadata_format);
}
if (cpool_seg->cache_mode == CACHE_MODE_UNSELECTED) {
cpool_seg->cache_mode = CACHE_MODE_WHEN_MISSING; cpool_seg->cache_mode = CACHE_MODE_WHEN_MISSING;
log_verbose("Cache pool %s is missing cache mode, using %s.", log_verbose("Cache pool %s is missing cache mode, using %s.",
display_lvname(cpool_seg->lv), display_lvname(cpool_seg->lv),
@ -107,6 +138,16 @@ static int _cache_pool_text_import(struct lv_segment *seg,
return SEG_LOG_ERROR("Failed to duplicate policy in"); return SEG_LOG_ERROR("Failed to duplicate policy in");
} }
if (dm_config_has_node(sn, "metadata_format")) {
if (!dm_config_get_uint32(sn, "metadata_format", &seg->cache_metadata_format) ||
((seg->cache_metadata_format != CACHE_METADATA_FORMAT_1) &&
(seg->cache_metadata_format != CACHE_METADATA_FORMAT_2)))
return SEG_LOG_ERROR("Unknown cache metadata format %u number in",
seg->cache_metadata_format);
if (seg->cache_metadata_format == CACHE_METADATA_FORMAT_2)
seg->lv->status |= LV_METADATA_FORMAT;
}
/* /*
* Read in policy args: * Read in policy args:
* policy_settings { * policy_settings {
@ -164,12 +205,31 @@ static int _cache_pool_text_export(const struct lv_segment *seg,
outf(f, "metadata = \"%s\"", seg->metadata_lv->name); outf(f, "metadata = \"%s\"", seg->metadata_lv->name);
outf(f, "chunk_size = %" PRIu32, seg->chunk_size); outf(f, "chunk_size = %" PRIu32, seg->chunk_size);
switch (seg->cache_metadata_format) {
case CACHE_METADATA_FORMAT_UNSELECTED:
/* Unselected format is not printed */
break;
case CACHE_METADATA_FORMAT_1:
/* If format 1 was already specified with cache pool, store it,
* otherwise format gets stored when LV is cached.
* NB: format 1 could be lost anytime, it's a default format.
* Older lvm2 tool can easily drop it.
*/
case CACHE_METADATA_FORMAT_2: /* more in future ? */
outf(f, "metadata_format = " FMTu32, seg->cache_metadata_format);
break;
default:
log_error(INTERNAL_ERROR "LV %s is using unknown cache metadada format %u.",
display_lvname(seg->lv), seg->cache_metadata_format);
return 0;
}
/* /*
* Cache pool used by a cache LV holds data. Not ideal, * Cache pool used by a cache LV holds data. Not ideal,
* but not worth to break backward compatibility, by shifting * but not worth to break backward compatibility, by shifting
* content to cache segment * content to cache segment
*/ */
if (seg->cache_mode != CACHE_MODE_UNDEFINED) { if (seg->cache_mode != CACHE_MODE_UNSELECTED) {
if (!(cache_mode = get_cache_mode_name(seg))) if (!(cache_mode = get_cache_mode_name(seg)))
return_0; return_0;
outf(f, "cache_mode = \"%s\"", cache_mode); outf(f, "cache_mode = \"%s\"", cache_mode);
@ -213,6 +273,7 @@ static int _target_present(struct cmd_context *cmd,
const char *aliasing; const char *aliasing;
} _features[] = { } _features[] = {
/* Assumption: cache >=1.9 always aliases MQ policy */ /* Assumption: cache >=1.9 always aliases MQ policy */
{ 1, 10, CACHE_FEATURE_METADATA2, 0, "metadata2" },
{ 1, 9, CACHE_FEATURE_POLICY_SMQ, CACHE_FEATURE_POLICY_MQ, "policy_smq", "cache-smq", { 1, 9, CACHE_FEATURE_POLICY_SMQ, CACHE_FEATURE_POLICY_MQ, "policy_smq", "cache-smq",
" and aliases cache-mq" }, " and aliases cache-mq" },
{ 1, 8, CACHE_FEATURE_POLICY_SMQ, 0, "policy_smq", "cache-smq" }, { 1, 8, CACHE_FEATURE_POLICY_SMQ, 0, "policy_smq", "cache-smq" },
@ -250,6 +311,16 @@ static int _target_present(struct cmd_context *cmd,
for (i = 0; i < DM_ARRAY_SIZE(_features); ++i) { for (i = 0; i < DM_ARRAY_SIZE(_features); ++i) {
if (_attrs & _features[i].cache_feature) if (_attrs & _features[i].cache_feature)
continue; /* already present */ continue; /* already present */
if (!_features[i].module[0]) {
if ((maj > _features[i].maj) ||
(maj == _features[i].maj && min >= _features[i].min)) {
log_debug_activation("Cache supports %s.",
_features[i].feature);
_attrs |= _features[i].cache_feature;
}
continue;
}
if (((maj > _features[i].maj) || if (((maj > _features[i].maj) ||
(maj == _features[i].maj && min >= _features[i].min)) && (maj == _features[i].maj && min >= _features[i].min)) &&
module_present(cmd, _features[i].module)) { module_present(cmd, _features[i].module)) {
@ -310,6 +381,7 @@ static int _modules_needed(struct dm_pool *mem,
#endif /* DEVMAPPER_SUPPORT */ #endif /* DEVMAPPER_SUPPORT */
static struct segtype_handler _cache_pool_ops = { static struct segtype_handler _cache_pool_ops = {
.display = _cache_display,
.text_import = _cache_pool_text_import, .text_import = _cache_pool_text_import,
.text_import_area_count = _cache_pool_text_import_area_count, .text_import_area_count = _cache_pool_text_import_area_count,
.text_export = _cache_pool_text_export, .text_export = _cache_pool_text_export,
@ -399,6 +471,7 @@ static int _cache_add_target_line(struct dev_manager *dm,
struct lv_segment *cache_pool_seg; struct lv_segment *cache_pool_seg;
char *metadata_uuid, *data_uuid, *origin_uuid; char *metadata_uuid, *data_uuid, *origin_uuid;
uint64_t feature_flags = 0; uint64_t feature_flags = 0;
unsigned attr;
if (!seg->pool_lv || !seg_is_cache(seg)) { if (!seg->pool_lv || !seg_is_cache(seg)) {
log_error(INTERNAL_ERROR "Passed segment is not cache."); log_error(INTERNAL_ERROR "Passed segment is not cache.");
@ -426,6 +499,26 @@ static int _cache_add_target_line(struct dev_manager *dm,
break; break;
} }
switch (cache_pool_seg->cache_metadata_format) {
case CACHE_METADATA_FORMAT_1: break;
case CACHE_METADATA_FORMAT_2:
if (!_target_present(cmd, NULL, &attr))
return_0;
if (!(attr & CACHE_FEATURE_METADATA2)) {
log_error("LV %s has metadata format %u unsuported by kernel.",
display_lvname(seg->lv), cache_pool_seg->cache_metadata_format);
return 0;
}
feature_flags |= DM_CACHE_FEATURE_METADATA2;
log_debug_activation("Using metadata2 format for %s.", display_lvname(seg->lv));
break;
default:
log_error(INTERNAL_ERROR "LV %s has unknown metadata format %u.",
display_lvname(seg->lv), cache_pool_seg->cache_metadata_format);
return 0;
}
if (!(metadata_uuid = build_dm_uuid(mem, cache_pool_seg->metadata_lv, NULL))) if (!(metadata_uuid = build_dm_uuid(mem, cache_pool_seg->metadata_lv, NULL)))
return_0; return_0;
@ -452,6 +545,7 @@ static int _cache_add_target_line(struct dev_manager *dm,
#endif /* DEVMAPPER_SUPPORT */ #endif /* DEVMAPPER_SUPPORT */
static struct segtype_handler _cache_ops = { static struct segtype_handler _cache_ops = {
.display = _cache_display,
.text_import = _cache_text_import, .text_import = _cache_text_import,
.text_import_area_count = _cache_text_import_area_count, .text_import_area_count = _cache_text_import_area_count,
.text_export = _cache_text_export, .text_export = _cache_text_export,

View File

@ -2442,21 +2442,13 @@ const char *get_default_activation_mirror_image_fault_policy_CFG(struct cmd_cont
int get_default_allocation_thin_pool_chunk_size_CFG(struct cmd_context *cmd, struct profile *profile) int get_default_allocation_thin_pool_chunk_size_CFG(struct cmd_context *cmd, struct profile *profile)
{ {
const char *str;
uint32_t chunk_size; uint32_t chunk_size;
int chunk_size_calc_method;
if (!(str = find_config_tree_str(cmd, allocation_thin_pool_chunk_size_policy_CFG, profile))) { if (!get_default_allocation_thin_pool_chunk_size(cmd, profile, &chunk_size,
log_error(INTERNAL_ERROR "Cannot find configuration."); &chunk_size_calc_method)) {
return 0; stack; /* Ignore this error, never happens... */
}
if (!strcasecmp(str, "generic"))
chunk_size = DEFAULT_THIN_POOL_CHUNK_SIZE * 2; chunk_size = DEFAULT_THIN_POOL_CHUNK_SIZE * 2;
else if (!strcasecmp(str, "performance"))
chunk_size = DEFAULT_THIN_POOL_CHUNK_SIZE_PERFORMANCE * 2;
else {
log_error("Thin pool chunk size calculation policy \"%s\" is unrecognised.", str);
return 0;
} }
return (int) chunk_size; return (int) chunk_size;

View File

@ -473,14 +473,23 @@ cfg(allocation_raid_stripe_all_devices_CFG, "raid_stripe_all_devices", allocatio
"when the command does not specify the number of stripes to use.\n" "when the command does not specify the number of stripes to use.\n"
"This was the default behaviour until release 2.02.162.\n") "This was the default behaviour until release 2.02.162.\n")
cfg(allocation_cache_pool_metadata_require_separate_pvs_CFG, "cache_pool_metadata_require_separate_pvs", allocation_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_CACHE_POOL_METADATA_REQUIRE_SEPARATE_PVS, vsn(2, 2, 106), NULL, 0, NULL, cfg(allocation_cache_pool_metadata_require_separate_pvs_CFG, "cache_pool_metadata_require_separate_pvs", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA, CFG_TYPE_BOOL, DEFAULT_CACHE_POOL_METADATA_REQUIRE_SEPARATE_PVS, vsn(2, 2, 106), NULL, 0, NULL,
"Cache pool metadata and data will always use different PVs.\n") "Cache pool metadata and data will always use different PVs.\n")
cfg(allocation_cache_pool_cachemode_CFG, "cache_pool_cachemode", allocation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_CACHE_MODE, vsn(2, 2, 113), NULL, vsn(2, 2, 128), cfg(allocation_cache_pool_cachemode_CFG, "cache_pool_cachemode", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_CACHE_MODE, vsn(2, 2, 113), NULL, vsn(2, 2, 128),
"This has been replaced by the allocation/cache_mode setting.\n", "This has been replaced by the allocation/cache_mode setting.\n",
"Cache mode.\n") "Cache mode.\n")
cfg(allocation_cache_mode_CFG, "cache_mode", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_CACHE_MODE, vsn(2, 2, 128), NULL, 0, NULL, cfg(allocation_cache_metadata_format_CFG, "cache_metadata_format", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_CACHE_METADATA_FORMAT, vsn(2, 2, 169), NULL, 0, NULL,
"Sets default metadata format for new cache.\n"
"#\n"
"Accepted values:\n"
" 0 Automatically detected best available format\n"
" 1 Original format\n"
" 2 Improved 2nd. generation format\n"
"#\n")
cfg(allocation_cache_mode_CFG, "cache_mode", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_CACHE_MODE, vsn(2, 2, 128), NULL, 0, NULL,
"The default cache mode used for new cache.\n" "The default cache mode used for new cache.\n"
"#\n" "#\n"
"Accepted values:\n" "Accepted values:\n"
@ -492,20 +501,20 @@ cfg(allocation_cache_mode_CFG, "cache_mode", allocation_CFG_SECTION, CFG_PROFILA
"#\n" "#\n"
"This setting replaces allocation/cache_pool_cachemode.\n") "This setting replaces allocation/cache_pool_cachemode.\n")
cfg(allocation_cache_policy_CFG, "cache_policy", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, 0, vsn(2, 2, 128), NULL, 0, NULL, cfg(allocation_cache_policy_CFG, "cache_policy", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, 0, vsn(2, 2, 128), NULL, 0, NULL,
"The default cache policy used for new cache volume.\n" "The default cache policy used for new cache volume.\n"
"Since kernel 4.2 the default policy is smq (Stochastic multique),\n" "Since kernel 4.2 the default policy is smq (Stochastic multiqueue),\n"
"otherwise the older mq (Multiqueue) policy is selected.\n") "otherwise the older mq (Multiqueue) policy is selected.\n")
cfg_section(allocation_cache_settings_CFG_SECTION, "cache_settings", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_DEFAULT_COMMENTED, vsn(2, 2, 128), 0, NULL, cfg_section(allocation_cache_settings_CFG_SECTION, "cache_settings", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_COMMENTED, vsn(2, 2, 128), 0, NULL,
"Settings for the cache policy.\n" "Settings for the cache policy.\n"
"See documentation for individual cache policies for more info.\n") "See documentation for individual cache policies for more info.\n")
cfg_section(policy_settings_CFG_SUBSECTION, "policy_settings", allocation_cache_settings_CFG_SECTION, CFG_NAME_VARIABLE | CFG_SECTION_NO_CHECK | CFG_PROFILABLE | CFG_DEFAULT_COMMENTED, vsn(2, 2, 128), 0, NULL, cfg_section(policy_settings_CFG_SUBSECTION, "policy_settings", allocation_cache_settings_CFG_SECTION, CFG_NAME_VARIABLE | CFG_SECTION_NO_CHECK | CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_COMMENTED, vsn(2, 2, 128), 0, NULL,
"Replace this subsection name with a policy name.\n" "Replace this subsection name with a policy name.\n"
"Multiple subsections for different policies can be created.\n") "Multiple subsections for different policies can be created.\n")
cfg_runtime(allocation_cache_pool_chunk_size_CFG, "cache_pool_chunk_size", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_DEFAULT_UNDEFINED, CFG_TYPE_INT, vsn(2, 2, 106), 0, NULL, cfg_runtime(allocation_cache_pool_chunk_size_CFG, "cache_pool_chunk_size", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_UNDEFINED, CFG_TYPE_INT, vsn(2, 2, 106), 0, NULL,
"The minimal chunk size in KiB for cache pool volumes.\n" "The minimal chunk size in KiB for cache pool volumes.\n"
"Using a chunk_size that is too large can result in wasteful use of\n" "Using a chunk_size that is too large can result in wasteful use of\n"
"the cache, where small reads and writes can cause large sections of\n" "the cache, where small reads and writes can cause large sections of\n"
@ -516,7 +525,7 @@ cfg_runtime(allocation_cache_pool_chunk_size_CFG, "cache_pool_chunk_size", alloc
"on the smaller end of the spectrum. Supported values range from\n" "on the smaller end of the spectrum. Supported values range from\n"
"32KiB to 1GiB in multiples of 32.\n") "32KiB to 1GiB in multiples of 32.\n")
cfg(allocation_cache_pool_max_chunks_CFG, "cache_pool_max_chunks", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_DEFAULT_UNDEFINED, CFG_TYPE_INT, 0, vsn(2, 2, 165), NULL, 0, NULL, cfg(allocation_cache_pool_max_chunks_CFG, "cache_pool_max_chunks", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_UNDEFINED, CFG_TYPE_INT, 0, vsn(2, 2, 165), NULL, 0, NULL,
"The maximum number of chunks in a cache pool.\n" "The maximum number of chunks in a cache pool.\n"
"For cache target v1.9 the recommended maximumm is 1000000 chunks.\n" "For cache target v1.9 the recommended maximumm is 1000000 chunks.\n"
"Using cache pool with more chunks may degrade cache performance.\n") "Using cache pool with more chunks may degrade cache performance.\n")
@ -992,7 +1001,7 @@ cfg_array(global_thin_disabled_features_CFG, "thin_disabled_features", global_CF
cfg_array(global_cache_disabled_features_CFG, "cache_disabled_features", global_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(2, 2, 128), NULL, 0, NULL, cfg_array(global_cache_disabled_features_CFG, "cache_disabled_features", global_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(2, 2, 128), NULL, 0, NULL,
"Features to not use in the cache driver.\n" "Features to not use in the cache driver.\n"
"This can be helpful for testing, or to avoid using a feature that is\n" "This can be helpful for testing, or to avoid using a feature that is\n"
"causing problems. Features include: policy_mq, policy_smq.\n" "causing problems. Features include: policy_mq, policy_smq, metadata2.\n"
"#\n" "#\n"
"Example\n" "Example\n"
"cache_disabled_features = [ \"policy_smq\" ]\n" "cache_disabled_features = [ \"policy_smq\" ]\n"

View File

@ -71,7 +71,7 @@
* FIXME: Increase these to 64 and further to the MD maximum * FIXME: Increase these to 64 and further to the MD maximum
* once the SubLVs split and name shift got enhanced * once the SubLVs split and name shift got enhanced
*/ */
#define DEFAULT_RAID1_MAX_IMAGES 10 #define DEFAULT_RAID1_MAX_IMAGES 64
#define DEFAULT_RAID_MAX_IMAGES 64 #define DEFAULT_RAID_MAX_IMAGES 64
#define DEFAULT_ALLOCATION_STRIPE_ALL_DEVICES 0 /* Don't stripe across all devices if not -i/--stripes given */ #define DEFAULT_ALLOCATION_STRIPE_ALL_DEVICES 0 /* Don't stripe across all devices if not -i/--stripes given */
@ -132,6 +132,7 @@
#define DEFAULT_CACHE_POOL_MIN_METADATA_SIZE 2048 /* KB */ #define DEFAULT_CACHE_POOL_MIN_METADATA_SIZE 2048 /* KB */
#define DEFAULT_CACHE_POOL_MAX_METADATA_SIZE (16 * 1024 * 1024) /* KB */ #define DEFAULT_CACHE_POOL_MAX_METADATA_SIZE (16 * 1024 * 1024) /* KB */
#define DEFAULT_CACHE_POLICY "mq" #define DEFAULT_CACHE_POLICY "mq"
#define DEFAULT_CACHE_METADATA_FORMAT CACHE_METADATA_FORMAT_UNSELECTED /* Autodetect */
#define DEFAULT_CACHE_MODE "writethrough" #define DEFAULT_CACHE_MODE "writethrough"
#define DEFAULT_UMASK 0077 #define DEFAULT_UMASK 0077

View File

@ -386,6 +386,7 @@ int lvdisplay_full(struct cmd_context *cmd,
dm_percent_t thin_data_percent, thin_metadata_percent; dm_percent_t thin_data_percent, thin_metadata_percent;
int thin_active = 0; int thin_active = 0;
dm_percent_t thin_percent; dm_percent_t thin_percent;
struct lv_status_cache *cache_status = NULL;
if (lv_is_historical(lv)) if (lv_is_historical(lv))
return _lvdisplay_historical_full(cmd, lv); return _lvdisplay_historical_full(cmd, lv);
@ -491,6 +492,19 @@ int lvdisplay_full(struct cmd_context *cmd,
seg = first_seg(lv); seg = first_seg(lv);
log_print("LV Pool metadata %s", seg->metadata_lv->name); log_print("LV Pool metadata %s", seg->metadata_lv->name);
log_print("LV Pool data %s", seg_lv(seg, 0)->name); log_print("LV Pool data %s", seg_lv(seg, 0)->name);
} else if (lv_is_cache_origin(lv)) {
log_print("LV origin of Cache LV %s",
get_only_segment_using_this_lv(lv)->lv->name);
} else if (lv_is_cache(lv)) {
seg = first_seg(lv);
if (inkernel && !lv_cache_status(lv, &cache_status))
return_0;
log_print("LV Cache pool name %s", seg->pool_lv->name);
log_print("LV Cache origin name %s", seg_lv(seg, 0)->name);
} else if (lv_is_cache_pool(lv)) {
seg = first_seg(lv);
log_print("LV Pool metadata %s", seg->metadata_lv->name);
log_print("LV Pool data %s", seg_lv(seg, 0)->name);
} }
if (inkernel && info.suspended) if (inkernel && info.suspended)
@ -510,6 +524,27 @@ int lvdisplay_full(struct cmd_context *cmd,
display_size(cmd, display_size(cmd,
snap_seg ? snap_seg->origin->size : lv->size)); snap_seg ? snap_seg->origin->size : lv->size));
if (cache_status) {
log_print("Cache used blocks %.2f%%",
dm_percent_to_float(cache_status->data_usage));
log_print("Cache metadata blocks %.2f%%",
dm_percent_to_float(cache_status->metadata_usage));
log_print("Cache dirty blocks %.2f%%",
dm_percent_to_float(cache_status->dirty_usage));
log_print("Cache read hits/misses " FMTu64 " / " FMTu64,
cache_status->cache->read_hits,
cache_status->cache->read_misses);
log_print("Cache wrt hits/misses " FMTu64 " / " FMTu64,
cache_status->cache->write_hits,
cache_status->cache->write_misses);
log_print("Cache demotions " FMTu64,
cache_status->cache->demotions);
log_print("Cache promotions " FMTu64,
cache_status->cache->promotions);
dm_pool_destroy(cache_status->mem);
}
if (thin_data_active) if (thin_data_active)
log_print("Allocated pool data %.2f%%", log_print("Allocated pool data %.2f%%",
dm_percent_to_float(thin_data_percent)); dm_percent_to_float(thin_data_percent));

View File

@ -128,8 +128,8 @@ int import_pv(const struct format_type *fmt, struct dm_pool *mem,
int generate_lvm1_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", if (dm_snprintf(s, NAME_LEN, "%s%s" FMTu64,
prefix, cmd->hostname, time(NULL)) < 0) { prefix, cmd->hostname, (uint64_t)time(NULL)) < 0) {
log_error("Generated LVM1 format system_id too long"); log_error("Generated LVM1 format system_id too long");
return 0; return 0;
} }

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. * Copyright (C) 2004-2017 Red Hat, Inc. All rights reserved.
* *
* This file is part of LVM2. * This file is part of LVM2.
* *
@ -225,8 +225,8 @@ static int _read_linear(struct cmd_context *cmd, struct lv_map *lvm)
while (le < lvm->lv->le_count) { while (le < lvm->lv->le_count) {
len = _area_length(lvm, le); len = _area_length(lvm, le);
if (!(seg = alloc_lv_segment(segtype, lvm->lv, le, len, 0, 0, if (!(seg = alloc_lv_segment(segtype, lvm->lv, le, len, 0, 0, 0,
NULL, 1, len, 0, 0, 0, NULL))) { NULL, 1, len, 0, 0, 0, 0, NULL))) {
log_error("Failed to allocate linear segment."); log_error("Failed to allocate linear segment.");
return 0; return 0;
} }
@ -297,10 +297,10 @@ static int _read_stripes(struct cmd_context *cmd, struct lv_map *lvm)
if (!(seg = alloc_lv_segment(segtype, lvm->lv, if (!(seg = alloc_lv_segment(segtype, lvm->lv,
lvm->stripes * first_area_le, lvm->stripes * first_area_le,
lvm->stripes * area_len, lvm->stripes * area_len, 0,
0, lvm->stripe_size, NULL, 0, lvm->stripe_size, NULL,
lvm->stripes, lvm->stripes,
area_len, 0, 0, 0, NULL))) { area_len, 0, 0, 0, 0, NULL))) {
log_error("Failed to allocate striped segment."); log_error("Failed to allocate striped segment.");
return 0; return 0;
} }

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (C) 1997-2004 Sistina Software, Inc. All rights reserved. * Copyright (C) 1997-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. * Copyright (C) 2004-2017 Red Hat, Inc. All rights reserved.
* *
* This file is part of LVM2. * This file is part of LVM2.
* *
@ -192,9 +192,9 @@ static int _add_stripe_seg(struct dm_pool *mem,
return_0; return_0;
if (!(seg = alloc_lv_segment(segtype, lv, *le_cur, if (!(seg = alloc_lv_segment(segtype, lv, *le_cur,
area_len * usp->num_devs, 0, area_len * usp->num_devs, 0, 0,
usp->striping, NULL, usp->num_devs, usp->striping, NULL, usp->num_devs,
area_len, 0, 0, 0, NULL))) { area_len, 0, 0, 0, 0, NULL))) {
log_error("Unable to allocate striped lv_segment structure"); log_error("Unable to allocate striped lv_segment structure");
return 0; return 0;
} }
@ -232,8 +232,8 @@ static int _add_linear_seg(struct dm_pool *mem,
area_len = (usp->devs[j].blocks) / POOL_PE_SIZE; area_len = (usp->devs[j].blocks) / POOL_PE_SIZE;
if (!(seg = alloc_lv_segment(segtype, lv, *le_cur, if (!(seg = alloc_lv_segment(segtype, lv, *le_cur,
area_len, 0, usp->striping, area_len, 0, 0, usp->striping,
NULL, 1, area_len, NULL, 1, area_len, 0,
POOL_PE_SIZE, 0, 0, NULL))) { POOL_PE_SIZE, 0, 0, NULL))) {
log_error("Unable to allocate linear lv_segment " log_error("Unable to allocate linear lv_segment "
"structure"); "structure");

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved. * Copyright (C) 2004-2017 Red Hat, Inc. All rights reserved.
* *
* This file is part of LVM2. * This file is part of LVM2.
* *
@ -350,7 +350,7 @@ static int _print_header(struct cmd_context *cmd, struct formatter *f,
_utsname.version, _utsname.machine); _utsname.version, _utsname.machine);
if (cmd->system_id && *cmd->system_id) if (cmd->system_id && *cmd->system_id)
outf(f, "creation_host_system_id = \"%s\"", cmd->system_id); outf(f, "creation_host_system_id = \"%s\"", cmd->system_id);
outf(f, "creation_time = %lu\t# %s", t, ctime(&t)); outf(f, "creation_time = " FMTu64 "\t# %s", (uint64_t)t, ctime(&t));
return 1; return 1;
} }
@ -583,8 +583,10 @@ static int _print_segment(struct formatter *f, struct volume_group *vg,
outf(f, "start_extent = %u", seg->le); outf(f, "start_extent = %u", seg->le);
outsize(f, (uint64_t) seg->len * vg->extent_size, outsize(f, (uint64_t) seg->len * vg->extent_size,
"extent_count = %u", seg->len); "extent_count = %u", seg->len);
outnl(f); outnl(f);
if (seg->reshape_len)
outsize(f, (uint64_t) seg->reshape_len * vg->extent_size,
"reshape_count = %u", seg->reshape_len);
outf(f, "type = \"%s\"", seg->segtype->name); outf(f, "type = \"%s\"", seg->segtype->name);
if (!_out_list(f, &seg->tags, "tags")) if (!_out_list(f, &seg->tags, "tags"))

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004-2013 Red Hat, Inc. All rights reserved. * Copyright (C) 2004-2017 Red Hat, Inc. All rights reserved.
* *
* This file is part of LVM2. * This file is part of LVM2.
* *
@ -61,9 +61,13 @@ static const struct flag _lv_flags[] = {
{LOCKED, "LOCKED", STATUS_FLAG}, {LOCKED, "LOCKED", STATUS_FLAG},
{LV_NOTSYNCED, "NOTSYNCED", STATUS_FLAG}, {LV_NOTSYNCED, "NOTSYNCED", STATUS_FLAG},
{LV_REBUILD, "REBUILD", STATUS_FLAG}, {LV_REBUILD, "REBUILD", STATUS_FLAG},
{LV_RESHAPE_DELTA_DISKS_PLUS, "RESHAPE_DELTA_DISKS_PLUS", STATUS_FLAG},
{LV_RESHAPE_DELTA_DISKS_MINUS, "RESHAPE_DELTA_DISKS_MINUS", STATUS_FLAG},
{LV_REMOVE_AFTER_RESHAPE, "REMOVE_AFTER_RESHAPE", STATUS_FLAG},
{LV_WRITEMOSTLY, "WRITEMOSTLY", STATUS_FLAG}, {LV_WRITEMOSTLY, "WRITEMOSTLY", STATUS_FLAG},
{LV_ACTIVATION_SKIP, "ACTIVATION_SKIP", COMPATIBLE_FLAG}, {LV_ACTIVATION_SKIP, "ACTIVATION_SKIP", COMPATIBLE_FLAG},
{LV_ERROR_WHEN_FULL, "ERROR_WHEN_FULL", COMPATIBLE_FLAG}, {LV_ERROR_WHEN_FULL, "ERROR_WHEN_FULL", COMPATIBLE_FLAG},
{LV_METADATA_FORMAT, "METADATA_FORMAT", STATUS_FLAG},
{LV_NOSCAN, NULL, 0}, {LV_NOSCAN, NULL, 0},
{LV_TEMPORARY, NULL, 0}, {LV_TEMPORARY, NULL, 0},
{POOL_METADATA_SPARE, NULL, 0}, {POOL_METADATA_SPARE, NULL, 0},

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004-2011 Red Hat, Inc. All rights reserved. * Copyright (C) 2004-2017 Red Hat, Inc. All rights reserved.
* *
* This file is part of LVM2. * This file is part of LVM2.
* *
@ -354,7 +354,7 @@ static int _read_segment(struct logical_volume *lv, const struct dm_config_node
struct lv_segment *seg; struct lv_segment *seg;
const struct dm_config_node *sn_child = sn->child; const struct dm_config_node *sn_child = sn->child;
const struct dm_config_value *cv; const struct dm_config_value *cv;
uint32_t start_extent, extent_count; uint32_t area_extents, start_extent, extent_count, reshape_count, data_copies;
struct segment_type *segtype; struct segment_type *segtype;
const char *segtype_str; const char *segtype_str;
@ -375,6 +375,12 @@ static int _read_segment(struct logical_volume *lv, const struct dm_config_node
return 0; return 0;
} }
if (!_read_int32(sn_child, "reshape_count", &reshape_count))
reshape_count = 0;
if (!_read_int32(sn_child, "data_copies", &data_copies))
data_copies = 1;
segtype_str = SEG_TYPE_NAME_STRIPED; segtype_str = SEG_TYPE_NAME_STRIPED;
if (!dm_config_get_str(sn_child, "type", &segtype_str)) { if (!dm_config_get_str(sn_child, "type", &segtype_str)) {
@ -389,9 +395,11 @@ static int _read_segment(struct logical_volume *lv, const struct dm_config_node
!segtype->ops->text_import_area_count(sn_child, &area_count)) !segtype->ops->text_import_area_count(sn_child, &area_count))
return_0; return_0;
area_extents = segtype->parity_devs ?
raid_rimage_extents(segtype, extent_count, area_count - segtype->parity_devs, data_copies) : extent_count;
if (!(seg = alloc_lv_segment(segtype, lv, start_extent, if (!(seg = alloc_lv_segment(segtype, lv, start_extent,
extent_count, 0, 0, NULL, area_count, extent_count, reshape_count, 0, 0, NULL, area_count,
extent_count, 0, 0, 0, NULL))) { area_extents, data_copies, 0, 0, 0, NULL))) {
log_error("Segment allocation failed"); log_error("Segment allocation failed");
return 0; return 0;
} }

View File

@ -35,7 +35,7 @@ const char *display_cache_mode(const struct lv_segment *seg)
seg = first_seg(seg->pool_lv); seg = first_seg(seg->pool_lv);
if (!seg_is_cache_pool(seg) || if (!seg_is_cache_pool(seg) ||
(seg->cache_mode == CACHE_MODE_UNDEFINED)) (seg->cache_mode == CACHE_MODE_UNSELECTED))
return ""; return "";
return get_cache_mode_name(seg); return get_cache_mode_name(seg);
@ -77,13 +77,14 @@ int set_cache_mode(cache_mode_t *mode, const char *cache_mode)
int cache_set_cache_mode(struct lv_segment *seg, cache_mode_t mode) int cache_set_cache_mode(struct lv_segment *seg, cache_mode_t mode)
{ {
struct cmd_context *cmd = seg->lv->vg->cmd; struct cmd_context *cmd = seg->lv->vg->cmd;
struct profile *profile = seg->lv->profile;
const char *str; const char *str;
int id; int id;
if (seg_is_cache(seg)) if (seg_is_cache(seg))
seg = first_seg(seg->pool_lv); seg = first_seg(seg->pool_lv);
else if (seg_is_cache_pool(seg)) { else if (seg_is_cache_pool(seg)) {
if (mode == CACHE_MODE_UNDEFINED) if (mode == CACHE_MODE_UNSELECTED)
return 1; /* Defaults only for cache */ return 1; /* Defaults only for cache */
} else { } else {
log_error(INTERNAL_ERROR "Cannot set cache mode for non cache volume %s.", log_error(INTERNAL_ERROR "Cannot set cache mode for non cache volume %s.",
@ -91,12 +92,12 @@ int cache_set_cache_mode(struct lv_segment *seg, cache_mode_t mode)
return 0; return 0;
} }
if (mode != CACHE_MODE_UNDEFINED) { if (mode != CACHE_MODE_UNSELECTED) {
seg->cache_mode = mode; seg->cache_mode = mode;
return 1; return 1;
} }
if (seg->cache_mode != CACHE_MODE_UNDEFINED) if (seg->cache_mode != CACHE_MODE_UNSELECTED)
return 1; /* Default already set in cache pool */ return 1; /* Default already set in cache pool */
/* Figure default settings from config/profiles */ /* Figure default settings from config/profiles */
@ -107,7 +108,7 @@ int cache_set_cache_mode(struct lv_segment *seg, cache_mode_t mode)
find_config_node(cmd, cmd->cft, allocation_cache_pool_cachemode_CFG)) find_config_node(cmd, cmd->cft, allocation_cache_pool_cachemode_CFG))
id = allocation_cache_pool_cachemode_CFG; id = allocation_cache_pool_cachemode_CFG;
if (!(str = find_config_tree_str(cmd, id, NULL))) { if (!(str = find_config_tree_str(cmd, id, profile))) {
log_error(INTERNAL_ERROR "Cache mode is not determined."); log_error(INTERNAL_ERROR "Cache mode is not determined.");
return 0; return 0;
} }
@ -152,25 +153,30 @@ static uint64_t _cache_min_metadata_size(uint64_t data_size, uint32_t chunk_size
return min_meta_size; return min_meta_size;
} }
int update_cache_pool_params(const struct segment_type *segtype, int update_cache_pool_params(struct cmd_context *cmd,
struct volume_group *vg, unsigned attr, struct profile *profile,
int passed_args, uint32_t pool_data_extents, uint32_t extent_size,
const struct segment_type *segtype,
unsigned attr,
uint32_t pool_data_extents,
uint32_t *pool_metadata_extents, uint32_t *pool_metadata_extents,
int *chunk_size_calc_method, uint32_t *chunk_size) int *chunk_size_calc_method, uint32_t *chunk_size)
{ {
uint64_t min_meta_size; uint64_t min_meta_size;
uint32_t extent_size = vg->extent_size;
uint64_t pool_metadata_size = (uint64_t) *pool_metadata_extents * extent_size; uint64_t pool_metadata_size = (uint64_t) *pool_metadata_extents * extent_size;
uint64_t pool_data_size = (uint64_t) pool_data_extents * extent_size; uint64_t pool_data_size = (uint64_t) pool_data_extents * extent_size;
uint64_t max_chunks = const uint64_t max_chunks =
get_default_allocation_cache_pool_max_chunks_CFG(vg->cmd, vg->profile); get_default_allocation_cache_pool_max_chunks_CFG(cmd, profile);
/* min chunk size in a multiple of DM_CACHE_MIN_DATA_BLOCK_SIZE */ /* min chunk size in a multiple of DM_CACHE_MIN_DATA_BLOCK_SIZE */
uint64_t min_chunk_size = (((pool_data_size + max_chunks - 1) / max_chunks + uint64_t min_chunk_size = (((pool_data_size + max_chunks - 1) / max_chunks +
DM_CACHE_MIN_DATA_BLOCK_SIZE - 1) / DM_CACHE_MIN_DATA_BLOCK_SIZE - 1) /
DM_CACHE_MIN_DATA_BLOCK_SIZE) * DM_CACHE_MIN_DATA_BLOCK_SIZE; DM_CACHE_MIN_DATA_BLOCK_SIZE) * DM_CACHE_MIN_DATA_BLOCK_SIZE;
if (!(passed_args & PASS_ARG_CHUNK_SIZE)) { if (!*chunk_size) {
*chunk_size = DEFAULT_CACHE_POOL_CHUNK_SIZE * 2; if (!(*chunk_size = find_config_tree_int(cmd, allocation_cache_pool_chunk_size_CFG,
profile) * 2))
*chunk_size = get_default_allocation_cache_pool_chunk_size_CFG(cmd,
profile);
if (*chunk_size < min_chunk_size) { if (*chunk_size < min_chunk_size) {
/* /*
* When using more then 'standard' default, * When using more then 'standard' default,
@ -178,25 +184,25 @@ int update_cache_pool_params(const struct segment_type *segtype,
*/ */
log_print_unless_silent("Using %s chunk size instead of default %s, " log_print_unless_silent("Using %s chunk size instead of default %s, "
"so cache pool has less then " FMTu64 " chunks.", "so cache pool has less then " FMTu64 " chunks.",
display_size(vg->cmd, min_chunk_size), display_size(cmd, min_chunk_size),
display_size(vg->cmd, *chunk_size), display_size(cmd, *chunk_size),
max_chunks); max_chunks);
*chunk_size = min_chunk_size; *chunk_size = min_chunk_size;
} else } else
log_verbose("Setting chunk size to %s.", log_verbose("Setting chunk size to %s.",
display_size(vg->cmd, *chunk_size)); display_size(cmd, *chunk_size));
} else if (*chunk_size < min_chunk_size) { } else if (*chunk_size < min_chunk_size) {
log_error("Chunk size %s is less then required minimal chunk size %s " log_error("Chunk size %s is less then required minimal chunk size %s "
"for a cache pool of %s size and limit " FMTu64 " chunks.", "for a cache pool of %s size and limit " FMTu64 " chunks.",
display_size(vg->cmd, *chunk_size), display_size(cmd, *chunk_size),
display_size(vg->cmd, min_chunk_size), display_size(cmd, min_chunk_size),
display_size(vg->cmd, pool_data_size), display_size(cmd, pool_data_size),
max_chunks); max_chunks);
log_error("To allow use of more chunks, see setting allocation/cache_pool_max_chunks."); log_error("To allow use of more chunks, see setting allocation/cache_pool_max_chunks.");
return 0; return 0;
} }
if (!validate_pool_chunk_size(vg->cmd, segtype, *chunk_size)) if (!validate_cache_chunk_size(cmd, *chunk_size))
return_0; return_0;
min_meta_size = _cache_min_metadata_size((uint64_t) pool_data_extents * extent_size, *chunk_size); min_meta_size = _cache_min_metadata_size((uint64_t) pool_data_extents * extent_size, *chunk_size);
@ -210,22 +216,31 @@ int update_cache_pool_params(const struct segment_type *segtype,
if (pool_metadata_size > (2 * DEFAULT_CACHE_POOL_MAX_METADATA_SIZE)) { if (pool_metadata_size > (2 * DEFAULT_CACHE_POOL_MAX_METADATA_SIZE)) {
pool_metadata_size = 2 * DEFAULT_CACHE_POOL_MAX_METADATA_SIZE; pool_metadata_size = 2 * DEFAULT_CACHE_POOL_MAX_METADATA_SIZE;
if (passed_args & PASS_ARG_POOL_METADATA_SIZE) if (*pool_metadata_extents)
log_warn("WARNING: Maximum supported pool metadata size is %s.", log_warn("WARNING: Maximum supported pool metadata size is %s.",
display_size(vg->cmd, pool_metadata_size)); display_size(cmd, pool_metadata_size));
} else if (pool_metadata_size < min_meta_size) { } else if (pool_metadata_size < min_meta_size) {
if (passed_args & PASS_ARG_POOL_METADATA_SIZE) if (*pool_metadata_extents)
log_warn("WARNING: Minimum required pool metadata size is %s " log_warn("WARNING: Minimum required pool metadata size is %s "
"(needs extra %s).", "(needs extra %s).",
display_size(vg->cmd, min_meta_size), display_size(cmd, min_meta_size),
display_size(vg->cmd, min_meta_size - pool_metadata_size)); display_size(cmd, min_meta_size - pool_metadata_size));
pool_metadata_size = min_meta_size; pool_metadata_size = min_meta_size;
} }
if (!(*pool_metadata_extents = if (!(*pool_metadata_extents =
extents_from_size(vg->cmd, pool_metadata_size, extent_size))) extents_from_size(cmd, pool_metadata_size, extent_size)))
return_0; return_0;
if ((uint64_t) *chunk_size > (uint64_t) pool_data_extents * extent_size) {
log_error("Size of %s data volume cannot be smaller than chunk size %s.",
segtype->name, display_size(cmd, *chunk_size));
return 0;
}
log_verbose("Preferred pool metadata size %s.",
display_size(cmd, (uint64_t)*pool_metadata_extents * extent_size));
return 1; return 1;
} }
@ -236,7 +251,7 @@ int update_cache_pool_params(const struct segment_type *segtype,
int validate_lv_cache_chunk_size(struct logical_volume *pool_lv, uint32_t chunk_size) int validate_lv_cache_chunk_size(struct logical_volume *pool_lv, uint32_t chunk_size)
{ {
struct volume_group *vg = pool_lv->vg; struct volume_group *vg = pool_lv->vg;
uint64_t max_chunks = get_default_allocation_cache_pool_max_chunks_CFG(vg->cmd, vg->profile); const uint64_t max_chunks = get_default_allocation_cache_pool_max_chunks_CFG(vg->cmd, pool_lv->profile);
uint64_t min_size = _cache_min_metadata_size(pool_lv->size, chunk_size); uint64_t min_size = _cache_min_metadata_size(pool_lv->size, chunk_size);
uint64_t chunks = pool_lv->size / chunk_size; uint64_t chunks = pool_lv->size / chunk_size;
int r = 1; int r = 1;
@ -292,7 +307,7 @@ int validate_lv_cache_create_pool(const struct logical_volume *pool_lv)
if (!dm_list_empty(&pool_lv->segs_using_this_lv)) { if (!dm_list_empty(&pool_lv->segs_using_this_lv)) {
seg = get_only_segment_using_this_lv(pool_lv); seg = get_only_segment_using_this_lv(pool_lv);
log_error("Logical volume %s is already in use by %s", log_error("Logical volume %s is already in use by %s.",
display_lvname(pool_lv), display_lvname(pool_lv),
seg ? display_lvname(seg->lv) : "another LV"); seg ? display_lvname(seg->lv) : "another LV");
return 0; return 0;
@ -333,6 +348,30 @@ int validate_lv_cache_create_origin(const struct logical_volume *origin_lv)
return 1; return 1;
} }
int validate_cache_chunk_size(struct cmd_context *cmd, uint32_t chunk_size)
{
const uint32_t min_size = DM_CACHE_MIN_DATA_BLOCK_SIZE;
const uint32_t max_size = DM_CACHE_MAX_DATA_BLOCK_SIZE;
int r = 1;
if ((chunk_size < min_size) || (chunk_size > max_size)) {
log_error("Cache chunk size %s is not in the range %s to %s.",
display_size(cmd, chunk_size),
display_size(cmd, min_size),
display_size(cmd, max_size));
r = 0;
}
if (chunk_size & (min_size - 1)) {
log_error("Cache chunk size %s must be a multiple of %s.",
display_size(cmd, chunk_size),
display_size(cmd, min_size));
r = 0;
}
return r;
}
/* /*
* lv_cache_create * lv_cache_create
* @pool * @pool
@ -370,6 +409,9 @@ struct logical_volume *lv_cache_create(struct logical_volume *pool_lv,
if (!attach_pool_lv(seg, pool_lv, NULL, NULL, NULL)) if (!attach_pool_lv(seg, pool_lv, NULL, NULL, NULL))
return_NULL; return_NULL;
if (!seg->lv->profile) /* Inherit profile from cache-pool */
seg->lv->profile = seg->pool_lv->profile;
return cache_lv; return cache_lv;
} }
@ -633,6 +675,26 @@ static const char *_get_default_cache_policy(struct cmd_context *cmd)
return def; return def;
} }
/* Autodetect best available cache metadata format for a user */
static cache_metadata_format_t _get_default_cache_metadata_format(struct cmd_context *cmd)
{
const struct segment_type *segtype = get_segtype_from_string(cmd, SEG_TYPE_NAME_CACHE);
unsigned attr;
cache_metadata_format_t f;
if (!segtype ||
!segtype->ops->target_present ||
!segtype->ops->target_present(cmd, NULL, &attr)) {
f = CACHE_METADATA_FORMAT_1;
log_warn("WARNING: Cannot detect default cache metadata format, using format: %u.", f);
} else {
f = (attr & CACHE_FEATURE_METADATA2) ? CACHE_METADATA_FORMAT_2 : CACHE_METADATA_FORMAT_1;
log_debug_metadata("Detected default cache metadata format: %u.", f);
}
return f;
}
int cache_set_policy(struct lv_segment *seg, const char *name, int cache_set_policy(struct lv_segment *seg, const char *name,
const struct dm_config_tree *settings) const struct dm_config_tree *settings)
{ {
@ -640,28 +702,36 @@ int cache_set_policy(struct lv_segment *seg, const char *name,
const struct dm_config_node *cns; const struct dm_config_node *cns;
struct dm_config_tree *old = NULL, *new = NULL, *tmp = NULL; struct dm_config_tree *old = NULL, *new = NULL, *tmp = NULL;
int r = 0; int r = 0;
const int passed_seg_is_cache = seg_is_cache(seg); struct profile *profile = seg->lv->profile;
if (passed_seg_is_cache) if (seg_is_cache(seg))
seg = first_seg(seg->pool_lv); seg = first_seg(seg->pool_lv);
else if (seg_is_cache_pool(seg)) {
if (!name && !settings)
return 1; /* Policy and settings can be selected later when caching LV */
} else {
log_error(INTERNAL_ERROR "Cannot set cache metadata format for non cache volume %s.",
display_lvname(seg->lv));
return 0;
}
if (name) { if (name) {
if (!(seg->policy_name = dm_pool_strdup(seg->lv->vg->vgmem, name))) { if (!(seg->policy_name = dm_pool_strdup(seg->lv->vg->vgmem, name))) {
log_error("Failed to duplicate policy name."); log_error("Failed to duplicate policy name.");
return 0; return 0;
} }
} else if (!seg->policy_name && passed_seg_is_cache) { } else if (!seg->policy_name) {
if (!(seg->policy_name = find_config_tree_str(seg->lv->vg->cmd, allocation_cache_policy_CFG, NULL)) && if (!(seg->policy_name = find_config_tree_str(seg->lv->vg->cmd, allocation_cache_policy_CFG,
profile)) &&
!(seg->policy_name = _get_default_cache_policy(seg->lv->vg->cmd))) !(seg->policy_name = _get_default_cache_policy(seg->lv->vg->cmd)))
return_0; return_0;
}
if (settings) {
if (!seg->policy_name) { if (!seg->policy_name) {
log_error(INTERNAL_ERROR "Can't set policy settings without policy name."); log_error(INTERNAL_ERROR "Can't set policy settings without policy name.");
return 0; return 0;
} }
}
if (settings) {
if (seg->policy_settings) { if (seg->policy_settings) {
if (!(old = dm_config_create())) if (!(old = dm_config_create()))
goto_out; goto_out;
@ -677,30 +747,26 @@ int cache_set_policy(struct lv_segment *seg, const char *name,
if ((cn = dm_config_find_node((tmp) ? tmp->root : settings->root, "policy_settings")) && if ((cn = dm_config_find_node((tmp) ? tmp->root : settings->root, "policy_settings")) &&
!(seg->policy_settings = dm_config_clone_node_with_mem(seg->lv->vg->vgmem, cn, 0))) !(seg->policy_settings = dm_config_clone_node_with_mem(seg->lv->vg->vgmem, cn, 0)))
goto_out; goto_out;
} else if (passed_seg_is_cache && /* Look for command's profile cache_policies */ } else if (!seg->policy_settings) {
(cns = find_config_tree_node(seg->lv->vg->cmd, allocation_cache_settings_CFG_SECTION, NULL))) { if ((cns = find_config_tree_node(seg->lv->vg->cmd, allocation_cache_settings_CFG_SECTION,
/* Try to find our section for given policy */ profile))) {
for (cn = cns->child; cn; cn = cn->sib) { /* Try to find our section for given policy */
/* Only matching section names */ for (cn = cns->child; cn; cn = cn->sib) {
if (cn->v || strcmp(cn->key, seg->policy_name) != 0) if (!cn->child)
continue; continue; /* Ignore section without settings */
if (!cn->child) if (cn->v || strcmp(cn->key, seg->policy_name) != 0)
break; continue; /* Ignore mismatching sections */
if (!(new = dm_config_create())) /* Clone nodes with policy name */
goto_out; if (!(seg->policy_settings = dm_config_clone_node_with_mem(seg->lv->vg->vgmem,
cn, 0)))
return_0;
if (!(new->root = dm_config_clone_node_with_mem(new->mem, /* Replace policy name key with 'policy_settings' */
cn->child, 1))) seg->policy_settings->key = "policy_settings";
goto_out; break; /* Only first match counts */
}
if (!(seg->policy_settings = dm_config_create_node(new, "policy_settings")))
goto_out;
seg->policy_settings->child = new->root;
break; /* Only first match counts */
} }
} }
@ -727,17 +793,94 @@ out:
return r; return r;
} }
/*
* Sets metadata format on cache pool segment with these rules:
* 1. When 'cache-pool' segment is passed, sets only for selected formats (1 or 2).
* 2. For 'cache' segment passed in we know cache pool segment.
* When passed format is 0 (UNSELECTED) with 'cache' segment - it's the moment
* lvm2 has to figure out 'default' metadata format (1 or 2) from
* configuration or profiles.
* 3. If still unselected or selected format is != 1, figure the best supported format
* and either use it or validate users settings is possible.
*
* Reasoning: A user may create cache-pool and may or may not specify CMFormat.
* If the CMFormat has been selected (1 or 2) store this in metadata, otherwise
* for an unused cache-pool UNSELECTED CMFormat is used. When caching LV, CMFormat
* must be decided and from this moment it's always stored. To support backward
* compatibility 'CMFormat 1' is used when it is NOT specified for a cached LV in
* lvm2 metadata (no metadata_format=#F element in cache-pool segment).
*/
int cache_set_metadata_format(struct lv_segment *seg, cache_metadata_format_t format)
{
cache_metadata_format_t best;
struct profile *profile = seg->lv->profile;
if (seg_is_cache(seg))
seg = first_seg(seg->pool_lv);
else if (seg_is_cache_pool(seg)) {
if (format == CACHE_METADATA_FORMAT_UNSELECTED)
return 1; /* Format can be selected later when caching LV */
} else {
log_error(INTERNAL_ERROR "Cannot set cache metadata format for non cache volume %s.",
display_lvname(seg->lv));
return 0;
}
/* Check if we need to search for configured cache metadata format */
if (format == CACHE_METADATA_FORMAT_UNSELECTED) {
if (seg->cache_metadata_format != CACHE_METADATA_FORMAT_UNSELECTED)
return 1; /* Format already selected in cache pool */
/* Check configurations and profiles */
format = find_config_tree_int(seg->lv->vg->cmd, allocation_cache_metadata_format_CFG,
profile);
}
/* See what is a 'best' available cache metadata format
* when the specifed format is other then always existing CMFormat 1 */
if (format != CACHE_METADATA_FORMAT_1) {
best = _get_default_cache_metadata_format(seg->lv->vg->cmd);
/* Format was not selected, so use best present on a system */
if (format == CACHE_METADATA_FORMAT_UNSELECTED)
format = best;
else if (format != best) {
/* Format is not valid (Only Format 1 or 2 is supported ATM) */
log_error("Cache metadata format %u is not supported by kernel target.", format);
return 0;
}
}
switch (format) {
case CACHE_METADATA_FORMAT_2: seg->lv->status |= LV_METADATA_FORMAT; break;
case CACHE_METADATA_FORMAT_1: seg->lv->status &= ~LV_METADATA_FORMAT; break;
default:
log_error(INTERNAL_ERROR "Invalid cache metadata format %u for cache volume %s.",
format, display_lvname(seg->lv));
return 0;
}
seg->cache_metadata_format = format;
return 1;
}
/* /*
* Universal 'wrapper' function do-it-all * Universal 'wrapper' function do-it-all
* to update all commonly specified cache parameters * to update all commonly specified cache parameters
*/ */
int cache_set_params(struct lv_segment *seg, int cache_set_params(struct lv_segment *seg,
uint32_t chunk_size,
cache_metadata_format_t format,
cache_mode_t mode, cache_mode_t mode,
const char *policy_name, const char *policy_name,
const struct dm_config_tree *policy_settings, const struct dm_config_tree *policy_settings)
uint32_t chunk_size)
{ {
struct lv_segment *pool_seg; struct lv_segment *pool_seg;
struct cmd_context *cmd = seg->lv->vg->cmd;
if (!cache_set_metadata_format(seg, format))
return_0;
if (!cache_set_cache_mode(seg, mode)) if (!cache_set_cache_mode(seg, mode))
return_0; return_0;
@ -748,16 +891,35 @@ int cache_set_params(struct lv_segment *seg,
pool_seg = seg_is_cache(seg) ? first_seg(seg->pool_lv) : seg; pool_seg = seg_is_cache(seg) ? first_seg(seg->pool_lv) : seg;
if (chunk_size) { if (chunk_size) {
if (!validate_lv_cache_chunk_size(pool_seg->lv, chunk_size)) if (seg_is_cache(seg) &&
!validate_lv_cache_chunk_size(pool_seg->lv, chunk_size))
return_0; return_0;
pool_seg->chunk_size = chunk_size; pool_seg->chunk_size = chunk_size;
} else { } else if (seg_is_cache(seg)) {
/* TODO: some calc_policy solution for cache ? */ /* Chunk size in profile has priority over cache-pool chunk size */
if (!recalculate_pool_chunk_size_with_dev_hints(pool_seg->lv, 0, if ((chunk_size = find_config_tree_int(cmd, allocation_cache_pool_chunk_size_CFG,
seg->lv->profile) * 2)) {
if (!validate_lv_cache_chunk_size(pool_seg->lv, chunk_size))
return_0;
if (pool_seg->chunk_size != chunk_size)
log_verbose("Replacing chunk size %s in cache pool %s with "
"chunk size %s from profile.",
display_size(cmd, pool_seg->chunk_size),
display_lvname(seg->lv),
display_size(cmd, chunk_size));
pool_seg->chunk_size = chunk_size;
}
} else if (seg_is_cache_pool(seg)) {
if (!pool_seg->chunk_size &&
/* TODO: some calc_policy solution for cache ? */
!recalculate_pool_chunk_size_with_dev_hints(pool_seg->lv,
THIN_CHUNK_SIZE_CALC_METHOD_GENERIC)) THIN_CHUNK_SIZE_CALC_METHOD_GENERIC))
return_0; return_0;
} }
if (seg_is_cache(seg))
cache_check_for_warns(seg);
return 1; return 1;
} }

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004-2016 Red Hat, Inc. All rights reserved. * Copyright (C) 2004-2017 Red Hat, Inc. All rights reserved.
* *
* This file is part of LVM2. * This file is part of LVM2.
* *
@ -220,19 +220,35 @@ char *lvseg_segtype_dup(struct dm_pool *mem, const struct lv_segment *seg)
char *lvseg_discards_dup(struct dm_pool *mem, const struct lv_segment *seg) char *lvseg_discards_dup(struct dm_pool *mem, const struct lv_segment *seg)
{ {
return dm_pool_strdup(mem, get_pool_discards_name(seg->discards)); if (lv_is_thin_pool(seg->lv))
return dm_pool_strdup(mem, get_pool_discards_name(seg->discards));
log_error("Cannot query non thin-pool segment of LV %s for discards property.",
display_lvname(seg->lv));
return NULL;
} }
char *lvseg_kernel_discards_dup_with_info_and_seg_status(struct dm_pool *mem, const struct lv_with_info_and_seg_status *lvdm) char *lvseg_kernel_discards_dup_with_info_and_seg_status(struct dm_pool *mem, const struct lv_with_info_and_seg_status *lvdm)
{ {
const char *s = ""; const char *s = "";
char *ret; char *ret;
thin_discards_t d;
if (lvdm->seg_status.type == SEG_STATUS_THIN_POOL) if (lvdm->seg_status.type == SEG_STATUS_THIN_POOL) {
s = get_pool_discards_name(lvdm->seg_status.thin_pool->discards); switch (lvdm->seg_status.thin_pool->discards) {
case DM_THIN_DISCARDS_IGNORE: d = THIN_DISCARDS_IGNORE; break;
case DM_THIN_DISCARDS_NO_PASSDOWN: d = THIN_DISCARDS_NO_PASSDOWN; break;
case DM_THIN_DISCARDS_PASSDOWN: d = THIN_DISCARDS_PASSDOWN; break;
default:
log_error("Kernel reports unknown discards status %u.",
lvdm->seg_status.thin_pool->discards);
return 0;
}
s = get_pool_discards_name(d);
}
if (!(ret = dm_pool_strdup(mem, s))) { if (!(ret = dm_pool_strdup(mem, s))) {
log_error("lvseg_kernel_discards_dup_with_info_and_seg_status: dm_pool_strdup failed"); log_error("lvseg_kernel_discards_dup_with_info_and_seg_status: dm_pool_strdup failed.");
return NULL; return NULL;
} }
@ -1104,6 +1120,19 @@ int lv_raid_healthy(const struct logical_volume *lv)
return 1; return 1;
} }
/* Helper: check for any sub LVs after a disk removing reshape */
static int _sublvs_remove_after_reshape(const struct logical_volume *lv)
{
uint32_t s;
struct lv_segment *seg = first_seg(lv);
for (s = seg->area_count -1; s; s--)
if (seg_lv(seg, s)->status & LV_REMOVE_AFTER_RESHAPE)
return 1;
return 0;
}
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_with_info_and_seg_status(struct dm_pool *mem, const struct lv_with_info_and_seg_status *lvdm)
{ {
const struct logical_volume *lv = lvdm->lv; const struct logical_volume *lv = lvdm->lv;
@ -1255,7 +1284,7 @@ char *lv_attr_dup_with_info_and_seg_status(struct dm_pool *mem, const struct lv_
if (((lv_is_thin_volume(lv) && (seg = first_seg(lv)) && seg->pool_lv && (seg = first_seg(seg->pool_lv))) || if (((lv_is_thin_volume(lv) && (seg = first_seg(lv)) && seg->pool_lv && (seg = first_seg(seg->pool_lv))) ||
(lv_is_thin_pool(lv) && (seg = first_seg(lv)))) && (lv_is_thin_pool(lv) && (seg = first_seg(lv)))) &&
seg->zero_new_blocks) (seg->zero_new_blocks == THIN_ZERO_YES))
repstr[7] = 'z'; repstr[7] = 'z';
else else
repstr[7] = '-'; repstr[7] = '-';
@ -1269,6 +1298,8 @@ char *lv_attr_dup_with_info_and_seg_status(struct dm_pool *mem, const struct lv_
repstr[8] = 'p'; repstr[8] = 'p';
else if (lv_is_raid_type(lv)) { else if (lv_is_raid_type(lv)) {
uint64_t n; uint64_t n;
char *sync_action;
if (!activation()) if (!activation())
repstr[8] = 'X'; /* Unknown */ repstr[8] = 'X'; /* Unknown */
else if (!lv_raid_healthy(lv)) else if (!lv_raid_healthy(lv))
@ -1276,8 +1307,17 @@ char *lv_attr_dup_with_info_and_seg_status(struct dm_pool *mem, const struct lv_
else if (lv_is_raid(lv)) { else if (lv_is_raid(lv)) {
if (lv_raid_mismatch_count(lv, &n) && n) if (lv_raid_mismatch_count(lv, &n) && n)
repstr[8] = 'm'; /* RAID has 'm'ismatches */ repstr[8] = 'm'; /* RAID has 'm'ismatches */
else if (lv_raid_sync_action(lv, &sync_action) &&
!strcmp(sync_action, "reshape"))
repstr[8] = 's'; /* LV is re(s)haping */
else if (_sublvs_remove_after_reshape(lv))
repstr[8] = 'R'; /* sub-LV got freed from raid set by reshaping
and has to be 'R'emoved */
} else if (lv->status & LV_WRITEMOSTLY) } else if (lv->status & LV_WRITEMOSTLY)
repstr[8] = 'w'; /* sub-LV has 'w'ritemostly */ repstr[8] = 'w'; /* sub-LV has 'w'ritemostly */
else if (lv->status & LV_REMOVE_AFTER_RESHAPE)
repstr[8] = 'R'; /* sub-LV got freed from raid set by reshaping
and has to be 'R'emoved */
} else if (lvdm->seg_status.type == SEG_STATUS_CACHE) { } else if (lvdm->seg_status.type == SEG_STATUS_CACHE) {
if (lvdm->seg_status.cache->fail) if (lvdm->seg_status.cache->fail)
repstr[8] = 'F'; repstr[8] = 'F';

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved. * Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004-2012 Red Hat, Inc. All rights reserved. * Copyright (C) 2004-2017 Red Hat, Inc. All rights reserved.
* *
* This file is part of LVM2. * This file is part of LVM2.
* *
@ -21,11 +21,13 @@
struct lv_segment *alloc_lv_segment(const struct segment_type *segtype, struct lv_segment *alloc_lv_segment(const struct segment_type *segtype,
struct logical_volume *lv, struct logical_volume *lv,
uint32_t le, uint32_t len, uint32_t le, uint32_t len,
uint32_t reshape_len,
uint64_t status, uint64_t status,
uint32_t stripe_size, uint32_t stripe_size,
struct logical_volume *log_lv, struct logical_volume *log_lv,
uint32_t area_count, uint32_t area_count,
uint32_t area_len, uint32_t area_len,
uint32_t data_copies,
uint32_t chunk_size, uint32_t chunk_size,
uint32_t region_size, uint32_t region_size,
uint32_t extents_copied, uint32_t extents_copied,

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004-2014 Red Hat, Inc. All rights reserved. * Copyright (C) 2004-2017 Red Hat, Inc. All rights reserved.
* *
* This file is part of LVM2. * This file is part of LVM2.
* *
@ -912,11 +912,13 @@ static uint32_t _round_to_stripe_boundary(struct volume_group *vg, uint32_t exte
struct lv_segment *alloc_lv_segment(const struct segment_type *segtype, struct lv_segment *alloc_lv_segment(const struct segment_type *segtype,
struct logical_volume *lv, struct logical_volume *lv,
uint32_t le, uint32_t len, uint32_t le, uint32_t len,
uint32_t reshape_len,
uint64_t status, uint64_t status,
uint32_t stripe_size, uint32_t stripe_size,
struct logical_volume *log_lv, struct logical_volume *log_lv,
uint32_t area_count, uint32_t area_count,
uint32_t area_len, uint32_t area_len,
uint32_t data_copies,
uint32_t chunk_size, uint32_t chunk_size,
uint32_t region_size, uint32_t region_size,
uint32_t extents_copied, uint32_t extents_copied,
@ -950,10 +952,12 @@ struct lv_segment *alloc_lv_segment(const struct segment_type *segtype,
seg->lv = lv; seg->lv = lv;
seg->le = le; seg->le = le;
seg->len = len; seg->len = len;
seg->reshape_len = reshape_len;
seg->status = status; seg->status = status;
seg->stripe_size = stripe_size; seg->stripe_size = stripe_size;
seg->area_count = area_count; seg->area_count = area_count;
seg->area_len = area_len; seg->area_len = area_len;
seg->data_copies = data_copies ? : lv_raid_data_copies(segtype, area_count);
seg->chunk_size = chunk_size; seg->chunk_size = chunk_size;
seg->region_size = region_size; seg->region_size = region_size;
seg->extents_copied = extents_copied; seg->extents_copied = extents_copied;
@ -1047,11 +1051,10 @@ static int _release_and_discard_lv_segment_area(struct lv_segment *seg, uint32_t
if (lv_is_raid_image(lv)) { if (lv_is_raid_image(lv)) {
/* Calculate the amount of extents to reduce per rmate/rimage LV */ /* Calculate the amount of extents to reduce per rmate/rimage LV */
uint32_t rimage_extents; uint32_t rimage_extents;
struct lv_segment *seg1 = first_seg(lv);
/* FIXME: avoid extra seg_is_*() conditonals */ /* FIXME: avoid extra seg_is_*() conditionals here */
area_reduction =_round_to_stripe_boundary(lv->vg, area_reduction, rimage_extents = raid_rimage_extents(seg1->segtype, area_reduction, seg_is_any_raid0(seg) ? 0 : _raid_stripes_count(seg),
(seg_is_raid1(seg) || seg_is_any_raid0(seg)) ? 0 : _raid_stripes_count(seg), 0);
rimage_extents = raid_rimage_extents(seg->segtype, area_reduction, seg_is_any_raid0(seg) ? 0 : _raid_stripes_count(seg),
seg_is_raid10(seg) ? 1 :_raid_data_copies(seg)); seg_is_raid10(seg) ? 1 :_raid_data_copies(seg));
if (!rimage_extents) if (!rimage_extents)
return 0; return 0;
@ -1258,7 +1261,7 @@ static uint32_t _calc_area_multiple(const struct segment_type *segtype,
* the 'stripes' argument will always need to * the 'stripes' argument will always need to
* be given. * be given.
*/ */
if (!strcmp(segtype->name, _lv_type_names[LV_TYPE_RAID10])) { if (segtype_is_raid10(segtype)) {
if (!stripes) if (!stripes)
return area_count / 2; return area_count / 2;
return stripes; return stripes;
@ -1278,16 +1281,17 @@ static uint32_t _calc_area_multiple(const struct segment_type *segtype,
static int _lv_segment_reduce(struct lv_segment *seg, uint32_t reduction) static int _lv_segment_reduce(struct lv_segment *seg, uint32_t reduction)
{ {
uint32_t area_reduction, s; uint32_t area_reduction, s;
uint32_t areas = (seg->area_count / (seg_is_raid10(seg) ? seg->data_copies : 1)) - seg->segtype->parity_devs;
/* Caller must ensure exact divisibility */ /* Caller must ensure exact divisibility */
if (seg_is_striped(seg)) { if (seg_is_striped(seg) || seg_is_striped_raid(seg)) {
if (reduction % seg->area_count) { if (reduction % areas) {
log_error("Segment extent reduction %" PRIu32 log_error("Segment extent reduction %" PRIu32
" not divisible by #stripes %" PRIu32, " not divisible by #stripes %" PRIu32,
reduction, seg->area_count); reduction, seg->area_count);
return 0; return 0;
} }
area_reduction = (reduction / seg->area_count); area_reduction = reduction / areas;
} else } else
area_reduction = reduction; area_reduction = reduction;
@ -1296,7 +1300,11 @@ static int _lv_segment_reduce(struct lv_segment *seg, uint32_t reduction)
return_0; return_0;
seg->len -= reduction; seg->len -= reduction;
seg->area_len -= area_reduction;
if (seg_is_raid(seg))
seg->area_len = seg->len;
else
seg->area_len -= area_reduction;
return 1; return 1;
} }
@ -1306,11 +1314,13 @@ static int _lv_segment_reduce(struct lv_segment *seg, uint32_t reduction)
*/ */
static int _lv_reduce(struct logical_volume *lv, uint32_t extents, int delete) static int _lv_reduce(struct logical_volume *lv, uint32_t extents, int delete)
{ {
struct lv_segment *seg; struct lv_segment *seg = first_seg(lv);;
uint32_t count = extents; uint32_t count = extents;
uint32_t reduction; uint32_t reduction;
struct logical_volume *pool_lv; struct logical_volume *pool_lv;
struct logical_volume *external_lv = NULL; struct logical_volume *external_lv = NULL;
int is_raid10 = seg_is_any_raid10(seg) && seg->reshape_len;
uint32_t data_copies = seg->data_copies;
if (lv_is_merging_origin(lv)) { if (lv_is_merging_origin(lv)) {
log_debug_metadata("Dropping snapshot merge of %s to removed origin %s.", log_debug_metadata("Dropping snapshot merge of %s to removed origin %s.",
@ -1373,8 +1383,18 @@ static int _lv_reduce(struct logical_volume *lv, uint32_t extents, int delete)
count -= reduction; count -= reduction;
} }
lv->le_count -= extents; seg = first_seg(lv);
if (is_raid10) {
lv->le_count -= extents * data_copies;
if (seg)
seg->len = seg->area_len = lv->le_count;
} else
lv->le_count -= extents;
lv->size = (uint64_t) lv->le_count * lv->vg->extent_size; lv->size = (uint64_t) lv->le_count * lv->vg->extent_size;
if (seg)
seg->extents_copied = seg->len;
if (!delete) if (!delete)
return 1; return 1;
@ -1487,11 +1507,10 @@ int lv_reduce(struct logical_volume *lv, uint32_t extents)
{ {
struct lv_segment *seg = first_seg(lv); struct lv_segment *seg = first_seg(lv);
/* Ensure stipe boundary extents on RAID LVs */ /* Ensure stripe boundary extents on RAID LVs */
if (lv_is_raid(lv) && extents != lv->le_count) if (lv_is_raid(lv) && extents != lv->le_count)
extents =_round_to_stripe_boundary(lv->vg, extents, extents =_round_to_stripe_boundary(lv->vg, extents,
seg_is_raid1(seg) ? 0 : _raid_stripes_count(seg), 0); seg_is_raid1(seg) ? 0 : _raid_stripes_count(seg), 0);
return _lv_reduce(lv, extents, 1); return _lv_reduce(lv, extents, 1);
} }
@ -1793,10 +1812,10 @@ static int _setup_alloced_segment(struct logical_volume *lv, uint64_t status,
area_multiple = _calc_area_multiple(segtype, area_count, 0); area_multiple = _calc_area_multiple(segtype, area_count, 0);
extents = aa[0].len * area_multiple; extents = aa[0].len * area_multiple;
if (!(seg = alloc_lv_segment(segtype, lv, lv->le_count, extents, if (!(seg = alloc_lv_segment(segtype, lv, lv->le_count, extents, 0,
status, stripe_size, NULL, status, stripe_size, NULL,
area_count, area_count,
aa[0].len, 0u, region_size, 0u, NULL))) { aa[0].len, 0, 0u, region_size, 0u, NULL))) {
log_error("Couldn't allocate new LV segment."); log_error("Couldn't allocate new LV segment.");
return 0; return 0;
} }
@ -3234,9 +3253,9 @@ int lv_add_virtual_segment(struct logical_volume *lv, uint64_t status,
seg->area_len += extents; seg->area_len += extents;
seg->len += extents; seg->len += extents;
} else { } else {
if (!(seg = alloc_lv_segment(segtype, lv, lv->le_count, extents, if (!(seg = alloc_lv_segment(segtype, lv, lv->le_count, extents, 0,
status, 0, NULL, 0, status, 0, NULL, 0,
extents, 0, 0, 0, NULL))) { extents, 0, 0, 0, 0, NULL))) {
log_error("Couldn't allocate new %s segment.", segtype->name); log_error("Couldn't allocate new %s segment.", segtype->name);
return 0; return 0;
} }
@ -3562,10 +3581,10 @@ static struct lv_segment *_convert_seg_to_mirror(struct lv_segment *seg,
} }
if (!(newseg = alloc_lv_segment(get_segtype_from_string(seg->lv->vg->cmd, SEG_TYPE_NAME_MIRROR), if (!(newseg = alloc_lv_segment(get_segtype_from_string(seg->lv->vg->cmd, SEG_TYPE_NAME_MIRROR),
seg->lv, seg->le, seg->len, seg->lv, seg->le, seg->len, 0,
seg->status, seg->stripe_size, seg->status, seg->stripe_size,
log_lv, log_lv,
seg->area_count, seg->area_len, seg->area_count, seg->area_len, 0,
seg->chunk_size, region_size, seg->chunk_size, region_size,
seg->extents_copied, NULL))) { seg->extents_copied, NULL))) {
log_error("Couldn't allocate converted LV segment."); log_error("Couldn't allocate converted LV segment.");
@ -3667,8 +3686,8 @@ int lv_add_segmented_mirror_image(struct alloc_handle *ah,
} }
if (!(new_seg = alloc_lv_segment(segtype, copy_lv, if (!(new_seg = alloc_lv_segment(segtype, copy_lv,
seg->le, seg->len, PVMOVE, 0, seg->le, seg->len, 0, PVMOVE, 0,
NULL, 1, seg->len, NULL, 1, seg->len, 0,
0, 0, 0, NULL))) 0, 0, 0, NULL)))
return_0; return_0;
@ -3863,9 +3882,9 @@ static int _lv_insert_empty_sublvs(struct logical_volume *lv,
/* /*
* First, create our top-level segment for our top-level LV * First, create our top-level segment for our top-level LV
*/ */
if (!(mapseg = alloc_lv_segment(segtype, lv, 0, 0, lv->status, if (!(mapseg = alloc_lv_segment(segtype, lv, 0, 0, 0, lv->status,
stripe_size, NULL, stripe_size, NULL,
devices, 0, 0, region_size, 0, NULL))) { devices, 0, 0, 0, region_size, 0, NULL))) {
log_error("Failed to create mapping segment for %s.", log_error("Failed to create mapping segment for %s.",
display_lvname(lv)); display_lvname(lv));
return 0; return 0;
@ -3925,7 +3944,7 @@ bad:
static int _lv_extend_layered_lv(struct alloc_handle *ah, static int _lv_extend_layered_lv(struct alloc_handle *ah,
struct logical_volume *lv, struct logical_volume *lv,
uint32_t extents, uint32_t first_area, uint32_t extents, uint32_t first_area,
uint32_t stripes, uint32_t stripe_size) uint32_t mirrors, uint32_t stripes, uint32_t stripe_size)
{ {
const struct segment_type *segtype; const struct segment_type *segtype;
struct logical_volume *sub_lv, *meta_lv; struct logical_volume *sub_lv, *meta_lv;
@ -3953,7 +3972,7 @@ static int _lv_extend_layered_lv(struct alloc_handle *ah,
for (fa = first_area, s = 0; s < seg->area_count; s++) { for (fa = first_area, s = 0; s < seg->area_count; s++) {
if (is_temporary_mirror_layer(seg_lv(seg, s))) { if (is_temporary_mirror_layer(seg_lv(seg, s))) {
if (!_lv_extend_layered_lv(ah, seg_lv(seg, s), extents / area_multiple, if (!_lv_extend_layered_lv(ah, seg_lv(seg, s), extents / area_multiple,
fa, stripes, stripe_size)) fa, mirrors, stripes, stripe_size))
return_0; return_0;
fa += lv_mirror_count(seg_lv(seg, s)); fa += lv_mirror_count(seg_lv(seg, s));
continue; continue;
@ -3967,6 +3986,8 @@ static int _lv_extend_layered_lv(struct alloc_handle *ah,
return 0; return 0;
} }
last_seg(lv)->data_copies = mirrors;
/* Extend metadata LVs only on initial creation */ /* Extend metadata LVs only on initial creation */
if (seg_is_raid_with_meta(seg) && !lv->le_count) { if (seg_is_raid_with_meta(seg) && !lv->le_count) {
if (!seg->meta_areas) { if (!seg->meta_areas) {
@ -4063,8 +4084,11 @@ static int _lv_extend_layered_lv(struct alloc_handle *ah,
lv_set_hidden(seg_metalv(seg, s)); lv_set_hidden(seg_metalv(seg, s));
} }
seg->area_len += extents / area_multiple;
seg->len += extents; seg->len += extents;
if (seg_is_raid(seg))
seg->area_len = seg->len;
else
seg->area_len += extents / area_multiple;
if (!_setup_lv_size(lv, lv->le_count + extents)) if (!_setup_lv_size(lv, lv->le_count + extents))
return_0; return_0;
@ -4171,7 +4195,7 @@ int lv_extend(struct logical_volume *lv,
} }
if (!(r = _lv_extend_layered_lv(ah, lv, new_extents - lv->le_count, 0, if (!(r = _lv_extend_layered_lv(ah, lv, new_extents - lv->le_count, 0,
stripes, stripe_size))) mirrors, stripes, stripe_size)))
goto_out; goto_out;
/* /*
@ -4749,6 +4773,19 @@ static int _lvresize_check(struct logical_volume *lv,
return 0; return 0;
} }
if (lv_is_raid(lv) &&
lp->resize == LV_REDUCE) {
unsigned attrs;
const struct segment_type *segtype = first_seg(lv)->segtype;
if (!segtype->ops->target_present ||
!segtype->ops->target_present(lv->vg->cmd, NULL, &attrs) ||
!(attrs & RAID_FEATURE_SHRINK)) {
log_error("RAID module does not support shrinking.");
return 0;
}
}
if (lp->use_policies && !lv_is_cow(lv) && !lv_is_thin_pool(lv)) { if (lp->use_policies && !lv_is_cow(lv) && !lv_is_thin_pool(lv)) {
log_error("Policy-based resize is supported only for snapshot and thin pool volumes."); log_error("Policy-based resize is supported only for snapshot and thin pool volumes.");
return 0; return 0;
@ -5391,6 +5428,17 @@ int lv_resize(struct logical_volume *lv,
if (!_lvresize_check(lv, lp)) if (!_lvresize_check(lv, lp))
return_0; return_0;
if (seg->reshape_len) {
/* Prevent resizing on out-of-sync reshapable raid */
if (!lv_raid_in_sync(lv)) {
log_error("Can't resize reshaping LV %s.", display_lvname(lv));
return 0;
}
/* Remove any striped raid reshape space for LV resizing */
if (!lv_raid_free_reshape_space(lv))
return_0;
}
if (lp->use_policies) { if (lp->use_policies) {
lp->extents = 0; lp->extents = 0;
lp->sign = SIGN_PLUS; lp->sign = SIGN_PLUS;
@ -5902,6 +5950,7 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
int ask_discard; int ask_discard;
struct lv_list *lvl; struct lv_list *lvl;
struct seg_list *sl; struct seg_list *sl;
struct lv_segment *seg = first_seg(lv);
int is_last_pool = lv_is_pool(lv); int is_last_pool = lv_is_pool(lv);
vg = lv->vg; vg = lv->vg;
@ -6008,6 +6057,13 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
is_last_pool = 1; is_last_pool = 1;
} }
/* Special case removing a striped raid LV with allocated reshape space */
if (seg && seg->reshape_len) {
if (!(seg->segtype = get_segtype_from_string(cmd, SEG_TYPE_NAME_STRIPED)))
return_0;
lv->le_count = seg->len = seg->area_len = seg_lv(seg, 0)->le_count * seg->area_count;
}
/* Used cache pool, COW or historical LV cannot be activated */ /* Used cache pool, COW or historical LV cannot be activated */
if ((!lv_is_cache_pool(lv) || dm_list_empty(&lv->segs_using_this_lv)) && if ((!lv_is_cache_pool(lv) || dm_list_empty(&lv->segs_using_this_lv)) &&
!lv_is_cow(lv) && !lv_is_historical(lv) && !lv_is_cow(lv) && !lv_is_historical(lv) &&
@ -6309,7 +6365,6 @@ static int _lv_update_and_reload(struct logical_volume *lv, int origin_only)
log_very_verbose("Updating logical volume %s on disk(s)%s.", log_very_verbose("Updating logical volume %s on disk(s)%s.",
display_lvname(lock_lv), origin_only ? " (origin only)": ""); display_lvname(lock_lv), origin_only ? " (origin only)": "");
if (!vg_write(vg)) if (!vg_write(vg))
return_0; return_0;
@ -6776,8 +6831,8 @@ struct logical_volume *insert_layer_for_lv(struct cmd_context *cmd,
return_NULL; return_NULL;
/* allocate a new linear segment */ /* allocate a new linear segment */
if (!(mapseg = alloc_lv_segment(segtype, lv_where, 0, layer_lv->le_count, if (!(mapseg = alloc_lv_segment(segtype, lv_where, 0, layer_lv->le_count, 0,
status, 0, NULL, 1, layer_lv->le_count, status, 0, NULL, 1, layer_lv->le_count, 0,
0, 0, 0, NULL))) 0, 0, 0, NULL)))
return_NULL; return_NULL;
@ -6833,8 +6888,8 @@ static int _extend_layer_lv_for_segment(struct logical_volume *layer_lv,
/* allocate a new segment */ /* allocate a new segment */
if (!(mapseg = alloc_lv_segment(segtype, layer_lv, layer_lv->le_count, if (!(mapseg = alloc_lv_segment(segtype, layer_lv, layer_lv->le_count,
seg->area_len, status, 0, seg->area_len, 0, status, 0,
NULL, 1, seg->area_len, 0, 0, 0, seg))) NULL, 1, seg->area_len, 0, 0, 0, 0, seg)))
return_0; return_0;
/* map the new segment to the original underlying are */ /* map the new segment to the original underlying are */
@ -7360,29 +7415,20 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
return NULL; return NULL;
} }
if (seg_is_cache(lp)) {
/* validate metadata size */
if (!validate_lv_cache_chunk_size(pool_lv, lp->chunk_size))
return_0;
first_seg(pool_lv)->chunk_size = lp->chunk_size;
}
/* Validate volume size to to aling on chunk for small extents */
/* Cache chunk size is always set */
size = first_seg(pool_lv)->chunk_size;
if (size > vg->extent_size) {
/* Align extents on chunk boundary size */
size = ((uint64_t)vg->extent_size * lp->extents + size - 1) /
size * size / vg->extent_size;
if (size != lp->extents) {
log_print_unless_silent("Rounding size (%d extents) up to chunk boundary "
"size (%d extents).", lp->extents, size);
lp->extents = size;
}
}
if (seg_is_thin_volume(lp)) { if (seg_is_thin_volume(lp)) {
/* Validate volume size to to aling on chunk for small extents */
size = first_seg(pool_lv)->chunk_size;
if (size > vg->extent_size) {
/* Align extents on chunk boundary size */
size = ((uint64_t)vg->extent_size * lp->extents + size - 1) /
size * size / vg->extent_size;
if (size != lp->extents) {
log_print_unless_silent("Rounding size (%d extents) up to chunk boundary "
"size (%d extents).", lp->extents, size);
lp->extents = size;
}
}
thin_pool_was_active = lv_is_active(pool_lv); thin_pool_was_active = lv_is_active(pool_lv);
if (lv_is_new_thin_pool(pool_lv)) { if (lv_is_new_thin_pool(pool_lv)) {
if (!check_new_thin_pool(pool_lv)) if (!check_new_thin_pool(pool_lv))
@ -7392,7 +7438,7 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
if (!activate_lv_excl_local(cmd, pool_lv)) { if (!activate_lv_excl_local(cmd, pool_lv)) {
log_error("Aborting. Failed to locally activate thin pool %s.", log_error("Aborting. Failed to locally activate thin pool %s.",
display_lvname(pool_lv)); display_lvname(pool_lv));
return 0; return NULL;
} }
if (!pool_below_threshold(first_seg(pool_lv))) { if (!pool_below_threshold(first_seg(pool_lv))) {
log_error("Cannot create new thin volume, free space in " log_error("Cannot create new thin volume, free space in "
@ -7630,10 +7676,11 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
if (lv_is_cache_pool(lv)) { if (lv_is_cache_pool(lv)) {
if (!cache_set_params(first_seg(lv), if (!cache_set_params(first_seg(lv),
lp->chunk_size,
lp->cache_metadata_format,
lp->cache_mode, lp->cache_mode,
lp->policy_name, lp->policy_name,
lp->policy_settings, lp->policy_settings)) {
lp->chunk_size)) {
stack; stack;
goto revert_new_lv; goto revert_new_lv;
} }
@ -7642,10 +7689,9 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
first_seg(lv)->max_recovery_rate = lp->max_recovery_rate; first_seg(lv)->max_recovery_rate = lp->max_recovery_rate;
} else if (lv_is_thin_pool(lv)) { } else if (lv_is_thin_pool(lv)) {
first_seg(lv)->chunk_size = lp->chunk_size; first_seg(lv)->chunk_size = lp->chunk_size;
first_seg(lv)->zero_new_blocks = lp->zero ? 1 : 0; first_seg(lv)->zero_new_blocks = lp->zero_new_blocks;
first_seg(lv)->discards = lp->discards; first_seg(lv)->discards = lp->discards;
if (!recalculate_pool_chunk_size_with_dev_hints(lv, lp->passed_args, if (!recalculate_pool_chunk_size_with_dev_hints(lv, lp->thin_chunk_size_calc_policy)) {
lp->thin_chunk_size_calc_policy)) {
stack; stack;
goto revert_new_lv; goto revert_new_lv;
} }
@ -7839,14 +7885,13 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
lv = tmp_lv; lv = tmp_lv;
if (!cache_set_params(first_seg(lv), if (!cache_set_params(first_seg(lv),
lp->chunk_size,
lp->cache_metadata_format,
lp->cache_mode, lp->cache_mode,
lp->policy_name, lp->policy_name,
lp->policy_settings, lp->policy_settings))
(lp->passed_args & PASS_ARG_CHUNK_SIZE) ? lp->chunk_size : 0))
return_NULL; /* revert? */ return_NULL; /* revert? */
cache_check_for_warns(first_seg(lv));
if (!lv_update_and_reload(lv)) { if (!lv_update_and_reload(lv)) {
/* FIXME Do a better revert */ /* FIXME Do a better revert */
log_error("Aborting. Manual intervention required."); log_error("Aborting. Manual intervention required.");

View File

@ -236,7 +236,7 @@ static void _check_raid_seg(struct lv_segment *seg, int *error_count)
if (!seg->areas) if (!seg->areas)
raid_seg_error("zero areas"); raid_seg_error("zero areas");
if (seg->extents_copied > seg->area_len) if (seg->extents_copied > seg->len)
raid_seg_error_val("extents_copied too large", seg->extents_copied); raid_seg_error_val("extents_copied too large", seg->extents_copied);
/* Default < 10, change once raid1 split shift and rename SubLVs works! */ /* Default < 10, change once raid1 split shift and rename SubLVs works! */
@ -328,6 +328,13 @@ static void _check_lv_segment(struct logical_volume *lv, struct lv_segment *seg,
if (seg_is_cache_pool(seg)) { if (seg_is_cache_pool(seg)) {
if (!dm_list_empty(&seg->lv->segs_using_this_lv)) { if (!dm_list_empty(&seg->lv->segs_using_this_lv)) {
switch (seg->cache_metadata_format) {
case CACHE_METADATA_FORMAT_2:
case CACHE_METADATA_FORMAT_1:
break;
default:
seg_error("has invalid cache metadata format");
}
switch (seg->cache_mode) { switch (seg->cache_mode) {
case CACHE_MODE_WRITETHROUGH: case CACHE_MODE_WRITETHROUGH:
case CACHE_MODE_WRITEBACK: case CACHE_MODE_WRITEBACK:
@ -339,13 +346,24 @@ static void _check_lv_segment(struct logical_volume *lv, struct lv_segment *seg,
if (!seg->policy_name) if (!seg->policy_name)
seg_error("is missing cache policy name"); seg_error("is missing cache policy name");
} }
if (!validate_cache_chunk_size(lv->vg->cmd, seg->chunk_size))
seg_error("has invalid chunk size.");
if (seg->lv->status & LV_METADATA_FORMAT) {
if (seg->cache_metadata_format != CACHE_METADATA_FORMAT_2)
seg_error("sets METADATA_FORMAT flag");
} else if (seg->cache_metadata_format == CACHE_METADATA_FORMAT_2)
seg_error("is missing METADATA_FORMAT flag");
} else { /* !cache_pool */ } else { /* !cache_pool */
if (seg->cache_metadata_format)
seg_error("sets cache metadata format");
if (seg->cache_mode) if (seg->cache_mode)
seg_error("sets cache mode"); seg_error("sets cache mode");
if (seg->policy_name) if (seg->policy_name)
seg_error("sets policy name"); seg_error("sets policy name");
if (seg->policy_settings) if (seg->policy_settings)
seg_error("sets policy settings"); seg_error("sets policy settings");
if (seg->lv->status & LV_METADATA_FORMAT)
seg_error("sets METADATA_FORMAT flag");
} }
if (!seg_can_error_when_full(seg) && lv_is_error_when_full(lv)) if (!seg_can_error_when_full(seg) && lv_is_error_when_full(lv))
@ -380,9 +398,6 @@ static void _check_lv_segment(struct logical_volume *lv, struct lv_segment *seg,
seg_error("is missing a pool metadata LV"); seg_error("is missing a pool metadata LV");
} else if (!(seg2 = first_seg(seg->metadata_lv)) || (find_pool_seg(seg2) != seg)) } else if (!(seg2 = first_seg(seg->metadata_lv)) || (find_pool_seg(seg2) != seg))
seg_error("metadata LV does not refer back to pool LV"); seg_error("metadata LV does not refer back to pool LV");
if (!validate_pool_chunk_size(lv->vg->cmd, seg->segtype, seg->chunk_size))
seg_error("has invalid chunk size.");
} else { /* !thin_pool && !cache_pool */ } else { /* !thin_pool && !cache_pool */
if (seg->metadata_lv) if (seg->metadata_lv)
seg_error("must not have pool metadata LV set"); seg_error("must not have pool metadata LV set");
@ -394,10 +409,17 @@ static void _check_lv_segment(struct logical_volume *lv, struct lv_segment *seg,
if (lv_is_thin_volume(lv)) if (lv_is_thin_volume(lv))
seg_error("is a thin volume that must not contain thin pool segment"); seg_error("is a thin volume that must not contain thin pool segment");
if (!validate_thin_pool_chunk_size(lv->vg->cmd, seg->chunk_size))
seg_error("has invalid chunk size.");
if (seg->zero_new_blocks != THIN_ZERO_YES &&
seg->zero_new_blocks != THIN_ZERO_NO)
seg_error("zero_new_blocks is invalid");
} else { /* !thin_pool */ } else { /* !thin_pool */
if (seg->zero_new_blocks) if (seg->zero_new_blocks != THIN_ZERO_UNSELECTED)
seg_error("sets zero_new_blocks"); seg_error("sets zero_new_blocks");
if (seg->discards) if (seg->discards != THIN_DISCARDS_UNSELECTED)
seg_error("sets discards"); seg_error("sets discards");
if (!dm_list_empty(&seg->thin_messages)) if (!dm_list_empty(&seg->thin_messages))
seg_error("sets thin_messages list"); seg_error("sets thin_messages list");
@ -475,7 +497,7 @@ int check_lv_segments(struct logical_volume *lv, int complete_vg)
struct lv_segment *seg, *seg2; struct lv_segment *seg, *seg2;
uint32_t le = 0; uint32_t le = 0;
unsigned seg_count = 0, seg_found, external_lv_found = 0; unsigned seg_count = 0, seg_found, external_lv_found = 0;
uint32_t area_multiplier, s; uint32_t data_rimage_count, s;
struct seg_list *sl; struct seg_list *sl;
struct glv_list *glvl; struct glv_list *glvl;
int error_count = 0; int error_count = 0;
@ -498,13 +520,13 @@ int check_lv_segments(struct logical_volume *lv, int complete_vg)
inc_error_count; inc_error_count;
} }
area_multiplier = segtype_is_striped(seg->segtype) ? data_rimage_count = seg->area_count - seg->segtype->parity_devs;
seg->area_count : 1; /* FIXME: raid varies seg->area_len? */
if (seg->len != seg->area_len &&
if (seg->area_len * area_multiplier != seg->len) { seg->len != seg->area_len * data_rimage_count) {
log_error("LV %s: segment %u has inconsistent " log_error("LV %s: segment %u with len=%u "
"area_len %u", " has inconsistent area_len %u",
lv->name, seg_count, seg->area_len); lv->name, seg_count, seg->len, seg->area_len);
inc_error_count; inc_error_count;
} }
@ -766,10 +788,10 @@ static int _lv_split_segment(struct logical_volume *lv, struct lv_segment *seg,
/* Clone the existing segment */ /* Clone the existing segment */
if (!(split_seg = alloc_lv_segment(seg->segtype, if (!(split_seg = alloc_lv_segment(seg->segtype,
seg->lv, seg->le, seg->len, seg->lv, seg->le, seg->len, seg->reshape_len,
seg->status, seg->stripe_size, seg->status, seg->stripe_size,
seg->log_lv, seg->log_lv,
seg->area_count, seg->area_len, seg->area_count, seg->area_len, seg->data_copies,
seg->chunk_size, seg->region_size, seg->chunk_size, seg->region_size,
seg->extents_copied, seg->pvmove_source_seg))) { seg->extents_copied, seg->pvmove_source_seg))) {
log_error("Couldn't allocate cloned LV segment."); log_error("Couldn't allocate cloned LV segment.");

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004-2016 Red Hat, Inc. All rights reserved. * Copyright (C) 2004-2017 Red Hat, Inc. All rights reserved.
* *
* This file is part of LVM2. * This file is part of LVM2.
* *
@ -137,7 +137,12 @@
e.g. to prohibit allocation of a RAID image e.g. to prohibit allocation of a RAID image
on a PV already holing an image of the RAID set */ on a PV already holing an image of the RAID set */
#define LOCKD_SANLOCK_LV UINT64_C(0x0080000000000000) /* LV - Internal use only */ #define LOCKD_SANLOCK_LV UINT64_C(0x0080000000000000) /* LV - Internal use only */
/* Next unused flag: UINT64_C(0x0100000000000000) */ #define LV_RESHAPE_DELTA_DISKS_PLUS UINT64_C(0x0100000000000000) /* LV reshape flag delta disks plus image(s) */
#define LV_RESHAPE_DELTA_DISKS_MINUS UINT64_C(0x0200000000000000) /* LV reshape flag delta disks minus image(s) */
#define LV_REMOVE_AFTER_RESHAPE UINT64_C(0x0400000000000000) /* LV needs to be removed after a shrinking reshape */
#define LV_METADATA_FORMAT UINT64_C(0x0800000000000000) /* LV has segments with metadata format */
/* Next unused flag: UINT64_C(0x1000000000000000) */
/* Format features flags */ /* Format features flags */
#define FMT_SEGMENTS 0x00000001U /* Arbitrary segment params? */ #define FMT_SEGMENTS 0x00000001U /* Arbitrary segment params? */
@ -271,18 +276,32 @@ enum {
}; };
typedef enum { typedef enum {
THIN_ZERO_UNSELECTED = 0,
THIN_ZERO_NO,
THIN_ZERO_YES,
} thin_zero_t;
typedef enum {
THIN_DISCARDS_UNSELECTED = 0,
THIN_DISCARDS_IGNORE, THIN_DISCARDS_IGNORE,
THIN_DISCARDS_NO_PASSDOWN, THIN_DISCARDS_NO_PASSDOWN,
THIN_DISCARDS_PASSDOWN, THIN_DISCARDS_PASSDOWN,
} thin_discards_t; } thin_discards_t;
typedef enum { typedef enum {
CACHE_MODE_UNDEFINED = 0, CACHE_MODE_UNSELECTED = 0,
CACHE_MODE_WRITETHROUGH, CACHE_MODE_WRITETHROUGH,
CACHE_MODE_WRITEBACK, CACHE_MODE_WRITEBACK,
CACHE_MODE_PASSTHROUGH, CACHE_MODE_PASSTHROUGH,
} cache_mode_t; } cache_mode_t;
/* ATM used for cache only */
typedef enum {
CACHE_METADATA_FORMAT_UNSELECTED = 0, /* On input means 'auto' */
CACHE_METADATA_FORMAT_1,
CACHE_METADATA_FORMAT_2,
} cache_metadata_format_t;
typedef enum { typedef enum {
LOCK_TYPE_INVALID = -1, LOCK_TYPE_INVALID = -1,
LOCK_TYPE_NONE = 0, LOCK_TYPE_NONE = 0,
@ -446,6 +465,7 @@ struct lv_segment {
const struct segment_type *segtype; const struct segment_type *segtype;
uint32_t le; uint32_t le;
uint32_t len; uint32_t len;
uint32_t reshape_len; /* For RAID: user hidden additional out of place reshaping length off area_len and len */
uint64_t status; uint64_t status;
@ -454,6 +474,7 @@ struct lv_segment {
uint32_t writebehind; /* For RAID (RAID1 only) */ uint32_t writebehind; /* For RAID (RAID1 only) */
uint32_t min_recovery_rate; /* For RAID */ uint32_t min_recovery_rate; /* For RAID */
uint32_t max_recovery_rate; /* For RAID */ uint32_t max_recovery_rate; /* For RAID */
uint32_t data_offset; /* For RAID: data offset in sectors on each data component image */
uint32_t area_count; uint32_t area_count;
uint32_t area_len; uint32_t area_len;
uint32_t chunk_size; /* For snapshots/thin_pool. In sectors. */ uint32_t chunk_size; /* For snapshots/thin_pool. In sectors. */
@ -464,6 +485,7 @@ struct lv_segment {
struct logical_volume *cow; struct logical_volume *cow;
struct dm_list origin_list; struct dm_list origin_list;
uint32_t region_size; /* For mirrors, replicators - in sectors */ uint32_t region_size; /* For mirrors, replicators - in sectors */
uint32_t data_copies; /* For RAID: number of data copies (e.g. 3 for RAID 6 */
uint32_t extents_copied;/* Number of extents synced for raids/mirrors */ uint32_t extents_copied;/* Number of extents synced for raids/mirrors */
struct logical_volume *log_lv; struct logical_volume *log_lv;
struct lv_segment *pvmove_source_seg; struct lv_segment *pvmove_source_seg;
@ -475,13 +497,14 @@ struct lv_segment {
struct lv_segment_area *meta_areas; /* For RAID */ struct lv_segment_area *meta_areas; /* For RAID */
struct logical_volume *metadata_lv; /* For thin_pool */ struct logical_volume *metadata_lv; /* For thin_pool */
uint64_t transaction_id; /* For thin_pool, thin */ uint64_t transaction_id; /* For thin_pool, thin */
unsigned zero_new_blocks; /* For thin_pool */ thin_zero_t zero_new_blocks; /* For thin_pool */
thin_discards_t discards; /* For thin_pool */ thin_discards_t discards; /* For thin_pool */
struct dm_list thin_messages; /* For thin_pool */ struct dm_list thin_messages; /* For thin_pool */
struct logical_volume *external_lv; /* For thin */ struct logical_volume *external_lv; /* For thin */
struct logical_volume *pool_lv; /* For thin, cache */ struct logical_volume *pool_lv; /* For thin, cache */
uint32_t device_id; /* For thin, 24bit */ uint32_t device_id; /* For thin, 24bit */
cache_metadata_format_t cache_metadata_format;/* For cache_pool */
cache_mode_t cache_mode; /* For cache_pool */ cache_mode_t cache_mode; /* For cache_pool */
const char *policy_name; /* For cache_pool */ const char *policy_name; /* For cache_pool */
struct dm_config_node *policy_settings; /* For cache_pool */ struct dm_config_node *policy_settings; /* For cache_pool */
@ -838,26 +861,22 @@ int pool_is_active(const struct logical_volume *pool_lv);
int pool_supports_external_origin(const struct lv_segment *pool_seg, const struct logical_volume *external_lv); int pool_supports_external_origin(const struct lv_segment *pool_seg, const struct logical_volume *external_lv);
int thin_pool_feature_supported(const struct logical_volume *pool_lv, int feature); int thin_pool_feature_supported(const struct logical_volume *pool_lv, int feature);
int recalculate_pool_chunk_size_with_dev_hints(struct logical_volume *pool_lv, int recalculate_pool_chunk_size_with_dev_hints(struct logical_volume *pool_lv,
int passed_args,
int chunk_size_calc_policy); int chunk_size_calc_policy);
int validate_cache_chunk_size(struct cmd_context *cmd, uint32_t chunk_size);
int validate_thin_pool_chunk_size(struct cmd_context *cmd, uint32_t chunk_size);
int validate_pool_chunk_size(struct cmd_context *cmd, const struct segment_type *segtype, uint32_t chunk_size); int validate_pool_chunk_size(struct cmd_context *cmd, const struct segment_type *segtype, uint32_t chunk_size);
int update_pool_lv(struct logical_volume *lv, int activate); int update_pool_lv(struct logical_volume *lv, int activate);
int update_pool_params(const struct segment_type *segtype, int get_default_allocation_thin_pool_chunk_size(struct cmd_context *cmd, struct profile *profile,
struct volume_group *vg, unsigned target_attr, uint32_t *chunk_size, int *chunk_size_calc_method);
int passed_args, uint32_t pool_data_extents, int update_thin_pool_params(struct cmd_context *cmd,
uint32_t *pool_metadata_extents, struct profile *profile,
int *chunk_size_calc_policy, uint32_t *chunk_size, uint32_t extent_size,
thin_discards_t *discards, int *zero); const struct segment_type *segtype,
int update_profilable_pool_params(struct cmd_context *cmd, struct profile *profile, unsigned attr,
int passed_args, int *chunk_size_calc_method, uint32_t pool_data_extents,
uint32_t *chunk_size, thin_discards_t *discards,
int *zero);
int update_thin_pool_params(const struct segment_type *segtype,
struct volume_group *vg, unsigned attr,
int passed_args, uint32_t pool_data_extents,
uint32_t *pool_metadata_extents, uint32_t *pool_metadata_extents,
int *chunk_size_calc_method, uint32_t *chunk_size, int *chunk_size_calc_method, uint32_t *chunk_size,
thin_discards_t *discards, int *zero); thin_discards_t *discards, thin_zero_t *zero_new_blocks);
const char *get_pool_discards_name(thin_discards_t discards); const char *get_pool_discards_name(thin_discards_t discards);
int set_pool_discards(thin_discards_t *discards, const char *str); int set_pool_discards(thin_discards_t *discards, const char *str);
struct logical_volume *alloc_pool_metadata(struct logical_volume *pool_lv, struct logical_volume *alloc_pool_metadata(struct logical_volume *pool_lv,
@ -909,8 +928,8 @@ struct lvcreate_params {
int wipe_signatures; /* all */ int wipe_signatures; /* all */
int32_t major; /* all */ int32_t major; /* all */
int32_t minor; /* all */ int32_t minor; /* all */
int log_count; /* mirror */ int log_count; /* mirror/RAID */
int nosync; /* mirror */ int nosync; /* mirror/RAID */
int pool_metadata_spare; /* pools */ int pool_metadata_spare; /* pools */
int type; /* type arg is given */ int type; /* type arg is given */
int temporary; /* temporary LV */ int temporary; /* temporary LV */
@ -920,6 +939,7 @@ struct lvcreate_params {
int activation_skip; /* activation skip flags */ int activation_skip; /* activation skip flags */
activation_change_t activate; /* non-snapshot, non-mirror */ activation_change_t activate; /* non-snapshot, non-mirror */
thin_discards_t discards; /* thin */ thin_discards_t discards; /* thin */
thin_zero_t zero_new_blocks;
#define THIN_CHUNK_SIZE_CALC_METHOD_GENERIC 0x01 #define THIN_CHUNK_SIZE_CALC_METHOD_GENERIC 0x01
#define THIN_CHUNK_SIZE_CALC_METHOD_PERFORMANCE 0x02 #define THIN_CHUNK_SIZE_CALC_METHOD_PERFORMANCE 0x02
int thin_chunk_size_calc_policy; int thin_chunk_size_calc_policy;
@ -933,27 +953,20 @@ struct lvcreate_params {
const char *lock_args; const char *lock_args;
/* Keep args given by the user on command line */ uint32_t stripes; /* striped/RAID */
/* FIXME: create some more universal solution here */ uint32_t stripe_size; /* striped/RAID */
#define PASS_ARG_CHUNK_SIZE 0x01
#define PASS_ARG_DISCARDS 0x02
#define PASS_ARG_POOL_METADATA_SIZE 0x04
#define PASS_ARG_ZERO 0x08
int passed_args;
uint32_t stripes; /* striped */
uint32_t stripe_size; /* striped */
uint32_t chunk_size; /* snapshot */ uint32_t chunk_size; /* snapshot */
uint32_t region_size; /* mirror */ uint32_t region_size; /* mirror/RAID */
unsigned stripes_supplied; /* striped */ unsigned stripes_supplied; /* striped/RAID */
unsigned stripe_size_supplied; /* striped */ unsigned stripe_size_supplied; /* striped/RAID */
uint32_t mirrors; /* mirror */ uint32_t mirrors; /* mirror/RAID */
uint32_t min_recovery_rate; /* RAID */ uint32_t min_recovery_rate; /* RAID */
uint32_t max_recovery_rate; /* RAID */ uint32_t max_recovery_rate; /* RAID */
cache_metadata_format_t cache_metadata_format; /* cache */
cache_mode_t cache_mode; /* cache */ cache_mode_t cache_mode; /* cache */
const char *policy_name; /* cache */ const char *policy_name; /* cache */
struct dm_config_tree *policy_settings; /* cache */ struct dm_config_tree *policy_settings; /* cache */
@ -1205,10 +1218,14 @@ struct logical_volume *first_replicator_dev(const struct logical_volume *lv);
int lv_is_raid_with_tracking(const struct logical_volume *lv); int lv_is_raid_with_tracking(const struct logical_volume *lv);
uint32_t lv_raid_image_count(const struct logical_volume *lv); uint32_t lv_raid_image_count(const struct logical_volume *lv);
int lv_raid_change_image_count(struct logical_volume *lv, int lv_raid_change_image_count(struct logical_volume *lv,
uint32_t new_count, struct dm_list *allocate_pvs); int yes,
int lv_raid_split(struct logical_volume *lv, const char *split_name, uint32_t new_count,
uint32_t new_region_size,
struct dm_list *allocate_pvs);
int lv_raid_split(struct logical_volume *lv, int yes, const char *split_name,
uint32_t new_count, struct dm_list *splittable_pvs); uint32_t new_count, struct dm_list *splittable_pvs);
int lv_raid_split_and_track(struct logical_volume *lv, int lv_raid_split_and_track(struct logical_volume *lv,
int yes,
struct dm_list *splittable_pvs); struct dm_list *splittable_pvs);
int lv_raid_merge(struct logical_volume *lv); int lv_raid_merge(struct logical_volume *lv);
int lv_raid_convert(struct logical_volume *lv, int lv_raid_convert(struct logical_volume *lv,
@ -1233,6 +1250,8 @@ uint32_t raid_ensure_min_region_size(const struct logical_volume *lv, uint64_t r
int lv_raid_change_region_size(struct logical_volume *lv, int lv_raid_change_region_size(struct logical_volume *lv,
int yes, int force, uint32_t new_region_size); int yes, int force, uint32_t new_region_size);
int lv_raid_in_sync(const struct logical_volume *lv); int lv_raid_in_sync(const struct logical_volume *lv);
uint32_t lv_raid_data_copies(const struct segment_type *segtype, uint32_t area_count);
int lv_raid_free_reshape_space(const struct logical_volume *lv);
/* -- metadata/raid_manip.c */ /* -- metadata/raid_manip.c */
/* ++ metadata/cache_manip.c */ /* ++ metadata/cache_manip.c */
@ -1248,17 +1267,22 @@ const char *display_cache_mode(const struct lv_segment *seg);
const char *get_cache_mode_name(const struct lv_segment *cache_seg); const char *get_cache_mode_name(const struct lv_segment *cache_seg);
int set_cache_mode(cache_mode_t *mode, const char *cache_mode); int set_cache_mode(cache_mode_t *mode, const char *cache_mode);
int cache_set_cache_mode(struct lv_segment *cache_seg, cache_mode_t mode); int cache_set_cache_mode(struct lv_segment *cache_seg, cache_mode_t mode);
int cache_set_metadata_format(struct lv_segment *cache_seg, cache_metadata_format_t format);
int cache_set_policy(struct lv_segment *cache_seg, const char *name, int cache_set_policy(struct lv_segment *cache_seg, const char *name,
const struct dm_config_tree *settings); const struct dm_config_tree *settings);
int cache_set_params(struct lv_segment *seg, int cache_set_params(struct lv_segment *seg,
uint32_t chunk_size,
cache_metadata_format_t format,
cache_mode_t mode, cache_mode_t mode,
const char *policy_name, const char *policy_name,
const struct dm_config_tree *policy_settings, const struct dm_config_tree *policy_settings);
uint32_t chunk_size);
void cache_check_for_warns(const struct lv_segment *seg); void cache_check_for_warns(const struct lv_segment *seg);
int update_cache_pool_params(const struct segment_type *segtype, int update_cache_pool_params(struct cmd_context *cmd,
struct volume_group *vg, unsigned attr, struct profile *profile,
int passed_args, uint32_t pool_data_extents, uint32_t extent_size,
const struct segment_type *segtype,
unsigned attr,
uint32_t pool_data_extents,
uint32_t *pool_metadata_extents, uint32_t *pool_metadata_extents,
int *chunk_size_calc_method, uint32_t *chunk_size); int *chunk_size_calc_method, uint32_t *chunk_size);
int validate_lv_cache_chunk_size(struct logical_volume *pool_lv, uint32_t chunk_size); int validate_lv_cache_chunk_size(struct logical_volume *pool_lv, uint32_t chunk_size);

View File

@ -394,44 +394,13 @@ int validate_pool_chunk_size(struct cmd_context *cmd,
const struct segment_type *segtype, const struct segment_type *segtype,
uint32_t chunk_size) uint32_t chunk_size)
{ {
uint32_t min_size, max_size; if (segtype_is_cache(segtype) || segtype_is_cache_pool(segtype))
const char *name; return validate_cache_chunk_size(cmd, chunk_size);
int r = 1;
if (segtype_is_cache(segtype) || segtype_is_cache_pool(segtype)) { return validate_thin_pool_chunk_size(cmd, chunk_size);
min_size = DM_CACHE_MIN_DATA_BLOCK_SIZE;
max_size = DM_CACHE_MAX_DATA_BLOCK_SIZE;
name = "Cache";
} else if (segtype_is_thin(segtype)) {
min_size = DM_THIN_MIN_DATA_BLOCK_SIZE;
max_size = DM_THIN_MAX_DATA_BLOCK_SIZE;
name = "Thin";
} else {
log_error(INTERNAL_ERROR "Cannot validate chunk size of "
"%s segtype.", segtype->name);
return 0;
}
if ((chunk_size < min_size) || (chunk_size > max_size)) {
log_error("%s pool chunk size %s is not in the range %s to %s.",
name, display_size(cmd, chunk_size),
display_size(cmd, min_size),
display_size(cmd, max_size));
r = 0;
}
if (chunk_size & (min_size - 1)) {
log_error("%s pool chunk size %s must be a multiple of %s.",
name, display_size(cmd, chunk_size),
display_size(cmd, min_size));
r = 0;
}
return r;
} }
int recalculate_pool_chunk_size_with_dev_hints(struct logical_volume *pool_lv, int recalculate_pool_chunk_size_with_dev_hints(struct logical_volume *pool_lv,
int passed_args,
int chunk_size_calc_policy) int chunk_size_calc_policy)
{ {
struct logical_volume *pool_data_lv; struct logical_volume *pool_data_lv;
@ -439,24 +408,17 @@ int recalculate_pool_chunk_size_with_dev_hints(struct logical_volume *pool_lv,
struct physical_volume *pv; struct physical_volume *pv;
struct cmd_context *cmd = pool_lv->vg->cmd; struct cmd_context *cmd = pool_lv->vg->cmd;
unsigned long previous_hint = 0, hint = 0; unsigned long previous_hint = 0, hint = 0;
uint32_t default_chunk_size;
uint32_t min_chunk_size, max_chunk_size; uint32_t min_chunk_size, max_chunk_size;
if (passed_args & PASS_ARG_CHUNK_SIZE) if (!chunk_size_calc_policy)
return 1; return 1; /* Chunk size was specified by user */
if (lv_is_thin_pool(pool_lv)) { if (lv_is_thin_pool(pool_lv)) {
if (find_config_tree_int(cmd, allocation_thin_pool_chunk_size_CFG, NULL))
return 1;
min_chunk_size = DM_THIN_MIN_DATA_BLOCK_SIZE; min_chunk_size = DM_THIN_MIN_DATA_BLOCK_SIZE;
max_chunk_size = DM_THIN_MAX_DATA_BLOCK_SIZE; max_chunk_size = DM_THIN_MAX_DATA_BLOCK_SIZE;
default_chunk_size = get_default_allocation_thin_pool_chunk_size_CFG(cmd, NULL);
} else if (lv_is_cache_pool(pool_lv)) { } else if (lv_is_cache_pool(pool_lv)) {
if (find_config_tree_int(cmd, allocation_cache_pool_chunk_size_CFG, NULL))
return 1;
min_chunk_size = DM_CACHE_MIN_DATA_BLOCK_SIZE; min_chunk_size = DM_CACHE_MIN_DATA_BLOCK_SIZE;
max_chunk_size = DM_CACHE_MAX_DATA_BLOCK_SIZE; max_chunk_size = DM_CACHE_MAX_DATA_BLOCK_SIZE;
default_chunk_size = get_default_allocation_cache_pool_chunk_size_CFG(cmd, NULL);
} else { } else {
log_error(INTERNAL_ERROR "%s is not a pool logical volume.", display_lvname(pool_lv)); log_error(INTERNAL_ERROR "%s is not a pool logical volume.", display_lvname(pool_lv));
return 0; return 0;
@ -494,40 +456,14 @@ int recalculate_pool_chunk_size_with_dev_hints(struct logical_volume *pool_lv,
display_size(cmd, hint), display_lvname(pool_lv), display_size(cmd, hint), display_lvname(pool_lv),
display_size(cmd, min_chunk_size), display_size(cmd, min_chunk_size),
display_size(cmd, max_chunk_size)); display_size(cmd, max_chunk_size));
else else if (hint > first_seg(pool_lv)->chunk_size) {
first_seg(pool_lv)->chunk_size = log_debug_alloc("Updating chunk size %s for pool %s to %s.",
(hint >= default_chunk_size) ? hint : default_chunk_size; display_size(cmd, first_seg(pool_lv)->chunk_size),
display_lvname(pool_lv),
return 1; display_size(cmd, hint));
} first_seg(pool_lv)->chunk_size = hint;
int update_pool_params(const struct segment_type *segtype,
struct volume_group *vg, unsigned target_attr,
int passed_args, uint32_t pool_data_extents,
uint32_t *pool_metadata_extents,
int *chunk_size_calc_policy, uint32_t *chunk_size,
thin_discards_t *discards, int *zero)
{
if (segtype_is_cache_pool(segtype) || segtype_is_cache(segtype)) {
if (!update_cache_pool_params(segtype, vg, target_attr, passed_args,
pool_data_extents, pool_metadata_extents,
chunk_size_calc_policy, chunk_size))
return_0;
} else if (!update_thin_pool_params(segtype, vg, target_attr, passed_args,
pool_data_extents, pool_metadata_extents,
chunk_size_calc_policy, chunk_size,
discards, zero)) /* thin-pool */
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 than chunk size %s.",
segtype->name, display_size(vg->cmd, *chunk_size));
return 0;
} }
log_verbose("Preferred pool metadata size %s.",
display_size(vg->cmd, (uint64_t)*pool_metadata_extents * vg->extent_size));
return 1; return 1;
} }

File diff suppressed because it is too large Load Diff

View File

@ -43,7 +43,8 @@ struct segment_type *get_segtype_from_flag(struct cmd_context *cmd, uint64_t fla
{ {
struct segment_type *segtype; struct segment_type *segtype;
dm_list_iterate_items(segtype, &cmd->segtypes) /* Iterate backwards to provide aliases; e.g. raid5 instead of raid5_ls */
dm_list_iterate_back_items(segtype, &cmd->segtypes)
if (flag & segtype->flags) if (flag & segtype->flags)
return segtype; return segtype;

View File

@ -28,50 +28,50 @@ struct dm_config_node;
struct dev_manager; struct dev_manager;
/* Feature flags */ /* Feature flags */
#define SEG_CAN_SPLIT 0x0000000000000001ULL #define SEG_CAN_SPLIT (1ULL << 0)
#define SEG_AREAS_STRIPED 0x0000000000000002ULL #define SEG_AREAS_STRIPED (1ULL << 1)
#define SEG_AREAS_MIRRORED 0x0000000000000004ULL #define SEG_AREAS_MIRRORED (1ULL << 2)
#define SEG_SNAPSHOT 0x0000000000000008ULL #define SEG_SNAPSHOT (1ULL << 3)
#define SEG_FORMAT1_SUPPORT 0x0000000000000010ULL #define SEG_FORMAT1_SUPPORT (1ULL << 4)
#define SEG_VIRTUAL 0x0000000000000020ULL #define SEG_VIRTUAL (1ULL << 5)
#define SEG_CANNOT_BE_ZEROED 0x0000000000000040ULL #define SEG_CANNOT_BE_ZEROED (1ULL << 6)
#define SEG_MONITORED 0x0000000000000080ULL #define SEG_MONITORED (1ULL << 7)
#define SEG_REPLICATOR 0x0000000000000100ULL #define SEG_REPLICATOR (1ULL << 8)
#define SEG_REPLICATOR_DEV 0x0000000000000200ULL #define SEG_REPLICATOR_DEV (1ULL << 9)
#define SEG_RAID 0x0000000000000400ULL #define SEG_RAID (1ULL << 10)
#define SEG_THIN_POOL 0x0000000000000800ULL #define SEG_THIN_POOL (1ULL << 11)
#define SEG_THIN_VOLUME 0x0000000000001000ULL #define SEG_THIN_VOLUME (1ULL << 12)
#define SEG_CACHE 0x0000000000002000ULL #define SEG_CACHE (1ULL << 13)
#define SEG_CACHE_POOL 0x0000000000004000ULL #define SEG_CACHE_POOL (1ULL << 14)
#define SEG_MIRROR 0x0000000000008000ULL #define SEG_MIRROR (1ULL << 15)
#define SEG_ONLY_EXCLUSIVE 0x0000000000010000ULL /* In cluster only exlusive activation */ #define SEG_ONLY_EXCLUSIVE (1ULL << 16) /* In cluster only exlusive activation */
#define SEG_CAN_ERROR_WHEN_FULL 0x0000000000020000ULL #define SEG_CAN_ERROR_WHEN_FULL (1ULL << 17)
#define SEG_RAID0 0x0000000000040000ULL #define SEG_RAID0 (1ULL << 18)
#define SEG_RAID0_META 0x0000000000080000ULL #define SEG_RAID0_META (1ULL << 19)
#define SEG_RAID1 0x0000000000100000ULL #define SEG_RAID1 (1ULL << 20)
#define SEG_RAID10_NEAR 0x0000000000200000ULL #define SEG_RAID10_NEAR (1ULL << 21)
#define SEG_RAID10 SEG_RAID10_NEAR #define SEG_RAID10 SEG_RAID10_NEAR
#define SEG_RAID4 0x0000000000400000ULL #define SEG_RAID4 (1ULL << 22)
#define SEG_RAID5_N 0x0000000000800000ULL #define SEG_RAID5_N (1ULL << 23)
#define SEG_RAID5_LA 0x0000000001000000ULL #define SEG_RAID5_LA (1ULL << 24)
#define SEG_RAID5_LS 0x0000000002000000ULL #define SEG_RAID5_LS (1ULL << 25)
#define SEG_RAID5_RA 0x0000000004000000ULL #define SEG_RAID5_RA (1ULL << 26)
#define SEG_RAID5_RS 0x0000000008000000ULL #define SEG_RAID5_RS (1ULL << 27)
#define SEG_RAID5 SEG_RAID5_LS #define SEG_RAID5 SEG_RAID5_LS
#define SEG_RAID6_NC 0x0000000010000000ULL #define SEG_RAID6_NC (1ULL << 28)
#define SEG_RAID6_NR 0x0000000020000000ULL #define SEG_RAID6_NR (1ULL << 29)
#define SEG_RAID6_ZR 0x0000000040000000ULL #define SEG_RAID6_ZR (1ULL << 30)
#define SEG_RAID6_LA_6 0x0000000080000000ULL #define SEG_RAID6_LA_6 (1ULL << 31)
#define SEG_RAID6_LS_6 0x0000000100000000ULL #define SEG_RAID6_LS_6 (1ULL << 32)
#define SEG_RAID6_RA_6 0x0000000200000000ULL #define SEG_RAID6_RA_6 (1ULL << 33)
#define SEG_RAID6_RS_6 0x0000000400000000ULL #define SEG_RAID6_RS_6 (1ULL << 34)
#define SEG_RAID6_N_6 0x0000000800000000ULL #define SEG_RAID6_N_6 (1ULL << 35)
#define SEG_RAID6 SEG_RAID6_ZR #define SEG_RAID6 SEG_RAID6_ZR
#define SEG_STRIPED_TARGET 0x0000008000000000ULL #define SEG_STRIPED_TARGET (1ULL << 39)
#define SEG_UNKNOWN 0x8000000000000000ULL #define SEG_UNKNOWN (1ULL << 63)
#define SEG_TYPE_NAME_LINEAR "linear" #define SEG_TYPE_NAME_LINEAR "linear"
#define SEG_TYPE_NAME_STRIPED "striped" #define SEG_TYPE_NAME_STRIPED "striped"
@ -140,7 +140,11 @@ struct dev_manager;
#define segtype_is_any_raid10(segtype) ((segtype)->flags & SEG_RAID10 ? 1 : 0) #define segtype_is_any_raid10(segtype) ((segtype)->flags & SEG_RAID10 ? 1 : 0)
#define segtype_is_raid10(segtype) ((segtype)->flags & SEG_RAID10 ? 1 : 0) #define segtype_is_raid10(segtype) ((segtype)->flags & SEG_RAID10 ? 1 : 0)
#define segtype_is_raid10_near(segtype) segtype_is_raid10(segtype) #define segtype_is_raid10_near(segtype) segtype_is_raid10(segtype)
/* FIXME: once raid10_offset supported */
#define segtype_is_raid10_offset(segtype) 0 /* FIXME ((segtype)->flags & SEG_RAID10_OFFSET ? 1 : 0 */
#define segtype_is_raid_with_meta(segtype) (segtype_is_raid(segtype) && !segtype_is_raid0(segtype)) #define segtype_is_raid_with_meta(segtype) (segtype_is_raid(segtype) && !segtype_is_raid0(segtype))
#define segtype_is_striped_raid(segtype) (segtype_is_raid(segtype) && !segtype_is_raid1(segtype))
#define segtype_is_reshapable_raid(segtype) ((segtype_is_striped_raid(segtype) && !segtype_is_any_raid0(segtype)) || segtype_is_raid10_near(segtype) || segtype_is_raid10_offset(segtype))
#define segtype_is_snapshot(segtype) ((segtype)->flags & SEG_SNAPSHOT ? 1 : 0) #define segtype_is_snapshot(segtype) ((segtype)->flags & SEG_SNAPSHOT ? 1 : 0)
#define segtype_is_striped(segtype) ((segtype)->flags & SEG_AREAS_STRIPED ? 1 : 0) #define segtype_is_striped(segtype) ((segtype)->flags & SEG_AREAS_STRIPED ? 1 : 0)
#define segtype_is_thin(segtype) ((segtype)->flags & (SEG_THIN_POOL|SEG_THIN_VOLUME) ? 1 : 0) #define segtype_is_thin(segtype) ((segtype)->flags & (SEG_THIN_POOL|SEG_THIN_VOLUME) ? 1 : 0)
@ -190,6 +194,8 @@ struct dev_manager;
#define seg_is_raid10(seg) segtype_is_raid10((seg)->segtype) #define seg_is_raid10(seg) segtype_is_raid10((seg)->segtype)
#define seg_is_raid10_near(seg) segtype_is_raid10_near((seg)->segtype) #define seg_is_raid10_near(seg) segtype_is_raid10_near((seg)->segtype)
#define seg_is_raid_with_meta(seg) segtype_is_raid_with_meta((seg)->segtype) #define seg_is_raid_with_meta(seg) segtype_is_raid_with_meta((seg)->segtype)
#define seg_is_striped_raid(seg) segtype_is_striped_raid((seg)->segtype)
#define seg_is_reshapable_raid(seg) segtype_is_reshapable_raid((seg)->segtype)
#define seg_is_replicator(seg) ((seg)->segtype->flags & SEG_REPLICATOR ? 1 : 0) #define seg_is_replicator(seg) ((seg)->segtype->flags & SEG_REPLICATOR ? 1 : 0)
#define seg_is_replicator_dev(seg) ((seg)->segtype->flags & SEG_REPLICATOR_DEV ? 1 : 0) #define seg_is_replicator_dev(seg) ((seg)->segtype->flags & SEG_REPLICATOR_DEV ? 1 : 0)
#define seg_is_snapshot(seg) segtype_is_snapshot((seg)->segtype) #define seg_is_snapshot(seg) segtype_is_snapshot((seg)->segtype)
@ -280,6 +286,8 @@ struct segment_type *init_unknown_segtype(struct cmd_context *cmd,
#define RAID_FEATURE_RAID0 (1U << 1) /* version 1.7 */ #define RAID_FEATURE_RAID0 (1U << 1) /* version 1.7 */
#define RAID_FEATURE_RESHAPING (1U << 2) /* version 1.8 */ #define RAID_FEATURE_RESHAPING (1U << 2) /* version 1.8 */
#define RAID_FEATURE_RAID4 (1U << 3) /* ! version 1.8 or 1.9.0 */ #define RAID_FEATURE_RAID4 (1U << 3) /* ! version 1.8 or 1.9.0 */
#define RAID_FEATURE_SHRINK (1U << 4) /* version 1.9.0 */
#define RAID_FEATURE_RESHAPE (1U << 5) /* version 1.10.1 */
#ifdef RAID_INTERNAL #ifdef RAID_INTERNAL
int init_raid_segtypes(struct cmd_context *cmd, struct segtype_library *seglib); int init_raid_segtypes(struct cmd_context *cmd, struct segtype_library *seglib);
@ -308,6 +316,7 @@ int init_cache_segtypes(struct cmd_context *cmd, struct segtype_library *seglib)
#define CACHE_FEATURE_POLICY_MQ (1U << 0) #define CACHE_FEATURE_POLICY_MQ (1U << 0)
#define CACHE_FEATURE_POLICY_SMQ (1U << 1) #define CACHE_FEATURE_POLICY_SMQ (1U << 1)
#define CACHE_FEATURE_METADATA2 (1U << 2)
#define SNAPSHOT_FEATURE_FIXED_LEAK (1U << 0) /* version 1.12 */ #define SNAPSHOT_FEATURE_FIXED_LEAK (1U << 0) /* version 1.12 */

View File

@ -238,8 +238,8 @@ static struct lv_segment *_alloc_snapshot_seg(struct logical_volume *lv)
return NULL; return NULL;
} }
if (!(seg = alloc_lv_segment(segtype, lv, 0, lv->le_count, 0, 0, if (!(seg = alloc_lv_segment(segtype, lv, 0, lv->le_count, 0, 0, 0,
NULL, 0, lv->le_count, 0, 0, 0, NULL))) { NULL, 0, lv->le_count, 0, 0, 0, 0, NULL))) {
log_error("Couldn't allocate new snapshot segment."); log_error("Couldn't allocate new snapshot segment.");
return NULL; return NULL;
} }

View File

@ -58,13 +58,13 @@
#define r1__r0m _takeover_from_raid1_to_raid0_meta #define r1__r0m _takeover_from_raid1_to_raid0_meta
#define r1__r1 _takeover_from_raid1_to_raid1 #define r1__r1 _takeover_from_raid1_to_raid1
#define r1__r10 _takeover_from_raid1_to_raid10 #define r1__r10 _takeover_from_raid1_to_raid10
#define r1__r45 _takeover_from_raid1_to_raid45 #define r1__r5 _takeover_from_raid1_to_raid5
#define r1__str _takeover_from_raid1_to_striped #define r1__str _takeover_from_raid1_to_striped
#define r45_lin _takeover_from_raid45_to_linear #define r45_lin _takeover_from_raid45_to_linear
#define r45_mir _takeover_from_raid45_to_mirrored #define r45_mir _takeover_from_raid45_to_mirrored
#define r45_r0 _takeover_from_raid45_to_raid0 #define r45_r0 _takeover_from_raid45_to_raid0
#define r45_r0m _takeover_from_raid45_to_raid0_meta #define r45_r0m _takeover_from_raid45_to_raid0_meta
#define r45_r1 _takeover_from_raid45_to_raid1 #define r5_r1 _takeover_from_raid5_to_raid1
#define r45_r54 _takeover_from_raid45_to_raid54 #define r45_r54 _takeover_from_raid45_to_raid54
#define r45_r6 _takeover_from_raid45_to_raid6 #define r45_r6 _takeover_from_raid45_to_raid6
#define r45_str _takeover_from_raid45_to_striped #define r45_str _takeover_from_raid45_to_striped
@ -109,8 +109,8 @@ static takeover_fn_t _takeover_fns[][11] = {
/* mirror */ { X , X , N , mir_r0, mir_r0m, mir_r1, mir_r45, X , mir_r10, X , X }, /* mirror */ { X , X , N , mir_r0, mir_r0m, mir_r1, mir_r45, X , mir_r10, X , X },
/* raid0 */ { r0__lin, r0__str, r0__mir, N , r0__r0m, r0__r1, r0__r45, r0__r6, r0__r10, X , X }, /* raid0 */ { r0__lin, r0__str, r0__mir, N , r0__r0m, r0__r1, r0__r45, r0__r6, r0__r10, X , X },
/* raid0_meta */ { r0m_lin, r0m_str, r0m_mir, r0m_r0, N , r0m_r1, r0m_r45, r0m_r6, r0m_r10, X , X }, /* raid0_meta */ { r0m_lin, r0m_str, r0m_mir, r0m_r0, N , r0m_r1, r0m_r45, r0m_r6, r0m_r10, X , X },
/* raid1 */ { r1__lin, r1__str, r1__mir, r1__r0, r1__r0m, r1__r1, r1__r45, X , r1__r10, X , X }, /* raid1 */ { r1__lin, r1__str, r1__mir, r1__r0, r1__r0m, r1__r1, r1__r5, X , r1__r10, X , X },
/* raid4/5 */ { r45_lin, r45_str, r45_mir, r45_r0, r45_r0m, r45_r1, r45_r54, r45_r6, X , X , X }, /* raid4/5 */ { r45_lin, r45_str, r45_mir, r45_r0, r45_r0m, r5_r1 , r45_r54, r45_r6, X , X , X },
/* raid6 */ { X , r6__str, X , r6__r0, r6__r0m, X , r6__r45, X , X , X , X }, /* raid6 */ { X , r6__str, X , r6__r0, r6__r0m, X , r6__r45, X , X , X , X },
/* raid10 */ { r10_lin, r10_str, r10_mir, r10_r0, r10_r0m, r10_r1, X , X , X , X , X }, /* raid10 */ { r10_lin, r10_str, r10_mir, r10_r0, r10_r0m, r10_r1, X , X , X , X , X },
/* raid01 */ // { X , r01_str, X , X , X , X , X , X , r01_r10, r01_r01, X }, /* raid01 */ // { X , r01_str, X , X , X , X , X , X , r01_r10, r01_r01, X },

View File

@ -100,9 +100,10 @@ int attach_thin_external_origin(struct lv_segment *seg,
external_lv->status &= ~LVM_WRITE; external_lv->status &= ~LVM_WRITE;
} }
// TODO: should we mark even origin read-only ? /* FIXME Mark origin read-only?
//if (lv_is_cache(external_lv)) /* read-only corigin of cache LV */ if (lv_is_cache(external_lv)) // read-only corigin of cache LV
// seg_lv(first_seg(external_lv), 0)->status &= ~LVM_WRITE; seg_lv(first_seg(external_lv), 0)->status &= ~LVM_WRITE;
*/
} }
return 1; return 1;
@ -547,19 +548,31 @@ int update_pool_lv(struct logical_volume *lv, int activate)
return ret; return ret;
} }
/* Estimate thin pool chunk size from data and metadata size (in sector units) */ static uint64_t _estimate_size(uint32_t data_extents, uint32_t extent_size, uint64_t size)
static size_t _estimate_chunk_size(uint64_t data_size, uint64_t metadata_size, int attr)
{ {
/* /*
* nr_pool_blocks = data_size / metadata_size * nr_pool_blocks = data_size / metadata_size
* chunk_size = nr_pool_blocks * 64b / sector_size * chunk_size = nr_pool_blocks * 64b / sector_size
*/ */
size_t chunk_size = data_size / (metadata_size * (SECTOR_SIZE / 64)); return (uint64_t) data_extents * extent_size / (size * (SECTOR_SIZE / UINT64_C(64)));
}
/* Estimate thin pool metadata size from data size and chunks size (in sector units) */
static uint64_t _estimate_metadata_size(uint32_t data_extents, uint32_t extent_size, uint32_t chunk_size)
{
return _estimate_size(data_extents, extent_size, chunk_size);
}
/* Estimate thin pool chunk size from data and metadata size (in sector units) */
static uint32_t _estimate_chunk_size(uint32_t data_extents, uint32_t extent_size,
uint64_t metadata_size, int attr)
{
uint32_t chunk_size = _estimate_size(data_extents, extent_size, metadata_size);
if (attr & THIN_FEATURE_BLOCK_SIZE) { if (attr & THIN_FEATURE_BLOCK_SIZE) {
/* Round up to 64KB */ /* Round up to 64KB */
chunk_size += DM_THIN_MIN_DATA_BLOCK_SIZE - 1; chunk_size += DM_THIN_MIN_DATA_BLOCK_SIZE - 1;
chunk_size &= ~(size_t)(DM_THIN_MIN_DATA_BLOCK_SIZE - 1); chunk_size &= ~(uint32_t)(DM_THIN_MIN_DATA_BLOCK_SIZE - 1);
} else { } else {
/* Round up to nearest power of 2 */ /* Round up to nearest power of 2 */
chunk_size--; chunk_size--;
@ -571,47 +584,64 @@ static size_t _estimate_chunk_size(uint64_t data_size, uint64_t metadata_size, i
chunk_size++; chunk_size++;
} }
if (chunk_size < DM_THIN_MIN_DATA_BLOCK_SIZE)
chunk_size = DM_THIN_MIN_DATA_BLOCK_SIZE;
else if (chunk_size > DM_THIN_MAX_DATA_BLOCK_SIZE)
chunk_size = DM_THIN_MAX_DATA_BLOCK_SIZE;
return chunk_size; return chunk_size;
} }
int update_thin_pool_params(const struct segment_type *segtype, int get_default_allocation_thin_pool_chunk_size(struct cmd_context *cmd, struct profile *profile,
struct volume_group *vg, uint32_t *chunk_size, int *chunk_size_calc_method)
unsigned attr, int passed_args, {
const char *str;
if (!(str = find_config_tree_str(cmd, allocation_thin_pool_chunk_size_policy_CFG, profile))) {
log_error(INTERNAL_ERROR "Cannot find configuration.");
return 0;
}
if (!strcasecmp(str, "generic")) {
*chunk_size = DEFAULT_THIN_POOL_CHUNK_SIZE * 2;
*chunk_size_calc_method = THIN_CHUNK_SIZE_CALC_METHOD_GENERIC;
} else if (!strcasecmp(str, "performance")) {
*chunk_size = DEFAULT_THIN_POOL_CHUNK_SIZE_PERFORMANCE * 2;
*chunk_size_calc_method = THIN_CHUNK_SIZE_CALC_METHOD_PERFORMANCE;
} else {
log_error("Thin pool chunk size calculation policy \"%s\" is unrecognised.", str);
return 0;
}
return 1;
}
int update_thin_pool_params(struct cmd_context *cmd,
struct profile *profile,
uint32_t extent_size,
const struct segment_type *segtype,
unsigned attr,
uint32_t pool_data_extents, uint32_t pool_data_extents,
uint32_t *pool_metadata_extents, uint32_t *pool_metadata_extents,
int *chunk_size_calc_method, uint32_t *chunk_size, int *chunk_size_calc_method, uint32_t *chunk_size,
thin_discards_t *discards, int *zero) thin_discards_t *discards, thin_zero_t *zero_new_blocks)
{ {
struct cmd_context *cmd = vg->cmd;
struct profile *profile = vg->profile;
uint32_t extent_size = vg->extent_size;
uint64_t pool_metadata_size = (uint64_t) *pool_metadata_extents * extent_size; uint64_t pool_metadata_size = (uint64_t) *pool_metadata_extents * extent_size;
size_t estimate_chunk_size; uint32_t estimate_chunk_size;
const char *str; const char *str;
if (!(passed_args & PASS_ARG_CHUNK_SIZE)) { if (!*chunk_size &&
if (!(*chunk_size = find_config_tree_int(cmd, allocation_thin_pool_chunk_size_CFG, profile) * 2)) { find_config_tree_node(cmd, allocation_thin_pool_chunk_size_CFG, profile))
if (!(str = find_config_tree_str(cmd, allocation_thin_pool_chunk_size_policy_CFG, profile))) { *chunk_size = find_config_tree_int(cmd, allocation_thin_pool_chunk_size_CFG, profile) * 2;
log_error(INTERNAL_ERROR "Could not find configuration.");
return 0; if (*chunk_size && !(attr & THIN_FEATURE_BLOCK_SIZE) &&
} !is_power_of_2(*chunk_size)) {
if (!strcasecmp(str, "generic")) log_error("Chunk size must be a power of 2 for this thin target version.");
*chunk_size_calc_method = THIN_CHUNK_SIZE_CALC_METHOD_GENERIC; return 0;
else if (!strcasecmp(str, "performance"))
*chunk_size_calc_method = THIN_CHUNK_SIZE_CALC_METHOD_PERFORMANCE;
else {
log_error("Thin pool chunk size calculation policy \"%s\" is unrecognised.", str);
return 0;
}
if (!(*chunk_size = get_default_allocation_thin_pool_chunk_size_CFG(cmd, profile)))
return_0;
}
} }
if (!validate_pool_chunk_size(cmd, segtype, *chunk_size)) if ((*discards == THIN_DISCARDS_UNSELECTED) &&
return_0; find_config_tree_node(cmd, allocation_thin_pool_discards_CFG, profile)) {
if (!(passed_args & PASS_ARG_DISCARDS)) {
if (!(str = find_config_tree_str(cmd, allocation_thin_pool_discards_CFG, profile))) { if (!(str = find_config_tree_str(cmd, allocation_thin_pool_discards_CFG, profile))) {
log_error(INTERNAL_ERROR "Could not find configuration."); log_error(INTERNAL_ERROR "Could not find configuration.");
return 0; return 0;
@ -620,21 +650,21 @@ int update_thin_pool_params(const struct segment_type *segtype,
return_0; return_0;
} }
if (!(passed_args & PASS_ARG_ZERO)) if ((*zero_new_blocks == THIN_ZERO_UNSELECTED) &&
*zero = find_config_tree_bool(cmd, allocation_thin_pool_zero_CFG, profile); find_config_tree_node(cmd, allocation_thin_pool_zero_CFG, profile))
*zero_new_blocks = find_config_tree_bool(cmd, allocation_thin_pool_zero_CFG, profile)
if (!(attr & THIN_FEATURE_BLOCK_SIZE) && ? THIN_ZERO_YES : THIN_ZERO_NO;
!is_power_of_2(*chunk_size)) {
log_error("Chunk size must be a power of 2 for this thin target version.");
return 0;
}
if (!pool_metadata_size) { if (!pool_metadata_size) {
/* Defaults to nr_pool_blocks * 64b converted to size in sectors */ if (!*chunk_size) {
pool_metadata_size = (uint64_t) pool_data_extents * extent_size / if (!get_default_allocation_thin_pool_chunk_size(cmd, profile,
(*chunk_size * (SECTOR_SIZE / UINT64_C(64))); chunk_size,
/* Check if we could eventually use bigger chunk size */ chunk_size_calc_method))
if (!(passed_args & PASS_ARG_CHUNK_SIZE)) { return_0;
pool_metadata_size = _estimate_metadata_size(pool_data_extents, extent_size, *chunk_size);
/* Check if we should eventually use bigger chunk size */
while ((pool_metadata_size > while ((pool_metadata_size >
(DEFAULT_THIN_POOL_OPTIMAL_SIZE / SECTOR_SIZE)) && (DEFAULT_THIN_POOL_OPTIMAL_SIZE / SECTOR_SIZE)) &&
(*chunk_size < DM_THIN_MAX_DATA_BLOCK_SIZE)) { (*chunk_size < DM_THIN_MAX_DATA_BLOCK_SIZE)) {
@ -643,29 +673,28 @@ int update_thin_pool_params(const struct segment_type *segtype,
} }
log_verbose("Setting chunk size to %s.", log_verbose("Setting chunk size to %s.",
display_size(cmd, *chunk_size)); display_size(cmd, *chunk_size));
} else if (pool_metadata_size > (DEFAULT_THIN_POOL_MAX_METADATA_SIZE * 2)) { } else {
/* Suggest bigger chunk size */ pool_metadata_size = _estimate_metadata_size(pool_data_extents, extent_size, *chunk_size);
estimate_chunk_size =
_estimate_chunk_size((uint64_t) pool_data_extents * extent_size, if (pool_metadata_size > (DEFAULT_THIN_POOL_MAX_METADATA_SIZE * 2)) {
(DEFAULT_THIN_POOL_MAX_METADATA_SIZE * 2), attr); /* Suggest bigger chunk size */
log_warn("WARNING: Chunk size is too small for pool, suggested minimum is %s.", estimate_chunk_size =
display_size(cmd, estimate_chunk_size)); _estimate_chunk_size(pool_data_extents, extent_size,
(DEFAULT_THIN_POOL_MAX_METADATA_SIZE * 2), attr);
log_warn("WARNING: Chunk size is too small for pool, suggested minimum is %s.",
display_size(cmd, estimate_chunk_size));
}
} }
/* Round up to extent size silently */ /* Round up to extent size silently */
if (pool_metadata_size % extent_size) if (pool_metadata_size % extent_size)
pool_metadata_size += extent_size - pool_metadata_size % extent_size; pool_metadata_size += extent_size - pool_metadata_size % extent_size;
} else { } else {
estimate_chunk_size = estimate_chunk_size = _estimate_chunk_size(pool_data_extents, extent_size,
_estimate_chunk_size((uint64_t) pool_data_extents * extent_size, pool_metadata_size, attr);
pool_metadata_size, attr);
if (estimate_chunk_size < DM_THIN_MIN_DATA_BLOCK_SIZE)
estimate_chunk_size = DM_THIN_MIN_DATA_BLOCK_SIZE;
else if (estimate_chunk_size > DM_THIN_MAX_DATA_BLOCK_SIZE)
estimate_chunk_size = DM_THIN_MAX_DATA_BLOCK_SIZE;
/* Check to eventually use bigger chunk size */ /* Check to eventually use bigger chunk size */
if (!(passed_args & PASS_ARG_CHUNK_SIZE)) { if (!*chunk_size) {
*chunk_size = estimate_chunk_size; *chunk_size = estimate_chunk_size;
log_verbose("Setting chunk size %s.", display_size(cmd, *chunk_size)); log_verbose("Setting chunk size %s.", display_size(cmd, *chunk_size));
} else if (*chunk_size < estimate_chunk_size) { } else if (*chunk_size < estimate_chunk_size) {
@ -675,22 +704,41 @@ int update_thin_pool_params(const struct segment_type *segtype,
} }
} }
if (!validate_thin_pool_chunk_size(cmd, *chunk_size))
return_0;
if (pool_metadata_size > (2 * DEFAULT_THIN_POOL_MAX_METADATA_SIZE)) { if (pool_metadata_size > (2 * DEFAULT_THIN_POOL_MAX_METADATA_SIZE)) {
pool_metadata_size = 2 * DEFAULT_THIN_POOL_MAX_METADATA_SIZE; pool_metadata_size = 2 * DEFAULT_THIN_POOL_MAX_METADATA_SIZE;
if (passed_args & PASS_ARG_POOL_METADATA_SIZE) if (*pool_metadata_extents)
log_warn("WARNING: Maximum supported pool metadata size is %s.", log_warn("WARNING: Maximum supported pool metadata size is %s.",
display_size(cmd, pool_metadata_size)); display_size(cmd, pool_metadata_size));
} else if (pool_metadata_size < (2 * DEFAULT_THIN_POOL_MIN_METADATA_SIZE)) { } else if (pool_metadata_size < (2 * DEFAULT_THIN_POOL_MIN_METADATA_SIZE)) {
pool_metadata_size = 2 * DEFAULT_THIN_POOL_MIN_METADATA_SIZE; pool_metadata_size = 2 * DEFAULT_THIN_POOL_MIN_METADATA_SIZE;
if (passed_args & PASS_ARG_POOL_METADATA_SIZE) if (*pool_metadata_extents)
log_warn("WARNING: Minimum supported pool metadata size is %s.", log_warn("WARNING: Minimum supported pool metadata size is %s.",
display_size(cmd, pool_metadata_size)); display_size(cmd, pool_metadata_size));
} }
if (!(*pool_metadata_extents = if (!(*pool_metadata_extents =
extents_from_size(vg->cmd, pool_metadata_size, extent_size))) extents_from_size(cmd, pool_metadata_size, extent_size)))
return_0; return_0;
if ((uint64_t) *chunk_size > (uint64_t) pool_data_extents * extent_size) {
log_error("Size of %s data volume cannot be smaller than chunk size %s.",
segtype->name, display_size(cmd, *chunk_size));
return 0;
}
if ((*discards == THIN_DISCARDS_UNSELECTED) &&
!set_pool_discards(discards, DEFAULT_THIN_POOL_DISCARDS))
return_0;
if (*zero_new_blocks == THIN_ZERO_UNSELECTED)
*zero_new_blocks = (DEFAULT_THIN_POOL_ZERO) ? THIN_ZERO_YES : THIN_ZERO_NO;
log_verbose("Preferred pool metadata size %s.",
display_size(cmd, (uint64_t)*pool_metadata_extents * extent_size));
return 1; return 1;
} }
@ -719,11 +767,10 @@ const char *get_pool_discards_name(thin_discards_t discards)
return "nopassdown"; return "nopassdown";
case THIN_DISCARDS_IGNORE: case THIN_DISCARDS_IGNORE:
return "ignore"; return "ignore";
default:
log_error(INTERNAL_ERROR "Unknown discards type encountered.");
return "unknown";
} }
log_error(INTERNAL_ERROR "Unknown discards type encountered.");
return "unknown";
} }
int lv_is_thin_origin(const struct logical_volume *lv, unsigned int *snap_count) int lv_is_thin_origin(const struct logical_volume *lv, unsigned int *snap_count)
@ -734,20 +781,16 @@ int lv_is_thin_origin(const struct logical_volume *lv, unsigned int *snap_count)
if (snap_count) if (snap_count)
*snap_count = 0; *snap_count = 0;
if (!lv_is_thin_volume(lv) || if (lv_is_thin_volume(lv))
dm_list_empty(&lv->segs_using_this_lv)) dm_list_iterate_items(segl, &lv->segs_using_this_lv)
return 0; if (segl->seg->origin == lv) {
r = 1;
if (!snap_count)
break;/* not interested in number of snapshots */
dm_list_iterate_items(segl, &lv->segs_using_this_lv) {
if (segl->seg->origin == lv) {
r = 1;
if (snap_count)
(*snap_count)++; (*snap_count)++;
else }
/* not interested in number of snapshots */
break;
}
}
return r; return r;
} }
@ -816,3 +859,27 @@ int check_new_thin_pool(const struct logical_volume *pool_lv)
return 1; return 1;
} }
int validate_thin_pool_chunk_size(struct cmd_context *cmd, uint32_t chunk_size)
{
const uint32_t min_size = DM_THIN_MIN_DATA_BLOCK_SIZE;
const uint32_t max_size = DM_THIN_MAX_DATA_BLOCK_SIZE;
int r = 1;
if ((chunk_size < min_size) || (chunk_size > max_size)) {
log_error("Thin pool chunk size %s is not in the range %s to %s.",
display_size(cmd, chunk_size),
display_size(cmd, min_size),
display_size(cmd, max_size));
r = 0;
}
if (chunk_size & (min_size - 1)) {
log_error("Thin pool chunk size %s must be a multiple of %s.",
display_size(cmd, chunk_size),
display_size(cmd, min_size));
r = 0;
}
return r;
}

View File

@ -137,6 +137,7 @@ static int _raid_text_import(struct lv_segment *seg,
} raid_attr_import[] = { } raid_attr_import[] = {
{ "region_size", &seg->region_size }, { "region_size", &seg->region_size },
{ "stripe_size", &seg->stripe_size }, { "stripe_size", &seg->stripe_size },
{ "data_copies", &seg->data_copies },
{ "writebehind", &seg->writebehind }, { "writebehind", &seg->writebehind },
{ "min_recovery_rate", &seg->min_recovery_rate }, { "min_recovery_rate", &seg->min_recovery_rate },
{ "max_recovery_rate", &seg->max_recovery_rate }, { "max_recovery_rate", &seg->max_recovery_rate },
@ -146,6 +147,10 @@ static int _raid_text_import(struct lv_segment *seg,
for (i = 0; i < DM_ARRAY_SIZE(raid_attr_import); i++, aip++) { for (i = 0; i < DM_ARRAY_SIZE(raid_attr_import); i++, aip++) {
if (dm_config_has_node(sn, aip->name)) { if (dm_config_has_node(sn, aip->name)) {
if (!dm_config_get_uint32(sn, aip->name, aip->var)) { if (!dm_config_get_uint32(sn, aip->name, aip->var)) {
if (!strcmp(aip->name, "data_copies")) {
*aip->var = 0;
continue;
}
log_error("Couldn't read '%s' for segment %s of logical volume %s.", log_error("Couldn't read '%s' for segment %s of logical volume %s.",
aip->name, dm_config_parent_name(sn), seg->lv->name); aip->name, dm_config_parent_name(sn), seg->lv->name);
return 0; return 0;
@ -165,6 +170,9 @@ static int _raid_text_import(struct lv_segment *seg,
return 0; return 0;
} }
if (seg->data_copies < 2)
seg->data_copies = lv_raid_data_copies(seg->segtype, seg->area_count);
if (seg_is_any_raid0(seg)) if (seg_is_any_raid0(seg))
seg->area_len /= seg->area_count; seg->area_len /= seg->area_count;
@ -183,18 +191,31 @@ static int _raid_text_export_raid0(const struct lv_segment *seg, struct formatte
static int _raid_text_export_raid(const struct lv_segment *seg, struct formatter *f) static int _raid_text_export_raid(const struct lv_segment *seg, struct formatter *f)
{ {
outf(f, "device_count = %u", seg->area_count); int raid0 = seg_is_any_raid0(seg);
if (raid0)
outfc(f, (seg->area_count == 1) ? "# linear" : NULL,
"stripe_count = %u", seg->area_count);
else {
outf(f, "device_count = %u", seg->area_count);
if (seg_is_any_raid10(seg) && seg->data_copies > 0)
outf(f, "data_copies = %" PRIu32, seg->data_copies);
if (seg->region_size)
outf(f, "region_size = %" PRIu32, seg->region_size);
}
if (seg->stripe_size) if (seg->stripe_size)
outf(f, "stripe_size = %" PRIu32, seg->stripe_size); outf(f, "stripe_size = %" PRIu32, seg->stripe_size);
if (seg->region_size)
outf(f, "region_size = %" PRIu32, seg->region_size); if (!raid0) {
if (seg->writebehind) if (seg_is_raid1(seg) && seg->writebehind)
outf(f, "writebehind = %" PRIu32, seg->writebehind); outf(f, "writebehind = %" PRIu32, seg->writebehind);
if (seg->min_recovery_rate) if (seg->min_recovery_rate)
outf(f, "min_recovery_rate = %" PRIu32, seg->min_recovery_rate); outf(f, "min_recovery_rate = %" PRIu32, seg->min_recovery_rate);
if (seg->max_recovery_rate) if (seg->max_recovery_rate)
outf(f, "max_recovery_rate = %" PRIu32, seg->max_recovery_rate); outf(f, "max_recovery_rate = %" PRIu32, seg->max_recovery_rate);
}
return out_areas(f, seg, "raid"); return out_areas(f, seg, "raid");
} }
@ -216,14 +237,16 @@ static int _raid_add_target_line(struct dev_manager *dm __attribute__((unused)),
struct dm_tree_node *node, uint64_t len, struct dm_tree_node *node, uint64_t len,
uint32_t *pvmove_mirror_count __attribute__((unused))) uint32_t *pvmove_mirror_count __attribute__((unused)))
{ {
int delta_disks = 0, delta_disks_minus = 0, delta_disks_plus = 0, data_offset = 0;
uint32_t s; uint32_t s;
uint64_t flags = 0; uint64_t flags = 0;
uint64_t rebuilds = 0; uint64_t rebuilds[RAID_BITMAP_SIZE];
uint64_t writemostly = 0; uint64_t writemostly[RAID_BITMAP_SIZE];
struct dm_tree_node_raid_params params; struct dm_tree_node_raid_params_v2 params;
int raid0 = seg_is_any_raid0(seg);
memset(&params, 0, sizeof(params)); memset(&params, 0, sizeof(params));
memset(&rebuilds, 0, sizeof(rebuilds));
memset(&writemostly, 0, sizeof(writemostly));
if (!seg->area_count) { if (!seg->area_count) {
log_error(INTERNAL_ERROR "_raid_add_target_line called " log_error(INTERNAL_ERROR "_raid_add_target_line called "
@ -232,64 +255,85 @@ static int _raid_add_target_line(struct dev_manager *dm __attribute__((unused)),
} }
/* /*
* 64 device restriction imposed by kernel as well. It is * 253 device restriction imposed by kernel due to MD and dm-raid bitfield limitation in superblock.
* not strictly a userspace limitation. * It is not strictly a userspace limitation.
*/ */
if (seg->area_count > 64) { if (seg->area_count > DEFAULT_RAID_MAX_IMAGES) {
log_error("Unable to handle more than 64 devices in a " log_error("Unable to handle more than %u devices in a "
"single RAID array"); "single RAID array", DEFAULT_RAID_MAX_IMAGES);
return 0; return 0;
} }
if (!raid0) { if (!seg_is_any_raid0(seg)) {
if (!seg->region_size) { if (!seg->region_size) {
log_error("Missing region size for mirror segment."); log_error("Missing region size for raid segment in %s.",
seg_lv(seg, 0)->name);
return 0; return 0;
} }
for (s = 0; s < seg->area_count; s++) for (s = 0; s < seg->area_count; s++) {
if (seg_lv(seg, s)->status & LV_REBUILD) uint64_t status = seg_lv(seg, s)->status;
rebuilds |= 1ULL << s;
for (s = 0; s < seg->area_count; s++) if (status & LV_REBUILD)
if (seg_lv(seg, s)->status & LV_WRITEMOSTLY) rebuilds[s/64] |= 1ULL << (s%64);
writemostly |= 1ULL << s;
if (status & LV_RESHAPE_DELTA_DISKS_PLUS) {
delta_disks++;
delta_disks_plus++;
} else if (status & LV_RESHAPE_DELTA_DISKS_MINUS) {
delta_disks--;
delta_disks_minus++;
}
if (delta_disks_plus && delta_disks_minus) {
log_error(INTERNAL_ERROR "Invalid request for delta disks minus and delta disks plus!");
return 0;
}
if (status & LV_WRITEMOSTLY)
writemostly[s/64] |= 1ULL << (s%64);
}
data_offset = seg->data_offset;
if (mirror_in_sync()) if (mirror_in_sync())
flags = DM_NOSYNC; flags = DM_NOSYNC;
} }
params.raid_type = lvseg_name(seg); params.raid_type = lvseg_name(seg);
params.stripe_size = seg->stripe_size;
params.flags = flags;
if (raid0) { if (seg->segtype->parity_devs) {
params.mirrors = 1;
params.stripes = seg->area_count;
} else if (seg->segtype->parity_devs) {
/* RAID 4/5/6 */ /* RAID 4/5/6 */
params.mirrors = 1; params.mirrors = 1;
params.stripes = seg->area_count - seg->segtype->parity_devs; params.stripes = seg->area_count - seg->segtype->parity_devs;
} else if (seg_is_raid10(seg)) { } else if (seg_is_any_raid0(seg)) {
/* RAID 10 only supports 2 mirrors now */ params.mirrors = 1;
params.mirrors = 2; params.stripes = seg->area_count;
params.stripes = seg->area_count / 2; } else if (seg_is_any_raid10(seg)) {
params.data_copies = seg->data_copies;
params.stripes = seg->area_count;
} else { } else {
/* RAID 1 */ /* RAID 1 */
params.mirrors = seg->area_count; params.mirrors = seg->data_copies;
params.stripes = 1; params.stripes = 1;
params.writebehind = seg->writebehind; params.writebehind = seg->writebehind;
memcpy(params.writemostly, writemostly, sizeof(params.writemostly));
} }
if (!raid0) { /* RAID 0 doesn't have a bitmap, thus no region_size, rebuilds etc. */
if (!seg_is_any_raid0(seg)) {
params.region_size = seg->region_size; params.region_size = seg->region_size;
params.rebuilds = rebuilds; memcpy(params.rebuilds, rebuilds, sizeof(params.rebuilds));
params.writemostly = writemostly;
params.min_recovery_rate = seg->min_recovery_rate; params.min_recovery_rate = seg->min_recovery_rate;
params.max_recovery_rate = seg->max_recovery_rate; params.max_recovery_rate = seg->max_recovery_rate;
params.delta_disks = delta_disks;
params.data_offset = data_offset;
} }
if (!dm_tree_node_add_raid_target_with_params(node, len, &params)) params.stripe_size = seg->stripe_size;
params.flags = flags;
if (!dm_tree_node_add_raid_target_with_params_v2(node, len, &params))
return_0; return_0;
return add_areas_line(dm, seg, node, 0u, seg->area_count); return add_areas_line(dm, seg, node, 0u, seg->area_count);
@ -404,19 +448,33 @@ out:
return r; return r;
} }
/* Define raid feature based on the tuple(major, minor, patchlevel) of raid target */
struct raid_feature {
uint32_t maj;
uint32_t min;
uint32_t patchlevel;
unsigned raid_feature;
const char *feature;
};
/* Return true if tuple(@maj, @min, @patchlevel) is greater/equal to @*feature members */
static int _check_feature(const struct raid_feature *feature, uint32_t maj, uint32_t min, uint32_t patchlevel)
{
return (maj > feature->maj) ||
(maj == feature->maj && min >= feature->min) ||
(maj == feature->maj && min == feature->min && patchlevel >= feature->patchlevel);
}
static int _raid_target_present(struct cmd_context *cmd, static int _raid_target_present(struct cmd_context *cmd,
const struct lv_segment *seg __attribute__((unused)), const struct lv_segment *seg __attribute__((unused)),
unsigned *attributes) unsigned *attributes)
{ {
/* List of features with their kernel target version */ /* List of features with their kernel target version */
static const struct feature { const struct raid_feature _features[] = {
uint32_t maj; { 1, 3, 0, RAID_FEATURE_RAID10, SEG_TYPE_NAME_RAID10 },
uint32_t min; { 1, 7, 0, RAID_FEATURE_RAID0, SEG_TYPE_NAME_RAID0 },
unsigned raid_feature; { 1, 9, 0, RAID_FEATURE_SHRINK, "shrinking" },
const char *feature; { 1, 10, 1, RAID_FEATURE_RESHAPE, "reshaping" },
} _features[] = {
{ 1, 3, RAID_FEATURE_RAID10, SEG_TYPE_NAME_RAID10 },
{ 1, 7, RAID_FEATURE_RAID0, SEG_TYPE_NAME_RAID0 },
}; };
static int _raid_checked = 0; static int _raid_checked = 0;
@ -438,13 +496,19 @@ static int _raid_target_present(struct cmd_context *cmd,
return_0; return_0;
for (i = 0; i < DM_ARRAY_SIZE(_features); ++i) for (i = 0; i < DM_ARRAY_SIZE(_features); ++i)
if ((maj > _features[i].maj) || if (_check_feature(_features + i, maj, min, patchlevel))
(maj == _features[i].maj && min >= _features[i].min))
_raid_attrs |= _features[i].raid_feature; _raid_attrs |= _features[i].raid_feature;
else else
log_very_verbose("Target raid does not support %s.", log_very_verbose("Target raid does not support %s.",
_features[i].feature); _features[i].feature);
/*
* Seperate check for proper raid4 mapping supported
*
* If we get more of these range checks, avoid them
* altogether by enhancing 'struct raid_feature'
* and _check_feature() to handle them.
*/
if (!(maj == 1 && (min == 8 || (min == 9 && patchlevel == 0)))) if (!(maj == 1 && (min == 8 || (min == 9 && patchlevel == 0))))
_raid_attrs |= RAID_FEATURE_RAID4; _raid_attrs |= RAID_FEATURE_RAID4;
else else

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved. * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004-2013 Red Hat, Inc. All rights reserved. * Copyright (C) 2004-2017 Red Hat, Inc. All rights reserved.
* *
* This file is part of LVM2. * This file is part of LVM2.
* *
@ -69,7 +69,7 @@ FIELD(LVS, lv, BIN, "ActExcl", lvid, 10, lvactiveexclusively, lv_active_exclusiv
FIELD(LVS, lv, SNUM, "Maj", major, 0, int32, lv_major, "Persistent major number or -1 if not persistent.", 0) FIELD(LVS, lv, SNUM, "Maj", major, 0, int32, lv_major, "Persistent major number or -1 if not persistent.", 0)
FIELD(LVS, lv, SNUM, "Min", minor, 0, int32, lv_minor, "Persistent minor number or -1 if not persistent.", 0) FIELD(LVS, lv, SNUM, "Min", minor, 0, int32, lv_minor, "Persistent minor number or -1 if not persistent.", 0)
FIELD(LVS, lv, SIZ, "Rahead", lvid, 0, lvreadahead, lv_read_ahead, "Read ahead setting in current units.", 0) FIELD(LVS, lv, SIZ, "Rahead", lvid, 0, lvreadahead, lv_read_ahead, "Read ahead setting in current units.", 0)
FIELD(LVS, lv, SIZ, "LSize", size, 0, size64, lv_size, "Size of LV in current units.", 0) FIELD(LVS, lv, SIZ, "LSize", lvid, 0, lv_size, lv_size, "Size of LV in current units.", 0)
FIELD(LVS, lv, SIZ, "MSize", lvid, 0, lvmetadatasize, lv_metadata_size, "For thin and cache pools, the size of the LV that holds the metadata.", 0) FIELD(LVS, lv, SIZ, "MSize", lvid, 0, lvmetadatasize, lv_metadata_size, "For thin and cache pools, the size of the LV that holds the metadata.", 0)
FIELD(LVS, lv, NUM, "#Seg", lvid, 0, lvsegcount, seg_count, "Number of segments in LV.", 0) FIELD(LVS, lv, NUM, "#Seg", lvid, 0, lvsegcount, seg_count, "Number of segments in LV.", 0)
FIELD(LVS, lv, STR, "Origin", lvid, 0, origin, origin, "For snapshots and thins, the origin device of this LV.", 0) FIELD(LVS, lv, STR, "Origin", lvid, 0, origin, origin, "For snapshots and thins, the origin device of this LV.", 0)
@ -140,6 +140,7 @@ FIELD(LVSSTATUS, lv, NUM, "CacheWriteHits", lvid, 16, cache_write_hits, cache_wr
FIELD(LVSSTATUS, lv, NUM, "CacheWriteMisses", lvid, 0, cache_write_misses, cache_write_misses, "Cache write misses.", 0) FIELD(LVSSTATUS, lv, NUM, "CacheWriteMisses", lvid, 0, cache_write_misses, cache_write_misses, "Cache write misses.", 0)
FIELD(LVSSTATUS, lv, STR_LIST, "KCacheSettings", lvid, 18, kernel_cache_settings, kernel_cache_settings, "Cache settings/parameters as set in kernel, including default values (cached segments only).", 0) FIELD(LVSSTATUS, lv, STR_LIST, "KCacheSettings", lvid, 18, kernel_cache_settings, kernel_cache_settings, "Cache settings/parameters as set in kernel, including default values (cached segments only).", 0)
FIELD(LVSSTATUS, lv, STR, "KCachePolicy", lvid, 18, kernel_cache_policy, kernel_cache_policy, "Cache policy used in kernel.", 0) FIELD(LVSSTATUS, lv, STR, "KCachePolicy", lvid, 18, kernel_cache_policy, kernel_cache_policy, "Cache policy used in kernel.", 0)
FIELD(LVSSTATUS, lv, NUM, "KMFmt", lvid, 0, kernelmetadataformat, kernel_metadata_format, "Cache metadata format used in kernel.", 0)
FIELD(LVSSTATUS, lv, STR, "Health", lvid, 15, lvhealthstatus, lv_health_status, "LV health status.", 0) FIELD(LVSSTATUS, lv, STR, "Health", lvid, 15, lvhealthstatus, lv_health_status, "LV health status.", 0)
FIELD(LVSSTATUS, lv, STR, "KDiscards", lvid, 0, kdiscards, kernel_discards, "For thin pools, how discards are handled in kernel.", 0) FIELD(LVSSTATUS, lv, STR, "KDiscards", lvid, 0, kdiscards, kernel_discards, "For thin pools, how discards are handled in kernel.", 0)
FIELD(LVSSTATUS, lv, BIN, "CheckNeeded", lvid, 15, lvcheckneeded, lv_check_needed, "For thin pools and cache volumes, whether metadata check is needed.", 0) FIELD(LVSSTATUS, lv, BIN, "CheckNeeded", lvid, 15, lvcheckneeded, lv_check_needed, "For thin pools and cache volumes, whether metadata check is needed.", 0)
@ -241,13 +242,21 @@ FIELD(VGS, vg, NUM, "#VMdaCps", cmd, 0, vgmdacopies, vg_mda_copies, "Target numb
* SEGS type fields * SEGS type fields
*/ */
FIELD(SEGS, seg, STR, "Type", list, 0, segtype, segtype, "Type of LV segment.", 0) FIELD(SEGS, seg, STR, "Type", list, 0, segtype, segtype, "Type of LV segment.", 0)
FIELD(SEGS, seg, NUM, "#Str", area_count, 0, uint32, stripes, "Number of stripes or mirror legs.", 0) FIELD(SEGS, seg, NUM, "#Str", list, 0, seg_stripes, stripes, "Number of stripes or mirror/raid1 legs.", 0)
FIELD(SEGS, seg, NUM, "#DStr", list, 0, seg_data_stripes, data_stripes, "Number of data stripes or mirror/raid1 legs.", 0)
FIELD(SEGS, seg, SIZ, "RSize", list, 0, seg_reshape_len, reshape_len, "Size of out-of-place reshape space in current units.", 0)
FIELD(SEGS, seg, NUM, "RSize", list, 0, seg_reshape_len_le, reshape_len_le, "Size of out-of-place reshape space in logical extents.", 0)
FIELD(SEGS, seg, NUM, "#Cpy", list, 0, seg_data_copies, data_copies, "Number of data copies.", 0)
FIELD(SEGS, seg, NUM, "DOff", list, 0, seg_data_offset, data_offset, "Data offset on each image device.", 0)
FIELD(SEGS, seg, NUM, "NOff", list, 0, seg_new_data_offset, new_data_offset, "New data offset after any reshape on each image device.", 0)
FIELD(SEGS, seg, NUM, "#Par", list, 0, seg_parity_chunks, parity_chunks, "Number of (rotating) parity chunks.", 0)
FIELD(SEGS, seg, SIZ, "Stripe", stripe_size, 0, size32, stripe_size, "For stripes, amount of data placed on one device before switching to the next.", 0) FIELD(SEGS, seg, SIZ, "Stripe", stripe_size, 0, size32, stripe_size, "For stripes, amount of data placed on one device before switching to the next.", 0)
FIELD(SEGS, seg, SIZ, "Region", region_size, 0, size32, region_size, "For mirrors, the unit of data copied when synchronising devices.", 0) FIELD(SEGS, seg, SIZ, "Region", region_size, 0, size32, region_size, "For mirrors/raids, the unit of data per leg when synchronizing devices.", 0)
FIELD(SEGS, seg, SIZ, "Chunk", list, 0, chunksize, chunk_size, "For snapshots, the unit of data used when tracking changes.", 0) FIELD(SEGS, seg, SIZ, "Chunk", list, 0, chunksize, chunk_size, "For snapshots, the unit of data used when tracking changes.", 0)
FIELD(SEGS, seg, NUM, "#Thins", list, 0, thincount, thin_count, "For thin pools, the number of thin volumes in this pool.", 0) FIELD(SEGS, seg, NUM, "#Thins", list, 0, thincount, thin_count, "For thin pools, the number of thin volumes in this pool.", 0)
FIELD(SEGS, seg, STR, "Discards", list, 0, discards, discards, "For thin pools, how discards are handled.", 0) FIELD(SEGS, seg, STR, "Discards", list, 0, discards, discards, "For thin pools, how discards are handled.", 0)
FIELD(SEGS, seg, STR, "CacheMode", list, 0, cachemode, cache_mode, "For cache pools, how writes are cached.", 0) FIELD(SEGS, seg, NUM, "CMFmt", list, 0, cachemetadataformat, cache_metadata_format, "For cache, metadata format in use.", 0)
FIELD(SEGS, seg, STR, "CacheMode", list, 0, cachemode, cache_mode, "For cache, how writes are cached.", 0)
FIELD(SEGS, seg, BIN, "Zero", list, 0, thinzero, zero, "For thin pools and volumes, if zeroing is enabled.", 0) FIELD(SEGS, seg, BIN, "Zero", list, 0, thinzero, zero, "For thin pools and volumes, if zeroing is enabled.", 0)
FIELD(SEGS, seg, NUM, "TransId", list, 0, transactionid, transaction_id, "For thin pools, the transaction id and creation transaction id for thins.", 0) FIELD(SEGS, seg, NUM, "TransId", list, 0, transactionid, transaction_id, "For thin pools, the transaction id and creation transaction id for thins.", 0)
FIELD(SEGS, seg, NUM, "ThId", list, 0, thinid, thin_id, "For thin volume, the thin device id.", 0) FIELD(SEGS, seg, NUM, "ThId", list, 0, thinid, thin_id, "For thin volume, the thin device id.", 0)

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2010-2013 Red Hat, Inc. All rights reserved. * Copyright (C) 2010-2017 Red Hat, Inc. All rights reserved.
* *
* This file is part of LVM2. * This file is part of LVM2.
* *
@ -446,8 +446,22 @@ GET_VG_NUM_PROPERTY_FN(vg_missing_pv_count, vg_missing_pv_count(vg))
/* LVSEG */ /* LVSEG */
GET_LVSEG_STR_PROPERTY_FN(segtype, lvseg_segtype_dup(lvseg->lv->vg->vgmem, lvseg)) GET_LVSEG_STR_PROPERTY_FN(segtype, lvseg_segtype_dup(lvseg->lv->vg->vgmem, lvseg))
#define _segtype_set prop_not_implemented_set #define _segtype_set prop_not_implemented_set
GET_LVSEG_NUM_PROPERTY_FN(data_copies, lvseg->data_copies)
#define _data_copies_set prop_not_implemented_set
GET_LVSEG_NUM_PROPERTY_FN(reshape_len, lvseg->reshape_len)
#define _reshape_len_set prop_not_implemented_set
GET_LVSEG_NUM_PROPERTY_FN(reshape_len_le, lvseg->reshape_len)
#define _reshape_len_le_set prop_not_implemented_set
GET_LVSEG_NUM_PROPERTY_FN(data_offset, lvseg->data_offset)
#define _data_offset_set prop_not_implemented_set
GET_LVSEG_NUM_PROPERTY_FN(new_data_offset, lvseg->data_offset)
#define _new_data_offset_set prop_not_implemented_set
GET_LVSEG_NUM_PROPERTY_FN(parity_chunks, lvseg->data_offset)
#define _parity_chunks_set prop_not_implemented_set
GET_LVSEG_NUM_PROPERTY_FN(stripes, lvseg->area_count) GET_LVSEG_NUM_PROPERTY_FN(stripes, lvseg->area_count)
#define _stripes_set prop_not_implemented_set #define _stripes_set prop_not_implemented_set
GET_LVSEG_NUM_PROPERTY_FN(data_stripes, lvseg->area_count)
#define _data_stripes_set prop_not_implemented_set
GET_LVSEG_NUM_PROPERTY_FN(stripe_size, (SECTOR_SIZE * lvseg->stripe_size)) GET_LVSEG_NUM_PROPERTY_FN(stripe_size, (SECTOR_SIZE * lvseg->stripe_size))
#define _stripe_size_set prop_not_implemented_set #define _stripe_size_set prop_not_implemented_set
GET_LVSEG_NUM_PROPERTY_FN(region_size, (SECTOR_SIZE * lvseg->region_size)) GET_LVSEG_NUM_PROPERTY_FN(region_size, (SECTOR_SIZE * lvseg->region_size))
@ -456,7 +470,7 @@ GET_LVSEG_NUM_PROPERTY_FN(chunk_size, (SECTOR_SIZE * lvseg_chunksize(lvseg)))
#define _chunk_size_set prop_not_implemented_set #define _chunk_size_set prop_not_implemented_set
GET_LVSEG_NUM_PROPERTY_FN(thin_count, dm_list_size(&lvseg->lv->segs_using_this_lv)) GET_LVSEG_NUM_PROPERTY_FN(thin_count, dm_list_size(&lvseg->lv->segs_using_this_lv))
#define _thin_count_set prop_not_implemented_set #define _thin_count_set prop_not_implemented_set
GET_LVSEG_NUM_PROPERTY_FN(zero, lvseg->zero_new_blocks) GET_LVSEG_NUM_PROPERTY_FN(zero, (lvseg->zero_new_blocks == THIN_ZERO_YES))
#define _zero_set prop_not_implemented_set #define _zero_set prop_not_implemented_set
GET_LVSEG_NUM_PROPERTY_FN(transaction_id, lvseg->transaction_id) GET_LVSEG_NUM_PROPERTY_FN(transaction_id, lvseg->transaction_id)
#define _transaction_id_set prop_not_implemented_set #define _transaction_id_set prop_not_implemented_set
@ -468,6 +482,8 @@ GET_LVSEG_STR_PROPERTY_FN(kernel_discards, lvseg_kernel_discards_dup(lvseg->lv->
#define _kernel_discards_set prop_not_implemented_set #define _kernel_discards_set prop_not_implemented_set
GET_LVSEG_STR_PROPERTY_FN(cache_mode, lvseg_cachemode_dup(lvseg->lv->vg->vgmem, lvseg)) GET_LVSEG_STR_PROPERTY_FN(cache_mode, lvseg_cachemode_dup(lvseg->lv->vg->vgmem, lvseg))
#define _cache_mode_set prop_not_implemented_set #define _cache_mode_set prop_not_implemented_set
GET_LVSEG_NUM_PROPERTY_FN(cache_metadata_format, lvseg->cache_metadata_format)
#define _cache_metadata_format_set prop_not_implemented_set
GET_LVSEG_NUM_PROPERTY_FN(seg_start, (SECTOR_SIZE * lvseg_start(lvseg))) GET_LVSEG_NUM_PROPERTY_FN(seg_start, (SECTOR_SIZE * lvseg_start(lvseg)))
#define _seg_start_set prop_not_implemented_set #define _seg_start_set prop_not_implemented_set
GET_LVSEG_NUM_PROPERTY_FN(seg_start_pe, lvseg->le) GET_LVSEG_NUM_PROPERTY_FN(seg_start_pe, lvseg->le)
@ -499,6 +515,8 @@ GET_LVSEG_STR_PROPERTY_FN(seg_monitor, lvseg_monitor_dup(lvseg->lv->vg->vgmem, l
#define _kernel_cache_settings_set prop_not_implemented_set #define _kernel_cache_settings_set prop_not_implemented_set
#define _kernel_cache_policy_get prop_not_implemented_get #define _kernel_cache_policy_get prop_not_implemented_get
#define _kernel_cache_policy_set prop_not_implemented_set #define _kernel_cache_policy_set prop_not_implemented_set
#define _kernel_metadata_format_get prop_not_implemented_get
#define _kernel_metadata_format_set prop_not_implemented_set
/* PVSEG */ /* PVSEG */
GET_PVSEG_NUM_PROPERTY_FN(pvseg_start, pvseg->pe) GET_PVSEG_NUM_PROPERTY_FN(pvseg_start, pvseg->pe)

View File

@ -54,6 +54,7 @@ enum {
static const uint64_t _zero64 = UINT64_C(0); static const uint64_t _zero64 = UINT64_C(0);
static const uint64_t _one64 = UINT64_C(1); static const uint64_t _one64 = UINT64_C(1);
static const uint64_t _two64 = UINT64_C(2);
static const char _str_zero[] = "0"; static const char _str_zero[] = "0";
static const char _str_one[] = "1"; static const char _str_one[] = "1";
static const char _str_no[] = "no"; static const char _str_no[] = "no";
@ -1007,7 +1008,7 @@ static int _translate_time_items(struct dm_report *rh, struct time_info *info,
dm_pool_free(info->mem, info->ti_list); dm_pool_free(info->mem, info->ti_list);
info->ti_list = NULL; info->ti_list = NULL;
if (dm_snprintf(buf, sizeof(buf), "@%ld:@%ld", t1, t2) == -1) { if (dm_snprintf(buf, sizeof(buf), "@" FMTd64 ":@" FMTd64, (int64_t)t1, (int64_t)t2) == -1) {
log_error("_translate_time_items: dm_snprintf failed"); log_error("_translate_time_items: dm_snprintf failed");
return 0; return 0;
} }
@ -1062,10 +1063,10 @@ static void *_lv_time_handler_get_dynamic_value(struct dm_report *rh,
struct dm_pool *mem, struct dm_pool *mem,
const char *data_in) const char *data_in)
{ {
time_t t1, t2; int64_t t1, t2;
time_t *result; time_t *result;
if (sscanf(data_in, "@%ld:@%ld", &t1, &t2) != 2) { if (sscanf(data_in, "@" FMTd64 ":@" FMTd64, &t1, &t2) != 2) {
log_error("Failed to get value for parsed time specification."); log_error("Failed to get value for parsed time specification.");
return NULL; return NULL;
} }
@ -1075,8 +1076,8 @@ static void *_lv_time_handler_get_dynamic_value(struct dm_report *rh,
return NULL; return NULL;
} }
result[0] = t1; result[0] = (time_t) t1; /* Validate range for 32b arch ? */
result[1] = t2; result[1] = (time_t) t2;
return result; return result;
} }
@ -1537,6 +1538,21 @@ static int _kernel_cache_policy_disp(struct dm_report *rh, struct dm_pool *mem,
GET_FIELD_RESERVED_VALUE(cache_policy_undef)); GET_FIELD_RESERVED_VALUE(cache_policy_undef));
} }
static int _kernelmetadataformat_disp(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field,
const void *data, void *private)
{
const struct lv_with_info_and_seg_status *lvdm = (const struct lv_with_info_and_seg_status *) data;
unsigned format;
if (lvdm->seg_status.type == SEG_STATUS_CACHE) {
format = (lvdm->seg_status.cache->feature_flags & DM_CACHE_FEATURE_METADATA2);
return dm_report_field_uint64(rh, field, format ? &_two64 : &_one64);
}
return _field_set_value(field, "", &GET_TYPE_RESERVED_VALUE(num_undef_64));
}
static int _cache_policy_disp(struct dm_report *rh, struct dm_pool *mem, static int _cache_policy_disp(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field, struct dm_report_field *field,
const void *data, void *private) const void *data, void *private)
@ -2296,6 +2312,22 @@ static int _size64_disp(struct dm_report *rh __attribute__((unused)),
return _field_set_value(field, repstr, sortval); return _field_set_value(field, repstr, sortval);
} }
static int _lv_size_disp(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field,
const void *data, void *private)
{
const struct logical_volume *lv = (const struct logical_volume *) data;
const struct lv_segment *seg = first_seg(lv);
uint64_t size = lv->le_count;
if (seg && !lv_is_raid_image(lv))
size -= seg->reshape_len * (seg->area_count > 2 ? (seg->area_count - seg->segtype->parity_devs) : 1);
size *= lv->vg->extent_size;
return _size64_disp(rh, mem, field, &size, private);
}
static int _uint32_disp(struct dm_report *rh, struct dm_pool *mem __attribute__((unused)), static int _uint32_disp(struct dm_report *rh, struct dm_pool *mem __attribute__((unused)),
struct dm_report_field *field, struct dm_report_field *field,
const void *data, void *private __attribute__((unused))) const void *data, void *private __attribute__((unused)))
@ -2412,6 +2444,197 @@ static int _segstartpe_disp(struct dm_report *rh,
return dm_report_field_uint32(rh, field, &seg->le); return dm_report_field_uint32(rh, field, &seg->le);
} }
/* Hepler: get used stripes = total stripes minux any to remove after reshape */
static int _get_seg_used_stripes(const struct lv_segment *seg)
{
uint32_t s;
uint32_t stripes = seg->area_count;
for (s = seg->area_count - 1; stripes && s; s--) {
if (seg_type(seg, s) == AREA_LV &&
seg_lv(seg, s)->status & LV_REMOVE_AFTER_RESHAPE)
stripes--;
else
break;
}
return stripes;
}
static int _seg_stripes_disp(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field,
const void *data, void *private)
{
const struct lv_segment *seg = ((const struct lv_segment *) data);
return dm_report_field_uint32(rh, field, &seg->area_count);
}
/* Report the number of data stripes, which is less than total stripes (e.g. 2 less for raid6) */
static int _seg_data_stripes_disp(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field,
const void *data, void *private)
{
const struct lv_segment *seg = (const struct lv_segment *) data;
uint32_t stripes = _get_seg_used_stripes(seg) - seg->segtype->parity_devs;
/* FIXME: in case of odd numbers of raid10 stripes */
if (seg_is_raid10(seg))
stripes /= seg->data_copies;
return dm_report_field_uint32(rh, field, &stripes);
}
/* Helper: return the top-level, reshapable raid LV in case @seg belongs to an raid rimage LV */
static struct logical_volume *_lv_for_raid_image_seg(const struct lv_segment *seg, struct dm_pool *mem)
{
char *lv_name;
if (seg_is_reshapable_raid(seg))
return seg->lv;
if (seg->lv &&
lv_is_raid_image(seg->lv) && !seg->le &&
(lv_name = dm_pool_strdup(mem, seg->lv->name))) {
char *p = strchr(lv_name, '_');
if (p) {
/* Handle duplicated sub LVs */
if (strstr(p, "_dup_"))
p = strchr(p + 5, '_');
if (p) {
struct lv_list *lvl;
*p = '\0';
if ((lvl = find_lv_in_vg(seg->lv->vg, lv_name)) &&
seg_is_reshapable_raid(first_seg(lvl->lv)))
return lvl->lv;
}
}
}
return NULL;
}
/* Helper: return the top-level raid LV in case it is reshapale for @seg or @seg if it is */
static const struct lv_segment *_get_reshapable_seg(const struct lv_segment *seg, struct dm_pool *mem)
{
return _lv_for_raid_image_seg(seg, mem) ? seg : NULL;
}
/* Display segment reshape length in current units */
static int _seg_reshape_len_disp(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field,
const void *data, void *private)
{
const struct lv_segment *seg = _get_reshapable_seg((const struct lv_segment *) data, mem);
if (seg) {
uint32_t reshape_len = seg->reshape_len * seg->area_count * seg->lv->vg->extent_size;
return _size32_disp(rh, mem, field, &reshape_len, private);
}
return _field_set_value(field, "", &GET_TYPE_RESERVED_VALUE(num_undef_64));
}
/* Display segment reshape length of in logical extents */
static int _seg_reshape_len_le_disp(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field,
const void *data, void *private)
{
const struct lv_segment *seg = _get_reshapable_seg((const struct lv_segment *) data, mem);
if (seg) {
uint32_t reshape_len = seg->reshape_len* seg->area_count;
return dm_report_field_uint32(rh, field, &reshape_len);
}
return _field_set_value(field, "", &GET_TYPE_RESERVED_VALUE(num_undef_64));
}
/* Display segment data copies (e.g. 3 for raid6) */
static int _seg_data_copies_disp(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field,
const void *data, void *private)
{
const struct lv_segment *seg = (const struct lv_segment *) data;
if (seg->data_copies)
return dm_report_field_uint32(rh, field, &seg->data_copies);
return _field_set_value(field, "", &GET_TYPE_RESERVED_VALUE(num_undef_64));
}
/* Helper: display segment data offset/new data offset in sectors */
static int _segdata_offset(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field,
const void *data, void *private, int new_data_offset)
{
const struct lv_segment *seg = (const struct lv_segment *) data;
struct logical_volume *lv;
if ((lv = _lv_for_raid_image_seg(seg, mem))) {
uint64_t data_offset;
if (lv_raid_data_offset(lv, &data_offset)) {
if (new_data_offset && !lv_raid_image_in_sync(seg->lv))
data_offset = data_offset ? 0 : (uint64_t) seg->reshape_len * lv->vg->extent_size;
return dm_report_field_uint64(rh, field, &data_offset);
}
}
return _field_set_value(field, "", &GET_TYPE_RESERVED_VALUE(num_undef_64));
}
static int _seg_data_offset_disp(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field,
const void *data, void *private)
{
return _segdata_offset(rh, mem, field, data, private, 0);
}
static int _seg_new_data_offset_disp(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field,
const void *data, void *private)
{
return _segdata_offset(rh, mem, field, data, private, 1);
}
static int _seg_parity_chunks_disp(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field,
const void *data, void *private)
{
const struct lv_segment *seg = (const struct lv_segment *) data;
uint32_t parity_chunks = seg->segtype->parity_devs ?: seg->data_copies - 1;
if (parity_chunks) {
uint32_t s, resilient_sub_lvs = 0;
for (s = 0; s < seg->area_count; s++) {
if (seg_type(seg, s) == AREA_LV) {
struct lv_segment *seg1 = first_seg(seg_lv(seg, s));
if (seg1->segtype->parity_devs ||
seg1->data_copies > 1)
resilient_sub_lvs++;
}
}
if (resilient_sub_lvs && resilient_sub_lvs == seg->area_count)
parity_chunks++;
return dm_report_field_uint32(rh, field, &parity_chunks);
}
return _field_set_value(field, "", &GET_TYPE_RESERVED_VALUE(num_undef_64));
}
static int _segsize_disp(struct dm_report *rh, struct dm_pool *mem, static int _segsize_disp(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field, struct dm_report_field *field,
const void *data, void *private) const void *data, void *private)
@ -2511,6 +2734,29 @@ static int _cachemode_disp(struct dm_report *rh, struct dm_pool *mem,
return _field_string(rh, field, display_cache_mode(seg)); return _field_string(rh, field, display_cache_mode(seg));
} }
static int _cachemetadataformat_disp(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field,
const void *data, void *private)
{
const struct lv_segment *seg = (const struct lv_segment *) data;
const uint64_t *fmt;
if (seg_is_cache(seg))
seg = first_seg(seg->pool_lv);
if (seg_is_cache_pool(seg)) {
switch (seg->cache_metadata_format) {
case CACHE_METADATA_FORMAT_1:
case CACHE_METADATA_FORMAT_2:
fmt = (seg->cache_metadata_format == CACHE_METADATA_FORMAT_2) ? &_two64 : &_one64;
return dm_report_field_uint64(rh, field, fmt);
default: /* unselected/undefined for all other cases */;
}
}
return _field_set_value(field, "", &GET_TYPE_RESERVED_VALUE(num_undef_64));
}
static int _originsize_disp(struct dm_report *rh, struct dm_pool *mem, static int _originsize_disp(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field, struct dm_report_field *field,
const void *data, void *private) const void *data, void *private)
@ -3447,7 +3693,7 @@ static int _thinzero_disp(struct dm_report *rh, struct dm_pool *mem,
seg = first_seg(seg->pool_lv); seg = first_seg(seg->pool_lv);
if (seg_is_thin_pool(seg)) if (seg_is_thin_pool(seg))
return _binary_disp(rh, mem, field, seg->zero_new_blocks, GET_FIRST_RESERVED_NAME(zero_y), private); return _binary_disp(rh, mem, field, (seg->zero_new_blocks == THIN_ZERO_YES), GET_FIRST_RESERVED_NAME(zero_y), private);
return _binary_undef_disp(rh, mem, field, private); return _binary_undef_disp(rh, mem, field, private);
} }

View File

@ -45,7 +45,7 @@ static void _thin_pool_display(const struct lv_segment *seg)
dm_list_size(&seg->lv->segs_using_this_lv)); dm_list_size(&seg->lv->segs_using_this_lv));
log_print(" Transaction ID\t%" PRIu64, seg->transaction_id); log_print(" Transaction ID\t%" PRIu64, seg->transaction_id);
log_print(" Zero new blocks\t%s", log_print(" Zero new blocks\t%s",
seg->zero_new_blocks ? "yes" : "no"); (seg->zero_new_blocks == THIN_ZERO_YES) ? "yes" : "no");
log_print(" "); log_print(" ");
} }
@ -84,6 +84,7 @@ static int _thin_pool_text_import(struct lv_segment *seg,
const char *lv_name; const char *lv_name;
struct logical_volume *pool_data_lv, *pool_metadata_lv; struct logical_volume *pool_data_lv, *pool_metadata_lv;
const char *discards_str = NULL; const char *discards_str = NULL;
uint32_t zero = 0;
if (!dm_config_get_str(sn, "metadata", &lv_name)) if (!dm_config_get_str(sn, "metadata", &lv_name))
return SEG_LOG_ERROR("Metadata must be a string in"); return SEG_LOG_ERROR("Metadata must be a string in");
@ -124,9 +125,11 @@ static int _thin_pool_text_import(struct lv_segment *seg,
seg->device_id); seg->device_id);
if (dm_config_has_node(sn, "zero_new_blocks") && if (dm_config_has_node(sn, "zero_new_blocks") &&
!dm_config_get_uint32(sn, "zero_new_blocks", &seg->zero_new_blocks)) !dm_config_get_uint32(sn, "zero_new_blocks", &zero))
return SEG_LOG_ERROR("Could not read zero_new_blocks for"); return SEG_LOG_ERROR("Could not read zero_new_blocks for");
seg->zero_new_blocks = (zero) ? THIN_ZERO_YES : THIN_ZERO_NO;
/* Read messages */ /* Read messages */
for (; sn; sn = sn->sib) for (; sn; sn = sn->sib)
if (!(sn->v) && !_thin_pool_add_message(seg, sn->key, sn->child)) if (!(sn->v) && !_thin_pool_add_message(seg, sn->key, sn->child))
@ -165,8 +168,13 @@ static int _thin_pool_text_export(const struct lv_segment *seg, struct formatter
return 0; return 0;
} }
if (seg->zero_new_blocks) if (seg->zero_new_blocks == THIN_ZERO_YES)
outf(f, "zero_new_blocks = 1"); outf(f, "zero_new_blocks = 1");
else if (seg->zero_new_blocks != THIN_ZERO_NO) {
log_error(INTERNAL_ERROR "Invalid zero new blocks value %d.",
seg->zero_new_blocks);
return 0;
}
dm_list_iterate_items(tmsg, &seg->thin_messages) { dm_list_iterate_items(tmsg, &seg->thin_messages) {
/* Extra validation */ /* Extra validation */
@ -304,7 +312,7 @@ static int _thin_pool_add_target_line(struct dev_manager *dm,
seg->transaction_id, seg->transaction_id,
metadata_dlid, pool_dlid, metadata_dlid, pool_dlid,
seg->chunk_size, low_water_mark, seg->chunk_size, low_water_mark,
seg->zero_new_blocks ? 0 : 1)) (seg->zero_new_blocks == THIN_ZERO_YES) ? 0 : 1))
return_0; return_0;
if (attr & THIN_FEATURE_DISCARDS) { if (attr & THIN_FEATURE_DISCARDS) {

View File

@ -260,7 +260,7 @@ struct dm_config_node *config_make_nodes_v(struct dm_config_tree *cft,
key[fmt - next] = '\0'; key[fmt - next] = '\0';
fmt += 2; fmt += 2;
if (!strcmp(fmt, "%d") || !strcmp(fmt, FMTd64)) { if (!strcmp(fmt, FMTd64)) {
int64_t value = va_arg(ap, int64_t); int64_t value = va_arg(ap, int64_t);
if (!(cn = make_int_node(cft, key, value, parent, pre_sib))) if (!(cn = make_int_node(cft, key, value, parent, pre_sib)))
return 0; return 0;

View File

@ -234,7 +234,6 @@ dm_tree_free
dm_tree_get_cookie dm_tree_get_cookie
dm_tree_children_use_uuid dm_tree_children_use_uuid
dm_tree_next_child dm_tree_next_child
dm_tree_node_add_cache_target
dm_tree_node_add_crypt_target dm_tree_node_add_crypt_target
dm_tree_node_add_error_target dm_tree_node_add_error_target
dm_tree_node_add_linear_target dm_tree_node_add_linear_target

View File

@ -1,5 +1,9 @@
dm_bit_get_last dm_bit_get_last
dm_bit_get_prev dm_bit_get_prev
dm_filemapd_mode_from_string
dm_stats_update_regions_from_fd dm_stats_update_regions_from_fd
dm_bitset_parse_list dm_bitset_parse_list
dm_stats_bind_from_fd dm_stats_bind_from_fd
dm_stats_start_filemapd
dm_tree_node_add_raid_target_with_params_v2
dm_tree_node_add_cache_target

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004-2015 Red Hat, Inc. All rights reserved. * Copyright (C) 2004-2017 Red Hat, Inc. All rights reserved.
* Copyright (C) 2006 Rackable Systems All rights reserved. * Copyright (C) 2006 Rackable Systems All rights reserved.
* *
* This file is part of the device-mapper userspace tools. * This file is part of the device-mapper userspace tools.
@ -331,6 +331,7 @@ struct dm_status_raid {
char *dev_health; char *dev_health;
/* idle, frozen, resync, recover, check, repair */ /* idle, frozen, resync, recover, check, repair */
char *sync_action; char *sync_action;
uint64_t data_offset; /* RAID out-of-place reshaping */
}; };
int dm_get_status_raid(struct dm_pool *mem, const char *params, int dm_get_status_raid(struct dm_pool *mem, const char *params,
@ -358,7 +359,7 @@ struct dm_status_cache {
uint64_t demotions; uint64_t demotions;
uint64_t promotions; uint64_t promotions;
uint64_t feature_flags; uint64_t feature_flags; /* DM_CACHE_FEATURE_? */
int core_argc; int core_argc;
char **core_argv; char **core_argv;
@ -1368,6 +1369,73 @@ uint64_t *dm_stats_create_regions_from_fd(struct dm_stats *dms, int fd,
uint64_t *dm_stats_update_regions_from_fd(struct dm_stats *dms, int fd, uint64_t *dm_stats_update_regions_from_fd(struct dm_stats *dms, int fd,
uint64_t group_id); uint64_t group_id);
/*
* The file map monitoring daemon can monitor files in two distinct
* ways: the mode affects the behaviour of the daemon when a file
* under monitoring is renamed or unlinked, and the conditions which
* cause the daemon to terminate.
*
* In both modes, the daemon will always shut down when the group
* being monitored is deleted.
*
* Follow inode:
* The daemon follows the inode of the file, as it was at the time the
* daemon started. The file descriptor referencing the file is kept
* open at all times, and the daemon will exit when it detects that
* the file has been unlinked and it is the last holder of a reference
* to the file.
*
* This mode is useful if the file is expected to be renamed, or moved
* within the file system, while it is being monitored.
*
* Follow path:
* The daemon follows the path that was given on the daemon command
* line. The file descriptor referencing the file is re-opened on each
* iteration of the daemon, and the daemon will exit if no file exists
* at this location (a tolerance is allowed so that a brief delay
* between unlink() and creat() is permitted).
*
* This mode is useful if the file is updated by unlinking the original
* and placing a new file at the same path.
*/
typedef enum {
DM_FILEMAPD_FOLLOW_INODE,
DM_FILEMAPD_FOLLOW_PATH,
DM_FILEMAPD_FOLLOW_NONE
} dm_filemapd_mode_t;
/*
* Parse a string representation of a dmfilemapd mode.
*
* Returns a valid dm_filemapd_mode_t value on success, or
* DM_FILEMAPD_FOLLOW_NONE on error.
*/
dm_filemapd_mode_t dm_filemapd_mode_from_string(const char *mode_str);
/*
* Start the dmfilemapd filemap monitoring daemon for the specified
* file descriptor, group, and file system path. The daemon will
* monitor the file for allocation changes, and when a change is
* detected, call dm_stats_update_regions_from_fd() to update the
* mapped regions for the file.
*
* The path provided to dm_stats_start_filemapd() must be an absolute
* path, and should reflect the path of 'fd' at the time that it was
* opened.
*
* The mode parameter controls the behaviour of the daemon when the
* file being monitored is unlinked or moved: see the comments for
* dm_filemapd_mode_t for a full description and possible values.
*
* The daemon can be stopped at any time by sending SIGTERM to the
* daemon pid.
*/
int dm_stats_start_filemapd(int fd, uint64_t group_id, const char *path,
dm_filemapd_mode_t mode, unsigned foreground,
unsigned verbose);
/* /*
* Call this to actually run the ioctl. * Call this to actually run the ioctl.
*/ */
@ -1738,6 +1806,11 @@ int dm_tree_node_add_raid_target(struct dm_tree_node *node,
*/ */
#define DM_CACHE_METADATA_MAX_SECTORS DM_THIN_METADATA_MAX_SECTORS #define DM_CACHE_METADATA_MAX_SECTORS DM_THIN_METADATA_MAX_SECTORS
/*
* Define number of elements in rebuild and writemostly arrays
* 'of struct dm_tree_node_raid_params'.
*/
struct dm_tree_node_raid_params { struct dm_tree_node_raid_params {
const char *raid_type; const char *raid_type;
@ -1749,29 +1822,75 @@ struct dm_tree_node_raid_params {
/* /*
* 'rebuilds' and 'writemostly' are bitfields that signify * 'rebuilds' and 'writemostly' are bitfields that signify
* which devices in the array are to be rebuilt or marked * which devices in the array are to be rebuilt or marked
* writemostly. By choosing a 'uint64_t', we limit ourself * writemostly. The kernel supports up to 253 legs.
* to RAID arrays with 64 devices. * We limit ourselves by choosing a lower value
* for DEFAULT_RAID{1}_MAX_IMAGES in defaults.h.
*/ */
uint64_t rebuilds; uint64_t rebuilds;
uint64_t writemostly; uint64_t writemostly;
uint32_t writebehind; /* I/Os (kernel default COUNTER_MAX / 2) */ uint32_t writebehind; /* I/Os (kernel default COUNTER_MAX / 2) */
uint32_t sync_daemon_sleep; /* ms (kernel default = 5sec) */
uint32_t max_recovery_rate; /* kB/sec/disk */
uint32_t min_recovery_rate; /* kB/sec/disk */
uint32_t stripe_cache; /* sectors */
uint64_t flags; /* [no]sync */
uint32_t reserved2;
};
/*
* Version 2 of above node raid params struct to keeep API compatibility.
*
* Extended for more than 64 legs (max 253 in the MD kernel runtime!),
* delta_disks for disk add/remove reshaping,
* data_offset for out-of-place reshaping
* and data_copies for odd number of raid10 legs.
*/
#define RAID_BITMAP_SIZE 4 /* 4 * 64 bit elements in rebuilds/writemostly arrays */
struct dm_tree_node_raid_params_v2 {
const char *raid_type;
uint32_t stripes;
uint32_t mirrors;
uint32_t region_size;
uint32_t stripe_size;
int delta_disks; /* +/- number of disks to add/remove (reshaping) */
int data_offset; /* data offset to set (out-of-place reshaping) */
/*
* 'rebuilds' and 'writemostly' are bitfields that signify
* which devices in the array are to be rebuilt or marked
* writemostly. The kernel supports up to 253 legs.
* We limit ourselvs by choosing a lower value
* for DEFAULT_RAID_MAX_IMAGES.
*/
uint64_t rebuilds[RAID_BITMAP_SIZE];
uint64_t writemostly[RAID_BITMAP_SIZE];
uint32_t writebehind; /* I/Os (kernel default COUNTER_MAX / 2) */
uint32_t data_copies; /* RAID # of data copies */
uint32_t sync_daemon_sleep; /* ms (kernel default = 5sec) */ uint32_t sync_daemon_sleep; /* ms (kernel default = 5sec) */
uint32_t max_recovery_rate; /* kB/sec/disk */ uint32_t max_recovery_rate; /* kB/sec/disk */
uint32_t min_recovery_rate; /* kB/sec/disk */ uint32_t min_recovery_rate; /* kB/sec/disk */
uint32_t stripe_cache; /* sectors */ uint32_t stripe_cache; /* sectors */
uint64_t flags; /* [no]sync */ uint64_t flags; /* [no]sync */
uint64_t reserved2;
}; };
int dm_tree_node_add_raid_target_with_params(struct dm_tree_node *node, int dm_tree_node_add_raid_target_with_params(struct dm_tree_node *node,
uint64_t size, uint64_t size,
const struct dm_tree_node_raid_params *p); const struct dm_tree_node_raid_params *p);
/* Version 2 API function taking dm_tree_node_raid_params_v2 for aforementioned extensions. */
int dm_tree_node_add_raid_target_with_params_v2(struct dm_tree_node *node,
uint64_t size,
const struct dm_tree_node_raid_params_v2 *p);
/* Cache feature_flags */ /* Cache feature_flags */
#define DM_CACHE_FEATURE_WRITEBACK 0x00000001 #define DM_CACHE_FEATURE_WRITEBACK 0x00000001
#define DM_CACHE_FEATURE_WRITETHROUGH 0x00000002 #define DM_CACHE_FEATURE_WRITETHROUGH 0x00000002
#define DM_CACHE_FEATURE_PASSTHROUGH 0x00000004 #define DM_CACHE_FEATURE_PASSTHROUGH 0x00000004
#define DM_CACHE_FEATURE_METADATA2 0x00000008 /* cache v1.10 */
struct dm_config_node; struct dm_config_node;
/* /*

View File

@ -205,11 +205,14 @@ struct load_segment {
struct dm_tree_node *replicator;/* Replicator-dev */ struct dm_tree_node *replicator;/* Replicator-dev */
uint64_t rdevice_index; /* Replicator-dev */ uint64_t rdevice_index; /* Replicator-dev */
uint64_t rebuilds; /* raid */ int delta_disks; /* raid reshape number of disks */
uint64_t writemostly; /* raid */ int data_offset; /* raid reshape data offset on disk to set */
uint64_t rebuilds[RAID_BITMAP_SIZE]; /* raid */
uint64_t writemostly[RAID_BITMAP_SIZE]; /* raid */
uint32_t writebehind; /* raid */ uint32_t writebehind; /* raid */
uint32_t max_recovery_rate; /* raid kB/sec/disk */ uint32_t max_recovery_rate; /* raid kB/sec/disk */
uint32_t min_recovery_rate; /* raid kB/sec/disk */ uint32_t min_recovery_rate; /* raid kB/sec/disk */
uint32_t data_copies; /* raid10 data_copies */
struct dm_tree_node *metadata; /* Thin_pool + Cache */ struct dm_tree_node *metadata; /* Thin_pool + Cache */
struct dm_tree_node *pool; /* Thin_pool, Thin */ struct dm_tree_node *pool; /* Thin_pool, Thin */
@ -1731,9 +1734,11 @@ static int _dm_tree_deactivate_children(struct dm_tree_node *dnode,
!child->callback(child, DM_NODE_CALLBACK_DEACTIVATED, !child->callback(child, DM_NODE_CALLBACK_DEACTIVATED,
child->callback_data)) child->callback_data))
stack; stack;
// FIXME: We need to let lvremove pass, /* FIXME Deactivation must currently ignore failure
// so for now deactivation ignores check result * here so that lvremove can continue: we need an
//r = 0; // FIXME: _node_clear_table() without callback ? * alternative way to handle this state without
* setting r=0. Or better, skip calling thin_check
* entirely if the device is about to be removed. */
if (dm_tree_node_num_children(child, 0) && if (dm_tree_node_num_children(child, 0) &&
!_dm_tree_deactivate_children(child, uuid_prefix, uuid_prefix_len, level + 1)) !_dm_tree_deactivate_children(child, uuid_prefix, uuid_prefix_len, level + 1))
@ -2353,16 +2358,66 @@ static int _mirror_emit_segment_line(struct dm_task *dmt, struct load_segment *s
return 1; return 1;
} }
/* Is parameter non-zero? */ static int _2_if_value(unsigned p)
#define PARAM_IS_SET(p) ((p) ? 1 : 0) {
return p ? 2 : 0;
}
/* Return number of bits assuming 4 * 64 bit size */ /* Return number of bits passed in @bits assuming 2 * 64 bit size */
static int _get_params_count(uint64_t bits) static int _get_params_count(uint64_t *bits)
{ {
int r = 0; int r = 0;
int i = RAID_BITMAP_SIZE;
r += 2 * hweight32(bits & 0xFFFFFFFF); while (i--) {
r += 2 * hweight32(bits >> 32); r += 2 * hweight32(bits[i] & 0xFFFFFFFF);
r += 2 * hweight32(bits[i] >> 32);
}
return r;
}
/*
* Get target version (major, minor and patchlevel) for @target_name
*
* FIXME: this function is derived from liblvm.
* Integrate with move of liblvm functions
* to libdm in future library layer purge
* (e.g. expose as API dm_target_version()?)
*/
static int _target_version(const char *target_name, uint32_t *maj,
uint32_t *min, uint32_t *patchlevel)
{
int r = 0;
struct dm_task *dmt;
struct dm_versions *target, *last_target = NULL;
log_very_verbose("Getting target version for %s", target_name);
if (!(dmt = dm_task_create(DM_DEVICE_LIST_VERSIONS)))
return_0;
if (!dm_task_run(dmt)) {
log_debug_activation("Failed to get %s target versions", target_name);
/* Assume this was because LIST_VERSIONS isn't supported */
maj = min = patchlevel = 0;
r = 1;
} else
for (target = dm_task_get_versions(dmt);
target != last_target;
last_target = target, target = (struct dm_versions *)((char *) target + target->next))
if (!strcmp(target_name, target->name)) {
*maj = target->version[0];
*min = target->version[1];
*patchlevel = target->version[2];
log_very_verbose("Found %s target "
"v%" PRIu32 ".%" PRIu32 ".%" PRIu32 ".",
target_name, *maj, *min, *patchlevel);
r = 1;
break;
}
dm_task_destroy(dmt);
return r; return r;
} }
@ -2373,61 +2428,129 @@ static int _raid_emit_segment_line(struct dm_task *dmt, uint32_t major,
size_t paramsize) size_t paramsize)
{ {
uint32_t i; uint32_t i;
uint32_t area_count = seg->area_count / 2;
uint32_t maj, min, patchlevel;
int param_count = 1; /* mandatory 'chunk size'/'stripe size' arg */ int param_count = 1; /* mandatory 'chunk size'/'stripe size' arg */
int pos = 0; int pos = 0;
unsigned type = seg->type; unsigned type;
if (seg->area_count % 2)
return 0;
if ((seg->flags & DM_NOSYNC) || (seg->flags & DM_FORCESYNC)) if ((seg->flags & DM_NOSYNC) || (seg->flags & DM_FORCESYNC))
param_count++; param_count++;
param_count += 2 * (PARAM_IS_SET(seg->region_size) + param_count += _2_if_value(seg->data_offset) +
PARAM_IS_SET(seg->writebehind) + _2_if_value(seg->delta_disks) +
PARAM_IS_SET(seg->min_recovery_rate) + _2_if_value(seg->region_size) +
PARAM_IS_SET(seg->max_recovery_rate)); _2_if_value(seg->writebehind) +
_2_if_value(seg->min_recovery_rate) +
_2_if_value(seg->max_recovery_rate) +
_2_if_value(seg->data_copies > 1);
/* rebuilds and writemostly are 64 bits */ /* rebuilds and writemostly are BITMAP_SIZE * 64 bits */
param_count += _get_params_count(seg->rebuilds); param_count += _get_params_count(seg->rebuilds);
param_count += _get_params_count(seg->writemostly); param_count += _get_params_count(seg->writemostly);
if ((type == SEG_RAID1) && seg->stripe_size) if ((seg->type == SEG_RAID1) && seg->stripe_size)
log_error("WARNING: Ignoring RAID1 stripe size"); log_info("WARNING: Ignoring RAID1 stripe size");
/* Kernel only expects "raid0", not "raid0_meta" */ /* Kernel only expects "raid0", not "raid0_meta" */
type = seg->type;
if (type == SEG_RAID0_META) if (type == SEG_RAID0_META)
type = SEG_RAID0; type = SEG_RAID0;
EMIT_PARAMS(pos, "%s %d %u", _dm_segtypes[type].target, EMIT_PARAMS(pos, "%s %d %u",
type == SEG_RAID10 ? "raid10" : _dm_segtypes[type].target,
param_count, seg->stripe_size); param_count, seg->stripe_size);
if (seg->flags & DM_NOSYNC) if (!_target_version("raid", &maj, &min, &patchlevel))
EMIT_PARAMS(pos, " nosync"); return_0;
else if (seg->flags & DM_FORCESYNC)
EMIT_PARAMS(pos, " sync");
if (seg->region_size) /*
EMIT_PARAMS(pos, " region_size %u", seg->region_size); * Target version prior to 1.9.0 and >= 1.11.0 emit
* order of parameters as of kernel target documentation
*/
if (maj > 1 || (maj == 1 && (min < 9 || min >= 11))) {
if (seg->flags & DM_NOSYNC)
EMIT_PARAMS(pos, " nosync");
else if (seg->flags & DM_FORCESYNC)
EMIT_PARAMS(pos, " sync");
for (i = 0; i < (seg->area_count / 2); i++) for (i = 0; i < area_count; i++)
if (seg->rebuilds & (1ULL << i)) if (seg->rebuilds[i/64] & (1ULL << (i%64)))
EMIT_PARAMS(pos, " rebuild %u", i); EMIT_PARAMS(pos, " rebuild %u", i);
if (seg->min_recovery_rate) if (seg->min_recovery_rate)
EMIT_PARAMS(pos, " min_recovery_rate %u", EMIT_PARAMS(pos, " min_recovery_rate %u",
seg->min_recovery_rate); seg->min_recovery_rate);
if (seg->max_recovery_rate) if (seg->max_recovery_rate)
EMIT_PARAMS(pos, " max_recovery_rate %u", EMIT_PARAMS(pos, " max_recovery_rate %u",
seg->max_recovery_rate); seg->max_recovery_rate);
for (i = 0; i < (seg->area_count / 2); i++) for (i = 0; i < area_count; i++)
if (seg->writemostly & (1ULL << i)) if (seg->writemostly[i/64] & (1ULL << (i%64)))
EMIT_PARAMS(pos, " write_mostly %u", i); EMIT_PARAMS(pos, " write_mostly %u", i);
if (seg->writebehind) if (seg->writebehind)
EMIT_PARAMS(pos, " max_write_behind %u", seg->writebehind); EMIT_PARAMS(pos, " max_write_behind %u", seg->writebehind);
if (seg->region_size)
EMIT_PARAMS(pos, " region_size %u", seg->region_size);
if (seg->data_copies > 1 && type == SEG_RAID10)
EMIT_PARAMS(pos, " raid10_copies %u", seg->data_copies);
if (seg->delta_disks)
EMIT_PARAMS(pos, " delta_disks %d", seg->delta_disks);
/* If seg-data_offset == 1, kernel needs a zero offset to adjust to it */
if (seg->data_offset)
EMIT_PARAMS(pos, " data_offset %d", seg->data_offset == 1 ? 0 : seg->data_offset);
/* Target version >= 1.9.0 && < 1.11.0 had a table line parameter ordering flaw */
} else {
if (seg->data_copies > 1 && type == SEG_RAID10)
EMIT_PARAMS(pos, " raid10_copies %u", seg->data_copies);
if (seg->flags & DM_NOSYNC)
EMIT_PARAMS(pos, " nosync");
else if (seg->flags & DM_FORCESYNC)
EMIT_PARAMS(pos, " sync");
if (seg->region_size)
EMIT_PARAMS(pos, " region_size %u", seg->region_size);
/* If seg-data_offset == 1, kernel needs a zero offset to adjust to it */
if (seg->data_offset)
EMIT_PARAMS(pos, " data_offset %d", seg->data_offset == 1 ? 0 : seg->data_offset);
if (seg->delta_disks)
EMIT_PARAMS(pos, " delta_disks %d", seg->delta_disks);
for (i = 0; i < area_count; i++)
if (seg->rebuilds[i/64] & (1ULL << (i%64)))
EMIT_PARAMS(pos, " rebuild %u", i);
for (i = 0; i < area_count; i++)
if (seg->writemostly[i/64] & (1ULL << (i%64)))
EMIT_PARAMS(pos, " write_mostly %u", i);
if (seg->writebehind)
EMIT_PARAMS(pos, " max_write_behind %u", seg->writebehind);
if (seg->max_recovery_rate)
EMIT_PARAMS(pos, " max_recovery_rate %u",
seg->max_recovery_rate);
if (seg->min_recovery_rate)
EMIT_PARAMS(pos, " min_recovery_rate %u",
seg->min_recovery_rate);
}
/* Print number of metadata/data device pairs */ /* Print number of metadata/data device pairs */
EMIT_PARAMS(pos, " %u", seg->area_count/2); EMIT_PARAMS(pos, " %u", area_count);
if (_emit_areas_line(dmt, seg, params, paramsize, &pos) <= 0) if (_emit_areas_line(dmt, seg, params, paramsize, &pos) <= 0)
return_0; return_0;
@ -2467,12 +2590,17 @@ static int _cache_emit_segment_line(struct dm_task *dmt,
/* Features */ /* Features */
/* feature_count = hweight32(seg->flags); */ /* feature_count = hweight32(seg->flags); */
/* EMIT_PARAMS(pos, " %u", feature_count); */ /* EMIT_PARAMS(pos, " %u", feature_count); */
if (seg->flags & DM_CACHE_FEATURE_METADATA2)
EMIT_PARAMS(pos, " 2 metadata2 ");
else
EMIT_PARAMS(pos, " 1 ");
if (seg->flags & DM_CACHE_FEATURE_PASSTHROUGH) if (seg->flags & DM_CACHE_FEATURE_PASSTHROUGH)
EMIT_PARAMS(pos, " 1 passthrough"); EMIT_PARAMS(pos, "passthrough");
else if (seg->flags & DM_CACHE_FEATURE_WRITETHROUGH) else if (seg->flags & DM_CACHE_FEATURE_WRITEBACK)
EMIT_PARAMS(pos, " 1 writethrough"); EMIT_PARAMS(pos, "writeback");
else if (seg->flags & DM_CACHE_FEATURE_WRITEBACK) else
EMIT_PARAMS(pos, " 1 writeback"); EMIT_PARAMS(pos, "writethrough");
/* Cache Policy */ /* Cache Policy */
name = seg->policy_name ? : "default"; name = seg->policy_name ? : "default";
@ -2690,7 +2818,7 @@ static int _emit_segment(struct dm_task *dmt, uint32_t major, uint32_t minor,
struct load_segment *seg, uint64_t *seg_start) struct load_segment *seg, uint64_t *seg_start)
{ {
char *params; char *params;
size_t paramsize = 4096; size_t paramsize = 4096; /* FIXME: too small for long RAID lines when > 64 devices supported */
int ret; int ret;
do { do {
@ -3267,8 +3395,10 @@ int dm_tree_node_add_raid_target_with_params(struct dm_tree_node *node,
seg->region_size = p->region_size; seg->region_size = p->region_size;
seg->stripe_size = p->stripe_size; seg->stripe_size = p->stripe_size;
seg->area_count = 0; seg->area_count = 0;
seg->rebuilds = p->rebuilds; memset(seg->rebuilds, 0, sizeof(seg->rebuilds));
seg->writemostly = p->writemostly; seg->rebuilds[0] = p->rebuilds;
memset(seg->writemostly, 0, sizeof(seg->writemostly));
seg->writemostly[0] = p->writemostly;
seg->writebehind = p->writebehind; seg->writebehind = p->writebehind;
seg->min_recovery_rate = p->min_recovery_rate; seg->min_recovery_rate = p->min_recovery_rate;
seg->max_recovery_rate = p->max_recovery_rate; seg->max_recovery_rate = p->max_recovery_rate;
@ -3296,6 +3426,47 @@ int dm_tree_node_add_raid_target(struct dm_tree_node *node,
return dm_tree_node_add_raid_target_with_params(node, size, &params); return dm_tree_node_add_raid_target_with_params(node, size, &params);
} }
/*
* Version 2 of dm_tree_node_add_raid_target() allowing for:
*
* - maximum 253 legs in a raid set (MD kernel limitation)
* - delta_disks for disk add/remove reshaping
* - data_offset for out-of-place reshaping
* - data_copies to cope witth odd numbers of raid10 disks
*/
int dm_tree_node_add_raid_target_with_params_v2(struct dm_tree_node *node,
uint64_t size,
const struct dm_tree_node_raid_params_v2 *p)
{
unsigned i;
struct load_segment *seg = NULL;
for (i = 0; i < DM_ARRAY_SIZE(_dm_segtypes) && !seg; ++i)
if (!strcmp(p->raid_type, _dm_segtypes[i].target))
if (!(seg = _add_segment(node,
_dm_segtypes[i].type, size)))
return_0;
if (!seg) {
log_error("Unsupported raid type %s.", p->raid_type);
return 0;
}
seg->region_size = p->region_size;
seg->stripe_size = p->stripe_size;
seg->area_count = 0;
seg->delta_disks = p->delta_disks;
seg->data_offset = p->data_offset;
memcpy(seg->rebuilds, p->rebuilds, sizeof(seg->rebuilds));
memcpy(seg->writemostly, p->writemostly, sizeof(seg->writemostly));
seg->writebehind = p->writebehind;
seg->data_copies = p->data_copies;
seg->min_recovery_rate = p->min_recovery_rate;
seg->max_recovery_rate = p->max_recovery_rate;
seg->flags = p->flags;
return 1;
}
int dm_tree_node_add_cache_target(struct dm_tree_node *node, int dm_tree_node_add_cache_target(struct dm_tree_node *node,
uint64_t size, uint64_t size,
uint64_t feature_flags, /* DM_CACHE_FEATURE_* */ uint64_t feature_flags, /* DM_CACHE_FEATURE_* */
@ -3308,19 +3479,33 @@ int dm_tree_node_add_cache_target(struct dm_tree_node *node,
{ {
struct dm_config_node *cn; struct dm_config_node *cn;
struct load_segment *seg; struct load_segment *seg;
static const uint64_t _modemask =
DM_CACHE_FEATURE_PASSTHROUGH |
DM_CACHE_FEATURE_WRITETHROUGH |
DM_CACHE_FEATURE_WRITEBACK;
switch (feature_flags & /* Detect unknown (bigger) feature bit */
(DM_CACHE_FEATURE_PASSTHROUGH | if (feature_flags >= (DM_CACHE_FEATURE_METADATA2 * 2)) {
DM_CACHE_FEATURE_WRITETHROUGH | log_error("Unsupported cache's feature flags set " FMTu64 ".",
DM_CACHE_FEATURE_WRITEBACK)) { feature_flags);
case DM_CACHE_FEATURE_PASSTHROUGH: return 0;
case DM_CACHE_FEATURE_WRITETHROUGH: }
case DM_CACHE_FEATURE_WRITEBACK:
break; switch (feature_flags & _modemask) {
default: case DM_CACHE_FEATURE_PASSTHROUGH:
log_error("Invalid cache's feature flag " FMTu64 ".", case DM_CACHE_FEATURE_WRITEBACK:
feature_flags); if (strcmp(policy_name, "cleaner") == 0) {
return 0; /* Enforce writethrough mode for cleaner policy */
feature_flags = ~_modemask;
feature_flags |= DM_CACHE_FEATURE_WRITETHROUGH;
}
/* Fall through */
case DM_CACHE_FEATURE_WRITETHROUGH:
break;
default:
log_error("Invalid cache's feature flag " FMTu64 ".",
feature_flags);
return 0;
} }
if (data_block_size < DM_CACHE_MIN_DATA_BLOCK_SIZE) { if (data_block_size < DM_CACHE_MIN_DATA_BLOCK_SIZE) {
@ -3366,8 +3551,7 @@ int dm_tree_node_add_cache_target(struct dm_tree_node *node,
return_0; return_0;
seg->data_block_size = data_block_size; seg->data_block_size = data_block_size;
/* Enforce WriteThough mode for cleaner policy */ seg->flags = feature_flags;
seg->flags = (strcmp(policy_name, "cleaner") == 0) ? DM_CACHE_FEATURE_WRITETHROUGH : feature_flags;
seg->policy_name = policy_name; seg->policy_name = policy_name;
/* FIXME: better validation missing */ /* FIXME: better validation missing */
@ -3926,13 +4110,15 @@ void dm_tree_node_set_callback(struct dm_tree_node *dnode,
dnode->callback_data = data; dnode->callback_data = data;
} }
/*
* Backward compatible dm_tree_node_size_changed() implementations.
*
* Keep these at the end of the file to avoid adding clutter around the
* current dm_tree_node_size_changed() version.
*/
#if defined(__GNUC__) #if defined(__GNUC__)
/*
* Backward compatible implementations.
*
* Keep these at the end of the file to make sure that
* no code in this file accidentally calls it.
*/
/* Backward compatible dm_tree_node_size_changed() implementations. */
int dm_tree_node_size_changed_base(const struct dm_tree_node *dnode); int dm_tree_node_size_changed_base(const struct dm_tree_node *dnode);
DM_EXPORT_SYMBOL_BASE(dm_tree_node_size_changed); DM_EXPORT_SYMBOL_BASE(dm_tree_node_size_changed);
int dm_tree_node_size_changed_base(const struct dm_tree_node *dnode) int dm_tree_node_size_changed_base(const struct dm_tree_node *dnode)
@ -3940,4 +4126,43 @@ int dm_tree_node_size_changed_base(const struct dm_tree_node *dnode)
/* Base does not make difference between smaller and bigger */ /* Base does not make difference between smaller and bigger */
return dm_tree_node_size_changed(dnode) ? 1 : 0; return dm_tree_node_size_changed(dnode) ? 1 : 0;
} }
/*
* Retain ABI compatibility after adding the DM_CACHE_FEATURE_METADATA2
* in version 1.02.138.
*
* Binaries compiled against version 1.02.138 onwards will use
* the new function dm_tree_node_add_cache_target which detects unknown
* feature flags and returns error for them.
*/
int dm_tree_node_add_cache_target_base(struct dm_tree_node *node,
uint64_t size,
uint64_t feature_flags, /* DM_CACHE_FEATURE_* */
const char *metadata_uuid,
const char *data_uuid,
const char *origin_uuid,
const char *policy_name,
const struct dm_config_node *policy_settings,
uint32_t data_block_size);
DM_EXPORT_SYMBOL_BASE(dm_tree_node_add_cache_target);
int dm_tree_node_add_cache_target_base(struct dm_tree_node *node,
uint64_t size,
uint64_t feature_flags,
const char *metadata_uuid,
const char *data_uuid,
const char *origin_uuid,
const char *policy_name,
const struct dm_config_node *policy_settings,
uint32_t data_block_size)
{
/* Old version supported only these FEATURE bits, others were ignored so masked them */
static const uint64_t _mask =
DM_CACHE_FEATURE_WRITEBACK |
DM_CACHE_FEATURE_WRITETHROUGH |
DM_CACHE_FEATURE_PASSTHROUGH;
return dm_tree_node_add_cache_target(node, size, feature_flags & _mask,
metadata_uuid, data_uuid, origin_uuid,
policy_name, policy_settings, data_block_size);
}
#endif #endif

View File

@ -264,9 +264,12 @@ static int _stats_group_id_present(const struct dm_stats *dms, uint64_t id)
if (id == DM_STATS_GROUP_NOT_PRESENT) if (id == DM_STATS_GROUP_NOT_PRESENT)
return 0; return 0;
if (!dms || !dms->regions) if (!dms)
return_0; return_0;
if (!dms->regions)
return 0;
if (id > dms->max_region) if (id > dms->max_region)
return 0; return 0;
@ -675,10 +678,10 @@ static void _check_group_regions_present(struct dm_stats *dms,
group_id = i = dm_bit_get_first(regions); group_id = i = dm_bit_get_first(regions);
for (; i > 0; dm_bit_get_next(regions, i)) for (; i > 0; i = dm_bit_get_next(regions, i))
if (!_stats_region_present(&dms->regions[i])) { if (!_stats_region_present(&dms->regions[i])) {
log_warn("Group descriptor " FMTi64 " contains " log_warn("Group descriptor " FMTd64 " contains "
"non-existent region_id " FMTi64 ".", "non-existent region_id " FMTd64 ".",
group_id, i); group_id, i);
dm_bit_clear(regions, i); dm_bit_clear(regions, i);
} }
@ -2384,6 +2387,9 @@ bad:
*/ */
void dm_stats_destroy(struct dm_stats *dms) void dm_stats_destroy(struct dm_stats *dms)
{ {
if (!dms)
return;
_stats_regions_destroy(dms); _stats_regions_destroy(dms);
_stats_groups_destroy(dms); _stats_groups_destroy(dms);
_stats_clear_binding(dms); _stats_clear_binding(dms);
@ -3312,8 +3318,8 @@ static struct dm_histogram *_aggregate_histogram(const struct dm_stats *dms,
uint64_t area_id) uint64_t area_id)
{ {
struct dm_histogram *dmh_aggr, *dmh_cur, **dmh_cachep; struct dm_histogram *dmh_aggr, *dmh_cur, **dmh_cachep;
uint64_t group_id = DM_STATS_GROUP_NOT_PRESENT;
int bin, nr_bins, group = 1; int bin, nr_bins, group = 1;
uint64_t group_id;
size_t hist_size; size_t hist_size;
if (area_id == DM_STATS_WALK_REGION) { if (area_id == DM_STATS_WALK_REGION) {
@ -4175,21 +4181,23 @@ int dm_stats_get_group_descriptor(const struct dm_stats *dms,
* Resize the group bitmap corresponding to group_id so that it can * Resize the group bitmap corresponding to group_id so that it can
* contain at least num_regions members. * contain at least num_regions members.
*/ */
static int _stats_resize_group(struct dm_stats_group *group, int num_regions) static int _stats_resize_group(struct dm_stats_group *group,
uint64_t num_regions)
{ {
int last_bit = dm_bit_get_last(group->regions); uint64_t last_bit = dm_bit_get_last(group->regions);
dm_bitset_t new, old; dm_bitset_t new, old;
if (last_bit >= num_regions) { if (last_bit >= num_regions) {
log_error("Cannot resize group bitmap to %d with bit %d set.", log_error("Cannot resize group bitmap to " FMTu64
num_regions, last_bit); " with bit " FMTu64 " set.", num_regions, last_bit);
return 0; return 0;
} }
log_very_verbose("Resizing group bitmap from %d to %d (last_bit: %d).", log_very_verbose("Resizing group bitmap from " FMTu64
" to " FMTu64 " (last_bit: " FMTu64 ").",
group->regions[0], num_regions, last_bit); group->regions[0], num_regions, last_bit);
new = dm_bitset_create(NULL, num_regions); new = dm_bitset_create(NULL, (unsigned) num_regions);
if (!new) { if (!new) {
log_error("Could not allocate memory for new group bitmap."); log_error("Could not allocate memory for new group bitmap.");
return 0; return 0;
@ -4211,7 +4219,7 @@ static int _stats_group_file_regions(struct dm_stats *dms, uint64_t *region_ids,
dm_bitset_t regions = dm_bitset_create(NULL, dms->nr_regions); dm_bitset_t regions = dm_bitset_create(NULL, dms->nr_regions);
uint64_t i, group_id = DM_STATS_GROUP_NOT_PRESENT; uint64_t i, group_id = DM_STATS_GROUP_NOT_PRESENT;
char *members = NULL; char *members = NULL;
int buflen; size_t buflen;
if (!regions) { if (!regions) {
log_error("Cannot map file: failed to allocate group bitmap."); log_error("Cannot map file: failed to allocate group bitmap.");
@ -4395,10 +4403,14 @@ static struct _extent *_stats_get_extents_for_file(struct dm_pool *mem, int fd,
unsigned long flags = 0; unsigned long flags = 0;
uint64_t *buf; uint64_t *buf;
/* grow temporary extent table in the pool */
if (!dm_pool_begin_object(mem, sizeof(*extents)))
return NULL;
buf = dm_zalloc(STATS_FIE_BUF_LEN); buf = dm_zalloc(STATS_FIE_BUF_LEN);
if (!buf) { if (!buf) {
log_error("Could not allocate memory for FIEMAP buffer."); log_error("Could not allocate memory for FIEMAP buffer.");
return NULL; goto bad;
} }
/* initialise pointers into the ioctl buffer. */ /* initialise pointers into the ioctl buffer. */
@ -4409,10 +4421,6 @@ static struct _extent *_stats_get_extents_for_file(struct dm_pool *mem, int fd,
*count = (STATS_FIE_BUF_LEN - sizeof(*fiemap)) *count = (STATS_FIE_BUF_LEN - sizeof(*fiemap))
/ sizeof(struct fiemap_extent); / sizeof(struct fiemap_extent);
/* grow temporary extent table in the pool */
if (!dm_pool_begin_object(mem, sizeof(*extents)))
return NULL;
flags = FIEMAP_FLAG_SYNC; flags = FIEMAP_FLAG_SYNC;
do { do {
@ -4466,7 +4474,7 @@ bad:
#define MATCH_EXTENT(e, s, l) \ #define MATCH_EXTENT(e, s, l) \
(((e).start == (s)) && ((e).len == (l))) (((e).start == (s)) && ((e).len == (l)))
static struct _extent *_find_extent(size_t nr_extents, struct _extent *extents, static struct _extent *_find_extent(uint64_t nr_extents, struct _extent *extents,
uint64_t start, uint64_t len) uint64_t start, uint64_t len)
{ {
size_t i; size_t i;
@ -4503,8 +4511,9 @@ static int _stats_unmap_regions(struct dm_stats *dms, uint64_t group_id,
{ {
struct dm_stats_region *region = NULL; struct dm_stats_region *region = NULL;
struct dm_stats_group *group = NULL; struct dm_stats_group *group = NULL;
int64_t nr_kept, nr_old, i; uint64_t nr_kept, nr_old;
struct _extent ext; struct _extent ext;
int64_t i;
group = &dms->groups[group_id]; group = &dms->groups[group_id];
@ -4534,8 +4543,9 @@ static int _stats_unmap_regions(struct dm_stats *dms, uint64_t group_id,
ext.id = i; ext.id = i;
nr_kept++; nr_kept++;
dm_pool_grow_object(mem, &ext, if (!dm_pool_grow_object(mem, &ext, sizeof(ext)))
sizeof(ext)); goto out;
log_very_verbose("Kept region " FMTu64, i); log_very_verbose("Kept region " FMTu64, i);
} else { } else {
@ -4557,12 +4567,12 @@ static int _stats_unmap_regions(struct dm_stats *dms, uint64_t group_id,
log_error("Could not finalize region extent table."); log_error("Could not finalize region extent table.");
goto out; goto out;
} }
log_very_verbose("Kept " FMTi64 " of " FMTi64 " old extents", log_very_verbose("Kept " FMTd64 " of " FMTd64 " old extents",
nr_kept, nr_old); nr_kept, nr_old);
log_very_verbose("Found " FMTu64 " new extents", log_very_verbose("Found " FMTu64 " new extents",
*count - nr_kept); *count - nr_kept);
return nr_kept; return (int) nr_kept;
out: out:
dm_pool_abandon_object(mem); dm_pool_abandon_object(mem);
return -1; return -1;
@ -4585,15 +4595,15 @@ static uint64_t *_stats_map_file_regions(struct dm_stats *dms, int fd,
uint64_t *count, int *regroup) uint64_t *count, int *regroup)
{ {
struct _extent *extents = NULL, *old_extents = NULL; struct _extent *extents = NULL, *old_extents = NULL;
uint64_t *regions = NULL, fail_region; uint64_t *regions = NULL, fail_region, i, num_bits;
struct dm_stats_group *group = NULL; struct dm_stats_group *group = NULL;
struct dm_pool *extent_mem = NULL; struct dm_pool *extent_mem = NULL;
struct _extent *old_ext; struct _extent *old_ext;
char *hist_arg = NULL; char *hist_arg = NULL;
int update, num_bits;
struct statfs fsbuf; struct statfs fsbuf;
int64_t nr_kept = 0, i; int64_t nr_kept = 0;
struct stat buf; struct stat buf;
int update;
update = _stats_group_id_present(dms, group_id); update = _stats_group_id_present(dms, group_id);
@ -4678,9 +4688,10 @@ static uint64_t *_stats_map_file_regions(struct dm_stats *dms, int fd,
*/ */
for (i = 0; i < *count; i++) { for (i = 0; i < *count; i++) {
if (update) { if (update) {
if ((old_ext = _find_extent(nr_kept, old_extents, if ((old_ext = _find_extent((uint64_t) nr_kept,
extents[i].start, old_extents,
extents[i].len))) { extents[i].start,
extents[i].len))) {
regions[i] = old_ext->id; regions[i] = old_ext->id;
continue; continue;
} }
@ -4736,7 +4747,8 @@ out_remove:
* single list operation and call _stats_delete_region() directly * single list operation and call _stats_delete_region() directly
* to avoid a @stats_list ioctl and list parsing for each region. * to avoid a @stats_list ioctl and list parsing for each region.
*/ */
dm_stats_list(dms, NULL); if (!dm_stats_list(dms, NULL))
goto out;
fail_region = i; fail_region = i;
_stats_cleanup_region_ids(dms, regions, fail_region); _stats_cleanup_region_ids(dms, regions, fail_region);
@ -4769,7 +4781,8 @@ uint64_t *dm_stats_create_regions_from_fd(struct dm_stats *dms, int fd,
} }
if (!(regions = _stats_map_file_regions(dms, fd, bounds, precise, if (!(regions = _stats_map_file_regions(dms, fd, bounds, precise,
-1, &count, &regroup))) DM_STATS_GROUP_NOT_PRESENT,
&count, &regroup)))
return NULL; return NULL;
if (!group) if (!group)
@ -4874,9 +4887,7 @@ out:
dm_free((char *) alias); dm_free((char *) alias);
return NULL; return NULL;
} }
#else /* !HAVE_LINUX_FIEMAP */
#else /* HAVE_LINUX_FIEMAP */
uint64_t *dm_stats_create_regions_from_fd(struct dm_stats *dms, int fd, uint64_t *dm_stats_create_regions_from_fd(struct dm_stats *dms, int fd,
int group, int precise, int group, int precise,
struct dm_histogram *bounds, struct dm_histogram *bounds,
@ -4894,6 +4905,158 @@ uint64_t *dm_stats_update_regions_from_fd(struct dm_stats *dms, int fd,
} }
#endif /* HAVE_LINUX_FIEMAP */ #endif /* HAVE_LINUX_FIEMAP */
#ifdef DMFILEMAPD
static const char *_filemapd_mode_names[] = {
"inode",
"path",
NULL
};
dm_filemapd_mode_t dm_filemapd_mode_from_string(const char *mode_str)
{
dm_filemapd_mode_t mode = DM_FILEMAPD_FOLLOW_INODE;
const char **mode_name;
if (mode_str) {
for (mode_name = _filemapd_mode_names; *mode_name; mode_name++)
if (!strcmp(*mode_name, mode_str))
break;
if (*mode_name)
mode = DM_FILEMAPD_FOLLOW_INODE
+ (mode_name - _filemapd_mode_names);
else {
log_error("Could not parse dmfilemapd mode: %s",
mode_str);
return DM_FILEMAPD_FOLLOW_NONE;
}
}
return mode;
}
#define DM_FILEMAPD "dmfilemapd"
#define NR_FILEMAPD_ARGS 7 /* includes argv[0] */
/*
* Start dmfilemapd to monitor the specified file descriptor, and to
* update the group given by 'group_id' when the file's allocation
* changes.
*
* usage: dmfilemapd <fd> <group_id> <mode> [<foreground>[<log_level>]]
*/
int dm_stats_start_filemapd(int fd, uint64_t group_id, const char *path,
dm_filemapd_mode_t mode, unsigned foreground,
unsigned verbose)
{
char fd_str[8], group_str[8], fg_str[2], verb_str[2];
const char *mode_str = _filemapd_mode_names[mode];
char *args[NR_FILEMAPD_ARGS + 1];
pid_t pid = 0;
int argc = 0;
if (fd < 0) {
log_error("dmfilemapd file descriptor must be "
"non-negative: %d", fd);
return 0;
}
if (path[0] != '/') {
log_error("Path argument must specify an absolute path.");
return 0;
}
if (mode > DM_FILEMAPD_FOLLOW_PATH) {
log_error("Invalid dmfilemapd mode argument: "
"Must be DM_FILEMAPD_FOLLOW_INODE or "
"DM_FILEMAPD_FOLLOW_PATH");
return 0;
}
if (foreground > 1) {
log_error("Invalid dmfilemapd foreground argument. "
"Must be 0 or 1: %d.", foreground);
return 0;
}
if (verbose > 3) {
log_error("Invalid dmfilemapd verbose argument. "
"Must be 0..3: %d.", verbose);
return 0;
}
/* set argv[0] */
args[argc++] = (char *) DM_FILEMAPD;
/* set <fd> */
if ((dm_snprintf(fd_str, sizeof(fd_str), "%d", fd)) < 0) {
log_error("Could not format fd argument.");
return 0;
}
args[argc++] = fd_str;
/* set <group_id> */
if ((dm_snprintf(group_str, sizeof(group_str), FMTu64, group_id)) < 0) {
log_error("Could not format group_id argument.");
return 0;
}
args[argc++] = group_str;
/* set <path> */
args[argc++] = (char *) path;
/* set <mode> */
args[argc++] = (char *) mode_str;
/* set <foreground> */
if ((dm_snprintf(fg_str, sizeof(fg_str), "%u", foreground)) < 0) {
log_error("Could not format foreground argument.");
return 0;
}
args[argc++] = fg_str;
/* set <verbose> */
if ((dm_snprintf(verb_str, sizeof(verb_str), "%u", verbose)) < 0) {
log_error("Could not format verbose argument.");
return 0;
}
args[argc++] = verb_str;
/* terminate args[argc] */
args[argc] = NULL;
log_very_verbose("Spawning daemon as '%s %d " FMTu64 " %s %s %u %u'",
*args, fd, group_id, path, mode_str,
foreground, verbose);
if (!foreground && ((pid = fork()) < 0)) {
log_error("Failed to fork dmfilemapd process.");
return 0;
}
if (pid > 0) {
log_very_verbose("Forked dmfilemapd process as pid %d", pid);
return 1;
}
execvp(args[0], args);
log_error("execvp() failed.");
if (!foreground)
_exit(127);
return 0;
}
# else /* !DMFILEMAPD */
dm_filemapd_mode_t dm_filemapd_mode_from_string(const char *mode_str)
{
return 0;
};
int dm_stats_start_filemapd(int fd, uint64_t group_id, const char *path,
dm_filemapd_mode_t mode, unsigned foreground,
unsigned verbose)
{
log_error("dmfilemapd support disabled.");
return 0;
}
#endif /* DMFILEMAPD */
/* /*
* Backward compatible dm_stats_create_region() implementations. * Backward compatible dm_stats_create_region() implementations.
* *

View File

@ -89,6 +89,8 @@ static unsigned _count_fields(const char *p)
* <raid_type> <#devs> <health_str> <sync_ratio> * <raid_type> <#devs> <health_str> <sync_ratio>
* Versions 1.5.0+ (6 fields): * Versions 1.5.0+ (6 fields):
* <raid_type> <#devs> <health_str> <sync_ratio> <sync_action> <mismatch_cnt> * <raid_type> <#devs> <health_str> <sync_ratio> <sync_action> <mismatch_cnt>
* Versions 1.9.0+ (7 fields):
* <raid_type> <#devs> <health_str> <sync_ratio> <sync_action> <mismatch_cnt> <data_offset>
*/ */
int dm_get_status_raid(struct dm_pool *mem, const char *params, int dm_get_status_raid(struct dm_pool *mem, const char *params,
struct dm_status_raid **status) struct dm_status_raid **status)
@ -117,7 +119,7 @@ int dm_get_status_raid(struct dm_pool *mem, const char *params,
goto_bad; goto_bad;
msg_fields = "<raid_type> <#devices> <health_chars> and <sync_ratio> "; msg_fields = "<raid_type> <#devices> <health_chars> and <sync_ratio> ";
if (sscanf(params, "%s %u %s %" PRIu64 "/%" PRIu64, if (sscanf(params, "%s %u %s " FMTu64 "/" FMTu64,
s->raid_type, s->raid_type,
&s->dev_count, &s->dev_count,
s->dev_health, s->dev_health,
@ -144,9 +146,25 @@ int dm_get_status_raid(struct dm_pool *mem, const char *params,
if (!(s->sync_action = dm_pool_zalloc(mem, pp - p))) if (!(s->sync_action = dm_pool_zalloc(mem, pp - p)))
goto_bad; goto_bad;
if (sscanf(p, "%s %" PRIu64, s->sync_action, &s->mismatch_count) != 2) if (sscanf(p, "%s " FMTu64, s->sync_action, &s->mismatch_count) != 2)
goto_bad; goto_bad;
if (num_fields < 7)
goto out;
/*
* All pre-1.9.0 version parameters are read. Now we check
* for additional 1.9.0+ parameters (i.e. nr_fields at least 7).
*
* Note that data_offset will be 0 if the
* kernel returns a pre-1.9.0 status.
*/
msg_fields = "<data_offset>";
if (!(p = _skip_fields(params, 6))) /* skip pre-1.9.0 params */
goto bad;
if (sscanf(p, FMTu64, &s->data_offset) != 1)
goto bad;
out: out:
*status = s; *status = s;
@ -226,14 +244,14 @@ int dm_get_status_cache(struct dm_pool *mem, const char *params,
/* Read in args that have definitive placement */ /* Read in args that have definitive placement */
if (sscanf(params, if (sscanf(params,
" %" PRIu32 " " FMTu32
" %" PRIu64 "/%" PRIu64 " " FMTu64 "/" FMTu64
" %" PRIu32 " " FMTu32
" %" PRIu64 "/%" PRIu64 " " FMTu64 "/" FMTu64
" %" PRIu64 " %" PRIu64 " " FMTu64 " " FMTu64
" %" PRIu64 " %" PRIu64 " " FMTu64 " " FMTu64
" %" PRIu64 " %" PRIu64 " " FMTu64 " " FMTu64
" %" PRIu64 " " FMTu64
" %d", " %d",
&s->metadata_block_size, &s->metadata_block_size,
&s->metadata_used_blocks, &s->metadata_total_blocks, &s->metadata_used_blocks, &s->metadata_total_blocks,
@ -256,8 +274,10 @@ int dm_get_status_cache(struct dm_pool *mem, const char *params,
s->feature_flags |= DM_CACHE_FEATURE_WRITETHROUGH; s->feature_flags |= DM_CACHE_FEATURE_WRITETHROUGH;
else if (!strncmp(p, "writeback ", 10)) else if (!strncmp(p, "writeback ", 10))
s->feature_flags |= DM_CACHE_FEATURE_WRITEBACK; s->feature_flags |= DM_CACHE_FEATURE_WRITEBACK;
else if (!strncmp(p, "passthrough ", 11)) else if (!strncmp(p, "passthrough ", 12))
s->feature_flags |= DM_CACHE_FEATURE_PASSTHROUGH; s->feature_flags |= DM_CACHE_FEATURE_PASSTHROUGH;
else if (!strncmp(p, "metadata2 ", 10))
s->feature_flags |= DM_CACHE_FEATURE_METADATA2;
else else
log_error("Unknown feature in status: %s", params); log_error("Unknown feature in status: %s", params);

View File

@ -566,7 +566,21 @@ static lv_create_params_t _lvm_lv_params_create_thin_pool(vg_t vg,
if (lvcp) { if (lvcp) {
lvcp->vg = vg; lvcp->vg = vg;
lvcp->lvp.discards = (thin_discards_t) discard; switch (discard) {
case LVM_THIN_DISCARDS_IGNORE:
lvcp->lvp.discards = THIN_DISCARDS_IGNORE;
break;
case LVM_THIN_DISCARDS_NO_PASSDOWN:
lvcp->lvp.discards = THIN_DISCARDS_NO_PASSDOWN;
break;
case LVM_THIN_DISCARDS_PASSDOWN:
lvcp->lvp.discards = THIN_DISCARDS_PASSDOWN;
break;
default:
log_error("Invalid discard argument %d for thin pool creation.", discard);
return NULL;
}
lvcp->lvp.zero_new_blocks = THIN_ZERO_YES;
if (chunk_size) if (chunk_size)
lvcp->lvp.chunk_size = chunk_size; lvcp->lvp.chunk_size = chunk_size;

View File

@ -13,7 +13,7 @@
# along with this program; if not, write to the Free Software Foundation, # along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
SHELL = /bin/sh SHELL = @SHELL@
@SET_MAKE@ @SET_MAKE@
@ -44,6 +44,8 @@ EGREP = @EGREP@
GREP = @GREP@ GREP = @GREP@
SORT = @SORT@ SORT = @SORT@
WC = @WC@ WC = @WC@
AR = ar
RM = rm -f
PYTHON2 = @PYTHON2@ PYTHON2 = @PYTHON2@
PYTHON3 = @PYTHON3@ PYTHON3 = @PYTHON3@
@ -156,6 +158,7 @@ INSTALL_ROOT_DIR = $(INSTALL) -m 700 -d
INSTALL_ROOT_DATA = $(INSTALL) -m 600 INSTALL_ROOT_DATA = $(INSTALL) -m 600
INSTALL_SCRIPT = $(INSTALL) -p $(M_INSTALL_PROGRAM) INSTALL_SCRIPT = $(INSTALL) -p $(M_INSTALL_PROGRAM)
.SUFFIXES:
.SUFFIXES: .c .cpp .d .o .so .a .po .pot .mo .dylib .SUFFIXES: .c .cpp .d .o .so .a .po .pot .mo .dylib
WFLAGS +=\ WFLAGS +=\
@ -410,8 +413,10 @@ cflow: $(CFLOW_TARGET).cflow $(CFLOW_TARGET).tree $(CFLOW_TARGET).rxref $(CFLOW_
endif endif
endif endif
.LIBPATTERNS = lib%.so lib%.a
%.o: %.c %.o: %.c
$(CC) -c $(INCLUDES) $(DEFS) $(WFLAGS) $(WCFLAGS) $(CFLAGS) $(CFLAGS_$@) $< -o $@ $(CC) -c $(INCLUDES) $(DEFS) $(DEFS_$@) $(WFLAGS) $(WCFLAGS) $(CFLAGS) $(CFLAGS_$@) $< -o $@
%.o: %.cpp %.o: %.cpp
$(CXX) -c $(INCLUDES) $(DEFS) $(WFLAGS) $(CXXFLAGS) $(CXXFLAGS_$@) $< -o $@ $(CXX) -c $(INCLUDES) $(DEFS) $(WFLAGS) $(CXXFLAGS) $(CXXFLAGS_$@) $< -o $@
@ -461,7 +466,7 @@ endif
$(LIB_STATIC): $(OBJECTS) $(LIB_STATIC): $(OBJECTS)
$(RM) $@ $(RM) $@
$(AR) rs $@ $(OBJECTS) $(AR) rsv $@ $(OBJECTS)
%.d: %.c $(INC_LNS) %.d: %.c $(INC_LNS)
$(MKDIR_P) $(dir $@); \ $(MKDIR_P) $(dir $@); \

2
man/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
*.gen
man-generator

View File

@ -1,6 +1,6 @@
# #
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. # Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
# Copyright (C) 2004-2011 Red Hat, Inc. All rights reserved. # Copyright (C) 2004-2017 Red Hat, Inc. All rights reserved.
# #
# This file is part of LVM2. # This file is part of LVM2.
# #
@ -19,6 +19,7 @@ top_builddir = @top_builddir@
FSADMMAN = fsadm.8 FSADMMAN = fsadm.8
BLKDEACTIVATEMAN = blkdeactivate.8 BLKDEACTIVATEMAN = blkdeactivate.8
DMEVENTDMAN = dmeventd.8 DMEVENTDMAN = dmeventd.8
DMFILEMAPDMAN = dmfilemapd.8
LVMETADMAN = lvmetad.8 LVMETADMAN = lvmetad.8
LVMPOLLDMAN = lvmpolld.8 LVMPOLLDMAN = lvmpolld.8
LVMLOCKDMAN = lvmlockd.8 lvmlockctl.8 LVMLOCKDMAN = lvmlockd.8 lvmlockctl.8
@ -31,20 +32,20 @@ LVMRAIDMAN = lvmraid.7
MAN5=lvm.conf.5 MAN5=lvm.conf.5
MAN7=lvmsystemid.7 lvmreport.7 MAN7=lvmsystemid.7 lvmreport.7
MAN8=lvm.8 lvmconf.8 lvmdump.8 MAN8=lvm.8 lvmconf.8 lvmdump.8 lvm-fullreport.8 lvm-lvpoll.8 \
lvcreate.8 lvchange.8 lvmconfig.8 lvconvert.8 lvdisplay.8 \
lvextend.8 lvreduce.8 lvremove.8 lvrename.8 lvresize.8 lvs.8 \
lvscan.8 pvchange.8 pvck.8 pvcreate.8 pvdisplay.8 pvmove.8 pvremove.8 \
pvresize.8 pvs.8 pvscan.8 vgcfgbackup.8 vgcfgrestore.8 vgchange.8 \
vgck.8 vgcreate.8 vgconvert.8 vgdisplay.8 vgexport.8 vgextend.8 \
vgimport.8 vgimportclone.8 vgmerge.8 vgmknodes.8 vgreduce.8 vgremove.8 \
vgrename.8 vgs.8 vgscan.8 vgsplit.8 \
lvmsar.8 lvmsadc.8 lvmdiskscan.8
MAN8SO=lvm-config.8 lvm-dumpconfig.8
MAN8DM=dmsetup.8 dmstats.8 MAN8DM=dmsetup.8 dmstats.8
MAN8CLUSTER= MAN8CLUSTER=
MAN8SYSTEMD_GENERATORS=lvm2-activation-generator.8 MAN8SYSTEMD_GENERATORS=lvm2-activation-generator.8
MAN8GEN=lvm-config.8 lvm-dumpconfig.8 lvm-fullreport.8 lvm-lvpoll.8 \
lvcreate.8 lvchange.8 lvmconfig.8 lvconvert.8 lvdisplay.8 lvextend.8 \
lvreduce.8 lvremove.8 lvrename.8 lvresize.8 lvs.8 \
lvscan.8 pvchange.8 pvck.8 pvcreate.8 pvdisplay.8 pvmove.8 pvremove.8 \
pvresize.8 pvs.8 pvscan.8 vgcfgbackup.8 vgcfgrestore.8 vgchange.8 \
vgck.8 vgcreate.8 vgconvert.8 vgdisplay.8 vgexport.8 vgextend.8 \
vgimport.8 vgimportclone.8 vgmerge.8 vgmknodes.8 vgreduce.8 vgremove.8 \
vgrename.8 vgs.8 vgscan.8 vgsplit.8 \
lvmsar.8 lvmsadc.8 lvmdiskscan.8 lvmchange.8
ifeq ($(MAKECMDGOALS),all_man) ifeq ($(MAKECMDGOALS),all_man)
MAN_ALL="yes" MAN_ALL="yes"
@ -56,7 +57,7 @@ endif
ifeq ($(MAN_ALL),"yes") ifeq ($(MAN_ALL),"yes")
MAN8+=$(FSADMMAN) $(LVMETADMAN) $(LVMPOLLDMAN) $(LVMLOCKDMAN) $(LVMDBUSDMAN) MAN8+=$(FSADMMAN) $(LVMETADMAN) $(LVMPOLLDMAN) $(LVMLOCKDMAN) $(LVMDBUSDMAN)
MAN8DM+=$(BLKDEACTIVATEMAN) $(DMEVENTDMAN) MAN8DM+=$(BLKDEACTIVATEMAN) $(DMEVENTDMAN) $(DMFILEMAPDMAN)
MAN8CLUSTER+=$(CLVMDMAN) $(CMIRRORDMAN) MAN8CLUSTER+=$(CLVMDMAN) $(CMIRRORDMAN)
MAN7+=$(LVMCACHEMAN) $(LVMTHINMAN) $(LVMRAIDMAN) MAN7+=$(LVMCACHEMAN) $(LVMTHINMAN) $(LVMRAIDMAN)
else else
@ -88,6 +89,10 @@ else
MAN8DM+=$(DMEVENTDMAN) MAN8DM+=$(DMEVENTDMAN)
endif endif
ifeq ("@DMFILEMAPD@", "yes")
MAN8DM+=$(DMFILEMAPDMAN)
endif
ifneq ("@CLVMD@", "none") ifneq ("@CLVMD@", "none")
MAN8CLUSTER+=$(CLVMDMAN) MAN8CLUSTER+=$(CLVMDMAN)
endif endif
@ -113,46 +118,123 @@ MAN5DIR=$(mandir)/man5
MAN7DIR=$(mandir)/man7 MAN7DIR=$(mandir)/man7
MAN8DIR=$(mandir)/man8 MAN8DIR=$(mandir)/man8
MANGENERATOR=$(top_builddir)/tools/man-generator
TESTMAN=test.gen
include $(top_builddir)/make.tmpl include $(top_builddir)/make.tmpl
CLEAN_TARGETS+=$(MAN5) $(MAN7) $(MAN8) $(MAN8GEN) $(MAN8CLUSTER) \ CLEAN_TARGETS+=$(MAN5) $(MAN7) $(MAN8) $(MAN8SO) $(MAN8:%.8=%.8_gen) $(MAN8CLUSTER) \
$(MAN8SYSTEMD_GENERATORS) $(MAN8DM) *.gen man-generator $(MAN8SYSTEMD_GENERATORS) $(MAN8DM) $(TESTMAN)
DISTCLEAN_TARGETS+=$(FSADMMAN) $(BLKDEACTIVATEMAN) $(DMEVENTDMAN) \ DISTCLEAN_TARGETS+=$(FSADMMAN) $(BLKDEACTIVATEMAN) $(DMEVENTDMAN) \
$(LVMETADMAN) $(LVMPOLLDMAN) $(LVMLOCKDMAN) $(CLVMDMAN) $(CMIRRORDMAN) \ $(LVMETADMAN) $(LVMPOLLDMAN) $(LVMLOCKDMAN) $(CLVMDMAN) $(CMIRRORDMAN) \
$(LVMCACHEMAN) $(LVMTHINMAN) $(LVMDBUSDMAN) $(LVMRAIDMAN) $(LVMCACHEMAN) $(LVMTHINMAN) $(LVMDBUSDMAN) $(LVMRAIDMAN) \
$(DMFILEMAPDMAN)
all: man device-mapper all: man device-mapper
.PHONY: man install_man5 install_man7 install_man8 .PHONY: man install_man5 install_man7 install_man8 pregenerated_man
device-mapper: $(MAN8DM) device-mapper: $(MAN8DM)
man: $(MAN5) $(MAN7) $(MAN8) $(MAN8GEN) $(MAN8CLUSTER) $(MAN8SYSTEMD_GENERATORS) man: $(MAN5) $(MAN7) $(MAN8) $(MAN8SO) $(MAN8CLUSTER) $(MAN8SYSTEMD_GENERATORS)
all_man: man all_man: man
$(MAN5) $(MAN7) $(MAN8) $(MAN8GEN) $(MAN8DM) $(MAN8CLUSTER): Makefile $(MAN5) $(MAN7) $(MAN8) $(MAN8SO) $(MAN8DM) $(MAN8CLUSTER) $(MAN8SYSTEMD_GENERATORS): Makefile
Makefile: Makefile.in # Test whether or not the man page generator works
@: $(TESTMAN): $(MANGENERATOR) Makefile
- $(MANGENERATOR) --primary lvmconfig > $@
%: %.in SEE_ALSO=$(srcdir)/see_also.end
@case "$@" in \
*/*) ;; \
*) echo "Creating $@" ; $(SED) -e "s+#VERSION#+$(LVM_VERSION)+;s+#DEFAULT_SYS_DIR#+$(DEFAULT_SYS_DIR)+;s+#DEFAULT_ARCHIVE_DIR#+$(DEFAULT_ARCHIVE_DIR)+;s+#DEFAULT_BACKUP_DIR#+$(DEFAULT_BACKUP_DIR)+;s+#DEFAULT_PROFILE_DIR#+$(DEFAULT_PROFILE_DIR)+;s+#DEFAULT_CACHE_DIR#+$(DEFAULT_CACHE_DIR)+;s+#DEFAULT_LOCK_DIR#+$(DEFAULT_LOCK_DIR)+;s+#CLVMD_PATH#+@CLVMD_PATH@+;s+#LVM_PATH#+@LVM_PATH@+;s+#DEFAULT_RUN_DIR#+@DEFAULT_RUN_DIR@+;s+#DEFAULT_PID_DIR#+@DEFAULT_PID_DIR@+;s+#SYSTEMD_GENERATOR_DIR#+$(SYSTEMD_GENERATOR_DIR)+;s+#DEFAULT_MANGLING#+$(DEFAULT_MANGLING)+;" $< > $@ ;; \
esac
man-generator: .PRECIOUS: %.8_gen
$(CC) -DMAN_PAGE_GENERATOR -I$(top_builddir)/tools $(CFLAGS) $(top_srcdir)/tools/command.c -o $@
- ./man-generator lvmconfig > test.gen
if [ ! -s test.gen ] ; then cp genfiles/*.gen $(top_builddir)/man; fi;
$(MAN8GEN): man-generator %.8_gen: $(srcdir)/%.8_des $(srcdir)/%.8_end $(MANGENERATOR) $(TESTMAN)
echo "Generating $@" ; ( \
if [ ! -e $@.gen ]; then ./man-generator $(basename $@) $(top_srcdir)/man/$@.des > $@.gen; fi if [ ! -s $(TESTMAN) ] ; then \
if [ -f $(top_srcdir)/man/$@.end ]; then cat $(top_srcdir)/man/$@.end >> $@.gen; fi; echo "Copying pre-generated template $@" ; \
cat $(top_srcdir)/man/see_also.end >> $@.gen else \
$(SED) -e "s+#VERSION#+$(LVM_VERSION)+;s+#DEFAULT_SYS_DIR#+$(DEFAULT_SYS_DIR)+;s+#DEFAULT_ARCHIVE_DIR#+$(DEFAULT_ARCHIVE_DIR)+;s+#DEFAULT_BACKUP_DIR#+$(DEFAULT_BACKUP_DIR)+;s+#DEFAULT_PROFILE_DIR#+$(DEFAULT_PROFILE_DIR)+;s+#DEFAULT_CACHE_DIR#+$(DEFAULT_CACHE_DIR)+;s+#DEFAULT_LOCK_DIR#+$(DEFAULT_LOCK_DIR)+;s+#CLVMD_PATH#+@CLVMD_PATH@+;s+#LVM_PATH#+@LVM_PATH@+;s+#DEFAULT_RUN_DIR#+@DEFAULT_RUN_DIR@+;s+#DEFAULT_PID_DIR#+@DEFAULT_PID_DIR@+;s+#SYSTEMD_GENERATOR_DIR#+$(SYSTEMD_GENERATOR_DIR)+;s+#DEFAULT_MANGLING#+$(DEFAULT_MANGLING)+;" $@.gen > $@ echo "Generating template $@" ; \
fi \
)
( \
if [ ! -s $(TESTMAN) ] ; then \
cat $(srcdir)/$(@:%.8_gen=%.8_pregen) ; \
else \
MANCMD=$(basename $@) && \
$(MANGENERATOR) --primary $$MANCMD $< && \
$(MANGENERATOR) --secondary $$MANCMD && \
cat $(srcdir)/$(basename $@).8_end && \
cat $(SEE_ALSO) ; \
fi \
) > $@
define SUBSTVARS
echo "Generating $@"
$(SED) -e "s+#VERSION#+$(LVM_VERSION)+" \
-e "s+#DEFAULT_SYS_DIR#+$(DEFAULT_SYS_DIR)+" \
-e "s+#DEFAULT_ARCHIVE_DIR#+$(DEFAULT_ARCHIVE_DIR)+" \
-e "s+#DEFAULT_BACKUP_DIR#+$(DEFAULT_BACKUP_DIR)+" \
-e "s+#DEFAULT_PROFILE_DIR#+$(DEFAULT_PROFILE_DIR)+" \
-e "s+#DEFAULT_CACHE_DIR#+$(DEFAULT_CACHE_DIR)+" \
-e "s+#DEFAULT_LOCK_DIR#+$(DEFAULT_LOCK_DIR)+" \
-e "s+#CLVMD_PATH#+/data/lvmtest/usr/sbin/clvmd+" \
-e "s+#LVM_PATH#+/data/lvmtest/sbin/lvm+" \
-e "s+#DEFAULT_RUN_DIR#+/var/run/lvm+" \
-e "s+#DEFAULT_PID_DIR#+/var/run+" \
-e "s+#SYSTEMD_GENERATOR_DIR#+$(SYSTEMD_GENERATOR_DIR)+" \
-e "s+#DEFAULT_MANGLING#+$(DEFAULT_MANGLING)+" $< > $@
endef
# Escape any '-':
#
# - multiple (>= 2)
# - in ' -'
# - in (cache|thin)-*
# - in ranges
# - in "$vg-$lv"
# - in middle of options (e.g. '--use-policies')
# - in symbolic use (e.g. '->')
# - in single one in '\\f.-'
define ESCAPEHYPHENS
$(SED) -i -e "s+\([^\\]\)-\{7\}+\1\\\-\\\-\\\-\\\-\\\-\\\-\\\-+g" \
-e "s+\([^\\]\)-\{6\}+\1\\\-\\\-\\\-\\\-\\\-\\\-+g" \
-e "s+\([^\\]\)-\{5\}+\1\\\-\\\-\\\-\\\-\\\-+g" \
-e "s+\([^\\]\)-\{4\}+\1\\\-\\\-\\\-\\\-+g" \
-e "s+\([^\\]\)-\{3\}+\1\\\-\\\-\\\-+g" \
-e "s+\([^\\]\)-\{2\}+\1\\\-\\\-+g" \
-e "s+^-\{2\}+\\\-\\\-+g" \
-e "s+ -\([[:alnum:]]\)+ \\\-\1+g" \
-e "s+\(cache\)-\([[:alpha:]]\{1,\}\)+\1\\\-\2+g" \
-e "s+\(thin\)-\([[:alpha:]]\{1,\}\)+\1\\\-\2+g" \
-e "s+\([ :\[][[:alnum:]]\{1,\}\)-\([[:alnum:]]\{1,\}[[ ]\)+\1\\\-\2+g" \
-e "s+\([[:alnum:]]\{2,\}\)-\([[:alnum:]]\{2,\}\)-\([[:alnum:]]\{2,\}\)+\1\\\-\2\\\-\3+g" \
-e "s+\([[:alnum:]]\{2,\}\)-\([[:alnum:]]\{2,\}\)+\1\\\-\2+g" \
-e "s+\(<\)-+\1\\\-+g" \
-e "s+[^\\]-\(>\)+\\\-\1+g" \
-e "s+\(\\\f.\)-\([^-]\)+\1\\\-\2+g" \
-e "s+\([[:digit:]]\{4\}\).*-\([[:digit:]]\{2\}\).*-\([[:digit:]]\{2\}\)+\1-\2-\3+g" $@
endef
%.5: $(srcdir)/%.5_main
$(SUBSTVARS)
$(ESCAPEHYPHENS)
%.7: $(srcdir)/%.7_main
$(SUBSTVARS)
$(ESCAPEHYPHENS)
%.8: $(srcdir)/%.8_main
$(SUBSTVARS)
$(ESCAPEHYPHENS)
%.8: %.8_gen
$(SUBSTVARS)
$(ESCAPEHYPHENS)
lvm-config.8 lvm-dumpconfig.8: lvmconfig.8
echo ".so $<" > $@
install_man5: $(MAN5) install_man5: $(MAN5)
$(INSTALL) -d $(MAN5DIR) $(INSTALL) -d $(MAN5DIR)
@ -162,10 +244,9 @@ install_man7: $(MAN7)
$(INSTALL) -d $(MAN7DIR) $(INSTALL) -d $(MAN7DIR)
$(INSTALL_DATA) $(MAN7) $(MAN7DIR)/ $(INSTALL_DATA) $(MAN7) $(MAN7DIR)/
install_man8: $(MAN8) $(MAN8GEN) install_man8: $(MAN8) $(MAN8SO)
$(INSTALL) -d $(MAN8DIR) $(INSTALL) -d $(MAN8DIR)
$(INSTALL_DATA) $(MAN8) $(MAN8DIR)/ $(INSTALL_DATA) $(MAN8) $(MAN8SO) $(MAN8DIR)/
$(INSTALL_DATA) $(MAN8GEN) $(MAN8DIR)/
install_lvm2: install_man5 install_man7 install_man8 install_lvm2: install_man5 install_man7 install_man8
@ -179,10 +260,19 @@ install_device-mapper: $(MAN8DM)
$(INSTALL) -d $(MAN8DIR) $(INSTALL) -d $(MAN8DIR)
$(INSTALL_DATA) $(MAN8DM) $(MAN8DIR)/ $(INSTALL_DATA) $(MAN8DM) $(MAN8DIR)/
install_systemd_generators: $(MAN8SYSTEMD_GENERATORS) install_systemdgenerators: $(MAN8SYSTEMD_GENERATORS)
$(INSTALL) -d $(MAN8DIR) $(INSTALL) -d $(MAN8DIR)
$(INSTALL_DATA) $(MAN8SYSTEMD_GENERATORS) $(MAN8DIR)/ $(INSTALL_DATA) $(MAN8SYSTEMD_GENERATORS) $(MAN8DIR)/
install: install_lvm2 install_device-mapper install_cluster install: install_lvm2 install_device-mapper install_cluster
install_all_man: install install_systemd_generators install_all_man: install install_systemd_generators
# Copy generated man pages back to source tree as fallback for machines where generator doesn't work
pregenerated_man: all
for i in $(srcdir)/*.8_des; do \
CMD=`basename $$i .8_des`; \
cat $${CMD}.8_gen > $(srcdir)/$$CMD.8_pregen ; \
done
generate: pregenerated_man

View File

@ -1,105 +0,0 @@
.TH "BLKDEACTIVATE" "8" "LVM TOOLS #VERSION#" "Red Hat, Inc" "\""
.SH "NAME"
blkdeactivate \(em utility to deactivate block devices
.SH SYNOPSIS
.B blkdeactivate
.RB [ \-d \ \fIdm_options\fP ]
.RB [ \-e ]
.RB [ \-h ]
.RB [ \-l \ \fIlvm_options\fP ]
.RB [ \-m \ \fImpath_options\fP ]
.RB [ \-u ]
.RB [ \-v ]
.RI [ device ]
.SH DESCRIPTION
blkdeactivate utility deactivates block devices. If a device
is mounted, the utility can unmount it automatically before
trying to deactivate. The utility currently supports
device-mapper devices (DM), including LVM volumes and
software RAID MD devices. LVM volumes are handled directly
using the \fBlvm\fP(8) command, the rest of device-mapper
based devices are handled using the \fBdmsetup\fP(8) command.
MD devices are handled using the \fBmdadm\fP(8) command.
.SH OPTIONS
.TP
.BR \-d ", " \-\-dmoption \ \fIdm_options\fP
Comma separated list of device-mapper specific options.
Accepted \fBdmsetup\fP(8) options are:
.RS
.IP \fIretry\fP
Retry removal several times in case of failure.
.IP \fIforce\fP
Force device removal.
.RE
.TP
.BR \-e ", " \-\-errors
Show errors reported from tools called by \fBblkdeactivate\fP. Without this
option, any error messages from these external tools are suppressed and the
\fBblkdeactivate\fP itself provides only a summary message about device being
skipped or not.
.TP
.BR \-h ", " \-\-help
Display the help text.
.TP
.BR \-l ", " \-\-lvmoption \ \fIlvm_options\fP
Comma separated list of LVM specific options:
.RS
.IP \fIretry\fP
Retry removal several times in case of failure.
.IP \fIwholevg\fP
Deactivate the whole LVM Volume Group when processing a Logical Volume.
Deactivating Volume Group as a whole takes less time than deactivating each
Logical Volume separately.
.RE
.TP
.BR \-m ", " \-\-mpathoption \ \fImpath_options\fP
Comma separated list of device-mapper multipath specific options:
.RS
.IP \fIdisablequeueing\fP
Disable queueing on all multipath devices first before deactivation.
This avoids a situation where blkdeactivate may end up waiting if
all paths are unavailable for any underlying device-mapper multipath
device.
.RE
.TP
.BR \-u ", " \-\-umount
Unmount a mounted device before trying to deactivate it.
Without this option used, a device that is mounted is not deactivated.
.TP
.BR \-v ", " \-\-verbose
Run in verbose mode. Use \-\-vv for even more verbose mode.
.SH EXAMPLES
.sp
Deactivate all supported block devices found in the system. If a device
is mounted, skip its deactivation.
.sp
.B blkdeactivate
Deactivate all supported block devices found in the system. If a device
is mounted, unmount it first if possible.
.sp
.B blkdeactivate \-u
Deactivate supplied device together with all its holders. If any of the
devices processed is mounted, unmount it first if possible.
.sp
.B blkdeactivate \-u /dev/vg/lvol0
Deactivate all supported block devices found in the system. Retry deactivation
of device-mapper devices in case the deactivation fails. Deactivate the whole
Volume Group at once when processing an LVM Logical Volume.
.sp
.B blkdeactivate \-u \-d retry \-l wholevg
Deactivate all supported block devices found in the system. Retry deactivation
of device-mapper devices in case the deactivation fails and force removal.
.sp
.B blkdeactivate \-d force,retry
.SH SEE ALSO
.BR dmsetup (8),
.BR lsblk (8),
.BR lvm (8),
.BR mdadm (8),
.BR multipathd (8),
.BR umount (8)

114
man/blkdeactivate.8_main Normal file
View File

@ -0,0 +1,114 @@
.TH "BLKDEACTIVATE" "8" "LVM TOOLS #VERSION#" "Red Hat, Inc" "\""
.SH "NAME"
blkdeactivate \(em utility to deactivate block devices
.SH SYNOPSIS
.B blkdeactivate
.RB [ -d \ \fIdm_options\fP ]
.RB [ -e ]
.RB [ -h ]
.RB [ -l \ \fIlvm_options\fP ]
.RB [ -m \ \fImpath_options\fP ]
.RB [ -u ]
.RB [ -v ]
.RI [ device ]
.SH DESCRIPTION
The blkdeactivate utility deactivates block devices. For mounted
block devices, it attempts to unmount it automatically before
trying to deactivate. The utility currently supports
device-mapper devices (DM), including LVM volumes and
software RAID MD devices. LVM volumes are handled directly
using the \fBlvm\fP(8) command, the rest of device-mapper
based devices are handled using the \fBdmsetup\fP(8) command.
MD devices are handled using the \fBmdadm\fP(8) command.
.SH OPTIONS
.TP
.BR -d ", " --dmoption \ \fIdm_options\fP
Comma separated list of device-mapper specific options.
Accepted \fBdmsetup\fP(8) options are:
.RS
.IP \fIretry\fP
Retry removal several times in case of failure.
.IP \fIforce\fP
Force device removal.
.RE
.TP
.BR -e ", " --errors
Show errors reported from tools called by \fBblkdeactivate\fP. Without this
option, any error messages from these external tools are suppressed and the
\fBblkdeactivate\fP itself provides only a summary message to indicate
the device was skipped.
.TP
.BR -h ", " --help
Display the help text.
.TP
.BR -l ", " --lvmoption \ \fIlvm_options\fP
Comma-separated list of LVM specific options:
.RS
.IP \fIretry\fP
Retry removal several times in case of failure.
.IP \fIwholevg\fP
Deactivate the whole LVM Volume Group when processing a Logical Volume.
Deactivating the Volume Group as a whole is quicker than deactivating
each Logical Volume separately.
.RE
.TP
.BR -m ", " --mpathoption \ \fImpath_options\fP
Comma-separated list of device-mapper multipath specific options:
.RS
.IP \fIdisablequeueing\fP
Disable queueing on all multipath devices before deactivation.
This avoids a situation where blkdeactivate may end up waiting if
all the paths are unavailable for any underlying device-mapper multipath
device.
.RE
.TP
.BR -u ", " --umount
Unmount a mounted device before trying to deactivate it.
Without this option used, a device that is mounted is not deactivated.
.TP
.BR -v ", " --verbose
Run in verbose mode. Use --vv for even more verbose mode.
.SH EXAMPLES
.
Deactivate all supported block devices found in the system, skipping mounted
devices.
.BR
#
.B blkdeactivate
.BR
.P
Deactivate all supported block devices found in the system, unmounting any
mounted devices first, if possible.
.BR
#
.B blkdeactivate -u
.BR
.P
Deactivate the device /dev/vg/lvol0 together with all its holders, unmounting
any mounted devices first, if possible.
.BR
#
.B blkdeactivate -u /dev/vg/lvol0
.BR
.P
Deactivate all supported block devices found in the system. If the deactivation
of a device-mapper device fails, retry it. Deactivate the whole
Volume Group at once when processing an LVM Logical Volume.
.BR
#
.B blkdeactivate -u -d retry -l wholevg
.BR
.P
Deactivate all supported block devices found in the system. If the deactivation
of a device-mapper device fails, retry it and force removal.
.BR
#
.B blkdeactivate -d force,retry
.
.SH SEE ALSO
.BR dmsetup (8),
.BR lsblk (8),
.BR lvm (8),
.BR mdadm (8),
.BR multipathd (8),
.BR umount (8)

View File

@ -8,22 +8,22 @@ clvmd \(em cluster LVM daemon
. .
.ad l .ad l
.B clvmd .B clvmd
.RB [ \-C ] .RB [ -C ]
.RB [ \-d .RB [ -d
.RI [ value ]] .RI [ value ]]
.RB [ \-E .RB [ -E
.IR lock_uuid ] .IR lock_uuid ]
.RB [ \-f ] .RB [ -f ]
.RB [ \-h ] .RB [ -h ]
.RB [ \-I .RB [ -I
.IR cluster_manager ] .IR cluster_manager ]
.RB [ \-R ] .RB [ -R ]
.RB [ \-S ] .RB [ -S ]
.RB [ \-t .RB [ -t
.IR timeout ] .IR timeout ]
.RB [ \-T .RB [ -T
.IR start_timeout ] .IR start_timeout ]
.RB [ \-V ] .RB [ -V ]
.ad b .ad b
. .
.SH DESCRIPTION .SH DESCRIPTION
@ -35,12 +35,12 @@ if a node in the cluster does not have this daemon running.
.SH OPTIONS .SH OPTIONS
. .
.HP .HP
.BR \-C .BR -C
.br .br
Only valid if \fB\-d\fP is also specified. Only valid if \fB-d\fP is also specified.
Tells all clvmds in a cluster to enable/disable debug logging. Tells all clvmds in a cluster to enable/disable debug logging.
Without this switch, only the local clvmd will change its debug level to that Without this switch, only the local clvmd will change its debug level to that
given with \fB\-d\fP. given with \fB-d\fP.
.br .br
This does not work correctly if specified on the command-line that starts clvmd. This does not work correctly if specified on the command-line that starts clvmd.
If you want to start clvmd \fBand\fP If you want to start clvmd \fBand\fP
@ -48,14 +48,14 @@ enable cluster-wide logging then the command needs to be issued twice, eg:
.br .br
.BR clvmd .BR clvmd
.br .br
.BR clvmd\ \-d2 .BR clvmd\ -d2
. .
.HP .HP
.BR \-d .BR -d
.RI [ value ] .RI [ value ]
.br .br
Set debug logging level. Set debug logging level.
If \fB\-d\fP is specified without a \fIvalue\fP If \fB-d\fP is specified without a \fIvalue\fP
then 1 is assumed. \fIValue\fP can be: then 1 is assumed. \fIValue\fP can be:
.PD 0 .PD 0
.IP .IP
@ -63,30 +63,30 @@ then 1 is assumed. \fIValue\fP can be:
\(em Disabled \(em Disabled
.IP .IP
.BR 1 .BR 1
\(em Sends debug logs to stderr (implies \fB\-f\fP) \(em Sends debug logs to stderr (implies \fB-f\fP)
.IP .IP
.BR 2 .BR 2
\(em Sends debug logs to \fBsyslog\fP(3) \(em Sends debug logs to \fBsyslog\fP(3)
.PD .PD
. .
.HP .HP
.BR \-E .BR -E
.IR lock_uuid .IR lock_uuid
.br .br
Pass lock uuid to be reacquired exclusively when clvmd is restarted. Pass lock uuid to be reacquired exclusively when clvmd is restarted.
. .
.HP .HP
.BR \-f .BR -f
.br .br
Don't fork, run in the foreground. Don't fork, run in the foreground.
. .
.HP .HP
.BR \-h .BR -h
.br .br
Show help information. Show help information.
. .
.HP .HP
.BR \-I .BR -I
.IR cluster_manager .IR cluster_manager
.br .br
Selects the cluster manager to use for locking and internal Selects the cluster manager to use for locking and internal
@ -94,24 +94,24 @@ communications. As it is quite possible to have multiple managers available on
the same system you might have to manually specify this option to override the the same system you might have to manually specify this option to override the
search. search.
By default, omit \fB-I\fP is equivalent to \fB\-Iauto\fP. By default, omit \fB-I\fP is equivalent to \fB-Iauto\fP.
Clvmd will use the first cluster manager that succeeds, Clvmd will use the first cluster manager that succeeds,
and it checks them in a predefined order and it checks them in a predefined order
.BR cman , .BR cman ,
.BR corosync , .BR corosync ,
.BR openais . .BR openais .
The available managers will be listed by order as part of the The available managers will be listed by order as part of the
\fBclvmd \-h\fP output. \fBclvmd -h\fP output.
. .
.HP .HP
.BR \-R .BR -R
.br .br
Tells all the running instance of \fBclvmd\fP in the cluster to reload their device cache and Tells all the running instance of \fBclvmd\fP in the cluster to reload their device cache and
re-read the lvm configuration file \fBlvm.conf\fP(5). This command should be run whenever the re-read the lvm configuration file \fBlvm.conf\fP(5). This command should be run whenever the
devices on a cluster system are changed. devices on a cluster system are changed.
. .
.HP .HP
.BR \-S .BR -S
.br .br
Tells the running \fBclvmd\fP to exit and reexecute itself, for example at the Tells the running \fBclvmd\fP to exit and reexecute itself, for example at the
end of a package upgrade. The new instance is instructed to reacquire end of a package upgrade. The new instance is instructed to reacquire
@ -120,7 +120,7 @@ methods of restarting the daemon have the side effect of changing
exclusive LV locks into shared locks.) exclusive LV locks into shared locks.)
. .
.HP .HP
.BR \-t .BR -t
.IR timeout .IR timeout
.br .br
Specifies the \fItimeout\fP for commands to run around the cluster. This should not Specifies the \fItimeout\fP for commands to run around the cluster. This should not
@ -129,7 +129,7 @@ may need to increase this on systems with very large disk farms.
The default is 60 seconds. The default is 60 seconds.
. .
.HP .HP
.BR \-T .BR -T
.IR start_timeout .IR start_timeout
.br .br
Specifies the start timeout for \fBclvmd\fP daemon startup. If the Specifies the start timeout for \fBclvmd\fP daemon startup. If the
@ -147,10 +147,10 @@ The default is \fB0\fP (no timeout) and the value is in seconds. Don't set this
small or you will experience spurious errors. 10 or 20 seconds might be small or you will experience spurious errors. 10 or 20 seconds might be
sensible. sensible.
This timeout will be ignored if you start \fBclvmd\fP with the \fB\-d\fP. This timeout will be ignored if you start \fBclvmd\fP with the \fB-d\fP.
. .
.HP .HP
.BR \-V .BR -V
.br .br
Display the version of the cluster LVM daemon. Display the version of the cluster LVM daemon.
. .
@ -176,9 +176,9 @@ clvmd attempts to activate the LV only on the local node.
If the LV type allows concurrent access, then shared mode is used, If the LV type allows concurrent access, then shared mode is used,
otherwise exclusive. otherwise exclusive.
.IP \fBn\fP .IP \fBn\fP
clvmd deactivates the LV on all nodes. clvmd attempts to deactivate the LV on all nodes.
.IP \fBln\fP .IP \fBln\fP
clvmd deactivates the LV on the local node. clvmd attempts to deactivate the LV on the local node.
. .
.SH ENVIRONMENT VARIABLES .SH ENVIRONMENT VARIABLES
.TP .TP

View File

@ -3,7 +3,7 @@
cmirrord \(em cluster mirror log daemon cmirrord \(em cluster mirror log daemon
.SH SYNOPSIS .SH SYNOPSIS
\fBcmirrord\fR [\fB\-f\fR] [\fB\-h\fR] \fBcmirrord\fR [\fB-f\fR] [\fB-h\fR]
.SH DESCRIPTION .SH DESCRIPTION
\fBcmirrord\fP is the daemon that tracks mirror log information in a cluster. \fBcmirrord\fP is the daemon that tracks mirror log information in a cluster.
@ -26,9 +26,9 @@ ignored. Active cluster mirrors should be shutdown before stopping the cluster
mirror log daemon. mirror log daemon.
.SH OPTIONS .SH OPTIONS
.IP "\fB\-f\fR, \fB\-\-foreground\fR" 4 .IP "\fB-f\fR, \fB--foreground\fR" 4
Do not fork and log to the terminal. Do not fork and log to the terminal.
.IP "\fB\-h\fR, \fB\-\-help\fR" 4 .IP "\fB-h\fR, \fB--help\fR" 4
Print usage. Print usage.
.SH SEE ALSO .SH SEE ALSO

View File

@ -7,15 +7,15 @@ dmeventd \(em Device-mapper event daemon
.SH SYNOPSIS .SH SYNOPSIS
. .
.B dmeventd .B dmeventd
.RB [ \-d .RB [ -d
.RB [ \-d .RB [ -d
.RB [ \-d ]]] .RB [ -d ]]]
.RB [ \-f ] .RB [ -f ]
.RB [ \-h ] .RB [ -h ]
.RB [ \-l ] .RB [ -l ]
.RB [ \-R ] .RB [ -R ]
.RB [ \-V ] .RB [ -V ]
.RB [ \-? ] .RB [ -? ]
. .
.SH DESCRIPTION .SH DESCRIPTION
. .
@ -27,46 +27,46 @@ particular events occur.
.SH OPTIONS .SH OPTIONS
. .
.HP .HP
.BR \-d .BR -d
.br .br
Repeat from 1 to 3 times ( Repeat from 1 to 3 times (
.BR \-d , .BR -d ,
.BR \-dd , .BR -dd ,
.BR \-ddd .BR -ddd
) to increase the detail of ) to increase the detail of
debug messages sent to syslog. debug messages sent to syslog.
Each extra d adds more debugging information. Each extra d adds more debugging information.
. .
.HP .HP
.BR \-f .BR -f
.br .br
Don't fork, run in the foreground. Don't fork, run in the foreground.
. .
.HP .HP
.BR \-h .BR -h
.br .br
Show help information. Show help information.
. .
.HP .HP
.BR \-l .BR -l
.br .br
Log through stdout and stderr instead of syslog. Log through stdout and stderr instead of syslog.
This option works only with option \-f, otherwise it is ignored. This option works only with option -f, otherwise it is ignored.
. .
.HP .HP
.BR \-? .BR -?
.br .br
Show help information on stderr. Show help information on stderr.
. .
.HP .HP
.BR \-R .BR -R
.br .br
Replace a running dmeventd instance. The running dmeventd must be version Replace a running dmeventd instance. The running dmeventd must be version
2.02.77 or newer. The new dmeventd instance will obtain a list of devices and 2.02.77 or newer. The new dmeventd instance will obtain a list of devices and
events to monitor from the currently running daemon. events to monitor from the currently running daemon.
. .
.HP .HP
.BR \-V .BR -V
.br .br
Show version of dmeventd. Show version of dmeventd.
. .

212
man/dmfilemapd.8_main Normal file
View File

@ -0,0 +1,212 @@
.TH DMFILEMAPD 8 "Dec 17 2016" "Linux" "MAINTENANCE COMMANDS"
.de OPT_FD
. RB [ file_descriptor ]
..
.
.de OPT_GROUP
. RB [ group_id ]
..
.de OPT_PATH
. RB [ abs_path ]
..
.
.de OPT_MODE
. RB [ mode ]
..
.
.de OPT_DEBUG
. RB [ foreground [ verbose ] ]
..
.
.SH NAME
.
dmfilemapd \(em device-mapper filemap monitoring daemon
.
.SH SYNOPSIS
.
.de CMD_DMFILEMAPD
. ad l
. IR dmfilemapd
. OPT_FD
. OPT_GROUP
. OPT_PATH
. OPT_MODE
. OPT_DEBUG
. ad b
..
.CMD_DMFILEMAPD
.
.PD
.ad b
.
.SH DESCRIPTION
.
The dmfilemapd daemon monitors groups of \fIdmstats\fP regions that
correspond to the extents of a file, adding and removing regions to
reflect the changing state of the file on-disk.
The daemon is normally launched automatically by the \fPdmstats
create\fP command, but can be run manually, either to create a new
daemon where one did not previously exist, or to change the options
previously used, by killing the existing daemon and starting a new
one.
.
.SH OPTIONS
.
.HP
.BR file_descriptor
.br
Specify the file descriptor number for the file to be monitored.
The file descriptor must reference a regular file, open for reading,
in a local file system that supports the FIEMAP ioctl, and that
returns data describing the physical location of extents.
The process that executes \fBdmfilemapd\fP is responsible for
opening the file descriptor that is handed to the daemon.
.
.HP
.BR group_id
.br
The \fBdmstats\fP group identifier of the group that \fBdmfilemapd\fP
should update. The group must exist and it should correspond to
a set of regions created by a previous filemap operation.
.
.HP
.BR abs_path
.br
The absolute path to the file being monitored, at the time that
it was opened. The use of \fBpath\fP by the daemon differs,
depending on the filemap following mode in use; see \fBMODES\fP
and the \fBmode\fP option for more information.
.br
.HP
.BR mode
.br
The filemap monitoring mode the daemon should use: either "inode"
(\fBDM_FILEMAP_FOLLOW_INODE\fP), or "path"
(\fBDM_FILEMAP_FOLLOW_PATH\fP), to enable follow-inode or
follow-path mode respectively.
.
.HP
.BR [foreground]
.br
If set to 1, disable forking and allow the daemon to run in the
foreground.
.
.HP
.BR [verbose]
Control daemon logging. If set to zero, the daemon will close all
stdio streams and run silently. If \fBverbose\fP is a number
between 1 and 3, stdio will be retained and the daemon will log
messages to stdout and stderr that match the specified verbosity
level.
.
.
.SH MODES
.
The file map monitoring daemon can monitor files in two distinct
ways: the mode affects the behaviour of the daemon when a file
under monitoring is renamed or unlinked, and the conditions which
cause the daemon to terminate.
In both modes, the daemon will always shut down when the group
being monitored is deleted.
.P
.B Follow inode
.P
The daemon follows the inode of the file, as it was at the time the
daemon started. The file descriptor referencing the file is kept
open at all times, and the daemon will exit when it detects that
the file has been unlinked and it is the last holder of a reference
to the file.
This mode is useful if the file is expected to be renamed, or moved
within the file system, while it is being monitored.
.P
.B Follow path
.P
The daemon follows the path that was given on the daemon command
line. The file descriptor referencing the file is re-opened on each
iteration of the daemon, and the daemon will exit if no file exists
at this location (a tolerance is allowed so that a brief delay
between removal and replacement is permitted).
This mode is useful if the file is updated by unlinking the original
and placing a new file at the same path.
.
.SH LIMITATIONS
.
The daemon attempts to maintain good synchronisation between the file
extents and the regions contained in the group, however, since the
daemon can only react to new allocations once they have been written,
there are inevitably some IO events that cannot be counted when a
file is growing, particularly if the file is being extended by a
single thread writing beyond EOF (for example, the \fBdd\fP program).
There is a further loss of events in that there is currently no way
to atomically resize a \fBdmstats\fP region and preserve its current
counter values. This affects files when they grow by extending the
final extent, rather than allocating a new extent: any events that
had accumulated in the region between any prior operation and the
resize are lost.
File mapping is currently most effective in cases where the majority
of IO does not trigger extent allocation. Future updates may address
these limitations when kernel support is available.
.
.SH EXAMPLES
.
Normally the daemon is started automatically by the \fBdmstats\fP
\fBcreate\fP or \fBupdate_filemap\fP commands but it can be run
manually for debugging or testing purposes.
.P
Start the daemon in the background, in follow-path mode
.br
#
.B dmfilemapd 3 0 /srv/images/vm.img path 0 0 3< /srv/images/vm.img
.br
.P
Start the daemon in follow-inode mode, disable forking and enable
verbose logging
.br
#
.B dmfilemapd 3 0 /var/tmp/data inode 1 3 3< /var/tmp/data
.br
Starting dmfilemapd with fd=3, group_id=0 mode=inode, path=/var/tmp/data
.br
dm version [ opencount flush ] [16384] (*1)
.br
dm info (253:0) [ opencount flush ] [16384] (*1)
.br
dm message (253:0) [ opencount flush ] @stats_list dmstats [16384] (*1)
.br
Read alias 'data' from aux_data
.br
Found group_id 0: alias="data"
.br
dm_stats_walk_init: initialised flags to 4000000000000
.br
starting stats walk with GROUP
.br
exiting _filemap_monitor_get_events() with deleted=0, check=0
.br
Waiting for check interval
.br
.P
.
.SH AUTHORS
.
Bryn M. Reeves <bmr@redhat.com>
.
.SH SEE ALSO
.
.BR dmstats (8)
LVM2 resource page: https://www.sourceware.org/lvm2/
.br
Device-mapper resource page: http://sources.redhat.com/dm/
.br

View File

@ -23,12 +23,12 @@ dmsetup \(em low level logical volume management
. ad l . ad l
. BR create . BR create
. IR device_name . IR device_name
. RB [ -u | \-\-uuid . RB [ -u | --uuid
. IR uuid ] . IR uuid ]
. RB \%[ \-\-addnodeoncreate | \-\-addnodeonresume ] . RB \%[ --addnodeoncreate | --addnodeonresume ]
. RB \%[ \-n | \-\-notable | \-\-table . RB \%[ -n | --notable | --table
. IR \%table | table_file ] . IR \%table | table_file ]
. RB [ \-\-readahead . RB [ --readahead
. RB \%[ + ] \fIsectors | auto | none ] . RB \%[ + ] \fIsectors | auto | none ]
. ad b . ad b
.. ..
@ -39,7 +39,7 @@ dmsetup \(em low level logical volume management
.de CMD_DEPS .de CMD_DEPS
. ad l . ad l
. BR deps . BR deps
. RB [ \-o . RB [ -o
. IR options ] . IR options ]
. RI [ device_name ...] . RI [ device_name ...]
. ad b . ad b
@ -50,7 +50,7 @@ dmsetup \(em low level logical volume management
.B dmsetup .B dmsetup
.de CMD_HELP .de CMD_HELP
. BR help . BR help
. RB [ \-c | \-C | \-\-columns ] . RB [ -c | -C | --columns ]
.. ..
.CMD_HELP .CMD_HELP
. .
@ -67,18 +67,18 @@ dmsetup \(em low level logical volume management
.de CMD_INFOLONG .de CMD_INFOLONG
. ad l . ad l
. BR info . BR info
. BR \-c | \-C | \-\-columns . BR -c | -C | --columns
. RB [ \-\-count . RB [ --count
. IR count ] . IR count ]
. RB [ \-\-interval . RB [ --interval
. IR seconds ] . IR seconds ]
. RB \%[ \-\-nameprefixes ] . RB \%[ --nameprefixes ]
. RB \%[ \-\-noheadings ] . RB \%[ --noheadings ]
. RB [ \-o . RB [ -o
. IR fields ] . IR fields ]
. RB [ \-O | \-\-sort . RB [ -O | --sort
. IR sort_fields ] . IR sort_fields ]
. RB [ \-\-separator . RB [ --separator
. IR separator ] . IR separator ]
. RI [ device_name ] . RI [ device_name ]
. ad b . ad b
@ -91,7 +91,7 @@ dmsetup \(em low level logical volume management
. ad l . ad l
. BR load . BR load
. IR device_name . IR device_name
. RB [ \-\-table . RB [ --table
. IR table | table_file ] . IR table | table_file ]
. ad b . ad b
.. ..
@ -102,12 +102,12 @@ dmsetup \(em low level logical volume management
.de CMD_LS .de CMD_LS
. ad l . ad l
. BR ls . BR ls
. RB [ \-\-target . RB [ --target
. IR target_type ] . IR target_type ]
. RB [ \-\-exec . RB [ --exec
. IR command ] . IR command ]
. RB [ \-\-tree ] . RB [ --tree ]
. RB [ \-o . RB [ -o
. IR options ] . IR options ]
. ad b . ad b
.. ..
@ -145,7 +145,7 @@ dmsetup \(em low level logical volume management
. ad l . ad l
. BR reload . BR reload
. IR device_name . IR device_name
. RB [ \-\-table . RB [ --table
. IR table | table_file ] . IR table | table_file ]
. ad b . ad b
.. ..
@ -156,9 +156,9 @@ dmsetup \(em low level logical volume management
.de CMD_REMOVE .de CMD_REMOVE
. ad l . ad l
. BR remove . BR remove
. RB [ \-f | \-\-force ] . RB [ -f | --force ]
. RB [ \-\-retry ] . RB [ --retry ]
. RB [ \-\-deferred ] . RB [ --deferred ]
. IR device_name ... . IR device_name ...
. ad b . ad b
.. ..
@ -168,8 +168,8 @@ dmsetup \(em low level logical volume management
.B dmsetup .B dmsetup
.de CMD_REMOVE_ALL .de CMD_REMOVE_ALL
. BR remove_all . BR remove_all
. RB [ \-f | \-\-force ] . RB [ -f | --force ]
. RB [ \-\-deferred ] . RB [ --deferred ]
.. ..
.CMD_REMOVE_ALL .CMD_REMOVE_ALL
. .
@ -187,7 +187,7 @@ dmsetup \(em low level logical volume management
.de CMD_RENAME_UUID .de CMD_RENAME_UUID
. BR rename . BR rename
. IR device_name . IR device_name
. BR \-\-setuuid . BR --setuuid
. IR uuid . IR uuid
.. ..
.CMD_RENAME_UUID .CMD_RENAME_UUID
@ -198,10 +198,10 @@ dmsetup \(em low level logical volume management
. ad l . ad l
. BR resume . BR resume
. IR device_name ... . IR device_name ...
. RB [ \-\-addnodeoncreate | \-\-addnodeonresume ] . RB [ --addnodeoncreate | --addnodeonresume ]
. RB [ \-\-noflush ] . RB [ --noflush ]
. RB [ \-\-nolockfs ] . RB [ --nolockfs ]
. RB \%[ \-\-readahead . RB \%[ --readahead
. RB \%[ + ] \fIsectors | auto | none ] . RB \%[ + ] \fIsectors | auto | none ]
. ad b . ad b
.. ..
@ -244,9 +244,9 @@ dmsetup \(em low level logical volume management
.de CMD_STATUS .de CMD_STATUS
. ad l . ad l
. BR status . BR status
. RB [ \-\-target . RB [ --target
. IR target_type ] . IR target_type ]
. RB [ \-\-noflush ] . RB [ --noflush ]
. RI [ device_name ...] . RI [ device_name ...]
. ad b . ad b
.. ..
@ -257,8 +257,8 @@ dmsetup \(em low level logical volume management
.de CMD_SUSPEND .de CMD_SUSPEND
. ad l . ad l
. BR suspend . BR suspend
. RB [ \-\-nolockfs ] . RB [ --nolockfs ]
. RB [ \-\-noflush ] . RB [ --noflush ]
. IR device_name ... . IR device_name ...
. ad b . ad b
.. ..
@ -269,9 +269,9 @@ dmsetup \(em low level logical volume management
.de CMD_TABLE .de CMD_TABLE
. ad l . ad l
. BR table . BR table
. RB [ \-\-target . RB [ --target
. IR target_type ] . IR target_type ]
. RB [ \-\-showkeys ] . RB [ --showkeys ]
. RI [ device_name ...] . RI [ device_name ...]
. ad b . ad b
.. ..
@ -342,7 +342,7 @@ dmsetup \(em low level logical volume management
.de CMD_WAIT .de CMD_WAIT
. ad l . ad l
. BR wait . BR wait
. RB [ \-\-noflush ] . RB [ --noflush ]
. IR device_name . IR device_name
. RI [ event_nr ] . RI [ event_nr ]
. ad b . ad b
@ -355,9 +355,9 @@ dmsetup \(em low level logical volume management
. ad l . ad l
. BR wipe_table . BR wipe_table
. IR device_name ... . IR device_name ...
. RB [ \-f | \-\-force ] . RB [ -f | --force ]
. RB [ \-\-noflush ] . RB [ --noflush ]
. RB [ \-\-nolockfs ] . RB [ --nolockfs ]
. ad b . ad b
.. ..
.CMD_WIPE_TABLE .CMD_WIPE_TABLE
@ -383,70 +383,70 @@ The second argument is the logical device name or uuid.
Invoking the dmsetup tool as \fBdevmap_name\fP Invoking the dmsetup tool as \fBdevmap_name\fP
(which is not normally distributed and is supported (which is not normally distributed and is supported
only for historical reasons) is equivalent to only for historical reasons) is equivalent to
.BI \%dmsetup\ info\ \-c\ \-\-noheadings\ \-j \ major\ \-m \ minor \c .BI \%dmsetup\ info\ -c\ --noheadings\ -j \ major\ -m \ minor \c
\fR. \fR.
.\" dot above here fixes -Thtml rendering for next HP option .\" dot above here fixes -Thtml rendering for next HP option
. .
.SH OPTIONS .SH OPTIONS
. .
.HP .HP
.BR \-\-addnodeoncreate .BR --addnodeoncreate
.br .br
Ensure \fI/dev/mapper\fP node exists after \fBdmsetup create\fP. Ensure \fI/dev/mapper\fP node exists after \fBdmsetup create\fP.
. .
.HP .HP
.BR \-\-addnodeonresume .BR --addnodeonresume
.br .br
Ensure \fI/dev/mapper\fP node exists after \fBdmsetup resume\fP (default with udev). Ensure \fI/dev/mapper\fP node exists after \fBdmsetup resume\fP (default with udev).
. .
.HP .HP
.BR \-\-checks .BR --checks
.br .br
Perform additional checks on the operations requested and report Perform additional checks on the operations requested and report
potential problems. Useful when debugging scripts. potential problems. Useful when debugging scripts.
In some cases these checks may slow down operations noticeably. In some cases these checks may slow down operations noticeably.
. .
.HP .HP
.BR \-c | \-C | \-\-columns .BR -c | -C | --columns
.br .br
Display output in columns rather than as Field: Value lines. Display output in columns rather than as Field: Value lines.
. .
.HP .HP
.BR \-\-count .BR --count
.IR count .IR count
.br .br
Specify the number of times to repeat a report. Set this to zero Specify the number of times to repeat a report. Set this to zero
continue until interrupted. The default interval is one second. continue until interrupted. The default interval is one second.
. .
.HP .HP
.BR \-f | \-\-force .BR -f | --force
.br .br
Try harder to complete operation. Try harder to complete operation.
. .
.HP .HP
.BR \-h | \-\-help .BR -h | --help
.br .br
Outputs a summary of the commands available, optionally including Outputs a summary of the commands available, optionally including
the list of report fields (synonym with \fBhelp\fP command). the list of report fields (synonym with \fBhelp\fP command).
. .
.HP .HP
.BR \-\-inactive .BR --inactive
.br .br
When returning any table information from the kernel report on the When returning any table information from the kernel report on the
inactive table instead of the live table. inactive table instead of the live table.
Requires kernel driver version 4.16.0 or above. Requires kernel driver version 4.16.0 or above.
. .
.HP .HP
.BR \-\-interval .BR --interval
.IR seconds .IR seconds
.br .br
Specify the interval in seconds between successive iterations for Specify the interval in seconds between successive iterations for
repeating reports. If \fB\-\-interval\fP is specified but \fB\-\-count\fP repeating reports. If \fB--interval\fP is specified but \fB--count\fP
is not, reports will continue to repeat until interrupted. is not, reports will continue to repeat until interrupted.
The default interval is one second. The default interval is one second.
. .
.HP .HP
.BR \-\-manglename .BR --manglename
.BR auto | hex | none .BR auto | hex | none
.br .br
Mangle any character not on a whitelist using mangling_mode when Mangle any character not on a whitelist using mangling_mode when
@ -466,69 +466,69 @@ Mangling mode could be also set through
environment variable. environment variable.
. .
.HP .HP
.BR \-j | \-\-major .BR -j | --major
.IR major .IR major
.br .br
Specify the major number. Specify the major number.
. .
.HP .HP
.BR \-m | \-\-minor .BR -m | --minor
.IR minor .IR minor
.br .br
Specify the minor number. Specify the minor number.
. .
.HP .HP
.BR \-n | \-\-notable .BR -n | --notable
.br .br
When creating a device, don't load any table. When creating a device, don't load any table.
. .
.HP .HP
.BR \-\-nameprefixes .BR --nameprefixes
.br .br
Add a "DM_" prefix plus the field name to the output. Useful with Add a "DM_" prefix plus the field name to the output. Useful with
\fB\-\-noheadings\fP to produce a list of \fB--noheadings\fP to produce a list of
field=value pairs that can be used to set environment variables field=value pairs that can be used to set environment variables
(for example, in (for example, in
.BR udev (7) .BR udev (7)
rules). rules).
. .
.HP .HP
.BR \-\-noheadings .BR --noheadings
Suppress the headings line when using columnar output. Suppress the headings line when using columnar output.
. .
.HP .HP
.BR \-\-noflush .BR --noflush
Do not flush outstading I/O when suspending a device, or do not Do not flush outstading I/O when suspending a device, or do not
commit thin-pool metadata when obtaining thin-pool status. commit thin-pool metadata when obtaining thin-pool status.
. .
.HP .HP
.BR \-\-nolockfs .BR --nolockfs
.br .br
Do not attempt to synchronize filesystem eg, when suspending a device. Do not attempt to synchronize filesystem eg, when suspending a device.
. .
.HP .HP
.BR \-\-noopencount .BR --noopencount
.br .br
Tell the kernel not to supply the open reference count for the device. Tell the kernel not to supply the open reference count for the device.
. .
.HP .HP
.BR \-\-noudevrules .BR --noudevrules
.br .br
Do not allow udev to manage nodes for devices in device-mapper directory. Do not allow udev to manage nodes for devices in device-mapper directory.
. .
.HP .HP
.BR \-\-noudevsync .BR --noudevsync
.br .br
Do not synchronise with udev when creating, renaming or removing devices. Do not synchronise with udev when creating, renaming or removing devices.
. .
.HP .HP
.BR \-o | \-\-options .BR -o | --options
.IR options .IR options
.br .br
Specify which fields to display. Specify which fields to display.
. .
.HP .HP
.BR \-\-readahead .BR --readahead
.RB [ + ] \fIsectors | auto | none .RB [ + ] \fIsectors | auto | none
.br .br
Specify read ahead size in units of sectors. Specify read ahead size in units of sectors.
@ -539,12 +539,12 @@ smaller than the value chosen by the kernel.
The value \fBnone\fP is equivalent to specifying zero. The value \fBnone\fP is equivalent to specifying zero.
. .
.HP .HP
.BR \-r | \-\-readonly .BR -r | --readonly
.br .br
Set the table being loaded read-only. Set the table being loaded read-only.
. .
.HP .HP
.BR \-S | \-\-select .BR -S | --select
.IR selection .IR selection
.br .br
Display only rows that match \fIselection\fP criteria. All rows are displayed Display only rows that match \fIselection\fP criteria. All rows are displayed
@ -557,14 +557,14 @@ selection operators, check the output of \fBdmsetup\ info\ -c\ -S\ help\fP
command. command.
. .
.HP .HP
.BR \-\-table .BR --table
.IR table .IR table
.br .br
Specify a one-line table directly on the command line. Specify a one-line table directly on the command line.
See below for more information on the table format. See below for more information on the table format.
. .
.HP .HP
.BR \-\-udevcookie .BR --udevcookie
.IR cookie .IR cookie
.br .br
Use cookie for udev synchronisation. Use cookie for udev synchronisation.
@ -573,29 +573,29 @@ multiple different devices. It's not adviced to combine different
operations on the single device. operations on the single device.
. .
.HP .HP
.BR \-u | \-\-uuid .BR -u | --uuid
.br .br
Specify the \fIuuid\fP. Specify the \fIuuid\fP.
. .
.HP .HP
.BR \-y | \-\-yes .BR -y | --yes
.br .br
Answer yes to all prompts automatically. Answer yes to all prompts automatically.
. .
.HP .HP
.BR \-v | \-\-verbose .BR -v | --verbose
.RB [ \-v | \-\-verbose ] .RB [ -v | --verbose ]
.br .br
Produce additional output. Produce additional output.
. .
.HP .HP
.BR \-\-verifyudev .BR --verifyudev
.br .br
If udev synchronisation is enabled, verify that udev operations get performed If udev synchronisation is enabled, verify that udev operations get performed
correctly and try to fix up the device nodes afterwards if not. correctly and try to fix up the device nodes afterwards if not.
. .
.HP .HP
.BR \-\-version .BR --version
.br .br
Display the library and kernel driver version. Display the library and kernel driver version.
.br .br
@ -612,7 +612,7 @@ Destroys the table in the inactive table slot for device_name.
.br .br
Creates a device with the given name. Creates a device with the given name.
If \fItable\fP or \fItable_file\fP is supplied, the table is loaded and made live. If \fItable\fP or \fItable_file\fP is supplied, the table is loaded and made live.
Otherwise a table is read from standard input unless \fB\-\-notable\fP is used. Otherwise a table is read from standard input unless \fB--notable\fP is used.
The optional \fIuuid\fP can be used in place of The optional \fIuuid\fP can be used in place of
device_name in subsequent dmsetup commands. device_name in subsequent dmsetup commands.
If successful the device will appear in table and for live If successful the device will appear in table and for live
@ -682,7 +682,7 @@ Device names on output can be customised by following options:
\fBdevno\fP (major and minor pair, used by default), \fBdevno\fP (major and minor pair, used by default),
\fBblkdevname\fP (block device name), \fBblkdevname\fP (block device name),
\fBdevname\fP (map name for device-mapper devices, equal to blkdevname otherwise). \fBdevname\fP (map name for device-mapper devices, equal to blkdevname otherwise).
\fB\-\-tree\fP displays dependencies between devices as a tree. \fB--tree\fP displays dependencies between devices as a tree.
It accepts a comma-separate list of \fIoptions\fP. It accepts a comma-separate list of \fIoptions\fP.
Some specify the information displayed against each node: Some specify the information displayed against each node:
.BR device / nodevice ; .BR device / nodevice ;
@ -705,11 +705,11 @@ If neither is supplied, reads a table from standard input.
Ensure existing device-mapper \fIdevice_name\fP and UUID is in the correct mangled Ensure existing device-mapper \fIdevice_name\fP and UUID is in the correct mangled
form containing only whitelisted characters (supported by udev) and do form containing only whitelisted characters (supported by udev) and do
a rename if necessary. Any character not on the whitelist will be mangled a rename if necessary. Any character not on the whitelist will be mangled
based on the \fB\-\-manglename\fP setting. Automatic rename works only for device based on the \fB--manglename\fP setting. Automatic rename works only for device
names and not for device UUIDs because the kernel does not allow changing names and not for device UUIDs because the kernel does not allow changing
the UUID of active devices. Any incorrect UUIDs are reported only and they the UUID of active devices. Any incorrect UUIDs are reported only and they
must be manually corrected by deactivating the device first and then must be manually corrected by deactivating the device first and then
reactivating it with proper mangling mode used (see also \fB\-\-manglename\fP). reactivating it with proper mangling mode used (see also \fB--manglename\fP).
. .
.HP .HP
.CMD_MESSAGE .CMD_MESSAGE
@ -728,16 +728,16 @@ driver, adding, changing or removing nodes as necessary.
.CMD_REMOVE .CMD_REMOVE
.br .br
Removes a device. It will no longer be visible to dmsetup. Open devices Removes a device. It will no longer be visible to dmsetup. Open devices
cannot be removed, but adding \fB\-\-force\fP will replace the table with one cannot be removed, but adding \fB--force\fP will replace the table with one
that fails all I/O. \fB\-\-deferred\fP will enable deferred removal of open that fails all I/O. \fB--deferred\fP will enable deferred removal of open
devices - the device will be removed when the last user closes it. The deferred devices - the device will be removed when the last user closes it. The deferred
removal feature is supported since version 4.27.0 of the device-mapper removal feature is supported since version 4.27.0 of the device-mapper
driver available in upstream kernel version 3.13. (Use \fBdmsetup version\fP driver available in upstream kernel version 3.13. (Use \fBdmsetup version\fP
to check this.) If an attempt to remove a device fails, perhaps because a process run to check this.) If an attempt to remove a device fails, perhaps because a process run
from a quick udev rule temporarily opened the device, the \fB\-\-retry\fP from a quick udev rule temporarily opened the device, the \fB--retry\fP
option will cause the operation to be retried for a few seconds before failing. option will cause the operation to be retried for a few seconds before failing.
Do NOT combine Do NOT combine
\fB\-\-force\fP and \fB\-\-udevcookie\fP, as udev may start to process udev \fB--force\fP and \fB--udevcookie\fP, as udev may start to process udev
rules in the middle of error target replacement and result in nondeterministic rules in the middle of error target replacement and result in nondeterministic
result. result.
. .
@ -746,8 +746,8 @@ result.
.br .br
Attempts to remove all device definitions i.e. reset the driver. This also runs Attempts to remove all device definitions i.e. reset the driver. This also runs
\fBmknodes\fP afterwards. Use with care! Open devices cannot be removed, but \fBmknodes\fP afterwards. Use with care! Open devices cannot be removed, but
adding \fB\-\-force\fP will replace the table with one that fails all I/O. adding \fB--force\fP will replace the table with one that fails all I/O.
\fB\-\-deferred\fP will enable deferred removal of open devices - the device \fB--deferred\fP will enable deferred removal of open devices - the device
will be removed when the last user closes it. The deferred removal feature is will be removed when the last user closes it. The deferred removal feature is
supported since version 4.27.0 of the device-mapper driver available in supported since version 4.27.0 of the device-mapper driver available in
upstream kernel version 3.13. upstream kernel version 3.13.
@ -797,8 +797,8 @@ for more details.
.CMD_STATUS .CMD_STATUS
.br .br
Outputs status information for each of the device's targets. Outputs status information for each of the device's targets.
With \fB\-\-target\fP, only information relating to the specified target type With \fB--target\fP, only information relating to the specified target type
any is displayed. With \fB\-\-noflush\fP, the thin target (from version 1.3.0) any is displayed. With \fB--noflush\fP, the thin target (from version 1.3.0)
doesn't commit any outstanding changes to disk before reporting its statistics. doesn't commit any outstanding changes to disk before reporting its statistics.
.HP .HP
@ -808,9 +808,9 @@ Suspends a device. Any I/O that has already been mapped by the device
but has not yet completed will be flushed. Any further I/O to that but has not yet completed will be flushed. Any further I/O to that
device will be postponed for as long as the device is suspended. device will be postponed for as long as the device is suspended.
If there's a filesystem on the device which supports the operation, If there's a filesystem on the device which supports the operation,
an attempt will be made to sync it first unless \fB\-\-nolockfs\fP is specified. an attempt will be made to sync it first unless \fB--nolockfs\fP is specified.
Some targets such as recent (October 2006) versions of multipath may support Some targets such as recent (October 2006) versions of multipath may support
the \fB\-\-noflush\fP option. This lets outstanding I/O that has not yet reached the the \fB--noflush\fP option. This lets outstanding I/O that has not yet reached the
device to remain unflushed. device to remain unflushed.
. .
.HP .HP
@ -818,10 +818,10 @@ device to remain unflushed.
.br .br
Outputs the current table for the device in a format that can be fed Outputs the current table for the device in a format that can be fed
back in using the create or load commands. back in using the create or load commands.
With \fB\-\-target\fP, only information relating to the specified target type With \fB--target\fP, only information relating to the specified target type
is displayed. is displayed.
Real encryption keys are suppressed in the table output for the crypt Real encryption keys are suppressed in the table output for the crypt
target unless the \fB\-\-showkeys\fP parameter is supplied. Kernel key target unless the \fB--showkeys\fP parameter is supplied. Kernel key
references prefixed with \fB:\fP are not affected by the parameter and get references prefixed with \fB:\fP are not affected by the parameter and get
displayed always. displayed always.
. .
@ -855,7 +855,7 @@ The output is a cookie value. Normally we don't need to create cookies since
dmsetup creates and destroys them for each action automatically. However, we can dmsetup creates and destroys them for each action automatically. However, we can
generate one explicitly to group several actions together and use only one generate one explicitly to group several actions together and use only one
cookie instead. We can define a cookie to use for each relevant command by using cookie instead. We can define a cookie to use for each relevant command by using
\fB\-\-udevcookie\fP option. Alternatively, we can export this value into the environment \fB--udevcookie\fP option. Alternatively, we can export this value into the environment
of the dmsetup process as \fBDM_UDEV_COOKIE\fP variable and it will be used automatically of the dmsetup process as \fBDM_UDEV_COOKIE\fP variable and it will be used automatically
with all subsequent commands until it is unset. with all subsequent commands until it is unset.
Invoking this command will create system-wide semaphore that needs to be cleaned Invoking this command will create system-wide semaphore that needs to be cleaned
@ -888,10 +888,10 @@ Outputs version information.
.CMD_WAIT .CMD_WAIT
.br .br
Sleeps until the event counter for device_name exceeds event_nr. Sleeps until the event counter for device_name exceeds event_nr.
Use \fB\-v\fP to see the event number returned. Use \fB-v\fP to see the event number returned.
To wait until the next event is triggered, use \fBinfo\fP to find To wait until the next event is triggered, use \fBinfo\fP to find
the last event number. the last event number.
With \fB\-\-noflush\fP, the thin target (from version 1.3.0) doesn't commit With \fB--noflush\fP, the thin target (from version 1.3.0) doesn't commit
any outstanding changes to disk before reporting its statistics. any outstanding changes to disk before reporting its statistics.
. .
.HP .HP
@ -1005,11 +1005,11 @@ Defaults to "\fI/dev\fP" and must be an absolute path.
.TP .TP
.B DM_UDEV_COOKIE .B DM_UDEV_COOKIE
A cookie to use for all relevant commands to synchronize with udev processing. A cookie to use for all relevant commands to synchronize with udev processing.
It is an alternative to using \fB\-\-udevcookie\fP option. It is an alternative to using \fB--udevcookie\fP option.
.TP .TP
.B DM_DEFAULT_NAME_MANGLING_MODE .B DM_DEFAULT_NAME_MANGLING_MODE
A default mangling mode. Defaults to "\fB#DEFAULT_MANGLING#\fP" A default mangling mode. Defaults to "\fB#DEFAULT_MANGLING#\fP"
and it is an alternative to using \fB\-\-manglename\fP option. and it is an alternative to using \fB--manglename\fP option.
. .
.SH AUTHORS .SH AUTHORS
. .

View File

@ -1,18 +1,21 @@
.TH DMSTATS 8 "Jun 23 2016" "Linux" "MAINTENANCE COMMANDS" .TH DMSTATS 8 "Jun 23 2016" "Linux" "MAINTENANCE COMMANDS"
.de OPT_PROGRAMS .de OPT_PROGRAMS
. RB \%[ \-\-allprograms | \-\-programid . RB \%[ --allprograms | --programid
. IR id ] . IR id ]
.. ..
. .
.de OPT_REGIONS .de OPT_REGIONS
. RB \%[ \-\-allregions | \-\-regionid . RB \%[ --allregions | --regionid
. IR id ] . IR id ]
.. ..
.de OPT_OBJECTS .de OPT_OBJECTS
. RB [ \-\-area ] . RB [ --area ]
. RB [ \-\-region ] . RB [ --region ]
. RB [ \-\-group ] . RB [ --group ]
..
.de OPT_FOREGROUND
. RB [ --foreground ]
.. ..
. .
.\" Print units suffix, use with arg to print human .\" Print units suffix, use with arg to print human
@ -54,13 +57,13 @@ dmstats \(em device-mapper statistics management
. ad l . ad l
. IR command . IR command
. IR device_name " |" . IR device_name " |"
. BR \-\-major . BR --major
. IR major . IR major
. BR \-\-minor . BR --minor
. IR minor " |" . IR minor " |"
. BR \-u | \-\-uuid . BR -u | --uuid
. IR uuid . IR uuid
. RB \%[ \-v | \-\-verbose] . RB \%[ -v | --verbose]
. ad b . ad b
.. ..
.CMD_COMMAND .CMD_COMMAND
@ -82,22 +85,26 @@ dmstats \(em device-mapper statistics management
.de CMD_CREATE .de CMD_CREATE
. ad l . ad l
. BR create . BR create
. IR device_name... | file_path... | \fB\-\-alldevices . IR device_name... | file_path... | \fB--alldevices
. RB [ \-\-areas . RB [ --areas
. IR nr_areas | \fB\-\-areasize . IR nr_areas | \fB--areasize
. IR area_size ] . IR area_size ]
. RB [ \-\-bounds . RB [ --bounds
. IR \%histogram_boundaries ] . IR \%histogram_boundaries ]
. RB [ \-\-filemap ] . RB [ --filemap ]
. RB [ \-\-nogroup ] . RB [ --follow
. RB [ \-\-precise ] . IR follow_mode ]
. RB [ \-\-start . OPT_FOREGROUND
. RB [ --nomonitor ]
. RB [ --nogroup ]
. RB [ --precise ]
. RB [ --start
. IR start_sector . IR start_sector
. BR \-\-length . BR --length
. IR length | \fB\-\-segments ] . IR length | \fB--segments ]
. RB \%[ \-\-userdata . RB \%[ --userdata
. IR user_data ] . IR user_data ]
. RB [ \-\-programid . RB [ --programid
. IR id ] . IR id ]
. ad b . ad b
.. ..
@ -108,7 +115,7 @@ dmstats \(em device-mapper statistics management
.de CMD_DELETE .de CMD_DELETE
. ad l . ad l
. BR delete . BR delete
. IR device_name | \fB\-\-alldevices . IR device_name | \fB--alldevices
. OPT_PROGRAMS . OPT_PROGRAMS
. OPT_REGIONS . OPT_REGIONS
. ad b . ad b
@ -120,10 +127,10 @@ dmstats \(em device-mapper statistics management
.de CMD_GROUP .de CMD_GROUP
. ad l . ad l
. BR group . BR group
. RI [ device_name | \fB\-\-alldevices ] . RI [ device_name | \fB--alldevices ]
. RB [ \-\-alias . RB [ --alias
. IR name ] . IR name ]
. RB [ \-\-regions . RB [ --regions
. IR regions ] . IR regions ]
. ad b . ad b
.. ..
@ -133,7 +140,7 @@ dmstats \(em device-mapper statistics management
.de CMD_HELP .de CMD_HELP
. ad l . ad l
. BR help . BR help
. RB [ \-c | \-C | \-\-columns ] . RB [ -c | -C | --columns ]
. ad b . ad b
.. ..
.CMD_HELP .CMD_HELP
@ -144,14 +151,14 @@ dmstats \(em device-mapper statistics management
. ad l . ad l
. BR list . BR list
. RI [ device_name ] . RI [ device_name ]
. RB [ \-\-histogram ] . RB [ --histogram ]
. OPT_PROGRAMS . OPT_PROGRAMS
. RB [ \-\-units . RB [ --units
. IR units ] . IR units ]
. OPT_OBJECTS . OPT_OBJECTS
. RB \%[ \-\-nosuffix ] . RB \%[ --nosuffix ]
. RB [ \-\-notimesuffix ] . RB [ --notimesuffix ]
. RB \%[ \-v | \-\-verbose] . RB \%[ -v | --verbose]
. ad b . ad b
.. ..
.CMD_LIST .CMD_LIST
@ -162,7 +169,7 @@ dmstats \(em device-mapper statistics management
. ad l . ad l
. BR print . BR print
. RI [ device_name ] . RI [ device_name ]
. RB [ \-\-clear ] . RB [ --clear ]
. OPT_PROGRAMS . OPT_PROGRAMS
. OPT_REGIONS . OPT_REGIONS
. ad b . ad b
@ -175,24 +182,24 @@ dmstats \(em device-mapper statistics management
. ad l . ad l
. BR report . BR report
. RI [ device_name ] . RI [ device_name ]
. RB [ \-\-interval . RB [ --interval
. IR seconds ] . IR seconds ]
. RB [ \-\-count . RB [ --count
. IR count ] . IR count ]
. RB [ \-\-units . RB [ --units
. IR units ] . IR units ]
. RB [ \-\-histogram ] . RB [ --histogram ]
. OPT_PROGRAMS . OPT_PROGRAMS
. OPT_REGIONS . OPT_REGIONS
. OPT_OBJECTS . OPT_OBJECTS
. RB [ \-O | \-\-sort . RB [ -O | --sort
. IR sort_fields ] . IR sort_fields ]
. RB [ \-S | \-\-select . RB [ -S | --select
. IR selection ] . IR selection ]
. RB [ \-\-units . RB [ --units
. IR units ] . IR units ]
. RB [ \-\-nosuffix ] . RB [ --nosuffix ]
. RB \%[ \-\-notimesuffix ] . RB \%[ --notimesuffix ]
. ad b . ad b
.. ..
.CMD_REPORT .CMD_REPORT
@ -201,8 +208,8 @@ dmstats \(em device-mapper statistics management
.de CMD_UNGROUP .de CMD_UNGROUP
. ad l . ad l
. BR ungroup . BR ungroup
. RI [ device_name | \fB\-\-alldevices ] . RI [ device_name | \fB--alldevices ]
. RB [ \-\-groupid . RB [ --groupid
. IR id ] . IR id ]
. ad b . ad b
.. ..
@ -213,8 +220,11 @@ dmstats \(em device-mapper statistics management
. ad l . ad l
. BR update_filemap . BR update_filemap
. IR file_path . IR file_path
. RB [ \-\-groupid . RB [ --groupid
. IR id ] . IR id ]
. RB [ --follow
. IR follow_mode ]
. OPT_FOREGROUND
. ad b . ad b
.. ..
.CMD_UPDATE_FILEMAP .CMD_UPDATE_FILEMAP
@ -238,47 +248,47 @@ control, and reporting behaviour.
When no device argument is given dmstats will by default operate on all When no device argument is given dmstats will by default operate on all
device-mapper devices present. The \fBcreate\fP and \fBdelete\fP device-mapper devices present. The \fBcreate\fP and \fBdelete\fP
commands require the use of \fB\-\-alldevices\fP when used in this way. commands require the use of \fB--alldevices\fP when used in this way.
. .
.SH OPTIONS .SH OPTIONS
. .
.HP .HP
.BR \-\-alias .BR --alias
.IR name .IR name
.br .br
Specify an alias name for a group. Specify an alias name for a group.
. .
.HP .HP
.BR \-\-alldevices .BR --alldevices
.br .br
If no device arguments are given allow operation on all devices when If no device arguments are given allow operation on all devices when
creating or deleting regions. creating or deleting regions.
. .
.HP .HP
.BR \-\-allprograms .BR --allprograms
.br .br
Include regions from all program IDs for list and report operations. Include regions from all program IDs for list and report operations.
.br .br
.HP .HP
.BR \-\-allregions .BR --allregions
.br .br
Include all present regions for commands that normally accept a single Include all present regions for commands that normally accept a single
region identifier. region identifier.
. .
.HP .HP
.BR \-\-area .BR --area
.br .br
When peforming a list or report, include objects of type area in the When peforming a list or report, include objects of type area in the
results. results.
. .
.HP .HP
.BR \-\-areas .BR --areas
.IR nr_areas .IR nr_areas
.br .br
Specify the number of statistics areas to create within a new region. Specify the number of statistics areas to create within a new region.
. .
.HP .HP
.BR \-\-areasize .BR --areasize
.IR area_size \c .IR area_size \c
.RB [ \c .RB [ \c
.UNITS .UNITS
@ -288,25 +298,25 @@ optional suffix selects units of:
.HELP_UNITS .HELP_UNITS
. .
.HP .HP
.BR \-\-clear .BR --clear
.br .br
When printing statistics counters, also atomically reset them to zero. When printing statistics counters, also atomically reset them to zero.
. .
.HP .HP
.BR \-\-count .BR --count
.IR count .IR count
.br .br
Specify the iteration count for repeating reports. If the count Specify the iteration count for repeating reports. If the count
argument is zero reports will continue to repeat until interrupted. argument is zero reports will continue to repeat until interrupted.
. .
.HP .HP
.BR \-\-group .BR --group
.br .br
When peforming a list or report, include objects of type group in the When peforming a list or report, include objects of type group in the
results. results.
. .
.HP .HP
.BR \-\-filemap .BR --filemap
.br .br
Instead of creating regions on a device as specified by command line Instead of creating regions on a device as specified by command line
options, open the file found at each \fBfile_path\fP argument, and options, open the file found at each \fBfile_path\fP argument, and
@ -314,13 +324,67 @@ create regions corresponding to the locations of the on-disk extents
allocated to the file(s). allocated to the file(s).
. .
.HP .HP
.BR \-\-groupid .BR --nomonitor
.br
Disable the \fBdmfilemapd\fP daemon when creating new file mapped
groups. Normally the device-mapper filemap monitoring daemon,
\fBdmfilemapd\fP, is started for each file mapped group to update the
set of regions as the file changes on-disk: use of this option
disables this behaviour.
Regions in the group may still be updated with the
\fBupdate_filemap\fP command, or by starting the daemon manually.
.
.HP
.BR --follow
.IR follow_mode
.br
Specify the \fBdmfilemapd\fP file following mode. The file map
monitoring daemon can monitor files in two distinct ways: the mode
affects the behaviour of the daemon when a file under monitoring is
renamed or unlinked, and the conditions which cause the daemon to
terminate.
The \fBfollow_mode\fP argument is either "inode", for follow-inode
mode, or "path", for follow-path.
If follow-inode mode is used, the daemon will hold the file open, and
continue to update regions from the same file descriptor. This means
that the mapping will follow rename, move (within the same file
system), and unlink operations. This mode is useful if the file is
expected to be moved, renamed, or unlinked while it is being
monitored.
In follow-inode mode, the daemon will exit once it detects that the
file has been unlinked and it is the last holder of a reference to it.
If follow-path is used, the daemon will re-open the provided path on
each monitoring iteration. This means that the group will be updated
to reflect a new file being moved to the same path as the original
file. This mode is useful for files that are expected to be updated
via unlink and rename.
In follow-path mode, the daemon will exit if the file is removed and
not replaced within a brief tolerance interval.
In either mode, the daemon exits automatically if the monitored group
is removed.
.
.HP
.BR --foreground
.br
Specify that the \fBdmfilemapd\fP daemon should run in the foreground.
The daemon will not fork into the background, and will replace the
\fBdmstats\fP command that started it.
.
.HP
.BR --groupid
.IR id .IR id
.br .br
Specify the group to operate on. Specify the group to operate on.
. .
.HP .HP
.BR \-\-bounds .BR --bounds
.IR histogram_boundaries \c .IR histogram_boundaries \c
.RB [ ns | us | ms | s ] .RB [ ns | us | ms | s ]
.br .br
@ -334,22 +398,22 @@ or \fBs\fP may be given after each value to specify units of
nanoseconds, microseconds, miliseconds or seconds respectively. nanoseconds, microseconds, miliseconds or seconds respectively.
. .
.HP .HP
.BR \-\-histogram .BR --histogram
.br .br
When used with the \fBreport\fP and \fBlist\fP commands select default When used with the \fBreport\fP and \fBlist\fP commands select default
fields that emphasize latency histogram data. fields that emphasize latency histogram data.
. .
.HP .HP
.BR \-\-interval .BR --interval
.IR seconds .IR seconds
.br .br
Specify the interval in seconds between successive iterations for Specify the interval in seconds between successive iterations for
repeating reports. If \fB\-\-interval\fP is specified but repeating reports. If \fB--interval\fP is specified but
\fB\-\-count\fP is not, \fB--count\fP is not,
reports will continue to repeat until interrupted. reports will continue to repeat until interrupted.
. .
.HP .HP
.BR \-\-length .BR --length
.IR length \c .IR length \c
.RB [ \c .RB [ \c
.UNITS .UNITS
@ -359,55 +423,55 @@ suffix selects units of:
.HELP_UNITS .HELP_UNITS
. .
.HP .HP
.BR \-j | \-\-major .BR -j | --major
.IR major .IR major
.br .br
Specify the major number. Specify the major number.
. .
.HP .HP
.BR \-m | \-\-minor .BR -m | --minor
.IR minor .IR minor
.br .br
Specify the minor number. Specify the minor number.
. .
.HP .HP
.BR \-\-nogroup .BR --nogroup
.br .br
When creating regions mapping the extents of a file in the file When creating regions mapping the extents of a file in the file
system, do not create a group or set an alias. system, do not create a group or set an alias.
. .
.HP .HP
.BR \-\-nosuffix .BR --nosuffix
.br .br
Suppress the suffix on output sizes. Use with \fB\-\-units\fP Suppress the suffix on output sizes. Use with \fB--units\fP
(except h and H) if processing the output. (except h and H) if processing the output.
. .
.HP .HP
.BR \-\-notimesuffix .BR --notimesuffix
.br .br
Suppress the suffix on output time values. Histogram boundary values Suppress the suffix on output time values. Histogram boundary values
will be reported in units of nanoseconds. will be reported in units of nanoseconds.
. .
.HP .HP
.BR \-o | \-\-options .BR -o | --options
.br .br
Specify which report fields to display. Specify which report fields to display.
. .
.HP .HP
.BR \-O | \-\-sort .BR -O | --sort
.IR sort_fields .IR sort_fields
.br .br
Sort output according to the list of fields given. Precede any Sort output according to the list of fields given. Precede any
sort field with '\fB-\fP' for a reverse sort on that column. sort field with '\fB-\fP' for a reverse sort on that column.
. .
.HP .HP
.BR \-\-precise .BR --precise
.br .br
Attempt to use nanosecond precision counters when creating new Attempt to use nanosecond precision counters when creating new
statistics regions. statistics regions.
. .
.HP .HP
.BR \-\-programid .BR --programid
.IR id .IR id
.br .br
Specify a program ID string. When creating new statistics regions this Specify a program ID string. When creating new statistics regions this
@ -416,19 +480,19 @@ program ID in order to select only regions with a matching value. The
default program ID for dmstats-managed regions is "dmstats". default program ID for dmstats-managed regions is "dmstats".
. .
.HP .HP
.BR \-\-region .BR --region
.br .br
When peforming a list or report, include objects of type region in the When peforming a list or report, include objects of type region in the
results. results.
. .
.HP .HP
.BR \-\-regionid .BR --regionid
.IR id .IR id
.br .br
Specify the region to operate on. Specify the region to operate on.
. .
.HP .HP
.BR \-\-regions .BR --regions
.IR region_list .IR region_list
.br .br
Specify a list of regions to group. The group list is a comma-separated Specify a list of regions to group. The group list is a comma-separated
@ -436,23 +500,23 @@ list of region identifiers. Continuous sequences of identifiers may be
expressed as a hyphen separated range, for example: '1-10'. expressed as a hyphen separated range, for example: '1-10'.
. .
.HP .HP
.BR \-\-relative .BR --relative
.br .br
If displaying the histogram report show relative (percentage) values If displaying the histogram report show relative (percentage) values
instead of absolute counts. instead of absolute counts.
. .
.HP .HP
.BR \-S | \-\-select .BR -S | --select
.IR selection .IR selection
.br .br
Display only rows that match \fIselection\fP criteria. All rows with the Display only rows that match \fIselection\fP criteria. All rows with the
additional "selected" column (\fB\-o selected\fP) showing 1 if the row matches additional "selected" column (\fB-o selected\fP) showing 1 if the row matches
the \fIselection\fP and 0 otherwise. The selection criteria are defined by the \fIselection\fP and 0 otherwise. The selection criteria are defined by
specifying column names and their valid values while making use of specifying column names and their valid values while making use of
supported comparison operators. supported comparison operators.
. .
.HP .HP
.BR \-\-start .BR --start
.IR start \c .IR start \c
.RB [ \c .RB [ \c
.UNITS .UNITS
@ -462,18 +526,18 @@ optional suffix selects units of:
.HELP_UNITS .HELP_UNITS
. .
.HP .HP
.BR \-\-segments .BR --segments
.br .br
When used with \fBcreate\fP, create a new statistics region for each When used with \fBcreate\fP, create a new statistics region for each
target contained in the given device(s). This causes a separate region target contained in the given device(s). This causes a separate region
to be allocated for each segment of the device. to be allocated for each segment of the device.
The newly created regions are automatically placed into a group unless The newly created regions are automatically placed into a group unless
the \fB\-\-nogroup\fP option is given. When grouping is enabled a group the \fB--nogroup\fP option is given. When grouping is enabled a group
alias may be specified using the \fB\-\-alias\fP option. alias may be specified using the \fB--alias\fP option.
. .
.HP .HP
.BR \-\-units .BR --units
.RI [ units ] \c .RI [ units ] \c
.RB [ h | H | \c .RB [ h | H | \c
.UNITS .UNITS
@ -482,10 +546,10 @@ Set the display units for report output.
All sizes are output in these units: All sizes are output in these units:
.RB ( h )uman-readable, .RB ( h )uman-readable,
.HELP_UNITS .HELP_UNITS
Can also specify custom units e.g. \fB\-\-units\ 3M\fP. Can also specify custom units e.g. \fB--units\ 3M\fP.
. .
.HP .HP
.BR \-\-userdata .BR --userdata
.IR user_data .IR user_data
.br .br
Specify user data (a word) to be stored with a new region. The value Specify user data (a word) to be stored with a new region. The value
@ -494,12 +558,12 @@ information), and stored with the region in the aux_data field provided
by the kernel. Whitespace is not permitted. by the kernel. Whitespace is not permitted.
. .
.HP .HP
.BR \-u | \-\-uuid .BR -u | --uuid
.br .br
Specify the uuid. Specify the uuid.
. .
.HP .HP
.BR \-v | \-\-verbose " [" \-v | \-\-verbose ] .BR -v | --verbose " [" -v | --verbose ]
.br .br
Produce additional output. Produce additional output.
. .
@ -516,17 +580,17 @@ regions (with the exception of in-flight IO counters).
.br .br
Creates one or more new statistics regions on the specified device(s). Creates one or more new statistics regions on the specified device(s).
The region will span the entire device unless \fB\-\-start\fP and The region will span the entire device unless \fB--start\fP and
\fB\-\-length\fP or \fB\-\-segments\fP are given. The \fB\-\-start\fP an \fB--length\fP or \fB--segments\fP are given. The \fB--start\fP an
\fB\-\-length\fP options allow a region of arbitrary length to be placed \fB--length\fP options allow a region of arbitrary length to be placed
at an arbitrary offset into the device. The \fB\-\-segments\fP option at an arbitrary offset into the device. The \fB--segments\fP option
causes a new region to be created for each target in the corresponding causes a new region to be created for each target in the corresponding
device-mapper device's table. device-mapper device's table.
If the \fB\-\-precise\fP option is used the command will attempt to If the \fB--precise\fP option is used the command will attempt to
create a region using nanosecond precision counters. create a region using nanosecond precision counters.
If \fB\-\-bounds\fP is given a latency histogram will be tracked for If \fB--bounds\fP is given a latency histogram will be tracked for
the new region. The boundaries of the histogram bins are given as a the new region. The boundaries of the histogram bins are given as a
comma separated list of latency values. There is an implicit lower bound comma separated list of latency values. There is an implicit lower bound
of zero on the first bin and an implicit upper bound of infinity (or the of zero on the first bin and an implicit upper bound of infinity (or the
@ -537,7 +601,7 @@ ms, or s may be given after each value to specify units of nanoseconds,
microseconds, miliseconds or seconds respectively, so for example, 10ms microseconds, miliseconds or seconds respectively, so for example, 10ms
is equivalent to 10000000. Latency values with a precision of less than is equivalent to 10000000. Latency values with a precision of less than
one milisecond can only be used when precise timestamps are enabled: if one milisecond can only be used when precise timestamps are enabled: if
\fB\-\-precise\fP is not given and values less than one milisecond are \fB--precise\fP is not given and values less than one milisecond are
used it will be enabled automatically. used it will be enabled automatically.
An optional \fBprogram_id\fP or \fBuser_data\fP string may be associated An optional \fBprogram_id\fP or \fBuser_data\fP string may be associated
@ -552,7 +616,7 @@ By default dmstats creates regions with a \fBprogram_id\fP of
On success the \fBregion_id\fP of the newly created region is printed On success the \fBregion_id\fP of the newly created region is printed
to stdout. to stdout.
If the \fB\-\-filemap\fP option is given with a regular file, or list If the \fB--filemap\fP option is given with a regular file, or list
of files, as the \fBfile_path\fP argument, instead of creating regions of files, as the \fBfile_path\fP argument, instead of creating regions
with parameters specified on the command line, \fBdmstats\fP will open with parameters specified on the command line, \fBdmstats\fP will open
the files located at \fBfile_path\fP and create regions corresponding to the files located at \fBfile_path\fP and create regions corresponding to
@ -560,15 +624,20 @@ the physical extents allocated to the file. This can be used to monitor
statistics for individual files in the file system, for example, virtual statistics for individual files in the file system, for example, virtual
machine images, swap areas, or large database files. machine images, swap areas, or large database files.
To work with the \fB\-\-filemap\fP option, files must be located on a To work with the \fB--filemap\fP option, files must be located on a
local file system, backed by a device-mapper device, that supports local file system, backed by a device-mapper device, that supports
physical extent data using the FIEMAP ioctl (Ext4 and XFS for e.g.). physical extent data using the FIEMAP ioctl (Ext4 and XFS for e.g.).
By default regions that map a file are placed into a group and the By default regions that map a file are placed into a group and the
group alias is set to the basename of the file. This behaviour can be group alias is set to the basename of the file. This behaviour can be
overridden with the \fB\-\-alias\fP and \fB\-\-nogroup\fP options. overridden with the \fB--alias\fP and \fB--nogroup\fP options.
Use the \fB\-\-group\fP option to only display information for groups Creating a group that maps a file automatically starts a daemon,
\fBdmfilemapd\fP to monitor the file and update the mapping as the
extents allocated to the file change. This behaviour can be disabled
using the \fB--nomonitor\fP option.
Use the \fB--group\fP option to only display information for groups
when listing and reporting. when listing and reporting.
. .
.HP .HP
@ -579,12 +648,12 @@ by the region are released and the region will not appear in the output
of subsequent list, print, or report operations. of subsequent list, print, or report operations.
All regions registered on a device may be removed using All regions registered on a device may be removed using
\fB\-\-allregions\fP. \fB--allregions\fP.
To remove all regions on all devices both \fB\-\-allregions\fP and To remove all regions on all devices both \fB--allregions\fP and
\fB\-\-alldevices\fP must be used. \fB--alldevices\fP must be used.
If a \fB\-\-groupid\fP is given instead of a \fB\-\-regionid\fP the If a \fB--groupid\fP is given instead of a \fB--regionid\fP the
command will attempt to delete the group and all regions that it command will attempt to delete the group and all regions that it
contains. contains.
@ -597,8 +666,8 @@ will also be removed.
Combine one or more statistics regions on the specified device into a Combine one or more statistics regions on the specified device into a
group. group.
The list of regions to be grouped is specified with \fB\-\-regions\fP The list of regions to be grouped is specified with \fB--regions\fP
and an optional alias may be assigned with \fB\-\-alias\fP. The set of and an optional alias may be assigned with \fB--alias\fP. The set of
regions is given as a comma-separated list of region identifiers. A regions is given as a comma-separated list of region identifiers. A
continuous range of identifers spanning from \fBR1\fP to \fBR2\fP may continuous range of identifers spanning from \fBR1\fP to \fBR2\fP may
be expressed as '\fBR1\fP-\fBR2\fP'. be expressed as '\fBR1\fP-\fBR2\fP'.
@ -624,21 +693,21 @@ the list of report fields.
.CMD_LIST .CMD_LIST
.br .br
List the statistics regions, areas, or groups registered on the device. List the statistics regions, areas, or groups registered on the device.
If the \fB\-\-allprograms\fP switch is given all regions will be listed If the \fB--allprograms\fP switch is given all regions will be listed
regardless of region program ID values. regardless of region program ID values.
By default only regions and groups are included in list output. If By default only regions and groups are included in list output. If
\fB\-v\fP or \fB\-\-verbose\fP is given the report will also include a \fB-v\fP or \fB--verbose\fP is given the report will also include a
row of information for each configured group and for each area contained row of information for each configured group and for each area contained
in each region displayed. in each region displayed.
Regions that contain a single area are by default omitted from the Regions that contain a single area are by default omitted from the
verbose list since their properties are identical to the area that they verbose list since their properties are identical to the area that they
contain - to view all regions regardless of the number of areas present contain - to view all regions regardless of the number of areas present
use \fB\-\-region\fP). To also view the areas contained within regions use \fB--region\fP). To also view the areas contained within regions
use \fB\-\-area\fP. use \fB--area\fP.
If \fB\-\-histogram\fP is given the report will include the bin count If \fB--histogram\fP is given the report will include the bin count
and latency boundary values for any configured histograms. and latency boundary values for any configured histograms.
.HP .HP
.CMD_PRINT .CMD_PRINT
@ -651,20 +720,20 @@ present regions.
.br .br
Start a report for the specified object or for all present objects. If Start a report for the specified object or for all present objects. If
the count argument is specified, the report will repeat at a fixed the count argument is specified, the report will repeat at a fixed
interval set by the \fB\-\-interval\fP option. The default interval is interval set by the \fB--interval\fP option. The default interval is
one second. one second.
If the \fB\-\-allprograms\fP switch is given, all regions will be If the \fB--allprograms\fP switch is given, all regions will be
listed, regardless of region program ID values. listed, regardless of region program ID values.
If the \fB\-\-histogram\fP is given the report will include the histogram If the \fB--histogram\fP is given the report will include the histogram
values and latency boundaries. values and latency boundaries.
If the \fB\-\-relative\fP is used the default histogram field displays If the \fB--relative\fP is used the default histogram field displays
bin values as a percentage of the total number of I/Os. bin values as a percentage of the total number of I/Os.
Object types (areas, regions and groups) to include in the report are Object types (areas, regions and groups) to include in the report are
selected using the \fB\-\-area\fP, \fB\-\-region\fP, and \fB\-\-group\fP selected using the \fB--area\fP, \fB--region\fP, and \fB--group\fP
options. options.
. .
.HP .HP
@ -673,22 +742,28 @@ options.
Remove an existing group and return all the group's regions to their Remove an existing group and return all the group's regions to their
original state. original state.
The group to be removed is specified using \fB\-\-groupid\fP. The group to be removed is specified using \fB--groupid\fP.
.HP .HP
.CMD_UPDATE_FILEMAP .CMD_UPDATE_FILEMAP
.br .br
Update a group of \fBdmstats\fP regions specified by \fBgroup_id\fP, Update a group of \fBdmstats\fP regions specified by \fBgroup_id\fP,
that were previously created with \fB\-\-filemap\fP. This will add that were previously created with \fB--filemap\fP, either directly,
and remove regions to reflect changes in the allocated extents of or by starting the monitoring daemon, \fBdmfilemapd\fP.
the file on-disk, since the time that it was crated or last updated.
This will add and remove regions to reflect changes in the allocated
extents of the file on-disk, since the time that it was crated or last
updated.
Use of this command is not normally needed since the \fBdmfilemapd\fP Use of this command is not normally needed since the \fBdmfilemapd\fP
daemon will automatically monitor filemap groups and perform these daemon will automatically monitor filemap groups and perform these
updates when required. updates when required.
If a filemapped group was created with \fB\-\-nominitor\fP, or the If a filemapped group was created with \fB--nomonitor\fP, or the
daemon has been killed, the \fBupdate_filemap\fP can be used to daemon has been killed, the \fBupdate_filemap\fP can be used to
manually force an update. manually force an update or start a new daemon.
Use \fB--nomonitor\fP to force a direct update and disable starting
the monitoring daemon.
. .
.SH REGIONS, AREAS, AND GROUPS .SH REGIONS, AREAS, AND GROUPS
. .
@ -711,8 +786,8 @@ The group metadata is stored with the first (lowest numbered)
the group and other group members will be returned to their prior the group and other group members will be returned to their prior
state. state.
By default new regions span the entire device. The \fB\-\-start\fP and By default new regions span the entire device. The \fB--start\fP and
\fB\-\-length\fP options allows a region of any size to be placed at any \fB--length\fP options allows a region of any size to be placed at any
location on the device. location on the device.
Using offsets it is possible to create regions that map individual Using offsets it is possible to create regions that map individual
@ -723,7 +798,7 @@ and data aggregation.
A region may be either divided into the specified number of equal-sized A region may be either divided into the specified number of equal-sized
areas, or into areas of the given size by specifying one of areas, or into areas of the given size by specifying one of
\fB\-\-areas\fP or \fB\-\-areasize\fP when creating a region with the \fB--areas\fP or \fB--areasize\fP when creating a region with the
\fBcreate\fP command. Depending on the size of the areas and the device \fBcreate\fP command. Depending on the size of the areas and the device
region the final area within the region may be smaller than requested. region the final area within the region may be smaller than requested.
.P .P
@ -750,6 +825,93 @@ containing device.
The \fBgroup_id\fP should be treated as an opaque identifier used to The \fBgroup_id\fP should be treated as an opaque identifier used to
reference the group. reference the group.
. .
.SH FILE MAPPING
.
Using \fB--filemap\fP, it is possible to create regions that
correspond to the extents of a file in the file system. This allows
IO statistics to be monitored on a per-file basis, for example to
observe large database files, virtual machine images, or other files
of interest.
To be able to use file mapping, the file must be backed by a
device-mapper device, and in a file system that supports the FIEMAP
ioctl (and which returns data describing the physical location of
extents). This currently includes \fBxfs(5)\fP and \fBext4(5)\fP.
By default the regions making up a file are placed together in a
group, and the group alias is set to the \fBbasename(3)\fP of the
file. This allows statistics to be reported for the file as a whole,
aggregating values for the regions making up the group. To see only
the whole file (group) when using the \fBlist\fP and \fBreport\fP
commands, use \fB--group\fP.
Since it is possible for the file to change after the initial
group of regions is created, the \fBupdate_filemap\fP command, and
\fBdmfilemapd\fP daemon are provided to update file mapped groups
either manually or automatically.
.
.P
.B File follow modes
.P
The file map monitoring daemon can monitor files in two distinct ways:
follow-inode mode, and follow-path mode.
The mode affects the behaviour of the daemon when a file under
monitoring is renamed or unlinked, and the conditions which cause the
daemon to terminate.
If follow-inode mode is used, the daemon will hold the file open, and
continue to update regions from the same file descriptor. This means
that the mapping will follow rename, move (within the same file
system), and unlink operations. This mode is useful if the file is
expected to be moved, renamed, or unlinked while it is being
monitored.
In follow-inode mode, the daemon will exit once it detects that the
file has been unlinked and it is the last holder of a reference to it.
If follow-path is used, the daemon will re-open the provided path on
each monitoring iteration. This means that the group will be updated
to reflect a new file being moved to the same path as the original
file. This mode is useful for files that are expected to be updated
via unlink and rename.
In follow-path mode, the daemon will exit if the file is removed and
not replaced within a brief tolerance interval (one second).
To stop the daemon, delete the group containing the mapped regions:
the daemon will automatically shut down.
The daemon can also be safely killed at any time and the group kept:
if the file is still being allocated the mapping will become
progressively out-of-date as extents are added and removed (in this
case the daemon can be re-started or the group updated manually with
the \fBupdate_filemap\fP command).
See the \fBcreate\fP command and \fB--filemap\fP, \fB--follow\fP,
and \fB--nomonitor\fP options for further information.
.
.P
.B Limitations
.P
The daemon attempts to maintain good synchronisation between the file
extents and the regions contained in the group, however, since it can
only react to new allocations once they have been written, there are
inevitably some IO events that cannot be counted when a file is
growing, particularly if the file is being extended by a single thread
writing beyond end-of-file (for example, the \fBdd\fP program).
There is a further loss of events in that there is currently no way
to atomically resize a \fBdmstats\fP region and preserve its current
counter values. This affects files when they grow by extending the
final extent, rather than allocating a new extent: any events that
had accumulated in the region between any prior operation and the
resize are lost.
File mapping is currently most effective in cases where the majority
of IO does not trigger extent allocation. Future updates may address
these limitations when kernel support is available.
.
.SH REPORT FIELDS .SH REPORT FIELDS
. .
The dmstats report provides several types of field that may be added to The dmstats report provides several types of field that may be added to
@ -822,11 +984,11 @@ when a statistics region is created.
.TP .TP
.B region_start .B region_start
The region start location. Display units are selected by the The region start location. Display units are selected by the
\fB\-\-units\fP option. \fB--units\fP option.
.TP .TP
.B region_len .B region_len
The length of the region. Display units are selected by the The length of the region. Display units are selected by the
\fB\-\-units\fP option. \fB--units\fP option.
.TP .TP
.B area_id .B area_id
Area identifier. Area identifiers are assigned by the device-mapper Area identifier. Area identifiers are assigned by the device-mapper
@ -839,11 +1001,11 @@ identifiers exist.
.TP .TP
.B area_start .B area_start
The area start location. Display units are selected by the The area start location. Display units are selected by the
\fB\-\-units\fP option. \fB--units\fP option.
.TP .TP
.B area_len .B area_len
The length of the area. Display units are selected by the The length of the area. Display units are selected by the
\fB\-\-units\fP option. \fB--units\fP option.
.TP .TP
.B area_count .B area_count
The number of areas in this region. The number of areas in this region.
@ -995,7 +1157,7 @@ vg00/lvol1: Created new region with 1 area(s) as region ID 0
Create a 32M region 1G into device d0 Create a 32M region 1G into device d0
.br .br
# #
.B dmstats create \-\-start 1G \-\-length 32M d0 .B dmstats create --start 1G --length 32M d0
.br .br
d0: Created new region with 1 area(s) as region ID 0 d0: Created new region with 1 area(s) as region ID 0
.P .P
@ -1003,7 +1165,7 @@ Create a whole-device region with 8 areas on every device
.br .br
.br .br
# #
.B dmstats create \-\-areas 8 .B dmstats create --areas 8
.br .br
vg00-lvol1: Created new region with 8 area(s) as region ID 0 vg00-lvol1: Created new region with 8 area(s) as region ID 0
.br .br
@ -1021,21 +1183,21 @@ Delete all regions on all devices
.br .br
.br .br
# #
.B dmstats delete \-\-alldevices \-\-allregions .B dmstats delete --alldevices --allregions
.P .P
Create a whole-device region with areas 10GiB in size on vg00/lvol1 Create a whole-device region with areas 10GiB in size on vg00/lvol1
using dmsetup using dmsetup
.br .br
.br .br
# #
.B dmsetup stats create \-\-areasize 10G vg00/lvol1 .B dmsetup stats create --areasize 10G vg00/lvol1
.br .br
vg00-lvol1: Created new region with 5 area(s) as region ID 1 vg00-lvol1: Created new region with 5 area(s) as region ID 1
.P .P
Create a 1GiB region with 16 areas at the start of vg00/lvol1 Create a 1GiB region with 16 areas at the start of vg00/lvol1
.br .br
# #
.B dmstats create \-\-start 0 \-\-len 1G \-\-areas=16 vg00/lvol1 .B dmstats create --start 0 --len 1G --areas=16 vg00/lvol1
.br .br
vg00-lvol1: Created new region with 16 area(s) as region ID 0 vg00-lvol1: Created new region with 16 area(s) as region ID 0
.P .P
@ -1056,7 +1218,7 @@ Display five statistics reports for vg00/lvol1 at an interval of one second
.br .br
.br .br
# #
.B dmstats report \-\-interval 1 \-\-count 5 vg00/lvol1 .B dmstats report --interval 1 --count 5 vg00/lvol1
.br .br
# #
.B dmstats report .B dmstats report
@ -1073,7 +1235,7 @@ Create one region for reach target contained in device vg00/lvol1
.br .br
.br .br
# #
.B dmstats create \-\-segments vg00/lvol1 .B dmstats create --segments vg00/lvol1
.br .br
vg00-lvol1: Created new region with 1 area(s) as region ID 0 vg00-lvol1: Created new region with 1 area(s) as region ID 0
.br .br
@ -1100,7 +1262,7 @@ images/vm3.img: Created new group with 2 region(s) as group ID 1560.
Print raw counters for region 4 on device d0 Print raw counters for region 4 on device d0
.br .br
# #
.B dmstats print \-\-regionid 4 d0 .B dmstats print --regionid 4 d0
.br .br
2097152+65536 0 0 0 0 29 0 264 701 0 41 701 0 41 2097152+65536 0 0 0 0 29 0 264 701 0 41 701 0 41
. .

View File

@ -35,32 +35,32 @@ filesystem.
.SH OPTIONS .SH OPTIONS
. .
.HP .HP
.BR \-e | \-\-ext\-offline .BR -e | --ext-offline
.br .br
Unmount ext2/ext3/ext4 filesystem before doing resize. Unmount ext2/ext3/ext4 filesystem before doing resize.
. .
.HP .HP
.BR \-f | \-\-force .BR -f | --force
.br .br
Bypass some sanity checks. Bypass some sanity checks.
. .
.HP .HP
.BR \-h | \-\-help .BR -h | --help
.br .br
Display the help text. Display the help text.
. .
.HP .HP
.BR \-n | \-\-dry\-run .BR -n | --dry-run
.br .br
Print commands without running them. Print commands without running them.
. .
.HP .HP
.BR \-v | \-\-verbose .BR -v | --verbose
.br .br
Be more verbose. Be more verbose.
. .
.HP .HP
.BR \-y | \-\-yes .BR -y | --yes
.br .br
Answer "yes" at any prompts. Answer "yes" at any prompts.
. .
@ -87,7 +87,7 @@ If \fI/dev/vg/test\fP contains ext2/ext3/ext4
filesystem it will be unmounted prior the resize. filesystem it will be unmounted prior the resize.
All [y/n] questions will be answered 'y'. All [y/n] questions will be answered 'y'.
.sp .sp
.B fsadm \-e \-y resize /dev/vg/test 1000M .B fsadm -e -y resize /dev/vg/test 1000M
. .
.SH ENVIRONMENT VARIABLES .SH ENVIRONMENT VARIABLES
. .

View File

@ -1,6 +1,4 @@
.SH EXAMPLES .SH EXAMPLES
Change LV permission to read-only: Change LV permission to read-only:
.sp .sp
.B lvchange \-pr vg00/lvol1 .B lvchange -pr vg00/lvol1

1161
man/lvchange.8_pregen Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,32 +0,0 @@
lvconvert changes the LV type and includes utilities for LV data
maintenance. The LV type controls data layout and redundancy.
The LV type is also called the segment type or segtype.
To display the current LV type, run the command:
.B lvs \-o name,segtype
.I LV
The
.B linear
type is equivalent to the
.B striped
type when one stripe exists.
In that case, the types can sometimes be used interchangably.
In most cases, the
.B mirror
type is deprecated and the
.B raid1
type should be used. They are both implementations of mirroring.
In some cases, an LV is a single device mapper (dm) layer above physical
devices. In other cases, hidden LVs (dm devices) are layered between the
visible LV and physical devices. LVs in the middle layers are called sub LVs.
A command run on a visible LV sometimes operates on a sub LV rather than
the specified LV. In other cases, a sub LV must be specified directly on
the command line.
Sub LVs can be displayed with the command
.B lvs -a

64
man/lvconvert.8_des Normal file
View File

@ -0,0 +1,64 @@
lvconvert changes the LV type and includes utilities for LV data
maintenance. The LV type controls data layout and redundancy.
The LV type is also called the segment type or segtype.
To display the current LV type, run the command:
.B lvs -o name,segtype
.I LV
The
.B linear
type is equivalent to the
.B striped
type when one stripe exists.
In that case, the types can sometimes be used interchangably.
In most cases, the
.B mirror
type is deprecated and the
.B raid1
type should be used. They are both implementations of mirroring.
In some cases, an LV is a single device mapper (dm) layer above physical
devices. In other cases, hidden LVs (dm devices) are layered between the
visible LV and physical devices. LVs in the middle layers are called sub LVs.
A command run on a visible LV sometimes operates on a sub LV rather than
the specified LV. In other cases, a sub LV must be specified directly on
the command line.
Striped raid types are
.B raid0/raid0_meta
,
.B raid5
(an alias for raid5_ls),
.B raid6
(an alias for raid6_zr) and
.B raid10
(an alias for raid10_near).
As opposed to mirroring, raid5 and raid6 stripe data and calculate parity
blocks. The parity blocks can be used for data block recovery in case devices
fail. A maximum number of one device in a raid5 LV may fail and two in case
of raid6. Striped raid types typically rotate the parity blocks for performance
reasons thus avoiding contention on a single device. Layouts of raid5 rotating
parity blocks can be one of left-asymmetric (raid5_la), left-symmetric (raid5_ls
with alias raid5), right-asymmetric (raid5_ra), right-symmetric (raid5_rs) and raid5_n,
which doesn't rotate parity blocks. Any \"_n\" layouts allow for conversion between
raid levels (raid5_n -> raid6 or raid5_n -> striped/raid0/raid0_meta).
raid6 layouts are zero-restart (raid6_zr with alias raid6), next-restart (raid6_nr),
next-continue (raid6_nc). Additionally, special raid6 layouts for raid level conversions
between raid5 and raid6 are raid6_ls_6, raid6_rs_6, raid6_la_6 and raid6_ra_6. Those
correspond to their raid5 counterparts (e.g. raid5_rs can be directly converted to raid6_rs_6
and vice-versa).
raid10 (an alias for raid10_near) is currently limited to one data copy and even number of
sub LVs. This is a mirror group layout thus a single sub LV may fail per mirror group
without data loss.
Striped raid types support converting the layout, their stripesize
and their number of stripes.
The striped raid types combined with raid1 allow for conversion from linear -> striped/raid0/raid0_meta
and vice-versa by e.g. linear <-> raid1 <-> raid5_n (then adding stripes) <-> striped/raid0/raid0_meta.
Sub LVs can be displayed with the command
.B lvs -a

View File

@ -1,5 +1,4 @@
.SH NOTES .SH NOTES
This previous command syntax would perform two different operations: This previous command syntax would perform two different operations:
.br .br
\fBlvconvert --thinpool\fP \fILV1\fP \fB--poolmetadata\fP \fILV2\fP \fBlvconvert --thinpool\fP \fILV1\fP \fB--poolmetadata\fP \fILV2\fP
@ -18,24 +17,22 @@ If LV1 was not a cache pool, the command would convert LV1 to
a cache pool, optionally using a specified LV for metadata. a cache pool, optionally using a specified LV for metadata.
But, if LV1 was already a cache pool, the command would swap But, if LV1 was already a cache pool, the command would swap
the current metadata LV with LV2 (for repair purposes.) the current metadata LV with LV2 (for repair purposes.)
.SH EXAMPLES .SH EXAMPLES
Convert a linear LV to a two-way mirror LV. Convert a linear LV to a two-way mirror LV.
.br .br
.B lvconvert \-\-type mirror \-\-mirrors 1 vg/lvol1 .B lvconvert --type mirror --mirrors 1 vg/lvol1
Convert a linear LV to a two-way RAID1 LV. Convert a linear LV to a two-way RAID1 LV.
.br .br
.B lvconvert \-\-type raid1 \-\-mirrors 1 vg/lvol1 .B lvconvert --type raid1 --mirrors 1 vg/lvol1
Convert a mirror LV to use an in\-memory log. Convert a mirror LV to use an in-memory log.
.br .br
.B lvconvert \-\-mirrorlog core vg/lvol1 .B lvconvert --mirrorlog core vg/lvol1
Convert a mirror LV to use a disk log. Convert a mirror LV to use a disk log.
.br .br
.B lvconvert \-\-mirrorlog disk vg/lvol1 .B lvconvert --mirrorlog disk vg/lvol1
Convert a mirror or raid1 LV to a linear LV. Convert a mirror or raid1 LV to a linear LV.
.br .br
@ -43,74 +40,73 @@ Convert a mirror or raid1 LV to a linear LV.
Convert a mirror LV to a raid1 LV with the same number of images. Convert a mirror LV to a raid1 LV with the same number of images.
.br .br
.B lvconvert \-\-type raid1 vg/lvol1 .B lvconvert --type raid1 vg/lvol1
Convert a linear LV to a two-way mirror LV, allocating new extents from specific Convert a linear LV to a two-way mirror LV, allocating new extents from specific
PV ranges. PV ranges.
.br .br
.B lvconvert \-\-mirrors 1 vg/lvol1 /dev/sda:0\-15 /dev/sdb:0\-15 .B lvconvert --mirrors 1 vg/lvol1 /dev/sda:0-15 /dev/sdb:0-15
Convert a mirror LV to a linear LV, freeing physical extents from a specific PV. Convert a mirror LV to a linear LV, freeing physical extents from a specific PV.
.br .br
.B lvconvert \-\-type linear vg/lvol1 /dev/sda .B lvconvert --type linear vg/lvol1 /dev/sda
Split one image from a mirror or raid1 LV, making it a new LV. Split one image from a mirror or raid1 LV, making it a new LV.
.br .br
.B lvconvert \-\-splitmirrors 1 \-\-name lv_split vg/lvol1 .B lvconvert --splitmirrors 1 --name lv_split vg/lvol1
Split one image from a raid1 LV, and track changes made to the raid1 LV Split one image from a raid1 LV, and track changes made to the raid1 LV
while the split image remains detached. while the split image remains detached.
.br .br
.B lvconvert \-\-splitmirrors 1 \-\-trackchanges vg/lvol1 .B lvconvert --splitmirrors 1 --trackchanges vg/lvol1
Merge an image (that was previously created with \-\-splitmirrors and Merge an image (that was previously created with --splitmirrors and
\-\-trackchanges) back into the original raid1 LV. --trackchanges) back into the original raid1 LV.
.br .br
.B lvconvert \-\-mergemirrors vg/lvol1_rimage_1 .B lvconvert --mergemirrors vg/lvol1_rimage_1
Replace PV /dev/sdb1 with PV /dev/sdf1 in a raid1/4/5/6/10 LV. Replace PV /dev/sdb1 with PV /dev/sdf1 in a raid1/4/5/6/10 LV.
.br .br
.B lvconvert \-\-replace /dev/sdb1 vg/lvol1 /dev/sdf1 .B lvconvert --replace /dev/sdb1 vg/lvol1 /dev/sdf1
Replace 3 PVs /dev/sd[b-d]1 with PVs /dev/sd[f-h]1 in a raid1 LV. Replace 3 PVs /dev/sd[b-d]1 with PVs /dev/sd[f-h]1 in a raid1 LV.
.br .br
.B lvconvert \-\-replace /dev/sdb1 \-\-replace /dev/sdc1 \-\-replace /dev/sdd1 .B lvconvert --replace /dev/sdb1 --replace /dev/sdc1 --replace /dev/sdd1
.RS .RS
.B vg/lvol1 /dev/sd[fgh]1 .B vg/lvol1 /dev/sd[fgh]1
.RE .RE
Replace the maximum of 2 PVs /dev/sd[bc]1 with PVs /dev/sd[gh]1 in a raid6 LV. Replace the maximum of 2 PVs /dev/sd[bc]1 with PVs /dev/sd[gh]1 in a raid6 LV.
.br .br
.B lvconvert \-\-replace /dev/sdb1 \-\-replace /dev/sdc1 vg/lvol1 /dev/sd[gh]1 .B lvconvert --replace /dev/sdb1 --replace /dev/sdc1 vg/lvol1 /dev/sd[gh]1
Convert an LV into a thin LV in the specified thin pool. The existing LV Convert an LV into a thin LV in the specified thin pool. The existing LV
is used as an external read\-only origin for the new thin LV. is used as an external read-only origin for the new thin LV.
.br .br
.B lvconvert \-\-type thin \-\-thinpool vg/tpool1 vg/lvol1 .B lvconvert --type thin --thinpool vg/tpool1 vg/lvol1
Convert an LV into a thin LV in the specified thin pool. The existing LV Convert an LV into a thin LV in the specified thin pool. The existing LV
is used as an external read\-only origin for the new thin LV, and is is used as an external read-only origin for the new thin LV, and is
renamed "external". renamed "external".
.br .br
.B lvconvert \-\-type thin \-\-thinpool vg/tpool1 .B lvconvert --type thin --thinpool vg/tpool1
.RS .RS
.B \-\-originname external vg/lvol1 .B --originname external vg/lvol1
.RE .RE
Convert an LV to a cache pool LV using another specified LV for cache pool Convert an LV to a cache pool LV using another specified LV for cache pool
metadata. metadata.
.br .br
.B lvconvert \-\-type cache-pool \-\-poolmetadata vg/poolmeta1 vg/lvol1 .B lvconvert --type cache-pool --poolmetadata vg/poolmeta1 vg/lvol1
Convert an LV to a cache LV using the specified cache pool and chunk size. Convert an LV to a cache LV using the specified cache pool and chunk size.
.br .br
.B lvconvert \-\-type cache \-\-cachepool vg/cpool1 \-c 128 vg/lvol1 .B lvconvert --type cache --cachepool vg/cpool1 -c 128 vg/lvol1
Detach and keep the cache pool from a cache LV. Detach and keep the cache pool from a cache LV.
.br .br
.B lvconvert \-\-splitcache vg/lvol1 .B lvconvert --splitcache vg/lvol1
Detach and remove the cache pool from a cache LV. Detach and remove the cache pool from a cache LV.
.br .br
.B lvconvert \-\-uncache vg/lvol1 .B lvconvert --uncache vg/lvol1

1877
man/lvconvert.8_pregen Normal file

File diff suppressed because it is too large Load Diff

View File

@ -25,15 +25,12 @@ Thin LVs are thinly provisioned from a thin pool, and are created with a
virtual size rather than a physical size. A cache LV is the combination of virtual size rather than a physical size. A cache LV is the combination of
a standard LV with a cache pool, used to cache active portions of the LV a standard LV with a cache pool, used to cache active portions of the LV
to improve performance. to improve performance.
.SS Usage notes .SS Usage notes
In the usage section below, \fB--size\fP \fISize\fP can be replaced
In the usage section below, \fB--size\fP \fINumber\fP can be replaced with \fB--extents\fP \fINumber\fP. See both descriptions
in each case with \fB--extents\fP \fINumberExtents\fP. Also see both the options section.
descriptions the options section.
In the usage section below, \fB--name\fP is omitted from the required In the usage section below, \fB--name\fP is omitted from the required
options, even though it is typically used. When the name is not options, even though it is typically used. When the name is not
specified, a new LV name is generated with the "lvol" prefix and a unique specified, a new LV name is generated with the "lvol" prefix and a unique
numeric suffix. Also see the description in the options section. numeric suffix. Also see the description in the options section.

View File

@ -3,56 +3,56 @@
Create a striped LV with 3 stripes, a stripe size of 8KiB and a size of 100MiB. Create a striped LV with 3 stripes, a stripe size of 8KiB and a size of 100MiB.
The LV name is chosen by lvcreate. The LV name is chosen by lvcreate.
.br .br
.B lvcreate \-i 3 \-I 8 \-L 100m vg00 .B lvcreate -i 3 -I 8 -L 100m vg00
Create a raid1 LV with two images, and a useable size of 500 MiB. This Create a raid1 LV with two images, and a useable size of 500 MiB. This
operation requires two devices, one for each mirror image. RAID metadata operation requires two devices, one for each mirror image. RAID metadata
(superblock and bitmap) is also included on the two devices. (superblock and bitmap) is also included on the two devices.
.br .br
.B lvcreate \-\-type raid1 \-m1 \-L 500m \-n mylv vg00 .B lvcreate --type raid1 -m1 -L 500m -n mylv vg00
Create a mirror LV with two images, and a useable size of 500 MiB. Create a mirror LV with two images, and a useable size of 500 MiB.
This operation requires three devices: two for mirror images and This operation requires three devices: two for mirror images and
one for a disk log. one for a disk log.
.br .br
.B lvcreate \-\-type mirror \-m1 \-L 500m \-n mylv vg00 .B lvcreate --type mirror -m1 -L 500m -n mylv vg00
Create a mirror LV with 2 images, and a useable size of 500 MiB. Create a mirror LV with 2 images, and a useable size of 500 MiB.
This operation requires 2 devices because the log is in memory. This operation requires 2 devices because the log is in memory.
.br .br
.B lvcreate \-\-type mirror \-m1 \-\-mirrorlog core \-L 500m \-n mylv vg00 .B lvcreate --type mirror -m1 --mirrorlog core -L 500m -n mylv vg00
Create a copy\-on\-write snapshot of an LV: Create a copy-on-write snapshot of an LV:
.br .br
.B lvcreate \-\-snapshot \-\-size 100m \-\-name mysnap vg00/mylv .B lvcreate --snapshot --size 100m --name mysnap vg00/mylv
Create a copy\-on\-write snapshot with a size sufficient Create a copy-on-write snapshot with a size sufficient
for overwriting 20% of the size of the original LV. for overwriting 20% of the size of the original LV.
.br .br
.B lvcreate \-s \-l 20%ORIGIN \-n mysnap vg00/mylv .B lvcreate -s -l 20%ORIGIN -n mysnap vg00/mylv
Create a sparse LV with 1TiB of virtual space, and actual space just under Create a sparse LV with 1TiB of virtual space, and actual space just under
100MiB. 100MiB.
.br .br
.B lvcreate \-\-snapshot \-\-virtualsize 1t \-\-size 100m \-\-name mylv vg00 .B lvcreate --snapshot --virtualsize 1t --size 100m --name mylv vg00
Create a linear LV with a usable size of 64MiB on specific physical extents. Create a linear LV with a usable size of 64MiB on specific physical extents.
.br .br
.B lvcreate \-L 64m \-n mylv vg00 /dev/sda:0\-7 /dev/sdb:0\-7 .B lvcreate -L 64m -n mylv vg00 /dev/sda:0-7 /dev/sdb:0-7
Create a RAID5 LV with a usable size of 5GiB, 3 stripes, a stripe size of Create a RAID5 LV with a usable size of 5GiB, 3 stripes, a stripe size of
64KiB, using a total of 4 devices (including one for parity). 64KiB, using a total of 4 devices (including one for parity).
.br .br
.B lvcreate \-\-type raid5 \-L 5G \-i 3 \-I 64 \-n mylv vg00 .B lvcreate --type raid5 -L 5G -i 3 -I 64 -n mylv vg00
Create a RAID5 LV using all of the free space in the VG and spanning all the Create a RAID5 LV using all of the free space in the VG and spanning all the
PVs in the VG (note that the command will fail if there are more than 8 PVs in PVs in the VG (note that the command will fail if there are more than 8 PVs in
the VG, in which case \fB\-i 7\fP must be used to get to the current maximum of the VG, in which case \fB-i 7\fP must be used to get to the current maximum of
8 devices including parity for RaidLVs). 8 devices including parity for RaidLVs).
.br .br
.B lvcreate \-\-config allocation/raid_stripe_all_devices=1 .B lvcreate --config allocation/raid_stripe_all_devices=1
.RS .RS
.B \-\-type raid5 \-l 100%FREE \-n mylv vg00 .B --type raid5 -l 100%FREE -n mylv vg00
.RE .RE
Create RAID10 LV with a usable size of 5GiB, using 2 stripes, each on Create RAID10 LV with a usable size of 5GiB, using 2 stripes, each on
@ -62,37 +62,36 @@ differently:
but \fB-m\fP specifies the number of images in addition but \fB-m\fP specifies the number of images in addition
to the first image). to the first image).
.br .br
.B lvcreate \-\-type raid10 \-L 5G \-i 2 \-m 1 \-n mylv vg00 .B lvcreate --type raid10 -L 5G -i 2 -m 1 -n mylv vg00
Create a 1TiB thin LV, first creating a new thin pool for it, where Create a 1TiB thin LV, first creating a new thin pool for it, where
the thin pool has 100MiB of space, uses 2 stripes, has a 64KiB stripe the thin pool has 100MiB of space, uses 2 stripes, has a 64KiB stripe
size, and 256KiB chunk size. size, and 256KiB chunk size.
.br .br
.B lvcreate \-\-type thin \-\-name mylv \-\-thinpool mypool .B lvcreate --type thin --name mylv --thinpool mypool
.RS .RS
.B \-V 1t \-L 100m \-i 2 \-I 64 \-c 256 vg00 .B -V 1t -L 100m -i 2 -I 64 -c 256 vg00
.RE .RE
Create a thin snapshot of a thin LV (the size option must not be Create a thin snapshot of a thin LV (the size option must not be
used, otherwise a copy-on-write snapshot would be created). used, otherwise a copy-on-write snapshot would be created).
.br .br
.B lvcreate \-\-snapshot \-\-name mysnap vg00/thinvol .B lvcreate --snapshot --name mysnap vg00/thinvol
Create a thin snapshot of the read-only inactive LV named "origin" Create a thin snapshot of the read-only inactive LV named "origin"
which becomes an external origin for the thin snapshot LV. which becomes an external origin for the thin snapshot LV.
.br .br
.B lvcreate \-\-snapshot \-\-name mysnap \-\-thinpool mypool vg00/origin .B lvcreate --snapshot --name mysnap --thinpool mypool vg00/origin
Create a cache pool from a fast physical device. The cache pool can Create a cache pool from a fast physical device. The cache pool can
then be used to cache an LV. then be used to cache an LV.
.br .br
.B lvcreate \-\-type cache-pool \-L 1G \-n my_cpool vg00 /dev/fast1 .B lvcreate --type cache-pool -L 1G -n my_cpool vg00 /dev/fast1
Create a cache LV, first creating a new origin LV on a slow physical device, Create a cache LV, first creating a new origin LV on a slow physical device,
then combining the new origin LV with an existing cache pool. then combining the new origin LV with an existing cache pool.
.br .br
.B lvcreate \-\-type cache \-\-cachepool my_cpool .B lvcreate --type cache --cachepool my_cpool
.RS .RS
.B \-L 100G \-n mylv vg00 /dev/slow1 .B -L 100G -n mylv vg00 /dev/slow1
.RE .RE

2738
man/lvcreate.8_pregen Normal file

File diff suppressed because it is too large Load Diff

0
man/lvdisplay.8_end Normal file
View File

579
man/lvdisplay.8_pregen Normal file
View File

@ -0,0 +1,579 @@
.TH LVDISPLAY 8 "LVM TOOLS #VERSION#" "Red Hat, Inc."
.SH NAME
lvdisplay - Display information about a logical volume
.
.SH SYNOPSIS
\fBlvdisplay\fP
.br
[ \fIoption_args\fP ]
.br
[ \fIposition_args\fP ]
.br
.SH DESCRIPTION
lvdisplay shows the attributes of LVs, like size, read/write status,
snapshot information, etc.
\fBlvs\fP(8) is a preferred alternative that shows the same information
and more, using a more compact and configurable output format.
.SH USAGE
\fBlvdisplay\fP
.br
.RS 4
.ad l
[ \fB-a\fP|\fB--all\fP ]
.ad b
.br
.ad l
[ \fB-c\fP|\fB--colon\fP ]
.ad b
.br
.ad l
[ \fB-C\fP|\fB--columns\fP ]
.ad b
.br
.ad l
[ \fB-H\fP|\fB--history\fP ]
.ad b
.br
.ad l
[ \fB-m\fP|\fB--maps\fP ]
.ad b
.br
.ad l
[ \fB-o\fP|\fB--options\fP \fIString\fP ]
.ad b
.br
.ad l
[ \fB-O\fP|\fB--sort\fP \fIString\fP ]
.ad b
.br
.ad l
[ \fB-P\fP|\fB--partial\fP ]
.ad b
.br
.ad l
[ \fB-S\fP|\fB--select\fP \fIString\fP ]
.ad b
.br
.ad l
[ \fB--aligned\fP ]
.ad b
.br
.ad l
[ \fB--binary\fP ]
.ad b
.br
.ad l
[ \fB--configreport\fP \fBlog\fP|\fBvg\fP|\fBlv\fP|\fBpv\fP|\fBpvseg\fP|\fBseg\fP ]
.ad b
.br
.ad l
[ \fB--foreign\fP ]
.ad b
.br
.ad l
[ \fB--ignorelockingfailure\fP ]
.ad b
.br
.ad l
[ \fB--ignoreskippedcluster\fP ]
.ad b
.br
.ad l
[ \fB--logonly\fP ]
.ad b
.br
.ad l
[ \fB--noheadings\fP ]
.ad b
.br
.ad l
[ \fB--nosuffix\fP ]
.ad b
.br
.ad l
[ \fB--readonly\fP ]
.ad b
.br
.ad l
[ \fB--reportformat\fP \fBbasic\fP|\fBjson\fP ]
.ad b
.br
.ad l
[ \fB--segments\fP ]
.ad b
.br
.ad l
[ \fB--separator\fP \fIString\fP ]
.ad b
.br
.ad l
[ \fB--shared\fP ]
.ad b
.br
.ad l
[ \fB--unbuffered\fP ]
.ad b
.br
.ad l
[ \fB--units\fP \fBr\fP|\fBR\fP|\fBh\fP|\fBH\fP|\fBb\fP|\fBB\fP|\fBs\fP|\fBS\fP|\fBk\fP|\fBK\fP|\fBm\fP|\fBM\fP|\fBg\fP|\fBG\fP|\fBt\fP|\fBT\fP|\fBp\fP|\fBP\fP|\fBe\fP|\fBE\fP ]
.ad b
.br
[ COMMON_OPTIONS ]
.RE
.br
.RS 4
[ \fIVG\fP|\fILV\fP|\fITag\fP ... ]
.RE
Common options for lvm:
.
.RS 4
.ad l
[ \fB-d\fP|\fB--debug\fP ]
.ad b
.br
.ad l
[ \fB-h\fP|\fB--help\fP ]
.ad b
.br
.ad l
[ \fB-q\fP|\fB--quiet\fP ]
.ad b
.br
.ad l
[ \fB-t\fP|\fB--test\fP ]
.ad b
.br
.ad l
[ \fB-v\fP|\fB--verbose\fP ]
.ad b
.br
.ad l
[ \fB-y\fP|\fB--yes\fP ]
.ad b
.br
.ad l
[ \fB--commandprofile\fP \fIString\fP ]
.ad b
.br
.ad l
[ \fB--config\fP \fIString\fP ]
.ad b
.br
.ad l
[ \fB--driverloaded\fP \fBy\fP|\fBn\fP ]
.ad b
.br
.ad l
[ \fB--longhelp\fP ]
.ad b
.br
.ad l
[ \fB--profile\fP \fIString\fP ]
.ad b
.br
.ad l
[ \fB--version\fP ]
.ad b
.RE
.SH OPTIONS
.HP
.ad l
\fB--aligned\fP
.br
Use with --separator to align the output columns
.ad b
.HP
.ad l
\fB-a\fP|\fB--all\fP
.br
Show information about internal LVs.
These are components of normal LVs, such as mirrors,
which are not independently accessible, e.g. not mountable.
.ad b
.HP
.ad l
\fB--binary\fP
.br
Use binary values "0" or "1" instead of descriptive literal values
for columns that have exactly two valid values to report (not counting
the "unknown" value which denotes that the value could not be determined).
.ad b
.HP
.ad l
\fB-c\fP|\fB--colon\fP
.br
Generate colon separated output for easier parsing in scripts or programs.
Also see vgs(8) which provides considerably more control over the output.
.ad b
.HP
.ad l
\fB-C\fP|\fB--columns\fP
.br
Display output in columns, the equivalent of vgs(8).
Options listed are the same as options given in vgs(8).
.ad b
.HP
.ad l
\fB--commandprofile\fP \fIString\fP
.br
The command profile to use for command configuration.
See \fBlvm.conf\fP(5) for more information about profiles.
.ad b
.HP
.ad l
\fB--config\fP \fIString\fP
.br
Config settings for the command. These override lvm.conf settings.
The String arg uses the same format as lvm.conf,
or may use section/field syntax.
See \fBlvm.conf\fP(5) for more information about config.
.ad b
.HP
.ad l
\fB--configreport\fP \fBlog\fP|\fBvg\fP|\fBlv\fP|\fBpv\fP|\fBpvseg\fP|\fBseg\fP
.br
See lvmreport(7).
.ad b
.HP
.ad l
\fB-d\fP|\fB--debug\fP ...
.br
Set debug level. Repeat from 1 to 6 times to increase the detail of
messages sent to the log file and/or syslog (if configured).
.ad b
.HP
.ad l
\fB--driverloaded\fP \fBy\fP|\fBn\fP
.br
If set to no, the command will not attempt to use device-mapper.
For testing and debugging.
.ad b
.HP
.ad l
\fB--foreign\fP
.br
Report/display foreign VGs that would otherwise be skipped.
See lvmsystemid(7) for more information about foreign VGs.
.ad b
.HP
.ad l
\fB-h\fP|\fB--help\fP
.br
Display help text.
.ad b
.HP
.ad l
\fB-H\fP|\fB--history\fP
.br
Include historical LVs in the output.
(This has no effect unless LVs were removed while
lvm.conf metadata/record_lvs_history was enabled.
.ad b
.HP
.ad l
\fB--ignorelockingfailure\fP
.br
Allows a command to continue with read-only metadata
operations after locking failures.
.ad b
.HP
.ad l
\fB--ignoreskippedcluster\fP
.br
Use to avoid exiting with an non-zero status code if the command is run
without clustered locking and clustered VGs are skipped.
.ad b
.HP
.ad l
\fB--logonly\fP
.br
Suppress command report and display only log report.
.ad b
.HP
.ad l
\fB--longhelp\fP
.br
Display long help text.
.ad b
.HP
.ad l
\fB-m\fP|\fB--maps\fP
.br
Display the mapping of logical extents to PVs and physical extents.
To map physical extents to logical extents use:
pvs --segments -o+lv_name,seg_start_pe,segtype
.ad b
.HP
.ad l
\fB--noheadings\fP
.br
Suppress the headings line that is normally the first line of output.
Useful if grepping the output.
.ad b
.HP
.ad l
\fB--nosuffix\fP
.br
Suppress the suffix on output sizes. Use with --units
(except h and H) if processing the output.
.ad b
.HP
.ad l
\fB-o\fP|\fB--options\fP \fIString\fP
.br
Comma-separated, ordered list of fields to display in columns.
String arg syntax is: [+|-|#]Field1[,Field2 ...]
The prefix \fB+\fP will append the specified fields to the default fields,
\fB-\fP will remove the specified fields from the default fields, and
\fB#\fP will compact specified fields (removing them when empty for all rows.)
Use \fB-o help\fP to view the list of all available fields.
Use separate lists of fields to add, remove or compact by repeating the -o option:
-o+field1,field2 -o-field3,field4 -o#field5.
These lists are evaluated from left to right.
Use field name \fBlv_all\fP to view all LV fields,
\fBvg_all\fP all VG fields,
\fBpv_all\fP all PV fields,
\fBpvseg_all\fP all PV segment fields,
\fBseg_all\fP all LV segment fields, and
\fBpvseg_all\fP all PV segment columns.
See the lvm.conf report section for more config options.
See lvmreport(7) for more information about reporting.
.ad b
.HP
.ad l
\fB-P\fP|\fB--partial\fP
.br
When set, the tools will do their best to provide access to VGs
that are only partially available (one or more PVs belonging
to the VG are missing from the system). Metadata may not be
changed with this option.
.ad b
.HP
.ad l
\fB--profile\fP \fIString\fP
.br
An alias for --commandprofile or --metadataprofile, depending
on the command.
.ad b
.HP
.ad l
\fB-q\fP|\fB--quiet\fP ...
.br
Suppress output and log messages. Overrides --debug and --verbose.
Repeat once to also suppress any prompts with answer no.
.ad b
.HP
.ad l
\fB--readonly\fP
.br
Run the command in a special read-only mode which will read on-disk
metadata without needing to take any locks. This can be used to peek
inside metadata used by a virtual machine image while the virtual
machine is running.
It can also be used to peek inside the metadata of clustered VGs
when clustered locking is not configured or running. No attempt
will be made to communicate with the device-mapper kernel driver, so
this option is unable to report whether or not LVs are
actually in use.
.ad b
.HP
.ad l
\fB--reportformat\fP \fBbasic\fP|\fBjson\fP
.br
Overrides current output format for reports which is defined globally by
the report/output_format setting in lvm.conf.
\fBbasic\fP is the original format with columns and rows.
If there is more than one report per command, each report is prefixed
with the report name for identification. \fBjson\fP produces report
output in JSON format. See \fBlvmreport\fP(7) for more information.
.ad b
.HP
.ad l
\fB--segments\fP
.br
.ad b
.HP
.ad l
\fB-S\fP|\fB--select\fP \fIString\fP
.br
Select objects for processing and reporting based on specified criteria.
The criteria syntax is described by \fB--select help\fP and \fBlvmreport\fP(7).
For reporting commands, one row is displayed for each object matching the criteria.
See \fB--options help\fP for selectable object fields.
Rows can be displayed with an additional "selected" field (-o selected)
showing 1 if the row matches the selection and 0 otherwise.
For non-reporting commands which process LVM entities, the selection is
used to choose items to process.
.ad b
.HP
.ad l
\fB--separator\fP \fIString\fP
.br
String to use to separate each column. Useful if grepping the output.
.ad b
.HP
.ad l
\fB--shared\fP
.br
Report/display shared VGs that would otherwise be skipped when
lvmlockd is not being used on the host.
See lvmlockd(8) for more information about shared VGs.
.ad b
.HP
.ad l
\fB-O\fP|\fB--sort\fP \fIString\fP
.br
Comma-separated ordered list of columns to sort by. Replaces the default
selection. Precede any column with \fB-\fP for a reverse sort on that column.
.ad b
.HP
.ad l
\fB-t\fP|\fB--test\fP
.br
Run in test mode. Commands will not update metadata.
This is implemented by disabling all metadata writing but nevertheless
returning success to the calling function. This may lead to unusual
error messages in multi-stage operations if a tool relies on reading
back metadata it believes has changed but hasn't.
.ad b
.HP
.ad l
\fB--unbuffered\fP
.br
Produce output immediately without sorting or aligning the columns properly.
.ad b
.HP
.ad l
\fB--units\fP \fBr\fP|\fBR\fP|\fBh\fP|\fBH\fP|\fBb\fP|\fBB\fP|\fBs\fP|\fBS\fP|\fBk\fP|\fBK\fP|\fBm\fP|\fBM\fP|\fBg\fP|\fBG\fP|\fBt\fP|\fBT\fP|\fBp\fP|\fBP\fP|\fBe\fP|\fBE\fP
.br
All sizes are output in these units:
human-(r)eadable with '<' rounding indicator,
(h)uman-readable, (b)ytes, (s)ectors, (k)ilobytes, (m)egabytes,
(g)igabytes, (t)erabytes, (p)etabytes, (e)xabytes.
Capitalise to use multiples of 1000 (S.I.) instead of 1024.
Custom units can be specified, e.g. --units 3M.
.ad b
.HP
.ad l
\fB-v\fP|\fB--verbose\fP ...
.br
Set verbose level. Repeat from 1 to 4 times to increase the detail
of messages sent to stdout and stderr.
.ad b
.HP
.ad l
\fB--version\fP
.br
Display version information.
.ad b
.HP
.ad l
\fB-y\fP|\fB--yes\fP
.br
Do not prompt for confirmation interactively but always assume the
answer yes. Use with extreme caution.
(For automatic no, see -qq.)
.ad b
.SH VARIABLES
.HP
\fIVG\fP
.br
Volume Group name. See \fBlvm\fP(8) for valid names.
.HP
\fILV\fP
.br
Logical Volume name. See \fBlvm\fP(8) for valid names.
An LV positional arg generally includes the VG name and LV name, e.g. VG/LV.
.HP
\fITag\fP
.br
Tag name. See \fBlvm\fP(8) for information about tag names and using tags
in place of a VG, LV or PV.
.HP
\fIString\fP
.br
See the option description for information about the string content.
.HP
\fISize\fP[UNIT]
.br
Size is an input number that accepts an optional unit.
Input units are always treated as base two values, regardless of
capitalization, e.g. 'k' and 'K' both refer to 1024.
The default input unit is specified by letter, followed by |UNIT.
UNIT represents other possible input units: \fBbBsSkKmMgGtTpPeE\fP.
b|B is bytes, s|S is sectors of 512 bytes, k|K is kilobytes,
m|M is megabytes, g|G is gigabytes, t|T is terabytes,
p|P is petabytes, e|E is exabytes.
(This should not be confused with the output control --units, where
capital letters mean multiple of 1000.)
.SH ENVIRONMENT VARIABLES
See \fBlvm\fP(8) for information about environment variables used by lvm.
For example, LVM_VG_NAME can generally be substituted for a required VG parameter.
.SH SEE ALSO
.BR lvm (8)
.BR lvm.conf (5)
.BR lvmconfig (8)
.BR pvchange (8)
.BR pvck (8)
.BR pvcreate (8)
.BR pvdisplay (8)
.BR pvmove (8)
.BR pvremove (8)
.BR pvresize (8)
.BR pvs (8)
.BR pvscan (8)
.BR vgcfgbackup (8)
.BR vgcfgrestore (8)
.BR vgchange (8)
.BR vgck (8)
.BR vgcreate (8)
.BR vgconvert (8)
.BR vgdisplay (8)
.BR vgexport (8)
.BR vgextend (8)
.BR vgimport (8)
.BR vgimportclone (8)
.BR vgmerge (8)
.BR vgmknodes (8)
.BR vgreduce (8)
.BR vgremove (8)
.BR vgrename (8)
.BR vgs (8)
.BR vgscan (8)
.BR vgsplit (8)
.BR lvcreate (8)
.BR lvchange (8)
.BR lvconvert (8)
.BR lvdisplay (8)
.BR lvextend (8)
.BR lvreduce (8)
.BR lvremove (8)
.BR lvrename (8)
.BR lvresize (8)
.BR lvs (8)
.BR lvscan (8)
.BR lvm2-activation-generator (8)
.BR blkdeactivate (8)
.BR lvmdump (8)
.BR dmeventd (8)
.BR lvmetad (8)
.BR lvmpolld (8)
.BR lvmlockd (8)
.BR lvmlockctl (8)
.BR clvmd (8)
.BR cmirrord (8)
.BR lvmdbusd (8)
.BR lvmsystemid (7)
.BR lvmreport (7)
.BR lvmraid (7)
.BR lvmthin (7)
.BR lvmcache (7)

View File

@ -1,5 +0,0 @@
lvextend extends the size of an LV. This requires allocating logical
extents from the VG's free physical extents. A copy\-on\-write snapshot LV
can also be extended to provide more space to hold COW blocks. Use
\fBlvconvert\fP(8) to change the number of data images in a RAID or
mirrored LV.

12
man/lvextend.8_des Normal file
View File

@ -0,0 +1,12 @@
lvextend extends the size of an LV. This requires allocating logical
extents from the VG's free physical extents. If the extension adds a new
LV segment, the new segment will use the existing segment type of the LV.
Extending a copy-on-write snapshot LV adds space for COW blocks.
Use \fBlvconvert\fP(8) to change the number of data images in a RAID or
mirrored LV.
In the usage section below, \fB--size\fP \fISize\fP can be replaced
with \fB--extents\fP \fINumber\fP. See both descriptions
the options section.

View File

@ -1,16 +1,14 @@
.SH EXAMPLES .SH EXAMPLES
Extend the size of an LV by 54MiB, using a specific PV. Extend the size of an LV by 54MiB, using a specific PV.
.br .br
.B lvextend \-L +54 vg01/lvol10 /dev/sdk3 .B lvextend -L +54 vg01/lvol10 /dev/sdk3
Extend the size of an LV by the amount of free Extend the size of an LV by the amount of free
space on PV /dev/sdk3. This is equivalent to specifying space on PV /dev/sdk3. This is equivalent to specifying
"\-l +100%PVS" on the command line. "-l +100%PVS" on the command line.
.br .br
.B lvextend vg01/lvol01 /dev/sdk3 .B lvextend vg01/lvol01 /dev/sdk3
Extend an LV by 16MiB using specific physical extents. Extend an LV by 16MiB using specific physical extents.
.br .br
.B lvextend \-L+16m vg01/lvol01 /dev/sda:8\-9 /dev/sdb:8\-9 .B lvextend -L+16m vg01/lvol01 /dev/sda:8-9 /dev/sdb:8-9

712
man/lvextend.8_pregen Normal file
View File

@ -0,0 +1,712 @@
.TH LVEXTEND 8 "LVM TOOLS #VERSION#" "Red Hat, Inc."
.SH NAME
lvextend - Add space to a logical volume
.
.SH SYNOPSIS
\fBlvextend\fP \fIoption_args\fP \fIposition_args\fP
.br
[ \fIoption_args\fP ]
.br
[ \fIposition_args\fP ]
.br
.P
.ad l
\fB--alloc\fP \fBcontiguous\fP|\fBcling\fP|\fBcling_by_tags\fP|\fBnormal\fP|\fBanywhere\fP|\fBinherit\fP
.ad b
.br
.ad l
\fB-A\fP|\fB--autobackup\fP \fBy\fP|\fBn\fP
.ad b
.br
.ad l
\fB--commandprofile\fP \fIString\fP
.ad b
.br
.ad l
\fB--config\fP \fIString\fP
.ad b
.br
.ad l
\fB-d\fP|\fB--debug\fP
.ad b
.br
.ad l
\fB--driverloaded\fP \fBy\fP|\fBn\fP
.ad b
.br
.ad l
\fB-l\fP|\fB--extents\fP [\fB+\fP]\fINumber\fP[PERCENT]
.ad b
.br
.ad l
\fB-f\fP|\fB--force\fP
.ad b
.br
.ad l
\fB-h\fP|\fB--help\fP
.ad b
.br
.ad l
\fB--longhelp\fP
.ad b
.br
.ad l
\fB-m\fP|\fB--mirrors\fP \fINumber\fP
.ad b
.br
.ad l
\fB-n\fP|\fB--nofsck\fP
.ad b
.br
.ad l
\fB--nosync\fP
.ad b
.br
.ad l
\fB--noudevsync\fP
.ad b
.br
.ad l
\fB--poolmetadatasize\fP [\fB+\fP]\fISize\fP[m|UNIT]
.ad b
.br
.ad l
\fB--profile\fP \fIString\fP
.ad b
.br
.ad l
\fB-q\fP|\fB--quiet\fP
.ad b
.br
.ad l
\fB--reportformat\fP \fBbasic\fP|\fBjson\fP
.ad b
.br
.ad l
\fB-r\fP|\fB--resizefs\fP
.ad b
.br
.ad l
\fB-L\fP|\fB--size\fP [\fB+\fP]\fISize\fP[m|UNIT]
.ad b
.br
.ad l
\fB-i\fP|\fB--stripes\fP \fINumber\fP
.ad b
.br
.ad l
\fB-I\fP|\fB--stripesize\fP \fISize\fP[k|UNIT]
.ad b
.br
.ad l
\fB-t\fP|\fB--test\fP
.ad b
.br
.ad l
\fB--type\fP \fBlinear\fP|\fBstriped\fP|\fBsnapshot\fP|\fBmirror\fP|\fBraid\fP|\fBthin\fP|\fBcache\fP|\fBthin-pool\fP|\fBcache-pool\fP
.ad b
.br
.ad l
\fB--usepolicies\fP
.ad b
.br
.ad l
\fB-v\fP|\fB--verbose\fP
.ad b
.br
.ad l
\fB--version\fP
.ad b
.br
.ad l
\fB-y\fP|\fB--yes\fP
.ad b
.SH DESCRIPTION
lvextend extends the size of an LV. This requires allocating logical
extents from the VG's free physical extents. If the extension adds a new
LV segment, the new segment will use the existing segment type of the LV.
Extending a copy-on-write snapshot LV adds space for COW blocks.
Use \fBlvconvert\fP(8) to change the number of data images in a RAID or
mirrored LV.
In the usage section below, \fB--size\fP \fISize\fP can be replaced
with \fB--extents\fP \fINumber\fP. See both descriptions
the options section.
.SH USAGE
Extend an LV by a specified size.
.br
.P
\fBlvextend\fP \fB-L\fP|\fB--size\fP [\fB+\fP]\fISize\fP[m|UNIT] \fILV\fP
.br
.RS 4
.ad l
[ \fB-l\fP|\fB--extents\fP [\fB+\fP]\fINumber\fP[PERCENT] ]
.ad b
.br
.ad l
[ \fB-r\fP|\fB--resizefs\fP ]
.ad b
.br
.ad l
[ \fB-i\fP|\fB--stripes\fP \fINumber\fP ]
.ad b
.br
.ad l
[ \fB-I\fP|\fB--stripesize\fP \fISize\fP[k|UNIT] ]
.ad b
.br
.ad l
[ \fB--poolmetadatasize\fP [\fB+\fP]\fISize\fP[m|UNIT] ]
.ad b
.br
[ COMMON_OPTIONS ]
.RE
.br
.RS 4
[ \fIPV\fP ... ]
.RE
-
Extend an LV by specified PV extents.
.br
.P
\fBlvextend\fP \fILV\fP \fIPV\fP ...
.br
.RS 4
.ad l
[ \fB-r\fP|\fB--resizefs\fP ]
.ad b
.br
.ad l
[ \fB-i\fP|\fB--stripes\fP \fINumber\fP ]
.ad b
.br
.ad l
[ \fB-I\fP|\fB--stripesize\fP \fISize\fP[k|UNIT] ]
.ad b
.br
[ COMMON_OPTIONS ]
.RE
.br
-
Extend a pool metadata SubLV by a specified size.
.br
.P
\fBlvextend\fP \fB--poolmetadatasize\fP [\fB+\fP]\fISize\fP[m|UNIT] \fILV\fP\fI_thinpool\fP
.br
.RS 4
.ad l
[ \fB-i\fP|\fB--stripes\fP \fINumber\fP ]
.ad b
.br
.ad l
[ \fB-I\fP|\fB--stripesize\fP \fISize\fP[k|UNIT] ]
.ad b
.br
[ COMMON_OPTIONS ]
.RE
.br
.RS 4
[ \fIPV\fP ... ]
.RE
-
Extend an LV according to a predefined policy.
.br
.P
\fBlvextend\fP \fB--usepolicies\fP \fILV\fP\fI_snapshot_thinpool\fP
.br
.RS 4
.ad l
[ \fB-r\fP|\fB--resizefs\fP ]
.ad b
.br
[ COMMON_OPTIONS ]
.RE
.br
.RS 4
[ \fIPV\fP ... ]
.RE
-
Common options for command:
.
.RS 4
.ad l
[ \fB-A\fP|\fB--autobackup\fP \fBy\fP|\fBn\fP ]
.ad b
.br
.ad l
[ \fB-f\fP|\fB--force\fP ]
.ad b
.br
.ad l
[ \fB-m\fP|\fB--mirrors\fP \fINumber\fP ]
.ad b
.br
.ad l
[ \fB-n\fP|\fB--nofsck\fP ]
.ad b
.br
.ad l
[ \fB--alloc\fP \fBcontiguous\fP|\fBcling\fP|\fBcling_by_tags\fP|\fBnormal\fP|\fBanywhere\fP|\fBinherit\fP ]
.ad b
.br
.ad l
[ \fB--nosync\fP ]
.ad b
.br
.ad l
[ \fB--noudevsync\fP ]
.ad b
.br
.ad l
[ \fB--reportformat\fP \fBbasic\fP|\fBjson\fP ]
.ad b
.br
.ad l
[ \fB--type\fP \fBlinear\fP|\fBstriped\fP|\fBsnapshot\fP|\fBmirror\fP|\fBraid\fP|\fBthin\fP|\fBcache\fP|\fBthin-pool\fP|\fBcache-pool\fP ]
.ad b
.RE
Common options for lvm:
.
.RS 4
.ad l
[ \fB-d\fP|\fB--debug\fP ]
.ad b
.br
.ad l
[ \fB-h\fP|\fB--help\fP ]
.ad b
.br
.ad l
[ \fB-q\fP|\fB--quiet\fP ]
.ad b
.br
.ad l
[ \fB-t\fP|\fB--test\fP ]
.ad b
.br
.ad l
[ \fB-v\fP|\fB--verbose\fP ]
.ad b
.br
.ad l
[ \fB-y\fP|\fB--yes\fP ]
.ad b
.br
.ad l
[ \fB--commandprofile\fP \fIString\fP ]
.ad b
.br
.ad l
[ \fB--config\fP \fIString\fP ]
.ad b
.br
.ad l
[ \fB--driverloaded\fP \fBy\fP|\fBn\fP ]
.ad b
.br
.ad l
[ \fB--longhelp\fP ]
.ad b
.br
.ad l
[ \fB--profile\fP \fIString\fP ]
.ad b
.br
.ad l
[ \fB--version\fP ]
.ad b
.RE
.SH OPTIONS
.HP
.ad l
\fB--alloc\fP \fBcontiguous\fP|\fBcling\fP|\fBcling_by_tags\fP|\fBnormal\fP|\fBanywhere\fP|\fBinherit\fP
.br
Determines the allocation policy when a command needs to allocate
Physical Extents (PEs) from the VG. Each VG and LV has an allocation policy
which can be changed with vgchange/lvchange, or overriden on the
command line.
\fBnormal\fP applies common sense rules such as not placing parallel stripes
on the same PV.
\fBinherit\fP applies the VG policy to an LV.
\fBcontiguous\fP requires new PEs be placed adjacent to existing PEs.
\fBcling\fP places new PEs on the same PV as existing PEs in the same
stripe of the LV.
If there are sufficient PEs for an allocation, but normal does not
use them, \fBanywhere\fP will use them even if it reduces performance,
e.g. by placing two stripes on the same PV.
Optional positional PV args on the command line can also be used to limit
which PVs the command will use for allocation.
See \fBlvm\fP(8) for more information about allocation.
.ad b
.HP
.ad l
\fB-A\fP|\fB--autobackup\fP \fBy\fP|\fBn\fP
.br
Specifies if metadata should be backed up automatically after a change.
Enabling this is strongly advised! See vgcfgbackup(8) for more information.
.ad b
.HP
.ad l
\fB--commandprofile\fP \fIString\fP
.br
The command profile to use for command configuration.
See \fBlvm.conf\fP(5) for more information about profiles.
.ad b
.HP
.ad l
\fB--config\fP \fIString\fP
.br
Config settings for the command. These override lvm.conf settings.
The String arg uses the same format as lvm.conf,
or may use section/field syntax.
See \fBlvm.conf\fP(5) for more information about config.
.ad b
.HP
.ad l
\fB-d\fP|\fB--debug\fP ...
.br
Set debug level. Repeat from 1 to 6 times to increase the detail of
messages sent to the log file and/or syslog (if configured).
.ad b
.HP
.ad l
\fB--driverloaded\fP \fBy\fP|\fBn\fP
.br
If set to no, the command will not attempt to use device-mapper.
For testing and debugging.
.ad b
.HP
.ad l
\fB-l\fP|\fB--extents\fP [\fB+\fP]\fINumber\fP[PERCENT]
.br
Specifies the new size of the LV in logical extents.
The --size and --extents options are alternate methods of specifying size.
The total number of physical extents used will be
greater when redundant data is needed for RAID levels.
An alternate syntax allows the size to be determined indirectly
as a percentage of the size of a related VG, LV, or set of PVs. The
suffix \fB%VG\fP denotes the total size of the VG, the suffix \fB%FREE\fP
the remaining free space in the VG, and the suffix \fB%PVS\fP the free
space in the specified PVs. For a snapshot, the size
can be expressed as a percentage of the total size of the origin LV
with the suffix \fB%ORIGIN\fP (\fB100%ORIGIN\fP provides space for
the whole origin).
When expressed as a percentage, the size defines an upper limit for the
number of logical extents in the new LV. The precise number of logical
extents in the new LV is not determined until the command has completed.
When the plus \fB+\fP or minus \fB-\fP prefix is used,
the value is not an absolute size, but is relative and added or subtracted
from the current size.
.ad b
.HP
.ad l
\fB-f\fP|\fB--force\fP ...
.br
Override various checks, confirmations and protections.
Use with extreme caution.
.ad b
.HP
.ad l
\fB-h\fP|\fB--help\fP
.br
Display help text.
.ad b
.HP
.ad l
\fB--longhelp\fP
.br
Display long help text.
.ad b
.HP
.ad l
\fB-m\fP|\fB--mirrors\fP \fINumber\fP
.br
Not used.
.ad b
.HP
.ad l
\fB-n\fP|\fB--nofsck\fP
.br
Do not perform fsck before resizing filesystem when filesystem
requires it. You may need to use --force to proceed with
this option.
.ad b
.HP
.ad l
\fB--nosync\fP
.br
Causes the creation of mirror, raid1, raid4, raid5 and raid10 to skip the
initial synchronization. In case of mirror, raid1 and raid10, any data
written afterwards will be mirrored, but the original contents will not be
copied. In case of raid4 and raid5, no parity blocks will be written,
though any data written afterwards will cause parity blocks to be stored.
This is useful for skipping a potentially long and resource intensive initial
sync of an empty mirror/raid1/raid4/raid5 and raid10 LV.
This option is not valid for raid6, because raid6 relies on proper parity
(P and Q Syndromes) being created during initial synchronization in order
to reconstruct proper user date in case of device failures.
raid0 and raid0_meta do not provide any data copies or parity support
and thus do not support initial synchronization.
.ad b
.HP
.ad l
\fB--noudevsync\fP
.br
Disables udev synchronisation. The process will not wait for notification
from udev. It will continue irrespective of any possible udev processing
in the background. Only use this if udev is not running or has rules that
ignore the devices LVM creates.
.ad b
.HP
.ad l
\fB--poolmetadatasize\fP [\fB+\fP]\fISize\fP[m|UNIT]
.br
Specifies the new size of the pool metadata LV.
The plus prefix \fB+\fP can be used, in which case
the value is added to the current size.
.ad b
.HP
.ad l
\fB--profile\fP \fIString\fP
.br
An alias for --commandprofile or --metadataprofile, depending
on the command.
.ad b
.HP
.ad l
\fB-q\fP|\fB--quiet\fP ...
.br
Suppress output and log messages. Overrides --debug and --verbose.
Repeat once to also suppress any prompts with answer no.
.ad b
.HP
.ad l
\fB--reportformat\fP \fBbasic\fP|\fBjson\fP
.br
Overrides current output format for reports which is defined globally by
the report/output_format setting in lvm.conf.
\fBbasic\fP is the original format with columns and rows.
If there is more than one report per command, each report is prefixed
with the report name for identification. \fBjson\fP produces report
output in JSON format. See \fBlvmreport\fP(7) for more information.
.ad b
.HP
.ad l
\fB-r\fP|\fB--resizefs\fP
.br
Resize underlying filesystem together with the LV using fsadm(8).
.ad b
.HP
.ad l
\fB-L\fP|\fB--size\fP [\fB+\fP]\fISize\fP[m|UNIT]
.br
Specifies the new size of the LV.
The --size and --extents options are alternate methods of specifying size.
The total number of physical extents used will be
greater when redundant data is needed for RAID levels.
When the plus \fB+\fP or minus \fB-\fP prefix is used,
the value is not an absolute size, but is relative and added or subtracted
from the current size.
.ad b
.HP
.ad l
\fB-i\fP|\fB--stripes\fP \fINumber\fP
.br
Specifies the number of stripes in a striped LV. This is the number of
PVs (devices) that a striped LV is spread across. Data that
appears sequential in the LV is spread across multiple devices in units of
the stripe size (see --stripesize). This does not change existing
allocated space, but only applies to space being allocated by the command.
When creating a RAID 4/5/6 LV, this number does not include the extra
devices that are required for parity. The largest number depends on
the RAID type (raid0: 64, raid10: 32, raid4/5: 63, raid6: 62), and
when unspecified, the default depends on the RAID type
(raid0: 2, raid10: 2, raid4/5: 3, raid6: 5.)
To stripe a new raid LV across all PVs by default,
see lvm.conf allocation/raid_stripe_all_devices.
.ad b
.HP
.ad l
\fB-I\fP|\fB--stripesize\fP \fISize\fP[k|UNIT]
.br
The amount of data that is written to one device before
moving to the next in a striped LV.
.ad b
.HP
.ad l
\fB-t\fP|\fB--test\fP
.br
Run in test mode. Commands will not update metadata.
This is implemented by disabling all metadata writing but nevertheless
returning success to the calling function. This may lead to unusual
error messages in multi-stage operations if a tool relies on reading
back metadata it believes has changed but hasn't.
.ad b
.HP
.ad l
\fB--type\fP \fBlinear\fP|\fBstriped\fP|\fBsnapshot\fP|\fBmirror\fP|\fBraid\fP|\fBthin\fP|\fBcache\fP|\fBthin-pool\fP|\fBcache-pool\fP
.br
The LV type, also known as "segment type" or "segtype".
See usage descriptions for the specific ways to use these types.
For more information about redundancy and performance (\fBraid\fP<N>, \fBmirror\fP, \fBstriped\fP, \fBlinear\fP) see \fBlvmraid\fP(7).
For thin provisioning (\fBthin\fP, \fBthin-pool\fP) see \fBlvmthin\fP(7).
For performance caching (\fBcache\fP, \fBcache-pool\fP) see \fBlvmcache\fP(7).
For copy-on-write snapshots (\fBsnapshot\fP) see usage definitions.
Several commands omit an explicit type option because the type
is inferred from other options or shortcuts
(e.g. --stripes, --mirrors, --snapshot, --virtualsize, --thin, --cache).
Use inferred types with care because it can lead to unexpected results.
.ad b
.HP
.ad l
\fB--usepolicies\fP
.br
Perform an operation according to the policy configured in lvm.conf
or a profile.
.ad b
.HP
.ad l
\fB-v\fP|\fB--verbose\fP ...
.br
Set verbose level. Repeat from 1 to 4 times to increase the detail
of messages sent to stdout and stderr.
.ad b
.HP
.ad l
\fB--version\fP
.br
Display version information.
.ad b
.HP
.ad l
\fB-y\fP|\fB--yes\fP
.br
Do not prompt for confirmation interactively but always assume the
answer yes. Use with extreme caution.
(For automatic no, see -qq.)
.ad b
.SH VARIABLES
.HP
\fILV\fP
.br
Logical Volume name. See \fBlvm\fP(8) for valid names.
An LV positional arg generally includes the VG name and LV name, e.g. VG/LV.
LV followed by _<type> indicates that an LV of the
given type is required. (raid represents raid<N> type)
.HP
\fIPV\fP
.br
Physical Volume name, a device path under /dev.
For commands managing physical extents, a PV positional arg
generally accepts a suffix indicating a range (or multiple ranges)
of physical extents (PEs). When the first PE is omitted, it defaults
to the start of the device, and when the last PE is omitted it defaults to end.
Start and end range (inclusive): \fIPV\fP[\fB:\fP\fIPE\fP\fB-\fP\fIPE\fP]...
Start and length range (counting from 0): \fIPV\fP[\fB:\fP\fIPE\fP\fB+\fP\fIPE\fP]...
.HP
\fIString\fP
.br
See the option description for information about the string content.
.HP
\fISize\fP[UNIT]
.br
Size is an input number that accepts an optional unit.
Input units are always treated as base two values, regardless of
capitalization, e.g. 'k' and 'K' both refer to 1024.
The default input unit is specified by letter, followed by |UNIT.
UNIT represents other possible input units: \fBbBsSkKmMgGtTpPeE\fP.
b|B is bytes, s|S is sectors of 512 bytes, k|K is kilobytes,
m|M is megabytes, g|G is gigabytes, t|T is terabytes,
p|P is petabytes, e|E is exabytes.
(This should not be confused with the output control --units, where
capital letters mean multiple of 1000.)
.SH ENVIRONMENT VARIABLES
See \fBlvm\fP(8) for information about environment variables used by lvm.
For example, LVM_VG_NAME can generally be substituted for a required VG parameter.
.SH EXAMPLES
Extend the size of an LV by 54MiB, using a specific PV.
.br
.B lvextend -L +54 vg01/lvol10 /dev/sdk3
Extend the size of an LV by the amount of free
space on PV /dev/sdk3. This is equivalent to specifying
"-l +100%PVS" on the command line.
.br
.B lvextend vg01/lvol01 /dev/sdk3
Extend an LV by 16MiB using specific physical extents.
.br
.B lvextend -L+16m vg01/lvol01 /dev/sda:8-9 /dev/sdb:8-9
.SH SEE ALSO
.BR lvm (8)
.BR lvm.conf (5)
.BR lvmconfig (8)
.BR pvchange (8)
.BR pvck (8)
.BR pvcreate (8)
.BR pvdisplay (8)
.BR pvmove (8)
.BR pvremove (8)
.BR pvresize (8)
.BR pvs (8)
.BR pvscan (8)
.BR vgcfgbackup (8)
.BR vgcfgrestore (8)
.BR vgchange (8)
.BR vgck (8)
.BR vgcreate (8)
.BR vgconvert (8)
.BR vgdisplay (8)
.BR vgexport (8)
.BR vgextend (8)
.BR vgimport (8)
.BR vgimportclone (8)
.BR vgmerge (8)
.BR vgmknodes (8)
.BR vgreduce (8)
.BR vgremove (8)
.BR vgrename (8)
.BR vgs (8)
.BR vgscan (8)
.BR vgsplit (8)
.BR lvcreate (8)
.BR lvchange (8)
.BR lvconvert (8)
.BR lvdisplay (8)
.BR lvextend (8)
.BR lvreduce (8)
.BR lvremove (8)
.BR lvrename (8)
.BR lvresize (8)
.BR lvs (8)
.BR lvscan (8)
.BR lvm2-activation-generator (8)
.BR blkdeactivate (8)
.BR lvmdump (8)
.BR dmeventd (8)
.BR lvmetad (8)
.BR lvmpolld (8)
.BR lvmlockd (8)
.BR lvmlockctl (8)
.BR clvmd (8)
.BR cmirrord (8)
.BR lvmdbusd (8)
.BR lvmsystemid (7)
.BR lvmreport (7)
.BR lvmraid (7)
.BR lvmthin (7)
.BR lvmcache (7)

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