1
0
mirror of git://sourceware.org/git/lvm2.git synced 2026-01-01 16:32:54 +03:00

Compare commits

...

220 Commits

Author SHA1 Message Date
Marian Csontos
cf06d942b8 test: api subdirectory is needed in PATH by pytest 2015-11-02 14:16:46 +01:00
Marian Csontos
83d3cc76f3 test: Run pytest with installed libs 2015-11-02 12:52:30 +01:00
Marian Csontos
89574055f7 spec: Add python bindings 2015-11-02 12:42:32 +01:00
Alasdair G Kergon
7831a65091 post-release 2015-10-31 01:35:47 +00:00
Alasdair G Kergon
15a97cc610 pre-release 2015-10-30 15:34:00 +00:00
Peter Rajnoha
3f1c63c812 WHATS_NEW: reporting commands and -o-/-o+ extension 2015-10-30 15:50:35 +01:00
Peter Rajnoha
dd52721b68 commands: update command help for -o|--options for reporting commands 2015-10-30 15:47:56 +01:00
Peter Rajnoha
7f125c1116 man: pvs/vgs/lvs and -o+, -o-, -o# 2015-10-30 15:47:56 +01:00
Peter Rajnoha
5b04eda93f tests: add report-fields.sh test 2015-10-30 15:47:56 +01:00
Peter Rajnoha
77c31d0c39 report: support "-o #field_name1,field_name2,..." 2015-10-30 15:47:56 +01:00
Peter Rajnoha
baf320455b report: recognize known prefix when processing "-o -field_name1,field_name2,..." 2015-10-30 15:47:56 +01:00
Peter Rajnoha
bb4d3fa7a7 report: add report_get_field_prefix function 2015-10-30 15:47:56 +01:00
Peter Rajnoha
3e18b101a0 report: support "-o -field_name1,field_name2,...." 2015-10-30 15:47:56 +01:00
Peter Rajnoha
df190dcfa5 report: make report options defined by "-o" groupable
Also, besides making "-o" groupable, use string lists to store
lists of options temporarily while processing all instances of
the "-o" group.
2015-10-30 15:47:56 +01:00
Peter Rajnoha
e149fe7fdf refactor: move code detecting report options to a separate function 2015-10-30 15:47:56 +01:00
Peter Rajnoha
77605457e7 str_list: add str_list_destroy function
The str_list_destroy function may be called to cleanup memory when
the list is not used anymore and the list itself was not allocated
from the memory pool.
2015-10-30 15:47:56 +01:00
Peter Rajnoha
0d5b1294f0 str_list: add str_list_to_str and str_to_str_list functions
The str_list_to_str and str_to_str_list are helper functions to
convert string list to a single string and vice versa.
2015-10-30 15:47:56 +01:00
Peter Rajnoha
097d14e64e str_list: also allow memory allocation without memory pool 2015-10-30 15:47:55 +01:00
David Teigland
17196103e0 New entries for pvs related fixes. 2015-10-30 09:05:21 -05:00
Peter Rajnoha
ccfc09f79b metadata: format_text: also count with calculated mda size of 0
When checking minimum mda size, make sure the mda_size after alignment
and calculation is more than 0 - if there's no place for an MDA at the
end of the disk, the _text_pv_add_metadata_area does not try to add it
there and it returns (because we already have the MDA at the start of
the disk at least).
2015-10-30 12:02:34 +01:00
Peter Rajnoha
9a3b64e81a tests: add test for minimum mda size 2015-10-30 10:02:00 +01:00
Peter Rajnoha
c2e88d1107 metadata: format_text: better check for metadata overlap
Actually, we don't need extra condition as introduced in commit
00348c0a63. We should fix the last
condition:

  (mdac->rlocn.size >= mdah->size)

...which should be:

  (MDA_HEADER_SIZE + (rlocn ? rlocn->size : 0) + mdac->rlocn.size >= mdah->size))

Where the "mdac" is new metadata, the "rlocn" is old metadata.

So the main problem with the previous condition was that it
didn't count in MDA_HEADER_SIZE properly (and possible existing
metadata - the "rlocn"). This could have caused the error state
where metadata in ring buffer overlap to not be hit.

Replace the new condition introduced in 00348c0a63
with the improved one for the condition that existed there
already but it was just incomplete.
2015-10-30 08:57:34 +01:00
Peter Rajnoha
406d8ff332 WHATS_NEW: recent commits 2015-10-29 16:50:09 +01:00
Peter Rajnoha
00348c0a63 metadata: format_text: check VG metadata do not overlap themselves
We're already checking whether old and new meta do not overlap in
ring buffer (as we need to keep both old and new meta during vg_write
up until vg_commit).

We also need to check whether the new metadata do not overlap
themselves in case we don't have old metadata yet (...because
we're in vgcreate). This could happen if we're creating a VG so
that the very first metadata written are long enough that it wraps
themselves in metadata ring buffer.

Although we limited the minimum metadata area size better with the
previous commit ccb8da404d which
makes the initial VG metadata overlap in ring buffer to be less
probable, the risk of hitting this overlap condition is still there
if we still manage to generate big enough metadata somehow.

For example, users can provide many and/or long VG tags during vgcreate
so that the VG metadata is long enough to start to wrap in the ring
buffer again...
2015-10-29 16:46:41 +01:00
Peter Rajnoha
ccb8da404d metadata: format_text: check metadata area size is at least MDA_SIZE_MIN 2015-10-29 16:00:32 +01:00
Zdenek Kabelac
28e54032c0 tests: update test for resize
Drop already tested 'threshold & create' which is in
lvextend-thin-full.sh

Count with now match faster 'dmeventd' wakeup on watermark
as it's now nearly instant after crossing threshold value.
2015-10-29 15:11:16 +01:00
Ondrej Kozina
bca55c9b20 tests: replace invalid use of 'fail' with 'die' 2015-10-29 13:30:29 +01:00
Zdenek Kabelac
f104a81932 tests: let pass bigger readahead
If the underlaying device has actually bigger read-ahead settings,
let it pass.
But anyway switch to 512 strip-size to get really high R-A sector count.
2015-10-29 12:39:07 +01:00
Zdenek Kabelac
3720eb63be tests: fix wrong line has been commented 2015-10-29 12:39:07 +01:00
Zdenek Kabelac
8b5525383f tests: no point in using should
lvmetad does not support lvm1 - so expect failure.
2015-10-29 12:39:07 +01:00
Zdenek Kabelac
f58c634103 cleanup: error is not a WARNING
Drop 'WARNING' from error message.
It's plain error message leading to command failure.
2015-10-29 12:38:59 +01:00
Zdenek Kabelac
175119fdcd cleanup: remove thin low_water_mark from metadata
This option could never have been printed in lvm2 metadata, so it could
be safely removed as it could have been set only as 0.

These configurable setting is supported via metadata profile.
2015-10-29 12:14:20 +01:00
Zdenek Kabelac
33a8a2febf cleanup: use same type 2015-10-29 12:14:20 +01:00
Zdenek Kabelac
f32f0bd2a7 cleanup: easier error messages 2015-10-29 12:14:20 +01:00
Zdenek Kabelac
99237f0908 thin: enable usage of kernel low_water_mark
Now with correctly functioning dmeventd enable usage of
low_water_mark for faster reaction on pool's threshold.

When user select e.g. 80% as a threshold value,
dmeventd doesn't need to wait 10 seconds till monitoring
timer expires, but nearly instantly resizes thin-pool
to fit bellow threshold.
2015-10-29 12:14:20 +01:00
Zdenek Kabelac
099466939e thin: dmeventd plugin check number of failures
If plugin's lvm command execution fails too often (>10 times),
there is no point to torture system more then necessary, just log
and drop monitoring in this case.
2015-10-29 12:14:20 +01:00
Peter Rajnoha
b3c81d02c9 revert: 3d03e504cd: message about VG metadata size vs. PV mda size
The message needs refinement - it's not correct in all situations.
2015-10-29 11:10:48 +01:00
David Teigland
5886ff64eb pvs: don't treat duplicate PVs as missed
The recent addition to check for PVs that were
missed during the first iteration of processing
was unintentionally catching duplicate PVs because
duplicates were not removed from the all_devices
list when the primary dev was processed.

Also change a message from warn back to verbose.
2015-10-27 12:03:57 -05:00
David Teigland
a4418b34c1 vgs, lvs: ignore error if VG is removed
If a VG is removed between the time that 'vgs'
or 'lvs' (with no args) creates the list of VGs
and the time that it reads the VG to process it,
then ignore the removed VG; don't report an error
that it could not be found, since it wasn't named
by the command.
2015-10-27 10:52:01 -05:00
Alasdair G Kergon
65ec00ce20 device: Tidy DASD CDL format detection code. 2015-10-27 15:27:52 +00:00
Zdenek Kabelac
6e1e0e8813 tests: using matching type
Compare time_t.
2015-10-27 16:00:10 +01:00
Zdenek Kabelac
4159680a0e tests: use more SKIP
Speed-up check_lvmpolld.
2015-10-27 16:00:09 +01:00
Zdenek Kabelac
76cff10a73 tests: avoid reading utils when skipping
Save even more CPU/time and avoid reading utils, when skipping test.
2015-10-27 16:00:09 +01:00
Marian Csontos
1af2ab10d0 cleanup: snapshots of snapshots message
No plans to support thick snapshost of snapshots.
2015-10-27 11:42:48 +01:00
Lidong Zhong
729f489009 pvcreate: don't support unpartitioned DASD devices with CDL formatted
The former patch(dab3ebce4c) is a little bit strict. For example, it is
OK to create PV on unpartitioned DASD devices with LDL formatted. So
after lvm version containing the patch, LVs created on those devices
could not be found.

Signed-off-by: Lidong Zhong <lzhong@suse.com>
2015-10-27 11:42:47 +01:00
Zdenek Kabelac
5d76bdcdbd dmeventd: event string parser handles empty field
Improve event string parser to avoid unneeded alloc+free.

Daemon talk function uses '-' to mark NULL/missing field.
So restore the NULL pointer back on parser.

This should have made old tools like 'dmevent_tool' work again.
As now 'uuid' or 'dso' could become NULL and then be
properly used in _want_registered_device() function.

Since lvm2 always fill these parameters, this change should
have no effect on lvm2.
2015-10-27 11:42:40 +01:00
Zdenek Kabelac
3b5939bbbb tests: use skip flags
corrected usage of skip flags.
2015-10-27 00:45:37 +01:00
Zdenek Kabelac
a2dd1f6e19 tests: support skip flags 2015-10-26 23:57:47 +01:00
Zdenek Kabelac
c301cc5d38 tests: extend timer for 4 hours
Extend max time for test suite to 4 hours.
Also replace some 'non-ascii' chars from source files
and keep them plain ascii.
2015-10-26 23:57:47 +01:00
Zdenek Kabelac
ba41ee1dc9 thin: limit no-flush using only for thin-pool
For this release keep usage of 'noflush' only for thin-volume/pool.

For rest of keep - keep usage of 'noflush' flag purely for
non-resized mirrors.
2015-10-26 23:57:31 +01:00
Zdenek Kabelac
b702d67747 dmevent: fix referencing
Plugin increments DSO refcounter in _alloc_thread_status().
2015-10-26 23:31:23 +01:00
David Teigland
44ba862674 toollib: fix wrong paren placement 2015-10-26 16:27:26 -05:00
David Teigland
6624833839 pvs: fix missing PVs when VG is removed
PVs could be missing from the 'pvs' output if
their VG was removed at the same time that the
'pvs' command was run.  To fix this:

1. If a VG is not found when processed, don't
silently skip the PVs in it, as is done when
the "skip" variable is set.

2. Repeat the VG search if some PVs are not
found on the first search through all VGs.
The second search uses a specific list of
PVs that were missed the first time.

testing:
/dev/sdb is a PV
/dev/sdd is a PV
/dev/sdg is not a PV

each test begins with:
vgcreate test /dev/sdb /dev/sdd

variations to test:
vgremove -f test & pvs
vgremove -f test & pvs -a
vgremove -f test & pvs /dev/sdb /dev/sdd
vgremove -f test & pvs /dev/sdg
vgremove -f test & pvs /dev/sdb /dev/sdg

The pvs command should always display /dev/sdb
and /dev/sdd, either as a part of VG test or not.

The pvs command should always print an error
indicating that /dev/sdg could not be found.
2015-10-26 16:07:12 -05:00
Zdenek Kabelac
b29593378f tests: snapshot now respects threshold 2015-10-26 07:38:23 +01:00
Zdenek Kabelac
428ca9b120 libdm: enable no_flush for driver version > 11
It appears the driver version 11 has troubles with usage of no_flush
So require at least version 12.
2015-10-26 07:37:59 +01:00
Zdenek Kabelac
f898cf7539 dev_manager: no flush for extension
Recognize the target only 'extends' and do not enforce
'flush' in this case.  Only the size reduction
still requires flush (so disables usage of no_flush flag).

If some other targets do require flush before suspend,
they have to explicitly ask for it.
2015-10-25 21:09:31 +01:00
Zdenek Kabelac
844b009584 dev_manager: enabled no_flush for suspend
While the activation code tries to evaluate which target
really needs flush with suspend and which may go without flush,
it has stayed effectively disabled by original commit:
33f732c5e9 since here
it only allows to pass non-pvmoving  'mirrors'.

So remove check for mirror LV type and only disable
no_flush for 'pvmove'..

TODO: Looking into history - it also seemed like raid target
would have always required flushing but it's been later
removed without clean explanation.

If some more targets really do need 'no_flush' it should
been handle at their 'level' - since we now stack multiple
targets over itself.
2015-10-25 21:07:37 +01:00
Zdenek Kabelac
9ef820a2a5 libdm: dm_tree_node_size_changed recognizes reduction
Add more functionality to size_changed function.
While 'existing' API only detected  0 for
unchanged,  and !0 for changed,
new improved API will also detected if the
size has only went bigger - or there was
size reduction.

Function work for the whole dm-tree - so
no change is size is always 0.
only size extension  1.
and if some size reduction is there - returns -1.

This result can be used for better evaluation
whether we need to flush before suspend.
2015-10-25 21:05:15 +01:00
Zdenek Kabelac
40eea582ae lv_manip: ensure it will fit bellow threshold
Use single code to evaluate if the percentage value has
crossed threshold.

Recalculate amount value to always fit bellow
threshold so there are not need any extra reiterations
to reach this state in case policy amount is too small.
2015-10-25 21:03:11 +01:00
Zdenek Kabelac
b780d329aa thin: fix percentage compare
Since plugin's percentage compare has been fixed,
it's now revealed wrong compare here.

The logic for threshold is - to allow to go as high
as given value e.g. 80% - so if pool is exactlu 80%
full it's still allowed to use it (dmeventd will not
resize it).
2015-10-25 21:01:54 +01:00
David Teigland
8f269697d2 vg_read: remove unused inconsistent check
Commit 1a74171ca5 added
a check to ignore a VG that was FAILED_INCONSISTENT
if the command doesn't care if the VG is not found.
Remove that check because that case is never reached
by the current code.
2015-10-23 12:19:11 -05:00
David Teigland
98d81a43ea vgextend: fix use of the wrong flag
The ONE_VGNAME_ARG was being passed and tested as
vg_read() flag but it's a cmd struct flag.

(It affects command arg processing in toollib,
not vg_read behavior.  Flags related to command
processing are generally cmd struct flags, while
vg_read arg flags are generally related to vg_read
behavior.)
2015-10-23 10:21:06 -05:00
David Teigland
1a74171ca5 vg_read: sometimes ignore read errors
Running "vgremove -f VG & pvs" results in the pvs
command reporting that the VG is not found or is
inconsistent.  If the VG is gone or being removed,
the pvs command should just skip it and not print
errors about it.

"Not found" is because the pvs command created the
list of VGs to process, including VG, then vgremove
removed the VG, then the pvs command came to to read
the VG to process it and did not find it.

An "inconsistent" error could be reported if vgremove
had only partially completed removing VG when pvs did
vg_read on the VG to process it, causing pvs to find
the VG in a partially-removed state.

This fix adds a flag that pvs uses to ignore a VG
that can't be read or is inconsistent.
2015-10-23 10:12:34 -05:00
Alasdair G Kergon
51735f09f7 thin: Fix typo in policy threshold message. 2015-10-23 15:38:31 +01:00
Peter Rajnoha
3a42c13ccf lvmcache: update cached info properly when moving from VG to orphan while lvmetad is used
When lvmetad is used and lvmcache update function (lvmcache_update_vgname_and_id)
was called to update existing lvmcache records, a condition was met
which made to retun from the update function immediately, effectively
making it NOOP.

It seems there's no reason for such condition and lvmcache should be
update appropriately even when lvmetad used as lvmcache may be reused,
most notably in lvm shell.

It's possible this is a remnant of the lvmetad development code which
didn't get removed for some reason and the bug didn't get spotted
because lvm shell is not used often (the condition dates back to 2012
or so).

Example, lvmetad and lvm shell used:

lvm> pvs
  PV         VG   Fmt  Attr PSize   PFree
  /dev/sda   vg   lvm2 a--  124.00m 124.00m

Before this patch:
==================
lvm> vgremove vg
  Volume group "vg" successfully removed

lvm> pvs

With this patch applied:
========================

lvm> vgremove vg
  Volume group "vg" successfully removed

lvm> pvs
  PV         VG   Fmt  Attr PSize   PFree
  /dev/sda        lvm2 ---  128.00m 128.00m
2015-10-23 15:58:31 +02:00
Peter Rajnoha
8b965bd3d5 pvremove: make sure even invalid info is removed from lvmcache on pvremove
The lvmcache info might be resued, most notably in lvm shell.
We need to be sure that even lvmcache_info marked as invalid
is removed from the lvmcache so it does not confuse any subsequent
code/commands executed later on.

Problematic example with the lvm shell:

lvm> pvs
  PV         VG   Fmt  Attr PSize   PFree
  /dev/sda        lvm2 ---  128.00m 128.00m

Before this patch (/dev/sda still displayed in a way):
======================================================

lvm> pvremove /dev/sda
  Labels on physical volume "/dev/sda" successfully wiped

(without lvmetad)
lvm> pvs
  No physical volume label read from /dev/sda

(with lvmetad)
lvm> pvs
  PV         VG   Fmt  Attr PSize   PFree
  /dev/sda        lvm2 ---  128.00m 128.00m

With this patch applied:
========================

lvm> pvremove /dev/sda
  Labels on physical volume "/dev/sda" successfully wiped

(without lvmetad)
lvm> pvs

(with lvmetad)
lvm> pvs
2015-10-23 15:48:06 +02:00
Zdenek Kabelac
1a7bea0f0f cleanup: drop debug 2015-10-23 10:54:13 +02:00
Zdenek Kabelac
b5b2a54834 cleanup: fix gcc compile with older pthread
Older pthread library was missing 'trick'
in pthread_cleanup_pop() which lead to
compilation error:

error: label at end of compound statement

Use explicit ';' to fix it.
2015-10-23 10:54:13 +02:00
Zdenek Kabelac
21748a8630 cleanup: gcc warning for old-style 2015-10-23 10:54:13 +02:00
Zdenek Kabelac
e5b686d693 tools: update for lvm2_disable_dmeventd_monitoring
Make lvm2_disable_dmeventd_monitoring() more explicit.

As memlock_inc_daemon() is also used by clvmd, which
does changes dmeventd and suspend ignore state at
some stages - make updates of these 2 variable
tied to the call of  lvm2_disable_dmeventd_monitoring().

Once this call is made dmeventd monitoring
and suspended devices are ignored.

TODO: all lvm-global settings should really be moved
to command context.
2015-10-23 10:54:13 +02:00
Zdenek Kabelac
87a39d8bac dmeventd: ensure filter is empty
On some error path we could have left filter set to some value.
Not a big issue - but lets make reporting correct as soon
as we can.
2015-10-23 10:54:13 +02:00
Zdenek Kabelac
cff1c728d8 dmeventd: debug error paths 2015-10-23 10:54:13 +02:00
Zdenek Kabelac
2786cd27da tests: enable raid test on 4.3
With kernel -rc6 it's passing our raid tests again - so enable
it in tests.

Note: related only to Fedora rawhide kernels...
2015-10-22 22:46:10 +02:00
Zdenek Kabelac
1a2d0a0c72 cleanup: indents 2015-10-22 22:46:10 +02:00
Zdenek Kabelac
b1319e0402 cleanup: drop uneeded header file 2015-10-22 22:46:10 +02:00
Zdenek Kabelac
8be60e6a65 cleanup: easier to read code
Avoid using #ifdef code and use 'cmd' instead of 'die'.
2015-10-22 22:46:10 +02:00
Zdenek Kabelac
39cffa4e9b cleanup: declare vars before code 2015-10-22 22:46:10 +02:00
Zdenek Kabelac
2af696c32f dmeventd: exit on idle
Implementing exit when 'dmeventd' is idle.
Default idle timeout set to 1 hour - after this time period
dmeventd will cleanly exit.

On systems with 'systemd' - service is automatically started with
next contact on dmeventd communication socket/fifo.

On other systems - new dmeventd starts again when lvm2 command detects
its missing and monitoring is needed.
2015-10-22 22:43:03 +02:00
Zdenek Kabelac
4284ba65eb dmeventd: debug signals 2015-10-22 22:41:12 +02:00
Zdenek Kabelac
aeec62ad19 dmeventd: snapshot plugin unmonitor
Send signal to itself to mark plugin as 'finished' as
the watching rule is no longer usable.
2015-10-22 22:41:12 +02:00
Zdenek Kabelac
12aa56d298 dmeventd: handle signal from plugin
Add support to unmonitor device when monitor recognizes there is
nothing to monitor anymore.

TODO: possibly API change with return value could be also used.
2015-10-22 22:40:07 +02:00
Zdenek Kabelac
9156c5d088 dmeventd: rework locking code
Redesign threading code:

- plugin registration runs within its new created thread for
  improved parallel usage.

- wait task is created just once and used during whole plugin lifetime.

- event thread is based over  'events' filter being set - when
  filter is 0, such thread is 'unused'.

- event loop is  simplified.

- timeout thread is never signaling 'processing' thread.

- pending of events filter cnange is properly reported and
  running event thread is signalled when possible.

- helgrind is not reporting problems.
2015-10-22 22:39:24 +02:00
Zdenek Kabelac
466a1c72b7 cleanup: use enums 2015-10-22 22:36:00 +02:00
Zdenek Kabelac
81e9ab3156 dmeventd: code mode _get_device_status
Move _get_device_status() in code.
Use dm_task_no_flush() function when reading status.
(e.g. none blocking for thins pool)
2015-10-22 22:35:25 +02:00
Zdenek Kabelac
15dbd4b56a dmeventd: minimize locking time for get_imeout
Don't hold lock when creating message (allocating memory).
Thread cannot dissapear as it's only the same thread which
may clean it.
2015-10-22 22:34:30 +02:00
Zdenek Kabelac
e2ea2a8147 dmeventd: drop unneded test
Function is never called without device.uuid.
2015-10-22 22:34:29 +02:00
Zdenek Kabelac
941c6354db dmeventd: wake up timer when setting new timeout 2015-10-22 22:34:29 +02:00
Zdenek Kabelac
02eb000f51 dmeventd: use dm_hold_control_dev
Need here to keep  control device opened while there is 'any' dso
plugin loaded - otherwise there would a race closing controlfd
inside lvm2 plugin while some other monitoring thread would
tried to execute another WAITEVENT task.
2015-10-22 22:34:27 +02:00
Zdenek Kabelac
efc76ca33d dmeventd: move dso handling into single code section
Move all DSO related function in front, so they could be easily
referenced from rest of code.

Add proper error paths with logging and error reporting.

Drop mutex locking when releasing DSO - since DSO is always
allocated and released in main 'event' processing thread.
2015-10-22 22:33:19 +02:00
Zdenek Kabelac
590091a4fa dmeventd: using warning level
When dmevend notices problems, but continues to operate normally
change log level to warning.
2015-10-22 22:33:19 +02:00
Zdenek Kabelac
9488cbdd0b dmeventd: no registering of 0 event mask
Whenever user tries to register 0 mask report this as EINVAL.
2015-10-22 22:33:19 +02:00
Zdenek Kabelac
fa9e41d2e3 dmeventd: thin plugin update
Use  dm_make_percent for percentage calculation like lvm2 command.

Use a single call for resize.
2015-10-22 22:33:07 +02:00
Zdenek Kabelac
6b0bc5b2d9 dmeventd: snapshot plugin device removal
Add #ifdef-ed code to have ability to even remove unusable device.
For now purely experimental.
2015-10-22 22:29:53 +02:00
Zdenek Kabelac
7ff5b03e5e dmeventd: snapshot plugin updates
Improve test for invalid snapshot.

Use dm_make_percent() to manipulate with exactly same percentage
as lvm2 command is using.
2015-10-22 22:29:50 +02:00
Zdenek Kabelac
91350f5c6a dmeventd: mirror plugin update
Don't use  --config  - this requires reload of lvm.conf
2015-10-22 22:28:37 +02:00
Zdenek Kabelac
9c5c9e2355 dmeventd: raid plugin reporting
Fix raid logging introduced with last updating commit.
2015-10-22 22:28:37 +02:00
Zdenek Kabelac
cde12cbe9e dmeventd: lvm2 plugin correctly debug
Fix debug message and report exit when really doing it.
Also add missing '_' to static function.
2015-10-22 22:28:37 +02:00
Zdenek Kabelac
ab6d16a8a5 dmeventd: check for malloc return 2015-10-22 22:28:37 +02:00
Zdenek Kabelac
09a62cca0c libdm: add dm_hold_control_dev
Support hold of control device open.
Useful for daemons so the control device is not frequently reopenned.
2015-10-22 22:27:31 +02:00
Zdenek Kabelac
075f85dcb5 tools: do not change signals for memlocked daemons 2015-10-22 22:26:30 +02:00
Zdenek Kabelac
d2c4ce254b tools: preselect some setting for memlocked daemons
When our daemon is locked into memory - avoid
communication with dmeventd and also skip
suspended devices.
2015-10-22 22:26:30 +02:00
Zdenek Kabelac
7b78d496bf memlock: report memlock daemon counter
Add internal memlock_count_daemon().

Function can be used to recognize it's being executed
from daemon restricted execution inside /lib code.
2015-10-22 22:26:27 +02:00
Zdenek Kabelac
19e272ba53 lib: better reporting of threshold
Simplify code reporting warning about incorrect thresholds.
2015-10-22 22:06:14 +02:00
David Teigland
73e679f33f man: document possible lvmetad -l values
In the man page and the lvmetad help output.
2015-10-21 13:36:57 -05:00
David Teigland
a0d819172f libdaemon: fix typo in last log enable commit 2015-10-21 11:22:22 -05:00
David Teigland
0aee04288e libdaemon: allow all debug levels for stderr
The parsing code for log levels was missing
some levels.  Also ignore an unrecognized
level name rather than failing.
2015-10-21 11:19:18 -05:00
Ondrej Kozina
ef4d69f456 tests: add lvmetad shutdown on idle test 2015-10-20 15:45:28 +02:00
Ondrej Kozina
c15649b3af lvmetad.8.in: update man page with timeout info 2015-10-20 15:45:21 +02:00
Ondrej Kozina
f67a52677b lvmetad: add optional timeout option 2015-10-20 15:45:14 +02:00
Ondrej Kozina
392248186e tests: add test for missing mirror in-sync info 2015-10-20 12:19:02 +02:00
Ondrej Kozina
33465066c5 polldaemon: fix missing mirror in-sync info with lvmpolld
CONVERTING status flag is a tricky one. It's not set when converting
a non-mirror LV type to the mirror type, i.e.: linear -> two leg mirror.
Also the conversion itself is instant and doesn't require to be polled.
When mirror reaches sync state there's no final update on VG metadata
for lvmpolld to be made thereby report_progress in fact doesn't report
percentage of mirror being converted but percentage of mirror
being in sync. Perhaps we should reword the lvconvert output here.

On the other hand CONVERTING is set while we upconvert the mirror
from i.e. two leg mirror to four leg mirror. In such case the operation
is required to be polled so that lvmpolld can cleanup temporary
conversion log when the conversion is over.

Ignore CONVERTING lv_type for the moment and match LVs only by uuids
during 'mirror conversion'/'waiting for a sync to finish'.
2015-10-20 12:18:55 +02:00
Peter Rajnoha
a5c4c4efbd conf: clarify compact output settings 2015-10-20 11:01:09 +02:00
David Teigland
83d475626a pvscan: use process_each_pv
The old code made two loops through the PVs: in the first
loop it found the max PV and VG name lengths, and in the
second loop it printed each PV using the name lengths as
field widths for aligning columns.

The new code uses process_each_pv() which makes one loop
through the PVs.  In the *first* call to pvscan_single(),
the max name lengths are found by looping through the
lvmcache entries which have been populated by the generic
process_each code prior to calling any _single functions.
Subsequent calls to pvscan_single() reuse the max lengths
that were found by the first call.
2015-10-19 16:15:51 -05:00
Peter Rajnoha
1ea7e2634d conf: regenerate 2015-10-19 10:01:14 +02:00
Peter Rajnoha
23d9b17a7b cleanup: typo in comment: compact_output_fields should be compact-output_cols 2015-10-19 09:59:05 +02:00
Peter Rajnoha
c3bfe07f2a config: add report/compact_output_cols to control which columns to compact in report output
The new report/compact_output_cols setting has exactly the same effect
as report/compact_output setting. The difference is that with the new
setting it's possible to define which cols should be compacted exactly
in contrast to all cols in case of report/compact_output.

In case both compact_output and compact_output_cols is enabled/set,
the compact_output prevails.

For example:

$ lvmconfig --type full report/compact_output report/compact_output_cols
compact_output=0
compact_output_cols=""

$ lvs vg
  LV    VG   Attr       LSize Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  lvol0 vg   -wi-a----- 4.00m

---

$ lvmconfig --type full report/compact_output report/compact_output_cols
compact_output=0
compact_output_cols="data_percent,metadata_percent,pool_lv,move_pv,origin"

$ lvs vg
  LV    VG   Attr       LSize Log Cpy%Sync Convert
  lvol0 vg   -wi-a----- 4.00m

---

$ lvmconfig --type full report/compact_output report/compact_output_cols
compact_output=1
compact_output_cols="data_percent,metadata_percent,pool_lv,move_pv,origin"

$ lvs vg
  LV    VG   Attr       LSize
  lvol0 vg   -wi-a----- 4.00m
2015-10-16 17:05:54 +02:00
Peter Rajnoha
508f0f5a21 libdm: add dm_report_compact_given_fields
dm_report_compact_given_fields is the same as dm_report_compact_fields,
but it processes only given fields, not all the fields in the report
like dm_report_compact_field does.
2015-10-16 17:05:54 +02:00
David Teigland
df34fcdafd lvmlockd: use flag to avoid blocking in sanlock_acquire
If a host failed while holding a sanlock lease,
sanlock_acquire will by default block and wait
for the lease to expire before returning.  We
want it to return with an error so we can retry
instead of blocking, which allows us to process
other lock operations.

(Enclose this in an ifdef until the new flag
appears in a sanlock release.)
2015-10-14 14:39:29 -05:00
Zdenek Kabelac
a6d1c8ac65 dmeventd: use matching function
Respect lvm2_log_fn prototype. The idea of 'reusing' print_log with
plain cast is causing very strange crashes with some older 'gcc'  compilers.
So just do it cleanly...
2015-10-14 14:25:27 +02:00
Zdenek Kabelac
7c36d7c90c thin: enforce local activation when creation new thin
As we need to check how full thin-pool is - require thin-pool is
locally active.
2015-10-14 01:00:35 +02:00
Zdenek Kabelac
bbef4edd06 makefiles: switch to rpath-link
Plain rpath is to invasive and gets into binary.
We only want to provide hint for linker.
2015-10-14 00:51:55 +02:00
Zdenek Kabelac
3f1a3b7090 dmeventd: fix missing '!'
During recent code changes '!' was badly converted.
2015-10-13 22:10:47 +02:00
Zdenek Kabelac
a91fbe9d27 makefiles: older gcc needs hint with rpath
gcc 4.3 seems not to be able to find linked library without
specifying -rpath to linker  (plain -L) is not enough.
2015-10-13 22:02:17 +02:00
Zdenek Kabelac
ccc39be053 dmeventd: compilable without DEBUG CFLAG
Missed compilability without DEBUG.
2015-10-13 20:59:35 +02:00
Alasdair G Kergon
0cf787a377 Revert "log: no file for external logging"
This reverts commit 1b1c01a27b.

This caused messages to get dropped instead of logged into the log file.

(The log file and log function are independent at the moment.)
2015-10-13 15:31:57 +01:00
Zdenek Kabelac
acc70de439 tests: more extend testing 2015-10-13 16:02:21 +02:00
Zdenek Kabelac
cf1c2da836 tests: wait for initial sync
Raid should be in-sync ATM for any gaming.
2015-10-13 16:02:21 +02:00
Zdenek Kabelac
c4cc5eabfe tests: start logging dmeventd output
Log dmeventd output from test - keep output logging in test
and avoid sending messages to syslog.
2015-10-13 16:02:21 +02:00
Zdenek Kabelac
8cc21354c2 tests: better regex check
Enhance check for matching prefix.
2015-10-13 16:02:20 +02:00
Zdenek Kabelac
2cb1f6eafe tests: show status in in_sync
Make visible actual status line when returing 'raid' is in sync.
Useful to prove when kernel is wrong.
2015-10-13 16:02:20 +02:00
Zdenek Kabelac
9322918406 makefiles: src dirs have depth 5
For tags generation scan depth 5.
2015-10-13 16:02:20 +02:00
Zdenek Kabelac
83f00e9156 makefiles: drop explicit linking
Nothing in /sscripts needs devmapper-event library so drop its linking.
2015-10-13 16:02:20 +02:00
Zdenek Kabelac
4f9e7f692e makefiles: generate Local
Use same  exported symbols list for other generated symfile
as it appeared to be the right way for libdm.

Local {
	local:
		*;
};
2015-10-13 16:02:20 +02:00
Zdenek Kabelac
4b586ad3c2 dmeventd: rework raid plugin
Switch to per-thread mem-pool and lock only for lvm2 calls.
Use libdm parser for raid status line.
2015-10-13 16:02:19 +02:00
Zdenek Kabelac
256e432e78 dmeventd: less locking mirror
Rework mirror plugin to use per-thread mem-pool.
This allows to use locking only for lvm2 library calls.
2015-10-13 16:02:18 +02:00
Zdenek Kabelac
51ff7d5ed8 dmeventd: less locking for snapshot and thin
Use lvm lock for lvm library calls.

dm functions in-use are 'thread-safe' since we use
local per-thread mem pool.
2015-10-13 16:01:41 +02:00
Zdenek Kabelac
49e11102c7 dmeventd: add local mempool for raid and mirror
Using local mempools allows to drop locks when such memory is needed.
2015-10-13 15:56:23 +02:00
Zdenek Kabelac
a11cd2ca2d dmeventd: use new macros to init mempool
For thin and snapshot use new macros
to simplify mempool init and destroy
2015-10-13 15:56:03 +02:00
Zdenek Kabelac
f9926e7e6c dmeventd: introduce macro for init
Simplify commonly used pool creation.
2015-10-13 15:56:03 +02:00
Zdenek Kabelac
76ea01dd20 dmeventd: new initialization of plugin threads
Rework thread creation code to better use resources.

New code will not leak 'timeout' registered thread on error path.

Also if the thread already exist - avoid creation of thread
object and it's later destruction.

If the race is noticed during adding new monitoring thread,
such thread is put on cleanup list and -EEXIST is reported.
2015-10-13 15:55:05 +02:00
Zdenek Kabelac
362558cd66 cleanup: typo in comment 2015-10-13 15:22:58 +02:00
Zdenek Kabelac
09a8479cb7 cleanup: move system defines before structs 2015-10-13 15:22:58 +02:00
Zdenek Kabelac
0a633750f1 cleanup: avoid using private
Switch private to user.
2015-10-13 15:22:58 +02:00
Zdenek Kabelac
0e2261dbd1 cleanup: remove multilog 2015-10-13 15:22:57 +02:00
Zdenek Kabelac
842a7a17e3 cleanup: always set nsec 2015-10-13 15:22:57 +02:00
Zdenek Kabelac
f4fb97c850 cleanup: more readable code 2015-10-13 15:22:57 +02:00
Zdenek Kabelac
8b9533f38f dmeventd: support logging on stdout
Add new supported option '-l' log to stdout/stderr.

It has to be paired with '-f' (foreground run).
2015-10-13 15:22:57 +02:00
Zdenek Kabelac
903e9af1b2 cleanup: static with _
Document ? is printing to stderr.
2015-10-13 15:16:56 +02:00
Zdenek Kabelac
e261af52eb dmeventd: handle snapshot overflow
When snapshot reports overflow, handle it in the same way as Invalid.
Until better ideas are implemented.
2015-10-13 15:15:44 +02:00
Zdenek Kabelac
3f03d46fc1 man: dmeventd update 2015-10-13 15:15:43 +02:00
Zdenek Kabelac
0e27210308 dmeventd: add more debug messages 2015-10-13 15:15:43 +02:00
Zdenek Kabelac
13086c2523 dmeventd: drop changing logging
As we now use 'unified' logging macro system - we no longer need
to protect from change of logging function pointer - it's set
once at the start of dmeventd and not change anymore
(as lvm2 library no longer interferers here).
2015-10-13 15:15:43 +02:00
Zdenek Kabelac
42a9c8b4a6 dmeventd: enable new logging 2015-10-13 15:13:28 +02:00
Zdenek Kabelac
e50583d721 dmeventd: enable new logging 2015-10-13 15:09:35 +02:00
Zdenek Kabelac
c90363b585 dmeventd: use log_ macros in plugins
Convert from syslog to standard log_() macros in plugins.
2015-10-13 15:09:03 +02:00
Zdenek Kabelac
915f0faac1 dmeventd: syslog -> log_xxxxx
Convert logging of dmeventd to libdm logging macros.
2015-10-13 14:43:30 +02:00
Zdenek Kabelac
0641e3a5fd libdmevent: add dm_event_log
Add dm_event_log() logging function.
Controled by dm_event_log_set().
2015-10-13 14:40:46 +02:00
Zdenek Kabelac
11a084cf42 dmeventd: log all commands with CMD: prefix
For easier grep of all processed command - add CMD: prefix to them.

Use  >>>  for entring command processing
and  <<<  when command is processed.
2015-10-13 14:40:46 +02:00
Zdenek Kabelac
d60794c3a3 dmeventd: fix loging report
msg.cmd holds return value from processing after _do_process_request,
so save it before call.
2015-10-13 14:40:46 +02:00
Zdenek Kabelac
1b1c01a27b log: no file for external logging
When external logging is set do not bother creating log file,
as it's not going to be used.
2015-10-13 14:40:44 +02:00
Zdenek Kabelac
72d700b064 toolcontext: do not change already set dm_log
If the dm_log is already set to non-default logger,
avoid to change it.
2015-10-13 14:39:37 +02:00
Zdenek Kabelac
86b04ebd19 thin: enhance logging
Add debug message with more details about threshold overflow.
2015-10-13 14:38:52 +02:00
Zdenek Kabelac
7e1c08bb6a dmeventd: correct ret code for fail
As  _do_register_device() calls  register_device() function that returns
1 success & 0 fail -  ret = -ENOMEM for fail case instead of 0.
2015-10-13 14:38:49 +02:00
Zdenek Kabelac
c7b4359ff4 thin: check for overflown pool earlier
Check for pool early before we actually start to modify metadata.
This requires locally active thin-pool.
2015-10-13 14:37:07 +02:00
Zdenek Kabelac
5695c6aca6 libdm: enforce writethrough mode for cleaner
With "cleaner" policy always use 'writethrough' mode.
2015-10-13 14:35:48 +02:00
Peter Rajnoha
5ac81657e5 wiping: make libblkid detect all copies of the same signature if use_blkid_wiping=1
Some signatures are spread around the disk in several copies, mainly for
backup. Make libblkid to detect these extra copies - there was missing
"blkid_probe_step_back" fn call after successful wipe of previous signature
copy.

An example with FAT table which has copies:

$ mkfs.vfat /dev/sda1

Before this patch:

$ pvcreate /dev/sda1
WARNING: vfat signature detected on /dev/sda1 at offset 54. Wipe it? [y/n]: y
  Wiping vfat signature on /dev/sda1.
  Physical volume "/dev/sda1" successfully created

With this patch applied:

$ pvcreate /dev/sda1
WARNING: vfat signature detected on /dev/sda1 at offset 54. Wipe it? [y/n]: y
  Wiping vfat signature on /dev/sda1.
WARNING: vfat signature detected on /dev/sda1 at offset 0. Wipe it? [y/n]: y
  Wiping vfat signature on /dev/sda1.
WARNING: vfat signature detected on /dev/sda1 at offset 510. Wipe it? [y/n]: y
  Wiping vfat signature on /dev/sda1.
  Physical volume "/dev/sda1" successfully created
2015-10-13 12:22:09 +02:00
Peter Rajnoha
5bd63df237 tests: test vgimportclone and -n option 2015-10-12 12:55:39 +02:00
Peter Rajnoha
75420282e1 vgimportclone: make sure there's no prefix in VG name list
Make sure log/prefix is set to "" when getting the list of VG names.
We need this for the format to be correct so it's properly searched
through later on.
2015-10-12 12:54:59 +02:00
Peter Rajnoha
38df48d108 vgimportclone: fix vgimportclone with -n to not add number unnecessarily to base VG name
$ vgcreate vgA /dev/sda
  Volume group "vgA" successfully created

$ dd if=/dev/sda of=/dev/sdb bs=1M
$ dd if=/dev/sda of=/dev/sdc bs=1M

(the new VG name is prefix of existing VG name)
$ vgimportclone -n vg /dev/sdb

(the new VG name is suffix of existing VG name)
$ vgimportclone -n gA /dev/sdc

Before this patch:
------------------
(we end up with "vg1" and "gA1" names with the "1" suffix which is not needed)
$ vgs -o vg_name
  VG
  gA1
  vg1
  vgA

With this patch applied:
------------------------
(we end up with "vg" and "gA" names as they're unique already and no extra suffix is added)
$ # vgs -o vg_name
  VG
  gA
  vg
  vgA

Of course, if the name supplied is not unique, the number is added correctly:
$ dd if=/dev/sda of=/dev/sdb bs=1M
$ vgimportclone -n vgA /dev/sdb
$ vgs -o vg_name
  VG
  vgA
  vgA1
2015-10-12 11:11:34 +02:00
David Teigland
21a8ac0cd3 Fix segfault when lvmlockd is running but not lvmetad
If lvmlockd is running, lvmetad is configured (use_lvmetad=1),
but lvmetad is not running, then commands will seg fault
when trying to send a message to lvmetad.

The difference is lvmetad being "active", not just "used".
2015-10-09 12:20:22 -05:00
Peter Rajnoha
1f30ba6178 vgimportclone: cleanup the script and remove dependency on awk, grep, cut and tr
We can replace the expressions with awk/grep/cut/tr with --select now and
more suitable reporting options and modes. Also, we don't need to check
the temporary lvm.conf generated within vgimportclone script since we're
generating it ourselves now using lvmconfig, not using sed anymore like
it was before (so we can be pretty sure it's correct - we use lvmconfig
now even for generating the lvm.conf itself).
2015-10-09 16:31:02 +02:00
Peter Rajnoha
8733a8d890 report: add vg_missing_pv_count field
We already have pv_count to report number of PVs that a VG has based
on metadata.

This patch exposes the information about how many of these PVs are
missing which is also useful information for a VG. Wwe could count
the sum of pv_missing reporting fields for each PV in the VG before,
but the new field is practical when reporting VG as a whole and there's
no need to process each PV from VG alone.
2015-10-09 16:28:58 +02:00
David Teigland
5446d17756 man lvmsystemid: fix typos 2015-10-08 13:26:09 -05:00
David Teigland
c9ff5c8223 man lvmsystemd: fix typo 2015-10-08 13:14:28 -05:00
David Teigland
d99dd4086d vgcreate: improve error message for multiple lock managers
If 'vgcreate --shared' finds both sanlock and dlm are running,
print a more accurate error message:
"Found multiple lock managers, select one with --lock-type."

When neither is running, we still print:
"Failed to detect a running lock manager to select lock type."
2015-10-08 10:41:13 -05:00
David Teigland
09981afc1c vgcreate: allow both --shared and --lock-type options
Using --lock-type sanlock|dlm implies --shared.

Using --shared selects lock type sanlock|dlm
(by choosing the one that's running.)

Using both --shared and --lock-type sanlock|dlm should
also be allowed (--shared is just redundant information.)
2015-10-08 10:14:33 -05:00
Peter Rajnoha
3d03e504cd metadata: format_text: provide more detailed error message when metadata too large for PV mda
Also, leave out the note about "circular buffer" which is
an internal imeplementation detail anyway and not quite
informational for users:

Before this patch:
$ vgcreate vg1 /dev/sda
  VG vg1 metadata too large for circular buffer
  Failed to write VG vg1.

With this patch applied:
$ vgcreate vg1 /dev/sda
  VG vg1 metadata too large: size of metadata to write is 691 bytes while PV metadata area size on /dev/sda is 512 bytes.
  Failed to write VG vg1.
2015-10-08 16:27:03 +02:00
Peter Rajnoha
e04424e87e report: identify LV hodling sanlock locks as 'private,lockd,sanlock' within lv_role report field
Before this patch:
$ lvs -a -o name,layout,role test/lvmlock
  LV        Layout     Role
  [lvmlock] linear     public

With this patch applied:
$ lvs -a -o name,layout,role test/lvmlock
  LV        Layout     Role
  [lvmlock] linear     private,lockd,sanlock
2015-10-08 13:44:29 +02:00
Zdenek Kabelac
277dd0aa7a tests: check devices with prefix aren't in use
Avoid running tests, when prefix already exist in the system.
As prefix just uses  PID number, we may hit a case for long
running tests, where devices from some previous runs were not
properly cleared away - detect this and fail early.
(Such machine should be inspected and fixed).
2015-10-06 15:23:55 +02:00
Zdenek Kabelac
ded9452174 man: lvcreate continue
Finish remaing bits of updating pages for better rendering
with -Thtml, -Tps.
2015-10-06 15:23:55 +02:00
Zdenek Kabelac
4b1cadbd87 man: fsadm 2015-10-06 15:21:36 +02:00
Zdenek Kabelac
2506275c3b cleanup: fix compiler warning 2015-10-06 14:57:30 +02:00
Peter Rajnoha
5f7a94a03e blkdeactivate: recognize and deactivate MD devices too 2015-10-06 13:25:41 +02:00
David Teigland
df59db6048 lockd: add error message for EEXIST
The EEXIST error for LV locks is unusual, and
was missing an explanatory error message.
2015-10-02 15:41:23 -05:00
Heinz Mauelshagen
b33d7586e7 raid_manip: fix wrong image size allocation on raid10 "lvconvert --replace ..." 2015-10-02 17:09:37 +02:00
Alasdair G Kergon
fb957ef322 raid: Add metadata dev information to reports.
Add metadata_devices and seg_metadata_le_ranges report fields.
Currently only defined for raid, but should probably be extended
to all other segment types that don't report all their device
usage in the 'devices' field.
2015-10-02 10:09:28 +01:00
David Teigland
5e5d48348b man lvmcache: updates for mode and policy
Correct some things, e.g. set mode and policy on
the cache lv, not the pool, lvm.conf field for
mode changed.

Add smq which was missing.

Make the sections on cache mode and cache policy
consistent in structure and style.
2015-10-01 14:23:39 -05:00
David Teigland
26da6a3e10 config: improve cache_settings description 2015-10-01 14:23:39 -05:00
Zdenek Kabelac
4c2cc782aa tests: ensure test will not block
This test is somewhat 'stupid' and simulates mostly unsupported
situation - so avoid blocking here.
2015-10-01 16:45:14 +02:00
Zdenek Kabelac
05e7fdd5ce tests: use proper target name for check 2015-10-01 16:05:51 +02:00
Zdenek Kabelac
796e3fb7e4 man: update lvm pages 2015-10-01 15:03:34 +02:00
Zdenek Kabelac
867a36b419 man: update dmsetup and dmstats pages
Try to provide properly rendered pages no just with
plain 'man' but also for:

man -Tps
man -Thtml
man2html
2015-10-01 15:03:12 +02:00
Zdenek Kabelac
a139275eca alloc: fix update or area_len
Commit: 192d9ad977
changed logic for area_len formula - so it returns
different values.

Placing () to restore previous behaviour and make it
explicit.
2015-10-01 15:02:49 +02:00
Marian Csontos
efcb3bbc8d test: Fix timeout handling
Timeouts were considered as warnings only. Signalling failure is
preferred.
2015-10-01 13:19:29 +02:00
David Teigland
309979d578 lockd: add VG name to debug logging
Add the VG name to the new debug logging in
the previous commit.
2015-09-29 14:07:08 -05:00
David Teigland
c805fa7c40 lockd: add debug logging for metadata error
When lvmetad_pvscan_vg() reads VG metadata from each PV,
it compares it to the last one to verify it matches.
If the VG metadata does not match on the PVs, an error
is printed and it fails to read the VG.  In this error
case, use log_debug to show the differences between
the two unmatching copies of the metadata.
2015-09-29 13:51:24 -05:00
David Teigland
634bf8c953 lockd: fix rescanning VG metadata
One host changes a VG, making the cached VG on another
host invalid.  The other host then rereads the VG from
disk to get the latest copy.  If the first host removed
a PV from the VG, the second host attempts to reread the
VG from old PV when rescanning.  Reading the VG from the
removed PV fails, causing vg_read to return "VG not found".
The fix is to simply not fail when a VG is not found while
rereading a PV and continue without it.

(This doesn't happen if the second host happens to first
run a command like 'vgs' that triggers a global revalidation
of metadata.)
2015-09-29 11:28:48 -05:00
Heinz Mauelshagen
be393f6722 raid: Introduce DEFAULT_RAID_MAX_IMAGES
Prepare to allow for the number of images in a raid set to be
larger than the limit for old-style dm raid1.
2015-09-28 21:38:40 +01:00
Alasdair G Kergon
d94ff20927 raid: Fail if kernel status denominator is zero. 2015-09-28 20:45:44 +01:00
Alasdair G Kergon
0173c260d8 libdm: Move status fns from deptree to targets.
libdm-deptree is only for functions working with dm tree nodes.
2015-09-28 20:28:31 +01:00
Heinz Mauelshagen
9d815e5f5a raid: Use loop for text uint32_t parameter import.
Plus some other tidying up of the same file.
2015-09-28 14:28:03 +01:00
Alasdair G Kergon
7097663ddd test: Cope with stripe rounding message change. 2015-09-28 12:25:31 +01:00
Heinz Mauelshagen
eab099b221 segtypes: Use flags in raid segtype macros. 2015-09-24 20:43:18 +01:00
Heinz Mauelshagen
3036620b48 raid: Add a segtype flag for each raid type. 2015-09-24 20:17:57 +01:00
David Teigland
d40830a2b1 lockd: fix changing lock type on VG with pool
vgchange --lock-type iterates through LVs to ensure
no LVs are active before changing the lock type of
the VG, but the loop was not checking that an LV
actually has a lock before trying it, so it would
fail if the VG had any LVs that don't use locks,
e.g it would fail on a tmeta LV from a pool.
2015-09-24 14:03:20 -05:00
Heinz Mauelshagen
028715b0f0 raid: Detect whether or not kernel supports raid0. 2015-09-24 19:59:29 +01:00
Alasdair G Kergon
4a74e19f80 alloc: Move _calc_area_multiple. 2015-09-24 17:56:19 +01:00
Alasdair G Kergon
e773e71910 stripes: Introduce _round_to_stripe_boundary. 2015-09-24 17:50:53 +01:00
Alasdair G Kergon
39a97d86f0 segtypes: Add and use new segtype macros.
Includes fixing an inverted raid10 segtype check in _raid_add_target_line.
2015-09-24 14:59:07 +01:00
Alasdair G Kergon
41fe225b0d style: lv_manip.c changes 2015-09-24 13:43:58 +01:00
Heinz Mauelshagen
1945a0f504 libdm: fix bogus macro causing false parameter count 2015-09-24 14:22:52 +02:00
Heinz Mauelshagen
4e60e62444 raid: Fix raid target write_behind parameter.
Now uses correct "max_write_behind" instead of "writebehind".
(Includes some tidying up.)
2015-09-23 15:53:27 +01:00
Heinz Mauelshagen
96a6210198 libdm: Improve raid segment parameter handling. 2015-09-23 15:25:46 +01:00
Heinz Mauelshagen
192d9ad977 style: Miscellaneous tidying up of metadata/lv* 2015-09-23 14:37:52 +01:00
Peter Rajnoha
cb82919b0d systemd: use {local,remote}-fs-pre.target instead of {local,remote}-fs.target
We want most of our units to be started before any local/remote mount
points are mounted - we used {local,remote}-fs.target for this purpose
before, but it was not 100% correct as there's even {local,remote}-fs-pre.target
special systemd unit reserved for this exact purpose.

See also man 7 systemd.special and "local-fs-pre.target"/"remote-fs-pre.target"
description.
2015-09-23 13:30:51 +02:00
Alasdair G Kergon
28aff5d240 segtypes: Make constants ULL. 2015-09-22 21:10:46 +01:00
David Teigland
532b2d2d4e man lvmthin: use --poolmetadatasize option
when extending a pool metadata lv, rather than
referencing the _tmeta device.
2015-09-22 13:44:09 -05:00
Alasdair G Kergon
214e2cddf6 segtypes: Use SEG_TYPE_NAME_ string constants. 2015-09-22 19:04:12 +01:00
Heinz Mauelshagen
0ce150280e segtypes: Extend flags to 64 bits. 2015-09-22 18:03:33 +01:00
Alasdair G Kergon
3a8a37187d post-release 2015-09-22 16:06:07 +01:00
333 changed files with 6655 additions and 4189 deletions

View File

@@ -234,7 +234,7 @@ ifneq ($(shell which ctags),)
.PHONY: tags
tags:
test -z "$(shell find $(top_srcdir) -type f -name '*.[ch]' -newer tags 2>/dev/null | head -1)" || $(RM) tags
test -f tags || find $(top_srcdir) -maxdepth 4 -type f -name '*.[ch]' -exec ctags -a '{}' +
test -f tags || find $(top_srcdir) -maxdepth 5 -type f -name '*.[ch]' -exec ctags -a '{}' +
CLEAN_TARGETS += tags
endif

View File

@@ -1 +1 @@
2.02.132(2)-git (2015-09-22)
2.02.134(2)-git (2015-10-30)

View File

@@ -1 +1 @@
1.02.109-git (2015-09-22)
1.02.111-git (2015-10-30)

View File

@@ -1,3 +1,38 @@
Version 2.02.134 -
====================================
Version 2.02.133 - 30th October 2015
====================================
Support repeated -o|--options for reporting commands.
Support -o- and -o# for reporting commands to remove and compact fields.
Fix missing PVs from pvs output if vgremove is run concurrently.
Remove unwanted error message when running pvs/vgs/lvs and vgremove at once.
Check newly created VG's metadata do not overlap in metadata ring buffer.
Check metadata area size is at least the minimum size defined for the format.
Thin pool targets uses low_water_mark from profile.
Dropping 'yet' from error of unsupported thick snapshot of snapshots.
Do not support unpartitioned DASD devices with CDL formatted with pvcreate.
For thins use flush for suspend only when volume size is reduced.
Enable code which detects the need of flush during suspend.
Ensure --use-policy will resize volume to fit below threshold.
Correct percentage evaluation when checking thin-pool over threshold.
Fix lvmcache to move PV from VG to orphans if VG is removed and lvmetad used.
Fix lvmcache to not cache even invalid info about PV which got removed.
Support checking of memlock daemon counter.
Allow all log levels to be used with the lvmetad -l option.
Add optional shutdown when idle support for lvmetad.
Fix missing in-sync progress info while lvconvert used with lvmpolld.
Add report/compact_output_cols to lvm.conf to define report cols to compact.
Do not change logging in lvm2 library when it's already set.
Check for enough space in thin-pool in command before creating new thin.
Make libblkid detect all copies of the same signature if use_blkid_wiping=1.
Fix vgimportclone with -n to not add number unnecessarily to base VG name.
Cleanup vgimportclone script and remove dependency on awk, grep, cut and tr.
Add vg_missing_pv_count report field to report number of missing PVs in a VG.
Properly identify internal LV holding sanlock locks within lv_role field.
Add metadata_devices and seg_metadata_le_ranges report fields for raid vols.
Fix lvm2-{activation,clvmd,cmirrord,monitor} service to exec before mounting.
Version 2.02.132 - 22nd September 2015
======================================
Fix lvmconf to set locking_type=2 if external locking library is requested.

View File

@@ -1,3 +1,34 @@
Version 1.02.111 -
====================================
Version 1.02.110 - 30th October 2015
====================================
Disable thin monitoring plugin when it fails too often (>10 times).
Fix/restore parsing of empty field '-' when processing dmeventd event.
Enhance dm_tree_node_size_changed() to recognize size reduction.
Support exit on idle for dmenventd (1 hour).
Add support to allow unmonitor device from plugin itself.
New design for thread co-operation in dmeventd.
Dmeventd read device status with 'noflush'.
Dmeventd closes control device when no device is monitored.
Thin plugin for dmeventd improved percentage usage.
Snapshot plugin for dmeventd improved percentage usage.
Add dm_hold_control_dev to allow holding of control device open.
Add dm_report_compact_given_fields to remove given empty fields from report.
Use libdm status parsing and local mem raid dmeventd plugin.
Use local mem pool and lock only lvm2 execution for mirror dmeventd plugin.
Lock protect only lvm2 execution for snapshot and thin dmeventd plugin.
Use local mempool for raid and mirror plugins.
Reworked thread initialization for dmeventd plugins.
Dmeventd handles snapshot overflow for now equally as invalid.
Convert dmeventd to use common logging macro system from libdm.
Return -ENOMEM when device registration fails instead of 0 (=success).
Enforce writethrough mode for cleaner policy.
Add support for recognition and deactivation of MD devices to blkdeactivate.
Move target status functions out of libdm-deptree.
Correct use of max_write_behind parameter when generating raid target line.
Fix dm-event systemd service to make sure it is executed before mounting.
Version 1.02.109 - 22nd September 2016
======================================
Update man pages for dmsetup and dmstats.

2
aclocal.m4 vendored
View File

@@ -15,7 +15,7 @@ m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun
# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
# serial 1 (pkg-config-0.24)
#
# Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
# Copyright (c) 2004 Scott James Remnant <scott@netsplit.com>.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by

View File

@@ -389,8 +389,8 @@ allocation {
# This configuration option does not have a default value defined.
# Configuration section allocation/cache_settings.
# Individual settings for policies.
# See the help for individual policies for more info.
# Settings for the cache policy.
# See documentation for individual cache policies for more info.
# This configuration section has an automatic default value.
# cache_settings {
# }
@@ -1494,13 +1494,25 @@ activation {
# report {
# Configuration option report/compact_output.
# Do not print empty report fields.
# Fields that don't have a value set for any of the rows reported are
# skipped and not printed. Compact output is applicable only if
# report/buffered is enabled.
# Do not print empty values for all report fields.
# If enabled, all fields that don't have a value set for any of the
# rows reported are skipped and not printed. Compact output is
# applicable only if report/buffered is enabled. If you need to
# compact only specified fields, use compact_output=0 and define
# report/compact_output_cols configuration setting instead.
# This configuration option has an automatic default value.
# compact_output = 0
# Configuration option report/compact_output_cols.
# Do not print empty values for specified report fields.
# If defined, specified fields that don't have a value set for any
# of the rows reported are skipped and not printed. Compact output
# is applicable only if report/buffered is enabled. If you need to
# compact all fields, use compact_output=1 instead in which case
# the compact_output_cols setting is then ignored.
# This configuration option has an automatic default value.
# compact_output_cols = ""
# Configuration option report/aligned.
# Align columns in report output.
# This configuration option has an automatic default value.

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2005-2007 Red Hat, Inc. All rights reserved.
* Copyright (C) 2005-2015 Red Hat, Inc. All rights reserved.
*
* This file is part of the device-mapper userspace tools.
*
@@ -12,9 +12,9 @@
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "dm-logging.h"
#include "dmlib.h"
#include "libdevmapper-event.h"
//#include "libmultilog.h"
#include "dmeventd.h"
#include <fcntl.h>
@@ -23,7 +23,11 @@
#include <sys/stat.h>
#include <sys/wait.h>
#include <arpa/inet.h> /* for htonl, ntohl */
#include <pthread.h>
#include <syslog.h>
static int _debug_level = 0;
static int _use_syslog = 0;
static int _sequence_nr = 0;
struct dm_event_handler {
@@ -194,7 +198,7 @@ static int _check_message_id(struct dm_event_daemon_message *msg)
if ((sscanf(msg->data, "%d:%d", &pid, &seq_nr) != 2) ||
(pid != getpid()) || (seq_nr != _sequence_nr)) {
log_error("Ignoring out-of-sequence reply from dmeventd. "
"Expected %d:%d but received %s", getpid(),
"Expected %d:%d but received %s.", getpid(),
_sequence_nr, msg->data);
return 0;
}
@@ -229,7 +233,7 @@ static int _daemon_read(struct dm_event_fifos *fifos,
FD_SET(fifos->server, &fds);
ret = select(fifos->server + 1, &fds, NULL, NULL, &tval);
if (ret < 0 && errno != EINTR) {
log_error("Unable to read from event server");
log_error("Unable to read from event server.");
return 0;
}
if ((ret == 0) && (i > 4) && !bytes) {
@@ -295,7 +299,7 @@ static int _daemon_write(struct dm_event_fifos *fifos,
if (ret < 0) {
if (errno == EINTR)
continue;
log_error("Unable to talk to event daemon");
log_error("Unable to talk to event daemon.");
return 0;
}
if (ret == 0)
@@ -304,7 +308,7 @@ static int _daemon_write(struct dm_event_fifos *fifos,
if (ret < 0) {
if ((errno == EINTR) || (errno == EAGAIN))
continue;
log_error("Unable to talk to event daemon");
log_error("Unable to talk to event daemon.");
return 0;
}
}
@@ -316,7 +320,7 @@ static int _daemon_write(struct dm_event_fifos *fifos,
FD_SET(fifos->client, &fds);
ret = select(fifos->client + 1, NULL, &fds, NULL, NULL);
if ((ret < 0) && (errno != EINTR)) {
log_error("Unable to talk to event daemon");
log_error("Unable to talk to event daemon.");
return 0;
}
} while (ret < 1);
@@ -326,7 +330,7 @@ static int _daemon_write(struct dm_event_fifos *fifos,
if ((errno == EINTR) || (errno == EAGAIN))
continue;
else {
log_error("Unable to talk to event daemon");
log_error("Unable to talk to event daemon.");
return 0;
}
}
@@ -356,7 +360,7 @@ int daemon_talk(struct dm_event_fifos *fifos,
getpid(), _sequence_nr,
dso_name ? : "-", dev_name ? : "-", evmask, timeout)))
< 0) {
log_error("_daemon_talk: message allocation failed");
log_error("_daemon_talk: message allocation failed.");
return -ENOMEM;
}
msg->cmd = cmd;
@@ -444,11 +448,11 @@ static int _start_daemon(char *dmeventd_path, struct dm_event_fifos *fifos)
else if (!pid) {
execvp(args[0], args);
log_error("Unable to exec dmeventd: %s", strerror(errno));
log_error("Unable to exec dmeventd: %s.", strerror(errno));
_exit(EXIT_FAILURE);
} else {
if (waitpid(pid, &status, 0) < 0)
log_error("Unable to start dmeventd: %s",
log_error("Unable to start dmeventd: %s.",
strerror(errno));
else if (WEXITSTATUS(status))
log_error("Unable to start dmeventd.");
@@ -521,7 +525,7 @@ static struct dm_task *_get_device_info(const struct dm_event_handler *dmevh)
struct dm_info info;
if (!(dmt = dm_task_create(DM_DEVICE_INFO))) {
log_error("_get_device_info: dm_task creation for info failed");
log_error("_get_device_info: dm_task creation for info failed.");
return NULL;
}
@@ -539,17 +543,17 @@ static struct dm_task *_get_device_info(const struct dm_event_handler *dmevh)
/* FIXME Add name or uuid or devno to messages */
if (!dm_task_run(dmt)) {
log_error("_get_device_info: dm_task_run() failed");
log_error("_get_device_info: dm_task_run() failed.");
goto bad;
}
if (!dm_task_get_info(dmt, &info)) {
log_error("_get_device_info: failed to get info for device");
log_error("_get_device_info: failed to get info for device.");
goto bad;
}
if (!info.exists) {
log_error("_get_device_info: %s%s%s%.0d%s%.0d%s%s: device not found",
log_error("_get_device_info: %s%s%s%.0d%s%.0d%s%s: device not found.",
dmevh->uuid ? : "",
(!dmevh->uuid && dmevh->dev_name) ? dmevh->dev_name : "",
(!dmevh->uuid && !dmevh->dev_name && dmevh->major > 0) ? "(" : "",
@@ -618,12 +622,12 @@ int dm_event_register_handler(const struct dm_event_handler *dmevh)
!strstr(dmevh->dso, "libdevmapper-event-lvm2snapshot.so") &&
!strstr(dmevh->dso, "libdevmapper-event-lvm2mirror.so") &&
!strstr(dmevh->dso, "libdevmapper-event-lvm2raid.so"))
log_warn("WARNING: %s: dmeventd plugins are deprecated", dmevh->dso);
log_warn("WARNING: %s: dmeventd plugins are deprecated.", dmevh->dso);
if ((err = _do_event(DM_EVENT_CMD_REGISTER_FOR_EVENT, dmevh->dmeventd_path, &msg,
dmevh->dso, uuid, dmevh->mask, dmevh->timeout)) < 0) {
log_error("%s: event registration failed: %s",
log_error("%s: event registration failed: %s.",
dm_task_get_name(dmt),
msg.data ? msg.data : strerror(-err));
ret = 0;
@@ -650,7 +654,7 @@ int dm_event_unregister_handler(const struct dm_event_handler *dmevh)
if ((err = _do_event(DM_EVENT_CMD_UNREGISTER_FOR_EVENT, dmevh->dmeventd_path, &msg,
dmevh->dso, uuid, dmevh->mask, dmevh->timeout)) < 0) {
log_error("%s: event deregistration failed: %s",
log_error("%s: event deregistration failed: %s.",
dm_task_get_name(dmt),
msg.data ? msg.data : strerror(-err));
ret = 0;
@@ -823,6 +827,79 @@ int dm_event_get_version(struct dm_event_fifos *fifos, int *version) {
return 1;
}
void dm_event_log_set(int debug_level, int use_syslog)
{
_debug_level = debug_level;
_use_syslog = use_syslog;
}
void dm_event_log(const char *subsys, int level, const char *file,
int line, int dm_errno_or_class,
const char *format, va_list ap)
{
static pthread_mutex_t _log_mutex = PTHREAD_MUTEX_INITIALIZER;
static time_t start = 0;
const char *indent = "";
FILE *stream = stdout;
int prio = -1;
time_t now;
switch (level & ~(_LOG_STDERR | _LOG_ONCE)) {
case _LOG_DEBUG:
if (_debug_level < 3)
return;
prio = LOG_DEBUG;
indent = " ";
break;
case _LOG_INFO:
if (_debug_level < 2)
return;
prio = LOG_INFO;
indent = " ";
break;
case _LOG_NOTICE:
if (_debug_level < 1)
return;
prio = LOG_NOTICE;
indent = " ";
break;
case _LOG_WARN:
prio = LOG_WARNING;
break;
case _LOG_ERR:
prio = LOG_ERR;
stream = stderr;
break;
default:
prio = LOG_CRIT;
}
/* Serialize to keep lines readable */
pthread_mutex_lock(&_log_mutex);
if (_use_syslog) {
vsyslog(prio, format, ap);
} else {
now = time(NULL);
if (!start)
start = now;
now -= start;
fprintf(stream, "[%2d:%02d] %8x:%-6s%s",
(int)now / 60, (int)now % 60,
// TODO: Maybe use shorter ID
// ((int)(pthread_self()) >> 6) & 0xffff,
(int)pthread_self(), subsys,
(_debug_level > 3) ? "" : indent);
if (_debug_level > 3)
fprintf(stream, "%28s:%4d %s", file, line, indent);
vfprintf(stream, _(format), ap);
fputc('\n', stream);
fflush(stream);
}
pthread_mutex_unlock(&_log_mutex);
}
#if 0 /* left out for now */
static char *_skip_string(char *src, const int delimiter)
@@ -856,7 +933,7 @@ int dm_event_get_timeout(const char *device_path, uint32_t *timeout)
0, 0))) {
char *p = _skip_string(msg.data, ' ');
if (!p) {
log_error("malformed reply from dmeventd '%s'\n",
log_error("Malformed reply from dmeventd '%s'.",
msg.data);
dm_free(msg.data);
return -EIO;

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2005-2007 Red Hat, Inc. All rights reserved.
* Copyright (C) 2005-2015 Red Hat, Inc. All rights reserved.
*
* This file is part of the device-mapper userspace tools.
*
@@ -105,6 +105,25 @@ int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next);
int dm_event_register_handler(const struct dm_event_handler *dmevh);
int dm_event_unregister_handler(const struct dm_event_handler *dmevh);
/* Set debug level for logging, and whether to log on stdout/stderr or syslog */
void dm_event_log_set(int debug_level, int use_syslog);
/* Log messages acroding to current debug level */
__attribute__((format(printf, 6, 0)))
void dm_event_log(const char *subsys, int level, const char *file,
int line, int dm_errno_or_class,
const char *format, va_list ap);
/* Macro to route print_log do dm_event_log() */
#define DM_EVENT_LOG_FN(subsys) \
void print_log(int level, const char *file, int line, int dm_errno_or_class,\
const char *format, ...)\
{\
va_list ap;\
va_start(ap, format);\
dm_event_log(subsys, level, file, line, dm_errno_or_class, format, ap);\
va_end(ap);\
}
/* Prototypes for DSO interface, see dmeventd.c, struct dso_data for
detailed descriptions. */
// FIXME misuse of bitmask as enum

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2010 Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2015 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
@@ -13,15 +13,11 @@
*/
#include "lib.h"
#include "log.h"
#include "lvm2cmd.h"
#include "dmeventd_lvm.h"
#include "libdevmapper-event.h"
#include "lvm2cmd.h"
#include <pthread.h>
#include <syslog.h>
extern int dmeventd_debug;
/*
* register_device() is called first and performs initialisation.
@@ -36,48 +32,19 @@ static int _register_count = 0;
static struct dm_pool *_mem_pool = NULL;
static void *_lvm_handle = NULL;
DM_EVENT_LOG_FN("lvm")
static void _lvm2_print_log(int level, const char *file, int line,
int dm_errno_or_class, const char *msg)
{
print_log(level, file, line, dm_errno_or_class, "%s", msg);
}
/*
* Currently only one event can be processed at a time.
*/
static pthread_mutex_t _event_mutex = PTHREAD_MUTEX_INITIALIZER;
/*
* FIXME Do not pass things directly to syslog, rather use the existing logging
* facilities to sort logging ... however that mechanism needs to be somehow
* configurable and we don't have that option yet
*/
static void _temporary_log_fn(int level,
const char *file __attribute__((unused)),
int line __attribute__((unused)),
int dm_errno __attribute__((unused)),
const char *message)
{
level &= ~(_LOG_STDERR | _LOG_ONCE);
switch (level) {
case _LOG_DEBUG:
if (dmeventd_debug >= 3)
syslog(LOG_DEBUG, "%s", message);
break;
case _LOG_INFO:
if (dmeventd_debug >= 2)
syslog(LOG_INFO, "%s", message);
break;
case _LOG_NOTICE:
if (dmeventd_debug >= 1)
syslog(LOG_NOTICE, "%s", message);
break;
case _LOG_WARN:
syslog(LOG_WARNING, "%s", message);
break;
case _LOG_ERR:
syslog(LOG_ERR, "%s", message);
break;
default:
syslog(LOG_CRIT, "%s", message);
}
}
void dmeventd_lvm2_lock(void)
{
pthread_mutex_lock(&_event_mutex);
@@ -95,8 +62,8 @@ int dmeventd_lvm2_init(void)
pthread_mutex_lock(&_register_mutex);
if (!_lvm_handle) {
if (!getenv("LVM_LOG_FILE_EPOCH"))
lvm2_log_fn(_temporary_log_fn);
lvm2_log_fn(_lvm2_print_log);
if (!(_lvm_handle = lvm2_init()))
goto out;
@@ -113,6 +80,7 @@ int dmeventd_lvm2_init(void)
lvm2_disable_dmeventd_monitoring(_lvm_handle);
/* FIXME Temporary: move to dmeventd core */
lvm2_run(_lvm_handle, "_memlock_inc");
log_debug("lvm plugin initilized.");
}
_register_count++;
@@ -128,11 +96,13 @@ void dmeventd_lvm2_exit(void)
pthread_mutex_lock(&_register_mutex);
if (!--_register_count) {
log_debug("lvm plugin shuting down.");
lvm2_run(_lvm_handle, "_memlock_dec");
dm_pool_destroy(_mem_pool);
_mem_pool = NULL;
lvm2_exit(_lvm_handle);
_lvm_handle = NULL;
log_debug("lvm plugin exited.");
}
pthread_mutex_unlock(&_register_mutex);
@@ -155,8 +125,8 @@ int dmeventd_lvm2_command(struct dm_pool *mem, char *buffer, size_t size,
int r;
if (!dm_split_lvm_name(mem, device, &vg, &lv, &layer)) {
syslog(LOG_ERR, "Unable to determine VG name from %s.\n",
device);
log_error("Unable to determine VG name from %s.",
device);
return 0;
}
@@ -170,7 +140,7 @@ int dmeventd_lvm2_command(struct dm_pool *mem, char *buffer, size_t size,
dm_pool_free(mem, vg);
if (r < 0) {
syslog(LOG_ERR, "Unable to form LVM command. (too long).\n");
log_error("Unable to form LVM command. (too long).");
return 0;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2010 Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2015 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
@@ -39,4 +39,36 @@ struct dm_pool *dmeventd_lvm2_pool(void);
int dmeventd_lvm2_command(struct dm_pool *mem, char *buffer, size_t size,
const char *cmd, const char *device);
#define dmeventd_lvm2_run_with_lock(cmdline) \
({\
int rc;\
dmeventd_lvm2_lock();\
rc = dmeventd_lvm2_run(cmdline);\
dmeventd_lvm2_unlock();\
rc;\
})
#define dmeventd_lvm2_init_with_pool(name, st) \
({\
struct dm_pool *mem;\
st = NULL;\
if (dmeventd_lvm2_init()) {\
if ((mem = dm_pool_create(name, 2048)) &&\
(st = dm_pool_zalloc(mem, sizeof(*st))))\
st->mem = mem;\
else {\
if (mem)\
dm_pool_destroy(mem);\
dmeventd_lvm2_exit();\
}\
}\
st;\
})
#define dmeventd_lvm2_exit_with_pool(pool) \
do {\
dm_pool_destroy(pool->mem);\
dmeventd_lvm2_exit();\
} while(0)
#endif /* _DMEVENTD_LVMWRAP_H */

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2005-2012 Red Hat, Inc. All rights reserved.
* Copyright (C) 2005-2015 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
@@ -13,20 +13,24 @@
*/
#include "lib.h"
#include "libdevmapper-event.h"
#include "dmeventd_lvm.h"
#include "defaults.h"
#include <syslog.h> /* FIXME Replace syslog with multilog */
/* FIXME Missing openlog? */
/* FIXME Replace most syslogs with log_error() style messages and add complete context. */
/* FIXME Reformat to 80 char lines. */
#define ME_IGNORE 0
#define ME_INSYNC 1
#define ME_FAILURE 2
struct dso_state {
struct dm_pool *mem;
char cmd_lvscan[512];
char cmd_lvconvert[512];
};
DM_EVENT_LOG_FN("mirr")
static int _process_status_code(const char status_code, const char *dev_name,
const char *dev_type, int r)
{
@@ -39,18 +43,15 @@ static int _process_status_code(const char status_code, const char *dev_name,
* U => Unclassified failure (bug)
*/
if (status_code == 'F') {
syslog(LOG_ERR, "%s device %s flush failed.",
dev_type, dev_name);
log_error("%s device %s flush failed.", dev_type, dev_name);
r = ME_FAILURE;
} else if (status_code == 'S')
syslog(LOG_ERR, "%s device %s sync failed.",
dev_type, dev_name);
log_error("%s device %s sync failed.", dev_type, dev_name);
else if (status_code == 'R')
syslog(LOG_ERR, "%s device %s read failed.",
dev_type, dev_name);
log_error("%s device %s read failed.", dev_type, dev_name);
else if (status_code != 'A') {
syslog(LOG_ERR, "%s device %s has failed (%c).",
dev_type, dev_name, status_code);
log_error("%s device %s has failed (%c).",
dev_type, dev_name, status_code);
r = ME_FAILURE;
}
@@ -125,62 +126,49 @@ out:
out_parse:
dm_free(args);
syslog(LOG_ERR, "Unable to parse mirror status string.");
log_error("Unable to parse mirror status string.");
return ME_IGNORE;
}
static int _remove_failed_devices(const char *device)
static int _remove_failed_devices(const char *cmd_lvscan, const char *cmd_lvconvert)
{
int r;
#define CMD_SIZE 256 /* FIXME Use system restriction */
char cmd_str[CMD_SIZE];
if (!dmeventd_lvm2_command(dmeventd_lvm2_pool(), cmd_str, sizeof(cmd_str),
"lvscan --cache", device))
return -1;
r = dmeventd_lvm2_run(cmd_str);
if (!r)
syslog(LOG_INFO, "Re-scan of mirror device %s failed.", device);
if (!dmeventd_lvm2_command(dmeventd_lvm2_pool(), cmd_str, sizeof(cmd_str),
"lvconvert --config devices{ignore_suspended_devices=1} "
"--repair --use-policies", device))
return -ENAMETOOLONG; /* FIXME Replace with generic error return - reason for failure has already got logged */
if (!dmeventd_lvm2_run_with_lock(cmd_lvscan))
log_info("Re-scan of mirrored device failed.");
/* if repair goes OK, report success even if lvscan has failed */
r = dmeventd_lvm2_run(cmd_str);
r = dmeventd_lvm2_run_with_lock(cmd_lvconvert);
syslog(LOG_INFO, "Repair of mirrored device %s %s.", device,
(r) ? "finished successfully" : "failed");
log_info("Repair of mirrored device %s.",
(r) ? "finished successfully" : "failed");
return (r) ? 0 : -1;
return r;
}
void process_event(struct dm_task *dmt,
enum dm_event_mask event __attribute__((unused)),
void **unused __attribute__((unused)))
void **user)
{
struct dso_state *state = *user;
void *next = NULL;
uint64_t start, length;
char *target_type = NULL;
char *params;
const char *device = dm_task_get_name(dmt);
dmeventd_lvm2_lock();
do {
next = dm_get_next_target(dmt, next, &start, &length,
&target_type, &params);
if (!target_type) {
syslog(LOG_INFO, "%s mapping lost.", device);
log_info("%s mapping lost.", device);
continue;
}
if (strcmp(target_type, "mirror")) {
syslog(LOG_INFO, "%s has unmirrored portion.", device);
log_info("%s has unmirrored portion.", device);
continue;
}
@@ -190,54 +178,75 @@ void process_event(struct dm_task *dmt,
_part_ of the device is in sync
Also, this is not an error
*/
syslog(LOG_NOTICE, "%s is now in-sync.", device);
log_notice("%s is now in-sync.", device);
break;
case ME_FAILURE:
syslog(LOG_ERR, "Device failure in %s.", device);
if (_remove_failed_devices(device))
log_error("Device failure in %s.", device);
if (!_remove_failed_devices(state->cmd_lvscan,
state->cmd_lvconvert))
/* FIXME Why are all the error return codes unused? Get rid of them? */
syslog(LOG_ERR, "Failed to remove faulty devices in %s.",
device);
log_error("Failed to remove faulty devices in %s.",
device);
/* Should check before warning user that device is now linear
else
syslog(LOG_NOTICE, "%s is now a linear device.\n",
device);
log_notice("%s is now a linear device.",
device);
*/
break;
case ME_IGNORE:
break;
default:
/* FIXME Provide value then! */
syslog(LOG_INFO, "Unknown event received.");
log_info("Unknown event received.");
}
} while (next);
dmeventd_lvm2_unlock();
}
int register_device(const char *device,
const char *uuid __attribute__((unused)),
int major __attribute__((unused)),
int minor __attribute__((unused)),
void **unused __attribute__((unused)))
void **user)
{
if (!dmeventd_lvm2_init())
return 0;
struct dso_state *state;
syslog(LOG_INFO, "Monitoring mirror device %s for events.", device);
if (!dmeventd_lvm2_init_with_pool("mirror_state", state))
goto_bad;
if (!dmeventd_lvm2_command(state->mem, state->cmd_lvscan, sizeof(state->cmd_lvscan),
"lvscan --cache", device)) {
dmeventd_lvm2_exit_with_pool(state);
goto_bad;
}
if (!dmeventd_lvm2_command(state->mem, state->cmd_lvconvert, sizeof(state->cmd_lvconvert),
"lvconvert --repair --use-policies", device)) {
dmeventd_lvm2_exit_with_pool(state);
goto_bad;
}
*user = state;
log_info("Monitoring mirror device %s for events.", device);
return 1;
bad:
log_error("Failed to monitor mirror %s.", device);
return 0;
}
int unregister_device(const char *device,
const char *uuid __attribute__((unused)),
int major __attribute__((unused)),
int minor __attribute__((unused)),
void **unused __attribute__((unused)))
void **user)
{
syslog(LOG_INFO, "No longer monitoring mirror device %s for events.",
device);
dmeventd_lvm2_exit();
struct dso_state *state = *user;
dmeventd_lvm2_exit_with_pool(state);
log_info("No longer monitoring mirror device %s for events.",
device);
return 1;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2005-2011 Red Hat, Inc. All rights reserved.
* Copyright (C) 2005-2015 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
@@ -13,168 +13,133 @@
*/
#include "lib.h"
#include "libdevmapper-event.h"
#include "dmeventd_lvm.h"
#include "libdevmapper-event.h"
struct dso_state {
struct dm_pool *mem;
char cmd_lvscan[512];
char cmd_lvconvert[512];
int failed;
};
DM_EVENT_LOG_FN("raid")
#include <syslog.h> /* FIXME Replace syslog with multilog */
/* FIXME Missing openlog? */
/* FIXME Replace most syslogs with log_error() style messages and add complete context. */
/* FIXME Reformat to 80 char lines. */
/*
* run_repair is a close copy to
* plugins/mirror/dmeventd_mirror.c:_remove_failed_devices()
*/
static int run_repair(const char *device)
static int _process_raid_event(struct dso_state *state, char *params, const char *device)
{
int r;
#define CMD_SIZE 256 /* FIXME Use system restriction */
char cmd_str[CMD_SIZE];
struct dm_status_raid *status;
const char *d;
if (!dmeventd_lvm2_command(dmeventd_lvm2_pool(), cmd_str, sizeof(cmd_str),
"lvscan --cache", device))
return -1;
r = dmeventd_lvm2_run(cmd_str);
if (!r)
syslog(LOG_INFO, "Re-scan of RAID device %s failed.", device);
if (!dmeventd_lvm2_command(dmeventd_lvm2_pool(), cmd_str, sizeof(cmd_str),
"lvconvert --config devices{ignore_suspended_devices=1} "
"--repair --use-policies", device))
return -1;
/* if repair goes OK, report success even if lvscan has failed */
r = dmeventd_lvm2_run(cmd_str);
if (!r)
syslog(LOG_INFO, "Repair of RAID device %s failed.", device);
return (r) ? 0 : -1;
}
static int _process_raid_event(char *params, const char *device)
{
int i, n, failure = 0;
char *p, *a[4];
char *raid_type;
char *num_devices;
char *health_chars;
char *resync_ratio;
/*
* RAID parms: <raid_type> <#raid_disks> \
* <health chars> <resync ratio>
*/
if (!dm_split_words(params, 4, 0, a)) {
syslog(LOG_ERR, "Failed to process status line for %s\n",
device);
return -EINVAL;
}
raid_type = a[0];
num_devices = a[1];
health_chars = a[2];
resync_ratio = a[3];
if (!(n = atoi(num_devices))) {
syslog(LOG_ERR, "Failed to parse number of devices for %s: %s",
device, num_devices);
return -EINVAL;
if (!dm_get_status_raid(state->mem, params, &status)) {
log_error("Failed to process status line for %s.", device);
return 0;
}
for (i = 0; i < n; i++) {
switch (health_chars[i]) {
case 'A':
/* Device is 'A'live and well */
case 'a':
/* Device is 'a'live, but not yet in-sync */
break;
case 'D':
syslog(LOG_ERR,
"Device #%d of %s array, %s, has failed.",
i, raid_type, device);
failure++;
break;
default:
/* Unhandled character returned from kernel */
break;
if ((d = strchr(status->dev_health, 'D'))) {
if (state->failed)
goto out; /* already reported */
log_error("Device #%d of %s array, %s, has failed.",
(int)(d - status->dev_health),
status->raid_type, device);
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 (!dmeventd_lvm2_run_with_lock(state->cmd_lvconvert)) {
log_info("Repair of RAID device %s failed.", device);
dm_pool_free(state->mem, status);
return 0;
}
if (failure)
return run_repair(device);
} else {
state->failed = 0;
log_info("%s array, %s, is %s in-sync.",
status->raid_type, device,
(status->insync_regions == status->total_regions) ? "now" : "not");
}
out:
dm_pool_free(state->mem, status);
p = strstr(resync_ratio, "/");
if (!p) {
syslog(LOG_ERR, "Failed to parse resync_ratio for %s: %s",
device, resync_ratio);
return -EINVAL;
}
p[0] = '\0';
syslog(LOG_INFO, "%s array, %s, is %s in-sync.",
raid_type, device, strcmp(resync_ratio, p+1) ? "not" : "now");
return 0;
return 1;
}
void process_event(struct dm_task *dmt,
enum dm_event_mask event __attribute__((unused)),
void **unused __attribute__((unused)))
void **user)
{
struct dso_state *state = *user;
void *next = NULL;
uint64_t start, length;
char *target_type = NULL;
char *params;
const char *device = dm_task_get_name(dmt);
dmeventd_lvm2_lock();
do {
next = dm_get_next_target(dmt, next, &start, &length,
&target_type, &params);
if (!target_type) {
syslog(LOG_INFO, "%s mapping lost.", device);
log_info("%s mapping lost.", device);
continue;
}
if (strcmp(target_type, "raid")) {
syslog(LOG_INFO, "%s has non-raid portion.", device);
log_info("%s has non-raid portion.", device);
continue;
}
if (_process_raid_event(params, device))
syslog(LOG_ERR, "Failed to process event for %s",
device);
if (!_process_raid_event(state, params, device))
log_error("Failed to process event for %s.",
device);
} while (next);
dmeventd_lvm2_unlock();
}
int register_device(const char *device,
const char *uuid __attribute__((unused)),
int major __attribute__((unused)),
int minor __attribute__((unused)),
void **unused __attribute__((unused)))
void **user)
{
if (!dmeventd_lvm2_init())
return 0;
struct dso_state *state;
syslog(LOG_INFO, "Monitoring RAID device %s for events.", device);
if (!dmeventd_lvm2_init_with_pool("raid_state", state))
goto_bad;
if (!dmeventd_lvm2_command(state->mem, state->cmd_lvscan, sizeof(state->cmd_lvscan),
"lvscan --cache", device) ||
!dmeventd_lvm2_command(state->mem, state->cmd_lvconvert, sizeof(state->cmd_lvconvert),
"lvconvert --config devices{ignore_suspended_devices=1} "
"--repair --use-policies", device)) {
dmeventd_lvm2_exit_with_pool(state);
goto_bad;
}
*user = state;
log_info("Monitoring RAID device %s for events.", device);
return 1;
bad:
log_error("Failed to monitor RAID %s.", device);
return 0;
}
int unregister_device(const char *device,
const char *uuid __attribute__((unused)),
int major __attribute__((unused)),
int minor __attribute__((unused)),
void **unused __attribute__((unused)))
void **user)
{
syslog(LOG_INFO, "No longer monitoring RAID device %s for events.",
device);
dmeventd_lvm2_exit();
struct dso_state *state = *user;
dmeventd_lvm2_exit_with_pool(state);
log_info("No longer monitoring RAID device %s for events.",
device);
return 1;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2007-2011 Red Hat, Inc. All rights reserved.
* Copyright (C) 2007-2015 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
@@ -13,31 +13,31 @@
*/
#include "lib.h"
#include "libdevmapper-event.h"
#include "dmeventd_lvm.h"
#include "libdevmapper-event.h"
#include <sys/wait.h>
#include <syslog.h> /* FIXME Replace syslog with multilog */
#include <stdarg.h>
/* FIXME Missing openlog? */
#include <pthread.h>
/* First warning when snapshot is 80% full. */
#define WARNING_THRESH 80
#define WARNING_THRESH (DM_PERCENT_1 * 80)
/* Run a check every 5%. */
#define CHECK_STEP 5
#define CHECK_STEP (DM_PERCENT_1 * 5)
/* Do not bother checking snapshots less than 50% full. */
#define CHECK_MINIMUM 50
#define CHECK_MINIMUM (DM_PERCENT_1 * 50)
#define UMOUNT_COMMAND "/bin/umount"
struct dso_state {
struct dm_pool *mem;
int percent_check;
dm_percent_t percent_check;
uint64_t known_size;
char cmd_str[1024];
char cmd_lvextend[512];
};
DM_EVENT_LOG_FN("snap")
static int _run(const char *cmd, ...)
{
va_list ap;
@@ -62,7 +62,7 @@ static int _run(const char *cmd, ...)
va_end(ap);
execvp(cmd, (char **)argv);
syslog(LOG_ERR, "Failed to execute %s: %s.\n", cmd, strerror(errno));
log_sys_error("exec", cmd);
exit(127);
}
@@ -81,18 +81,56 @@ static int _run(const char *cmd, ...)
static int _extend(const char *cmd)
{
return dmeventd_lvm2_run(cmd);
log_debug("Extending snapshot via %s.", cmd);
return dmeventd_lvm2_run_with_lock(cmd);
}
#ifdef SNAPSHOT_REMOVE
/* Remove invalid snapshot from dm-table */
/* Experimental for now and not used by default */
static int _remove(const char *uuid)
{
int r = 1;
uint32_t cookie = 0;
struct dm_task *dmt;
if (!(dmt = dm_task_create(DM_DEVICE_REMOVE)))
return 0;
if (!dm_task_set_uuid(dmt, uuid)) {
r = 0;
goto_out;
}
dm_task_retry_remove(dmt);
if (!dm_task_set_cookie(dmt, &cookie, 0)) {
r = 0;
goto_out;
}
if (!dm_task_run(dmt)) {
r = 0;
goto_out;
}
out:
dm_task_destroy(dmt);
return r;
}
#endif /* SNAPSHOT_REMOVE */
static void _umount(const char *device, int major, int minor)
{
FILE *mounts;
char buffer[4096];
char *words[3];
struct stat st;
const char procmounts[] = "/proc/mounts";
if (!(mounts = fopen("/proc/mounts", "r"))) {
syslog(LOG_ERR, "Could not read /proc/mounts. Not umounting %s.\n", device);
if (!(mounts = fopen(procmounts, "r"))) {
log_sys_error("fopen", procmounts);
log_error("Not umounting %s.", device);
return;
}
@@ -112,21 +150,22 @@ static void _umount(const char *device, int major, int minor)
if (S_ISBLK(st.st_mode) &&
major(st.st_rdev) == major &&
minor(st.st_rdev) == minor) {
syslog(LOG_ERR, "Unmounting invalid snapshot %s from %s.\n", device, words[1]);
if (!_run(UMOUNT_COMMAND, "-fl", words[1], NULL))
syslog(LOG_ERR, "Failed to umount snapshot %s from %s: %s.\n",
device, words[1], strerror(errno));
log_error("Unmounting invalid snapshot %s from %s.", device, words[1]);
if (!_run(UMOUNT_COMMAND, "-fl", words[1], NULL))
log_error("Failed to umount snapshot %s from %s: %s.",
device, words[1], strerror(errno));
}
}
if (fclose(mounts))
syslog(LOG_ERR, "Failed to close /proc/mounts.\n");
log_sys_error("close", procmounts);
}
void process_event(struct dm_task *dmt,
enum dm_event_mask event __attribute__((unused)),
void **private)
void **user)
{
struct dso_state *state = *user;
void *next = NULL;
uint64_t start, length;
char *target_type = NULL;
@@ -134,28 +173,47 @@ void process_event(struct dm_task *dmt,
struct dm_status_snapshot *status = NULL;
const char *device = dm_task_get_name(dmt);
int percent;
struct dso_state *state = *private;
struct dm_info info;
/* No longer monitoring, waiting for remove */
if (!state->percent_check)
return;
dmeventd_lvm2_lock();
dm_get_next_target(dmt, next, &start, &length, &target_type, &params);
if (!target_type)
goto out;
if (!target_type || strcmp(target_type, "snapshot")) {
log_error("Target %s is not snapshot.", target_type);
return;
}
if (!dm_get_status_snapshot(state->mem, params, &status))
goto out;
if (!dm_get_status_snapshot(state->mem, params, &status)) {
log_error("Cannot parse snapshot %s state: %s.", device, params);
return;
}
if (status->invalid) {
struct dm_info info;
if (dm_task_get_info(dmt, &info)) {
dmeventd_lvm2_unlock();
/*
* If the snapshot has been invalidated or we failed to parse
* the status string. Report the full status string to syslog.
*/
if (status->invalid || status->overflow || !status->total_sectors) {
log_warn("WARNING: Snapshot %s changed state to: %s and should be removed.",
device, params);
state->percent_check = 0;
if (dm_task_get_info(dmt, &info))
_umount(device, info.major, info.minor);
return;
} /* else; too bad, but this is best-effort thing... */
#ifdef SNAPSHOT_REMOVE
/* Maybe configurable ? */
_remove(dm_task_get_uuid(dmt));
#endif
pthread_kill(pthread_self(), SIGALRM);
goto out;
}
if (length <= (status->used_sectors - status->metadata_sectors)) {
/* TODO eventually recognize earlier when room is enough */
log_info("Dropping monitoring of fully provisioned snapshot %s.",
device);
pthread_kill(pthread_self(), SIGALRM);
goto out;
}
/* Snapshot size had changed. Clear the threshold. */
@@ -164,69 +222,50 @@ void process_event(struct dm_task *dmt,
state->known_size = status->total_sectors;
}
/*
* If the snapshot has been invalidated or we failed to parse
* the status string. Report the full status string to syslog.
*/
if (status->invalid || !status->total_sectors) {
syslog(LOG_ERR, "Snapshot %s changed state to: %s\n", device, params);
state->percent_check = 0;
goto out;
}
percent = (int) (100 * status->used_sectors / status->total_sectors);
percent = dm_make_percent(status->used_sectors, status->total_sectors);
if (percent >= state->percent_check) {
/* Usage has raised more than CHECK_STEP since the last
time. Run actions. */
state->percent_check = (percent / CHECK_STEP) * CHECK_STEP + CHECK_STEP;
if (percent >= WARNING_THRESH) /* Print a warning to syslog. */
syslog(LOG_WARNING, "Snapshot %s is now %i%% full.\n", device, percent);
/* Try to extend the snapshot, in accord with user-set policies */
if (!_extend(state->cmd_str))
syslog(LOG_ERR, "Failed to extend snapshot %s.\n", device);
}
log_warn("WARNING: Snapshot %s is now %.2f%% full.",
device, dm_percent_to_float(percent));
/* Try to extend the snapshot, in accord with user-set policies */
if (!_extend(state->cmd_lvextend))
log_error("Failed to extend snapshot %s.", device);
}
out:
if (status)
dm_pool_free(state->mem, status);
dmeventd_lvm2_unlock();
dm_pool_free(state->mem, status);
}
int register_device(const char *device,
const char *uuid __attribute__((unused)),
int major __attribute__((unused)),
int minor __attribute__((unused)),
void **private)
void **user)
{
struct dm_pool *statemem = NULL;
struct dso_state *state;
if (!dmeventd_lvm2_init())
goto out;
if (!dmeventd_lvm2_init_with_pool("snapshot_state", state))
goto_bad;
if (!(statemem = dm_pool_create("snapshot_state", 512)) ||
!(state = dm_pool_zalloc(statemem, sizeof(*state))))
goto bad;
if (!dmeventd_lvm2_command(state->mem, state->cmd_lvextend,
sizeof(state->cmd_lvextend),
"lvextend --use-policies", device)) {
dmeventd_lvm2_exit_with_pool(state);
goto_bad;
}
if (!dmeventd_lvm2_command(statemem, state->cmd_str,
sizeof(state->cmd_str),
"lvextend --use-policies", device))
goto bad;
state->mem = statemem;
state->percent_check = CHECK_MINIMUM;
*private = state;
*user = state;
syslog(LOG_INFO, "Monitoring snapshot %s\n", device);
log_info("Monitoring snapshot %s.", device);
return 1;
bad:
if (statemem)
dm_pool_destroy(statemem);
dmeventd_lvm2_exit();
out:
syslog(LOG_ERR, "Failed to monitor snapshot %s.\n", device);
log_error("Failed to monitor snapshot %s.", device);
return 0;
}
@@ -235,13 +274,12 @@ int unregister_device(const char *device,
const char *uuid __attribute__((unused)),
int major __attribute__((unused)),
int minor __attribute__((unused)),
void **private)
void **user)
{
struct dso_state *state = *private;
struct dso_state *state = *user;
syslog(LOG_INFO, "No longer monitoring snapshot %s\n", device);
dm_pool_destroy(state->mem);
dmeventd_lvm2_exit();
dmeventd_lvm2_exit_with_pool(state);
log_info("No longer monitoring snapshot %s.", device);
return 1;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2011-2013 Red Hat, Inc. All rights reserved.
* Copyright (C) 2011-2015 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
@@ -12,25 +12,33 @@
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "lib.h"
#include "libdevmapper-event.h"
#include "lib.h" /* using here lvm log */
#include "dmeventd_lvm.h"
#include "libdevmapper-event.h"
#include <sys/wait.h>
#include <syslog.h> /* FIXME Replace syslog with multilog */
#include <stdarg.h>
/* FIXME Missing openlog? */
#include <pthread.h>
/* First warning when thin is 80% full. */
#define WARNING_THRESH 80
/* TODO - move this mountinfo code into library to be reusable */
#ifdef __linux__
# include "kdev_t.h"
#else
# define MAJOR(x) major((x))
# define MINOR(x) minor((x))
#endif
/* First warning when thin data or metadata is 80% full. */
#define WARNING_THRESH (DM_PERCENT_1 * 80)
/* Run a check every 5%. */
#define CHECK_STEP 5
/* Do not bother checking thins less than 50% full. */
#define CHECK_MINIMUM 50
#define CHECK_STEP (DM_PERCENT_1 * 5)
/* Do not bother checking thin data or metadata is less than 50% full. */
#define CHECK_MINIMUM (DM_PERCENT_1 * 50)
#define UMOUNT_COMMAND "/bin/umount"
#define MAX_FAILS (10)
#define THIN_DEBUG 0
struct dso_state {
@@ -39,18 +47,11 @@ struct dso_state {
int data_percent_check;
uint64_t known_metadata_size;
uint64_t known_data_size;
unsigned fails;
char cmd_str[1024];
};
/* TODO - move this mountinfo code into library to be reusable */
#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
DM_EVENT_LOG_FN("thin")
/* Get dependencies for device, and try to find matching device */
static int _has_deps(const char *name, int tp_major, int tp_minor, int *dev_minor)
@@ -93,8 +94,8 @@ static int _has_deps(const char *name, int tp_major, int tp_minor, int *dev_mino
{
char dev_name[PATH_MAX];
if (dm_device_get_name(major, minor, 0, dev_name, sizeof(dev_name)))
syslog(LOG_DEBUG, "Found %s (%u:%u) depends on %s",
name, major, *dev_minor, dev_name);
log_debug("Found %s (%u:%u) depends on %s.",
name, major, *dev_minor, dev_name);
}
#endif
r = 1;
@@ -141,14 +142,6 @@ out:
return r;
}
static int _extend(struct dso_state *state)
{
#if THIN_DEBUG
syslog(LOG_INFO, "dmeventd executes: %s.\n", state->cmd_str);
#endif
return dmeventd_lvm2_run(state->cmd_str);
}
static int _run(const char *cmd, ...)
{
va_list ap;
@@ -168,12 +161,12 @@ static int _run(const char *cmd, ...)
argv = alloca(sizeof(const char *) * (argc + 1));
argv[0] = cmd;
va_start(ap, cmd);
va_start(ap, cmd);
while ((argv[++i] = va_arg(ap, const char *)));
va_end(ap);
execvp(cmd, (char **)argv);
syslog(LOG_ERR, "Failed to execute %s: %s.\n", cmd, strerror(errno));
log_sys_error("exec", cmd);
exit(127);
}
@@ -191,9 +184,9 @@ static int _run(const char *cmd, ...)
}
struct mountinfo_s {
const char *device;
struct dm_info info;
dm_bitset_t minors; /* Bitset for active thin pool minors */
const char *device;
};
static int _umount_device(char *buffer, unsigned major, unsigned minor,
@@ -202,11 +195,11 @@ static int _umount_device(char *buffer, unsigned major, unsigned minor,
struct mountinfo_s *data = cb_data;
if ((major == data->info.major) && dm_bit(data->minors, minor)) {
syslog(LOG_INFO, "Unmounting thin volume %s from %s.\n",
data->device, target);
log_info("Unmounting thin volume %s from %s.",
data->device, target);
if (!_run(UMOUNT_COMMAND, "-fl", target, NULL))
syslog(LOG_ERR, "Failed to umount thin %s from %s: %s.\n",
data->device, target, strerror(errno));
log_error("Failed to umount thin %s from %s: %s.",
data->device, target, strerror(errno));
}
return 1;
@@ -216,78 +209,94 @@ static int _umount_device(char *buffer, unsigned major, unsigned minor,
* Find all thin pool users and try to umount them.
* TODO: work with read-only thin pool support
*/
static void _umount(struct dm_task *dmt, const char *device)
static void _umount(struct dm_task *dmt)
{
/* TODO: Convert to use hash to reduce memory usage */
static const size_t MINORS = (1U << 20); /* 20 bit */
struct mountinfo_s data = {
.device = device,
};
struct mountinfo_s data = { NULL };
if (!dm_task_get_info(dmt, &data.info))
return;
dmeventd_lvm2_unlock();
data.device = dm_task_get_name(dmt);
if (!(data.minors = dm_bitset_create(NULL, MINORS))) {
syslog(LOG_ERR, "Failed to allocate bitset. Not unmounting %s.\n", device);
log_error("Failed to allocate bitset. Not unmounting %s.", data.device);
goto out;
}
if (!_find_all_devs(data.minors, data.info.major, data.info.minor)) {
syslog(LOG_ERR, "Failed to detect mounted volumes for %s.\n", device);
log_error("Failed to detect mounted volumes for %s.", data.device);
goto out;
}
if (!dm_mountinfo_read(_umount_device, &data)) {
syslog(LOG_ERR, "Could not parse mountinfo file.\n");
log_error("Could not parse mountinfo file.");
goto out;
}
out:
if (data.minors)
dm_bitset_destroy(data.minors);
dmeventd_lvm2_lock();
}
static void _use_policy(struct dm_task *dmt, struct dso_state *state)
{
#if THIN_DEBUG
log_info("dmeventd executes: %s.", state->cmd_str);
#endif
if (!dmeventd_lvm2_run_with_lock(state->cmd_str)) {
log_error("Failed to extend thin pool %s.",
dm_task_get_name(dmt));
_umount(dmt);
state->fails++;
} else
state->fails = 0;
}
void process_event(struct dm_task *dmt,
enum dm_event_mask event __attribute__((unused)),
void **private)
void **user)
{
const char *device = dm_task_get_name(dmt);
int percent;
struct dso_state *state = *private;
struct dso_state *state = *user;
struct dm_status_thin_pool *tps = NULL;
void *next = NULL;
uint64_t start, length;
char *target_type = NULL;
char *params;
int needs_policy = 0;
#if 0
/* No longer monitoring, waiting for remove */
if (!state->meta_percent_check && !state->data_percent_check)
return;
#endif
dmeventd_lvm2_lock();
if (event & DM_EVENT_DEVICE_ERROR) {
/* Error -> no need to check and do instant resize */
_use_policy(dmt, state);
goto out;
}
dm_get_next_target(dmt, next, &start, &length, &target_type, &params);
if (!target_type || (strcmp(target_type, "thin-pool") != 0)) {
syslog(LOG_ERR, "Invalid target type.\n");
log_error("Invalid target type.");
goto out;
}
if (!dm_get_status_thin_pool(state->mem, params, &tps)) {
syslog(LOG_ERR, "Failed to parse status.\n");
_umount(dmt, device);
log_error("Failed to parse status.");
_umount(dmt);
goto out;
}
#if THIN_DEBUG
syslog(LOG_INFO, "%p: Got status %" PRIu64 " / %" PRIu64
" %" PRIu64 " / %" PRIu64 ".\n", state,
tps->used_metadata_blocks, tps->total_metadata_blocks,
tps->used_data_blocks, tps->total_data_blocks);
log_debug("Thin pool status " FMTu64 "/" FMTu64 " "
FMTu64 "/" FMTu64 ".",
tps->used_metadata_blocks, tps->total_metadata_blocks,
tps->used_data_blocks, tps->total_data_blocks);
#endif
/* Thin pool size had changed. Clear the threshold. */
@@ -301,7 +310,7 @@ void process_event(struct dm_task *dmt,
state->known_data_size = tps->total_data_blocks;
}
percent = 100 * tps->used_metadata_blocks / tps->total_metadata_blocks;
percent = dm_make_percent(tps->used_metadata_blocks, tps->total_metadata_blocks);
if (percent >= state->metadata_percent_check) {
/*
* Usage has raised more than CHECK_STEP since the last
@@ -311,18 +320,12 @@ void process_event(struct dm_task *dmt,
/* FIXME: extension of metadata needs to be written! */
if (percent >= WARNING_THRESH) /* Print a warning to syslog. */
syslog(LOG_WARNING, "Thin metadata %s is now %i%% full.\n",
device, percent);
/* Try to extend the metadata, in accord with user-set policies */
if (!_extend(state)) {
syslog(LOG_ERR, "Failed to extend thin metadata %s.\n",
device);
_umount(dmt, device);
}
/* FIXME: hmm READ-ONLY switch should happen in error path */
log_warn("WARNING: Thin pool %s metadata is now %.2f%% full.",
device, dm_percent_to_float(percent));
needs_policy = 1;
}
percent = 100 * tps->used_data_blocks / tps->total_data_blocks;
percent = dm_make_percent(tps->used_data_blocks, tps->total_data_blocks);
if (percent >= state->data_percent_check) {
/*
* Usage has raised more than CHECK_STEP since
@@ -331,56 +334,53 @@ void process_event(struct dm_task *dmt,
state->data_percent_check = (percent / CHECK_STEP) * CHECK_STEP + CHECK_STEP;
if (percent >= WARNING_THRESH) /* Print a warning to syslog. */
syslog(LOG_WARNING, "Thin %s is now %i%% full.\n", device, percent);
/* Try to extend the thin data, in accord with user-set policies */
if (!_extend(state)) {
syslog(LOG_ERR, "Failed to extend thin %s.\n", device);
state->data_percent_check = 0;
_umount(dmt, device);
}
/* FIXME: hmm READ-ONLY switch should happen in error path */
log_warn("WARNING: Thin pool %s data is now %.2f%% full.",
device, dm_percent_to_float(percent));
needs_policy = 1;
}
if (needs_policy)
_use_policy(dmt, state);
out:
if (tps)
dm_pool_free(state->mem, tps);
dmeventd_lvm2_unlock();
if (state->fails >= MAX_FAILS) {
log_warn("WARNING: Dropping monitoring of %s. "
"lvm2 command fails too often (%u times in raw).",
device, state->fails);
pthread_kill(pthread_self(), SIGALRM);
}
}
int register_device(const char *device,
const char *uuid __attribute__((unused)),
int major __attribute__((unused)),
int minor __attribute__((unused)),
void **private)
void **user)
{
struct dm_pool *statemem = NULL;
struct dso_state *state;
if (!dmeventd_lvm2_init())
goto bad;
if (!dmeventd_lvm2_init_with_pool("thin_pool_state", state))
goto_bad;
if (!(statemem = dm_pool_create("thin_pool_state", 2048)) ||
!(state = dm_pool_zalloc(statemem, sizeof(*state))) ||
!dmeventd_lvm2_command(statemem, state->cmd_str,
if (!dmeventd_lvm2_command(state->mem, state->cmd_str,
sizeof(state->cmd_str),
"lvextend --use-policies",
device)) {
if (statemem)
dm_pool_destroy(statemem);
dmeventd_lvm2_exit();
goto bad;
dmeventd_lvm2_exit_with_pool(state);
goto_bad;
}
state->mem = statemem;
state->metadata_percent_check = CHECK_MINIMUM;
state->data_percent_check = CHECK_MINIMUM;
*private = state;
*user = state;
syslog(LOG_INFO, "Monitoring thin %s.\n", device);
log_info("Monitoring thin %s.", device);
return 1;
bad:
syslog(LOG_ERR, "Failed to monitor thin %s.\n", device);
log_error("Failed to monitor thin %s.", device);
return 0;
}
@@ -389,13 +389,12 @@ int unregister_device(const char *device,
const char *uuid __attribute__((unused)),
int major __attribute__((unused)),
int minor __attribute__((unused)),
void **private)
void **user)
{
struct dso_state *state = *private;
struct dso_state *state = *user;
syslog(LOG_INFO, "No longer monitoring thin %s.\n", device);
dm_pool_destroy(state->mem);
dmeventd_lvm2_exit();
dmeventd_lvm2_exit_with_pool(state);
log_info("No longer monitoring thin %s.", device);
return 1;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2012 Red Hat, Inc.
* Copyright (C) 2012-2015 Red Hat, Inc.
*
* This file is part of LVM2.
*
@@ -24,6 +24,7 @@
#include "lvm-version.h"
#include <assert.h>
#include <errno.h>
#include <pthread.h>
#define LVMETAD_SOCKET DEFAULT_RUN_DIR "/lvmetad.socket"
@@ -123,6 +124,7 @@ struct vg_info {
#define VGFL_INVALID 0x00000001
typedef struct {
daemon_idle *idle;
log_state *log; /* convenience */
const char *log_config;
@@ -1592,6 +1594,9 @@ static int init(daemon_state *s)
/* if (ls->initial_registrations)
_process_initial_registrations(ds->initial_registrations); */
if (ls->idle)
ls->idle->is_idle = 1;
return 1;
}
@@ -1614,21 +1619,39 @@ static int fini(daemon_state *s)
return 1;
}
static int process_timeout_arg(const char *str, unsigned *max_timeouts)
{
char *endptr;
unsigned long l;
errno = 0;
l = strtoul(str, &endptr, 10);
if (errno || *endptr || l >= UINT_MAX)
return 0;
*max_timeouts = (unsigned) l;
return 1;
}
static void usage(const char *prog, FILE *file)
{
fprintf(file, "Usage:\n"
"%s [-V] [-h] [-f] [-l {all|wire|debug}] [-s path]\n\n"
"%s [-V] [-h] [-f] [-l level[,level ...]] [-s path] [-t secs]\n\n"
" -V Show version of lvmetad\n"
" -h Show this help information\n"
" -f Don't fork, run in the foreground\n"
" -l Logging message level (-l {all|wire|debug})\n"
" -l Logging message levels (all,fatal,error,warn,info,wire,debug)\n"
" -p Set path to the pidfile\n"
" -s Set path to the socket to listen on\n\n", prog);
" -s Set path to the socket to listen on\n"
" -t Time to wait in seconds before shutdown on idle (missing or 0 = inifinite)\n\n", prog);
}
int main(int argc, char *argv[])
{
signed char opt;
struct timeval timeout;
daemon_idle di = { .ptimeout = &timeout };
lvmetad_state ls = { .log_config = "" };
daemon_state s = {
.daemon_fini = fini,
@@ -1643,7 +1666,7 @@ int main(int argc, char *argv[])
};
// use getopt_long
while ((opt = getopt(argc, argv, "?fhVl:p:s:")) != EOF) {
while ((opt = getopt(argc, argv, "?fhVl:p:s:t:")) != EOF) {
switch (opt) {
case 'h':
usage(argv[0], stdout);
@@ -1663,6 +1686,15 @@ int main(int argc, char *argv[])
case 's': // --socket
s.socket_path = optarg;
break;
case 't':
if (!process_timeout_arg(optarg, &di.max_timeouts)) {
fprintf(stderr, "Invalid value of timeout parameter.\n");
exit(EXIT_FAILURE);
}
/* 0 equals to wait indefinitely */
if (di.max_timeouts)
s.idle = ls.idle = &di;
break;
case 'V':
printf("lvmetad version: " LVM_VERSION "\n");
exit(1);

View File

@@ -1392,6 +1392,15 @@ int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode,
if (adopt)
flags |= SANLK_ACQUIRE_ORPHAN_ONLY;
#ifdef SANLOCK_HAS_ACQUIRE_OWNER_NOWAIT
/*
* Don't block waiting for a failed lease to expire since it causes
* sanlock_acquire to block for a long time, which would prevent this
* thread from processing other lock requests.
*/
flags |= SANLK_ACQUIRE_OWNER_NOWAIT;
#endif
rv = sanlock_acquire(lms->sock, -1, flags, 1, &rs, NULL);
if (rv == -EAGAIN) {
@@ -1462,6 +1471,26 @@ int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode,
return -EAGAIN;
}
#ifdef SANLOCK_HAS_ACQUIRE_OWNER_NOWAIT
if (rv == SANLK_ACQUIRE_OWNED_RETRY) {
/*
* The lock is held by a failed host, and will eventually
* expire. If we retry we'll eventually acquire the lock
* (or find someone else has acquired it). The EAGAIN retry
* attempts for SH locks above would not be sufficient for
* the length of expiration time. We could add a longer
* retry time here to cover the full expiration time and block
* the activation command for that long. For now just return
* the standard error indicating that another host still owns
* the lease. FIXME: return a different error number so the
* command can print an different error indicating that the
* owner of the lease is in the process of expiring?
*/
log_debug("S %s R %s lock_san acquire mode %d rv %d", ls->name, r->name, ld_mode, rv);
*retry = 0;
return -EAGAIN;
}
#endif
if (rv < 0) {
log_error("S %s R %s lock_san acquire error %d",
ls->name, r->name, rv);

View File

@@ -62,6 +62,7 @@ SOURCES =\
device/dev-swap.c \
device/dev-type.c \
device/dev-luks.c \
device/dev-dasd.c \
display/display.c \
error/errseg.c \
unknown/unknown.c \

View File

@@ -143,23 +143,23 @@ static int _get_segment_status_from_target_params(const char *target_name,
return 0;
}
if (!strcmp(segtype->name, "cache")) {
if (segtype_is_cache(segtype)) {
if (!dm_get_status_cache(seg_status->mem, params, &(seg_status->cache)))
return_0;
seg_status->type = SEG_STATUS_CACHE;
} else if (!strcmp(segtype->name, "raid")) {
} else if (segtype_is_raid(segtype)) {
if (!dm_get_status_raid(seg_status->mem, params, &seg_status->raid))
return_0;
seg_status->type = SEG_STATUS_RAID;
} else if (!strcmp(segtype->name, "thin")) {
} else if (segtype_is_thin_volume(segtype)) {
if (!dm_get_status_thin(seg_status->mem, params, &seg_status->thin))
return_0;
seg_status->type = SEG_STATUS_THIN;
} else if (!strcmp(segtype->name, "thin-pool")) {
} else if (segtype_is_thin_pool(segtype)) {
if (!dm_get_status_thin_pool(seg_status->mem, params, &seg_status->thin_pool))
return_0;
seg_status->type = SEG_STATUS_THIN_POOL;
} else if (!strcmp(segtype->name, "snapshot")) {
} else if (segtype_is_snapshot(segtype)) {
if (!dm_get_status_snapshot(seg_status->mem, params, &seg_status->snapshot))
return_0;
seg_status->type = SEG_STATUS_SNAPSHOT;
@@ -3277,7 +3277,7 @@ static int _tree_action(struct dev_manager *dm, const struct logical_volume *lv,
break;
case SUSPEND:
dm_tree_skip_lockfs(root);
if (!dm->flush_required && lv_is_mirror(lv) && !lv_is_pvmove(lv))
if (!dm->flush_required && !lv_is_pvmove(lv))
dm_tree_use_no_flush_suspend(root);
/* Fall through */
case SUSPEND_WITH_LOCKFS:
@@ -3296,7 +3296,14 @@ static int _tree_action(struct dev_manager *dm, const struct logical_volume *lv,
if (!dm_tree_preload_children(root, dlid, DLID_SIZE))
goto_out;
if (dm_tree_node_size_changed(root))
if ((dm_tree_node_size_changed(root) < 0))
dm->flush_required = 1;
/* Currently keep the code require flush for any
* non 'thin pool/volume, mirror' or with any size change */
if (!lv_is_thin_volume(lv) &&
!lv_is_thin_pool(lv) &&
(!lv_is_mirror(lv) || dm_tree_node_size_changed(root)))
dm->flush_required = 1;
if (action == ACTIVATE) {

28
lib/cache/lvmcache.c vendored
View File

@@ -1542,10 +1542,6 @@ int lvmcache_update_vgname_and_id(struct lvmcache_info *info, struct lvmcache_vg
vgid = vgname;
}
/* When using lvmetad, the PV could not have become orphaned. */
if (lvmetad_active() && is_orphan_vg(vgname) && info->vginfo)
return 1;
/* If PV without mdas is already in a real VG, don't make it orphan */
if (is_orphan_vg(vgname) && info->vginfo &&
mdas_empty_or_ignored(&info->mdas) &&
@@ -2358,3 +2354,27 @@ int lvmcache_contains_lock_type_sanlock(struct cmd_context *cmd)
return 0;
}
void lvmcache_get_max_name_lengths(struct cmd_context *cmd,
unsigned *pv_max_name_len,
unsigned *vg_max_name_len)
{
struct lvmcache_vginfo *vginfo;
struct lvmcache_info *info;
unsigned len;
*vg_max_name_len = 0;
*pv_max_name_len = 0;
dm_list_iterate_items(vginfo, &_vginfos) {
len = strlen(vginfo->vgname);
if (*vg_max_name_len < len)
*vg_max_name_len = len;
dm_list_iterate_items(info, &vginfo->infos) {
len = strlen(dev_name(info->dev));
if (*pv_max_name_len < len)
*pv_max_name_len = len;
}
}
}

View File

@@ -190,4 +190,8 @@ void lvmcache_set_preferred_duplicates(const char *vgid);
int lvmcache_contains_lock_type_sanlock(struct cmd_context *cmd);
void lvmcache_get_max_name_lengths(struct cmd_context *cmd,
unsigned *pv_max_name_len, unsigned *vg_max_name_len);
#endif

94
lib/cache/lvmetad.c vendored
View File

@@ -37,6 +37,70 @@ static struct cmd_context *_lvmetad_cmd = NULL;
static struct volume_group *lvmetad_pvscan_vg(struct cmd_context *cmd, struct volume_group *vg);
static int _log_debug_inequality(const char *name, struct dm_config_node *a, struct dm_config_node *b)
{
int result = 0;
int final_result = 0;
if (a->v && b->v) {
result = compare_value(a->v, b->v);
if (result) {
struct dm_config_value *av = a->v;
struct dm_config_value *bv = b->v;
if (!strcmp(a->key, b->key)) {
if (a->v->type == DM_CFG_STRING && b->v->type == DM_CFG_STRING)
log_debug_lvmetad("VG %s metadata inequality at %s / %s: %s / %s",
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)
log_debug_lvmetad("VG %s metadata inequality at %s / %s: " FMTi64 " / " FMTi64,
name, a->key, b->key, av->v.i, bv->v.i);
else
log_debug_lvmetad("VG %s metadata inequality at %s / %s: type %d / type %d",
name, a->key, b->key, av->type, bv->type);
} else {
log_debug_lvmetad("VG %s metadata inequality at %s / %s", name, a->key, b->key);
}
final_result = result;
}
}
if (a->v && !b->v) {
log_debug_lvmetad("VG %s metadata inequality at %s / %s", name, a->key, b->key);
final_result = 1;
}
if (!a->v && b->v) {
log_debug_lvmetad("VG %s metadata inequality at %s / %s", name, a->key, b->key);
final_result = -1;
}
if (a->child && b->child) {
result = _log_debug_inequality(name, a->child, b->child);
if (result)
final_result = result;
}
if (a->sib && b->sib) {
result = _log_debug_inequality(name, a->sib, b->sib);
if (result)
final_result = result;
}
if (a->sib && !b->sib) {
log_debug_lvmetad("VG %s metadata inequality at %s / %s", name, a->key, b->key);
final_result = 1;
}
if (!a->sib && b->sib) {
log_debug_lvmetad("VG %s metadata inequality at %s / %s", name, a->key, b->key);
final_result = -1;
}
return final_result;
}
void lvmetad_disconnect(void)
{
if (_lvmetad_connected)
@@ -1122,6 +1186,8 @@ static int _lvmetad_pvscan_single(struct metadata_area *mda, void *baton)
* due to something like an lvcreate from another host.
* This is limited to changes that only affect the vg (not global state like
* orphan PVs), so we only need to reread mdas on the vg's existing pvs.
* But, a previous PV in the VG may have been removed since we last read
* the VG, and that PV may have been reused for another VG.
*/
static struct volume_group *lvmetad_pvscan_vg(struct cmd_context *cmd, struct volume_group *vg)
@@ -1134,6 +1200,7 @@ static struct volume_group *lvmetad_pvscan_vg(struct cmd_context *cmd, struct vo
struct format_instance *fid;
struct format_instance_ctx fic = { .type = 0 };
struct _lvmetad_pvscan_baton baton;
struct device *save_dev = NULL;
dm_list_iterate_items(pvl, &vg->pvs) {
/* missing pv */
@@ -1160,9 +1227,25 @@ static struct volume_group *lvmetad_pvscan_vg(struct cmd_context *cmd, struct vo
lvmcache_foreach_mda(info, _lvmetad_pvscan_single, &baton);
/*
* The PV may have been removed from the VG by another host
* since we last read the VG.
*/
if (!baton.vg) {
log_debug_lvmetad("Did not find VG %s in scan of PV %s", vg->name, dev_name(pvl->pv->dev));
lvmcache_fmt(info)->ops->destroy_instance(baton.fid);
return NULL;
continue;
}
/*
* The PV may have been removed from the VG and used for a
* different VG since we last read the VG.
*/
if (strcmp(baton.vg->name, vg->name)) {
log_debug_lvmetad("Did not find VG %s in scan of PV %s which is now VG %s",
vg->name, dev_name(pvl->pv->dev), baton.vg->name);
release_vg(baton.vg);
continue;
}
if (!(vgmeta = export_vg_to_config_tree(baton.vg))) {
@@ -1173,9 +1256,12 @@ static struct volume_group *lvmetad_pvscan_vg(struct cmd_context *cmd, struct vo
if (!vgmeta_ret) {
vgmeta_ret = vgmeta;
save_dev = pvl->pv->dev;
} else {
if (compare_config(vgmeta_ret->root, vgmeta->root)) {
log_error("VG metadata comparison failed");
log_error("VG %s metadata comparison failed for device %s vs %s",
vg->name, dev_name(pvl->pv->dev), save_dev ? dev_name(save_dev) : "none");
_log_debug_inequality(vg->name, vgmeta_ret->root, vgmeta->root);
dm_config_destroy(vgmeta);
dm_config_destroy(vgmeta_ret);
release_vg(baton.vg);
@@ -1245,7 +1331,7 @@ int lvmetad_pvscan_single(struct cmd_context *cmd, struct device *dev,
log_warn("WARNING: Ignoring obsolete format of metadata (%s) on device %s when using lvmetad",
baton.fid->fmt->name, dev_name(dev));
else
log_error("WARNING: Ignoring obsolete format of metadata (%s) on device %s when using lvmetad",
log_error("Ignoring obsolete format of metadata (%s) on device %s when using lvmetad.",
baton.fid->fmt->name, dev_name(dev));
lvmcache_fmt(info)->ops->destroy_instance(baton.fid);
@@ -1597,7 +1683,7 @@ void lvmetad_validate_global_cache(struct cmd_context *cmd, int force)
return;
}
if (!lvmetad_used())
if (!lvmetad_active())
return;
log_debug_lvmetad("Validating global lvmetad cache");

View File

@@ -420,7 +420,7 @@ int init_cache_segtypes(struct cmd_context *cmd,
return 0;
}
segtype->name = "cache-pool";
segtype->name = SEG_TYPE_NAME_CACHE_POOL;
segtype->flags = SEG_CACHE_POOL | SEG_CANNOT_BE_ZEROED | SEG_ONLY_EXCLUSIVE;
segtype->ops = &_cache_pool_ops;
@@ -434,7 +434,7 @@ int init_cache_segtypes(struct cmd_context *cmd,
return 0;
}
segtype->name = "cache";
segtype->name = SEG_TYPE_NAME_CACHE;
segtype->flags = SEG_CACHE | SEG_ONLY_EXCLUSIVE;
segtype->ops = &_cache_ops;

View File

@@ -362,7 +362,8 @@ static void _init_logging(struct cmd_context *cmd)
/* Tell device-mapper about our logging */
#ifdef DEVMAPPER_SUPPORT
dm_log_with_errno_init(print_log);
if (!dm_log_is_non_default())
dm_log_with_errno_init(print_log);
#endif
reset_log_duplicated();
reset_lvm_errno(1);

View File

@@ -474,8 +474,8 @@ cfg(allocation_cache_policy_CFG, "cache_policy", allocation_CFG_SECTION, CFG_PRO
"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,
"Individual settings for policies.\n"
"See the help for individual policies for more info.\n")
"Settings for the cache policy.\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,
"Replace this subsection name with a policy name.\n"
@@ -1416,10 +1416,20 @@ cfg(disk_area_size_CFG, "size", disk_area_CFG_SUBSECTION, CFG_UNSUPPORTED | CFG_
cfg(disk_area_id_CFG, "id", disk_area_CFG_SUBSECTION, CFG_UNSUPPORTED | CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(1, 0, 0), NULL, 0, NULL, NULL)
cfg(report_compact_output_CFG, "compact_output", report_CFG_SECTION, CFG_PROFILABLE | CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_REP_COMPACT_OUTPUT, vsn(2, 2, 115), NULL, 0, NULL,
"Do not print empty report fields.\n"
"Fields that don't have a value set for any of the rows reported are\n"
"skipped and not printed. Compact output is applicable only if\n"
"report/buffered is enabled.\n")
"Do not print empty values for all report fields.\n"
"If enabled, all fields that don't have a value set for any of the\n"
"rows reported are skipped and not printed. Compact output is\n"
"applicable only if report/buffered is enabled. If you need to\n"
"compact only specified fields, use compact_output=0 and define\n"
"report/compact_output_cols configuration setting instead.\n")
cfg(report_compact_output_cols_CFG, "compact_output_cols", report_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_PROFILABLE | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_COMPACT_OUTPUT_COLS, vsn(2, 2, 133), NULL, 0, NULL,
"Do not print empty values for specified report fields.\n"
"If defined, specified fields that don't have a value set for any\n"
"of the rows reported are skipped and not printed. Compact output\n"
"is applicable only if report/buffered is enabled. If you need to\n"
"compact all fields, use compact_output=1 instead in which case\n"
"the compact_output_cols setting is then ignored.\n")
cfg(report_aligned_CFG, "aligned", report_CFG_SECTION, CFG_PROFILABLE | CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_REP_ALIGNED, vsn(1, 0, 0), NULL, 0, NULL,
"Align columns in report output.\n")

View File

@@ -63,6 +63,8 @@
#define DEFAULT_MIRROR_LOG_FAULT_POLICY "allocate"
#define DEFAULT_MIRROR_IMAGE_FAULT_POLICY "remove"
#define DEFAULT_MIRROR_MAX_IMAGES 8 /* limited by kernel DM_KCOPYD_MAX_REGIONS */
#define DEFAULT_RAID_MAX_IMAGES 8
#define DEFAULT_RAID_FAULT_POLICY "warn"
#define DEFAULT_DMEVENTD_RAID_LIB "libdevmapper-event-lvm2raid.so"
@@ -199,6 +201,8 @@
#define DEFAULT_REP_LIST_ITEM_SEPARATOR ","
#define DEFAULT_TIME_FORMAT "%Y-%m-%d %T %z"
#define DEFAULT_COMPACT_OUTPUT_COLS ""
#define DEFAULT_LVS_COLS "lv_name,vg_name,lv_attr,lv_size,pool_lv,origin,data_percent,metadata_percent,move_pv,mirror_log,copy_percent,convert_lv"
#define DEFAULT_VGS_COLS "vg_name,pv_count,lv_count,snap_count,vg_attr,vg_size,vg_free"
#define DEFAULT_PVS_COLS "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free"

View File

@@ -16,11 +16,14 @@
#include "lib.h"
#include "str_list.h"
#include <ctype.h>
struct dm_list *str_list_create(struct dm_pool *mem)
{
struct dm_list *sl;
if (!(sl = dm_pool_alloc(mem, sizeof(struct dm_list)))) {
if (!(sl = mem ? dm_pool_alloc(mem, sizeof(struct dm_list))
: dm_malloc(sizeof(struct dm_list)))) {
log_errno(ENOMEM, "str_list allocation failed");
return NULL;
}
@@ -37,7 +40,8 @@ static int _str_list_add_no_dup_check(struct dm_pool *mem, struct dm_list *sll,
if (!str)
return_0;
if (!(sln = dm_pool_alloc(mem, sizeof(*sln))))
if (!(sln = mem ? dm_pool_alloc(mem, sizeof(*sln))
: dm_malloc(sizeof(*sln))))
return_0;
sln->str = str;
@@ -158,3 +162,101 @@ int str_list_lists_equal(const struct dm_list *sll, const struct dm_list *sll2)
return 1;
}
char *str_list_to_str(struct dm_pool *mem, const struct dm_list *list,
const char *delim)
{
size_t delim_len = strlen(delim);
unsigned list_size = dm_list_size(list);
struct dm_str_list *sl;
char *str, *p;
size_t len = 0;
unsigned i = 0;
dm_list_iterate_items(sl, list)
len += strlen(sl->str);
if (list_size > 1)
len += ((list_size - 1) * delim_len);
str = mem ? dm_pool_alloc(mem, len+1) : dm_malloc(len+1);
if (!str) {
log_error("str_list_to_str: string allocation failed.");
return NULL;
}
str[len] = '\0';
p = str;
dm_list_iterate_items(sl, list) {
len = strlen(sl->str);
memcpy(p, sl->str, len);
p += len;
if (++i != list_size) {
memcpy(p, delim, delim_len);
p += delim_len;
}
}
return str;
}
struct dm_list *str_to_str_list(struct dm_pool *mem, const char *str,
const char *delim, int ignore_multiple_delim)
{
size_t delim_len = strlen(delim);
struct dm_list *list;
const char *p1, *p2, *next;
char *str_item;
size_t len;
if (!(list = str_list_create(mem))) {
log_error("str_to_str_list: string list allocation failed.");
return NULL;
}
p1 = p2 = str;
while (*p1) {
if (!(p2 = strstr(p1, delim)))
next = p2 = str + strlen(str);
else
next = p2 + delim_len;
len = p2 - p1;
str_item = mem ? dm_pool_alloc(mem, len+1) : dm_malloc(len+1);
if (!str_item) {
log_error("str_to_str_list: string list item allocation failed.");
goto bad;
}
memcpy(str_item, p1, len);
str_item[len] = '\0';
if (!str_list_add_no_dup_check(mem, list, str_item))
goto_bad;
if (ignore_multiple_delim) {
while (!strncmp(next, delim, delim_len))
next += delim_len;
}
p1 = next;
}
return list;
bad:
if (mem)
dm_pool_free(mem, list);
return NULL;
}
void str_list_destroy(struct dm_list *list, int deallocate_strings)
{
struct dm_str_list *sl, *tmp_sl;
dm_list_iterate_items_safe(sl, tmp_sl, list) {
dm_list_del(&sl->list);
if (deallocate_strings)
dm_free((char *)sl->str);
dm_free(sl);
}
dm_free(list);
}

View File

@@ -30,5 +30,9 @@ int str_list_match_list(const struct dm_list *sll, const struct dm_list *sll2, c
int str_list_lists_equal(const struct dm_list *sll, const struct dm_list *sll2);
int str_list_dup(struct dm_pool *mem, struct dm_list *sllnew,
const struct dm_list *sllold);
char *str_list_to_str(struct dm_pool *mem, const struct dm_list *list, const char *delim);
struct dm_list *str_to_str_list(struct dm_pool *mem, const char *str, const char *delim, int ignore_multiple_delim);
/* Only for lists which were *not* allocated from the mem pool! */
void str_list_destroy(struct dm_list *list, int deallocate_strings);
#endif

111
lib/device/dev-dasd.c Normal file
View File

@@ -0,0 +1,111 @@
/*
* Copyright (C) 2015 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "lib.h"
#include "metadata.h"
#include "dev-type.h"
#include <sys/ioctl.h>
#ifdef __linux__
/*
* Interface taken from kernel header arch/s390/include/uapi/asm/dasd.h
*/
/*
* Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
* Copyright IBM Corp. 1999, 2000
* EMC Symmetrix ioctl Copyright EMC Corporation, 2008
* Author.........: Nigel Hislop <hislop_nigel@emc.com>
*/
#define DASD_IOCTL_LETTER 'D'
#define DASD_API_VERSION 6
/*
* struct dasd_information2_t
* represents any data about the device, which is visible to userspace.
* including foramt and featueres.
*/
typedef struct dasd_information2_t {
unsigned int devno; /* S/390 devno */
unsigned int real_devno; /* for aliases */
unsigned int schid; /* S/390 subchannel identifier */
unsigned int cu_type : 16; /* from SenseID */
unsigned int cu_model : 8; /* from SenseID */
unsigned int dev_type : 16; /* from SenseID */
unsigned int dev_model : 8; /* from SenseID */
unsigned int open_count;
unsigned int req_queue_len;
unsigned int chanq_len; /* length of chanq */
char type[4]; /* from discipline.name, 'none' for unknown */
unsigned int status; /* current device level */
unsigned int label_block; /* where to find the VOLSER */
unsigned int FBA_layout; /* fixed block size (like AIXVOL) */
unsigned int characteristics_size;
unsigned int confdata_size;
char characteristics[64]; /* from read_device_characteristics */
char configuration_data[256]; /* from read_configuration_data */
unsigned int format; /* format info like formatted/cdl/ldl/... */
unsigned int features; /* dasd features like 'ro',... */
unsigned int reserved0; /* reserved for further use ,... */
unsigned int reserved1; /* reserved for further use ,... */
unsigned int reserved2; /* reserved for further use ,... */
unsigned int reserved3; /* reserved for further use ,... */
unsigned int reserved4; /* reserved for further use ,... */
unsigned int reserved5; /* reserved for further use ,... */
unsigned int reserved6; /* reserved for further use ,... */
unsigned int reserved7; /* reserved for further use ,... */
} dasd_information2_t;
#define DASD_FORMAT_CDL 2
/* Get information on a dasd device (enhanced) */
#define BIODASDINFO2 _IOR(DASD_IOCTL_LETTER,3,dasd_information2_t)
/*
* End of included interface.
*/
int dasd_is_cdl_formatted(struct device *dev)
{
int ret = 0;
dasd_information2_t dasd_info2;
if (!dev_open_readonly(dev))
return_0;
if (ioctl(dev->fd, BIODASDINFO2, &dasd_info2)) {
log_sys_error("ioctl BIODASDINFO2", dev_name(dev));
goto out;
}
if (dasd_info2.format == DASD_FORMAT_CDL)
ret = 1;
out:
if (!dev_close(dev))
stack;
return ret;
}
#else
int dasd_is_cdl_formatted(struct device *dev)
{
return 0;
}
#endif

View File

@@ -363,7 +363,7 @@ static int _native_dev_is_partitioned(struct dev_types *dt, struct device *dev)
return 0;
/* Unpartitioned DASD devices are not supported. */
if (MAJOR(dev->dev) == dt->dasd_major)
if ((MAJOR(dev->dev) == dt->dasd_major) && dasd_is_cdl_formatted(dev))
return 1;
if (!dev_open_readonly_quiet(dev)) {
@@ -651,8 +651,13 @@ static int _wipe_known_signatures_with_blkid(struct device *dev, const char *nam
BLKID_SUBLKS_BADCSUM);
while (!blkid_do_probe(probe)) {
if ((r_wipe = _blkid_wipe(probe, dev, name, types_to_exclude, types_no_prompt, yes, force)) == 1)
if ((r_wipe = _blkid_wipe(probe, dev, name, types_to_exclude, types_no_prompt, yes, force)) == 1) {
(*wiped)++;
if (blkid_probe_step_back(probe)) {
log_error("Failed to step back blkid probe to check just wiped signature.");
goto out;
}
}
/* do not count excluded types */
if (r_wipe != 2)
found++;

View File

@@ -59,6 +59,7 @@ int major_is_scsi_device(struct dev_types *dt, int major);
int dev_is_md(struct device *dev, uint64_t *sb);
int dev_is_swap(struct device *dev, uint64_t *signature);
int dev_is_luks(struct device *dev, uint64_t *signature);
int dasd_is_cdl_formatted(struct device *dev);
/* Signature wiping. */
#define TYPE_LVM1_MEMBER 0x001

View File

@@ -95,7 +95,7 @@ struct segment_type *init_error_segtype(struct cmd_context *cmd)
return_NULL;
segtype->ops = &_error_ops;
segtype->name = "error";
segtype->name = SEG_TYPE_NAME_ERROR;
segtype->flags = SEG_CAN_SPLIT | SEG_VIRTUAL | SEG_CANNOT_BE_ZEROED;
log_very_verbose("Initialised segtype: %s", segtype->name);

View File

@@ -219,7 +219,7 @@ static int _read_linear(struct cmd_context *cmd, struct lv_map *lvm)
struct lv_segment *seg;
struct segment_type *segtype;
if (!(segtype = get_segtype_from_string(cmd, "striped")))
if (!(segtype = get_segtype_from_string(cmd, SEG_TYPE_NAME_STRIPED)))
return_0;
while (le < lvm->lv->le_count) {
@@ -281,7 +281,7 @@ static int _read_stripes(struct cmd_context *cmd, struct lv_map *lvm)
total_area_len = lvm->lv->le_count / lvm->stripes;
if (!(segtype = get_segtype_from_string(cmd, "striped")))
if (!(segtype = get_segtype_from_string(cmd, SEG_TYPE_NAME_STRIPED)))
return_0;
while (first_area_le < total_area_len) {

View File

@@ -188,8 +188,7 @@ static int _add_stripe_seg(struct dm_pool *mem,
area_len = (usp->devs[0].blocks) / POOL_PE_SIZE;
if (!(segtype = get_segtype_from_string(lv->vg->cmd,
"striped")))
if (!(segtype = get_segtype_from_string(lv->vg->cmd, SEG_TYPE_NAME_STRIPED)))
return_0;
if (!(seg = alloc_lv_segment(segtype, lv, *le_cur,
@@ -226,7 +225,7 @@ static int _add_linear_seg(struct dm_pool *mem,
unsigned j;
uint32_t area_len;
if (!(segtype = get_segtype_from_string(lv->vg->cmd, "striped")))
if (!(segtype = get_segtype_from_string(lv->vg->cmd, SEG_TYPE_NAME_STRIPED)))
return_0;
for (j = 0; j < usp->num_devs; j++) {

View File

@@ -654,7 +654,7 @@ static int _vg_write_raw(struct format_instance *fid, struct volume_group *vg,
if ((new_wrap && old_wrap) ||
(rlocn && (new_wrap || old_wrap) && (new_end > rlocn->offset)) ||
(mdac->rlocn.size >= mdah->size)) {
(MDA_HEADER_SIZE + (rlocn ? rlocn->size : 0) + mdac->rlocn.size >= mdah->size)) {
log_error("VG %s metadata too large for circular buffer",
vg->name);
goto out;
@@ -2146,7 +2146,6 @@ static int _text_pv_add_metadata_area(const struct format_type *fmt,
goto bad;
}
/* Otherwise, give up and take any usable space. */
/* FIXME: We should probably check for some minimum MDA size here. */
else
mda_size = limit - mda_start;
@@ -2243,6 +2242,12 @@ static int _text_pv_add_metadata_area(const struct format_type *fmt,
mda_size, limit_name, limit);
if (mda_size) {
if (mda_size < MDA_SIZE_MIN) {
log_error("Metadata area size too small: %" PRIu64" bytes. "
"It must be at least %u bytes.", mda_size, MDA_SIZE_MIN);
goto bad;
}
/* Wipe metadata area with zeroes. */
if (!dev_set((struct device *) pv->dev, mda_start,
(size_t) ((mda_size > wipe_size) ?

View File

@@ -375,7 +375,7 @@ static int _read_segment(struct logical_volume *lv, const struct dm_config_node
return 0;
}
segtype_str = "striped";
segtype_str = SEG_TYPE_NAME_STRIPED;
if (!dm_config_get_str(sn_child, "type", &segtype_str)) {
log_error("Segment type must be a string.");

View File

@@ -33,7 +33,7 @@ struct segment_type *init_free_segtype(struct cmd_context *cmd)
return_NULL;
segtype->ops = &_freeseg_ops;
segtype->name = "free";
segtype->name = SEG_TYPE_NAME_FREE;
segtype->flags = SEG_VIRTUAL | SEG_CANNOT_BE_ZEROED;
log_very_verbose("Initialised segtype: %s", segtype->name);

View File

@@ -337,7 +337,7 @@ static int _create_sanlock_lv(struct cmd_context *cmd, struct volume_group *vg,
dm_list_init(&lp.tags);
if (!(lp.segtype = get_segtype_from_string(vg->cmd, "striped")))
if (!(lp.segtype = get_segtype_from_string(vg->cmd, SEG_TYPE_NAME_STRIPED)))
return_0;
lv = lv_create_single(vg, &lp);
@@ -879,6 +879,9 @@ static int _lockd_all_lvs(struct cmd_context *cmd, struct volume_group *vg)
struct lv_list *lvl;
dm_list_iterate_items(lvl, &vg->lvs) {
if (!lockd_lv_uses_lock(lvl->lv))
continue;
if (!lockd_lv(cmd, lvl->lv, "ex", 0)) {
log_error("LV %s/%s must be inactive on all hosts.",
vg->name, lvl->lv->name);
@@ -2007,6 +2010,15 @@ int lockd_lv_name(struct cmd_context *cmd, struct volume_group *vg,
return 0;
}
if (result == -EEXIST) {
/*
* This happens if lvchange tries to modify the LV with an ex
* LV lock when the LV is already active with a sh LV lock.
*/
log_error("LV is already locked with incompatible mode: %s/%s", vg->name, lv_name);
return 0;
}
if (result == -EMSGSIZE) {
/* Another host probably extended lvmlock. */
if (!refreshed++) {
@@ -2549,7 +2561,7 @@ int lockd_rename_vg_final(struct cmd_context *cmd, struct volume_group *vg, int
return 1;
}
const char *lockd_running_lock_type(struct cmd_context *cmd)
const char *lockd_running_lock_type(struct cmd_context *cmd, int *found_multiple)
{
daemon_reply reply;
const char *lock_type = NULL;
@@ -2571,10 +2583,9 @@ const char *lockd_running_lock_type(struct cmd_context *cmd)
switch (result) {
case -EXFULL:
log_error("lvmlockd found multiple lock managers, use --lock-type to select one.");
*found_multiple = 1;
break;
case -ENOLCK:
log_error("lvmlockd found no lock manager running.");
break;
case LOCK_TYPE_SANLOCK:
log_debug("lvmlockd found sanlock");

View File

@@ -89,7 +89,7 @@ int lockd_init_lv_args(struct cmd_context *cmd, struct volume_group *vg,
int lockd_free_lv(struct cmd_context *cmd, struct volume_group *vg,
const char *lv_name, struct id *lv_id, const char *lock_args);
const char *lockd_running_lock_type(struct cmd_context *cmd);
const char *lockd_running_lock_type(struct cmd_context *cmd, int *found_multiple);
int handle_sanlock_lv(struct cmd_context *cmd, struct volume_group *vg);
@@ -223,7 +223,7 @@ static inline int lockd_free_lv(struct cmd_context *cmd, struct volume_group *vg
return 1;
}
static inline const char *lockd_running_lock_type(struct cmd_context *cmd)
static inline const char *lockd_running_lock_type(struct cmd_context *cmd, int *found_multiple)
{
log_error("Using a shared lock type requires lvmlockd.");
return NULL;

View File

@@ -19,8 +19,6 @@
#include "lvm-string.h"
#include "activate.h"
#include <signal.h>
/*
* No locking
*/

View File

@@ -49,10 +49,7 @@ static size_t _lvm_errmsg_len = 0;
void init_log_fn(lvm2_log_fn_t log_fn)
{
if (log_fn)
_lvm2_log_fn = log_fn;
else
_lvm2_log_fn = NULL;
_lvm2_log_fn = log_fn;
}
/*

View File

@@ -16,9 +16,9 @@
#ifndef _LVM_LOGGING_H
#define _LVM_LOGGING_H
__attribute__ ((format(printf, 5, 6)))
void print_log(int level, const char *file, int line, int dm_errno_or_class,
const char *format, ...)
__attribute__ ((format(printf, 5, 6)));
const char *format, ...);
#define LOG_LINE(l, x...) \
print_log(l, __FILE__, __LINE__ , 0, ## x)

View File

@@ -261,7 +261,7 @@ struct logical_volume *lv_cache_create(struct logical_volume *pool_lv,
if (lv_is_thin_pool(cache_lv))
cache_lv = seg_lv(first_seg(cache_lv), 0); /* cache _tdata */
if (!(segtype = get_segtype_from_string(cmd, "cache")))
if (!(segtype = get_segtype_from_string(cmd, SEG_TYPE_NAME_CACHE)))
return_NULL;
if (!insert_layer_for_lv(cmd, cache_lv, CACHE, "_corig"))
@@ -407,7 +407,7 @@ int lv_cache_remove(struct logical_volume *cache_lv)
/* Replace 'error' with 'cache' segtype */
cache_seg = first_seg(corigin_lv);
if (!(cache_seg->segtype = get_segtype_from_string(corigin_lv->vg->cmd, "cache")))
if (!(cache_seg->segtype = get_segtype_from_string(corigin_lv->vg->cmd, SEG_TYPE_NAME_CACHE)))
return_0;
if (!(cache_seg->areas = dm_pool_zalloc(cache_lv->vg->vgmem, sizeof(*cache_seg->areas))))
@@ -453,7 +453,7 @@ int lv_is_cache_origin(const struct logical_volume *lv)
static const char *_get_default_cache_policy(struct cmd_context *cmd)
{
const struct segment_type *segtype = get_segtype_from_string(cmd, "cache");
const struct segment_type *segtype = get_segtype_from_string(cmd, SEG_TYPE_NAME_CACHE);
unsigned attr = ~0;
const char *def = NULL;

View File

@@ -29,7 +29,7 @@ static struct utsname _utsname;
static int _utsinit = 0;
static char *_format_pvsegs(struct dm_pool *mem, const struct lv_segment *seg,
int range_format)
int range_format, int metadata_areas_only)
{
unsigned int s;
const char *name = NULL;
@@ -41,13 +41,19 @@ static char *_format_pvsegs(struct dm_pool *mem, const struct lv_segment *seg,
return NULL;
}
if (metadata_areas_only && (!seg_is_raid(seg) || lv_is_raid_metadata(seg->lv) || lv_is_raid_image(seg->lv)))
goto out;
for (s = 0; s < seg->area_count; s++) {
switch (seg_type(seg, s)) {
switch (metadata_areas_only ? seg_metatype(seg, s) : seg_type(seg, s)) {
case AREA_LV:
name = seg_lv(seg, s)->name;
extent = seg_le(seg, s);
name = metadata_areas_only ? seg_metalv(seg, s)->name : seg_lv(seg, s)->name;
extent = metadata_areas_only ? seg_le(seg, s) : 0;
break;
case AREA_PV:
/* Raid metadata never uses PVs directly */
if (metadata_areas_only)
continue;
name = dev_name(seg_dev(seg, s));
extent = seg_pe(seg, s);
break;
@@ -79,7 +85,7 @@ static char *_format_pvsegs(struct dm_pool *mem, const struct lv_segment *seg,
if (range_format) {
if (dm_snprintf(extent_str, sizeof(extent_str),
FMTu32, extent + seg->area_len - 1) < 0) {
FMTu32, metadata_areas_only ? extent + seg_metalv(seg, s)->le_count - 1 : extent + seg->area_len - 1) < 0) {
log_error("Extent number dm_snprintf failed");
return NULL;
}
@@ -96,6 +102,7 @@ static char *_format_pvsegs(struct dm_pool *mem, const struct lv_segment *seg,
}
}
out:
if (!dm_pool_grow_object(mem, "\0", 1)) {
log_error("dm_pool_grow_object failed");
return NULL;
@@ -106,12 +113,22 @@ static char *_format_pvsegs(struct dm_pool *mem, const struct lv_segment *seg,
char *lvseg_devices(struct dm_pool *mem, const struct lv_segment *seg)
{
return _format_pvsegs(mem, seg, 0);
return _format_pvsegs(mem, seg, 0, 0);
}
char *lvseg_metadata_devices(struct dm_pool *mem, const struct lv_segment *seg)
{
return _format_pvsegs(mem, seg, 0, 1);
}
char *lvseg_seg_pe_ranges(struct dm_pool *mem, const struct lv_segment *seg)
{
return _format_pvsegs(mem, seg, 1);
return _format_pvsegs(mem, seg, 1, 0);
}
char *lvseg_seg_metadata_le_ranges(struct dm_pool *mem, const struct lv_segment *seg)
{
return _format_pvsegs(mem, seg, 1, 1);
}
char *lvseg_tags_dup(const struct lv_segment *seg)
@@ -648,6 +665,7 @@ int lv_raid_image_in_sync(const struct logical_volume *lv)
if ((seg = first_seg(lv)))
raid_seg = get_only_segment_using_this_lv(seg->lv);
if (!raid_seg) {
log_error("Failed to find RAID segment for %s", lv->name);
return 0;

View File

@@ -35,8 +35,8 @@ struct logical_volume {
int32_t major;
int32_t minor;
uint64_t size; /* Sectors */
uint32_t le_count;
uint64_t size; /* Sectors visible */
uint32_t le_count; /* Logical extents visible */
uint32_t origin_count;
uint32_t external_count;
@@ -101,7 +101,9 @@ char *lvseg_cachemode_dup(struct dm_pool *mem, const struct lv_segment *seg);
char *lvseg_monitor_dup(struct dm_pool *mem, const struct lv_segment *seg);
char *lvseg_tags_dup(const struct lv_segment *seg);
char *lvseg_devices(struct dm_pool *mem, const struct lv_segment *seg);
char *lvseg_metadata_devices(struct dm_pool *mem, const struct lv_segment *seg);
char *lvseg_seg_pe_ranges(struct dm_pool *mem, const struct lv_segment *seg);
char *lvseg_seg_metadata_le_ranges(struct dm_pool *mem, const struct lv_segment *seg);
char *lv_time_dup(struct dm_pool *mem, const struct logical_volume *lv, int iso_mode);
char *lv_host_dup(struct dm_pool *mem, const struct logical_volume *lv);
int lv_set_creation(struct logical_volume *lv,

View File

@@ -129,6 +129,8 @@ enum {
LV_TYPE_RAID6_ZR,
LV_TYPE_RAID6_NR,
LV_TYPE_RAID6_NC,
LV_TYPE_LOCKD,
LV_TYPE_SANLOCK
};
static const char *_lv_type_names[] = {
@@ -173,6 +175,8 @@ static const char *_lv_type_names[] = {
[LV_TYPE_RAID6_ZR] = SEG_TYPE_NAME_RAID6_ZR,
[LV_TYPE_RAID6_NR] = SEG_TYPE_NAME_RAID6_NR,
[LV_TYPE_RAID6_NC] = SEG_TYPE_NAME_RAID6_NC,
[LV_TYPE_LOCKD] = "lockd",
[LV_TYPE_SANLOCK] = "sanlock",
};
static int _lv_layout_and_role_mirror(struct dm_pool *mem,
@@ -224,7 +228,7 @@ static int _lv_layout_and_role_raid(struct dm_pool *mem,
int *public_lv)
{
int top_level = 0;
const char *seg_name;
const struct segment_type *segtype;
/* non-top-level LVs */
if (lv_is_raid_image(lv)) {
@@ -251,45 +255,45 @@ static int _lv_layout_and_role_raid(struct dm_pool *mem,
if (!str_list_add_no_dup_check(mem, layout, _lv_type_names[LV_TYPE_RAID]))
goto_bad;
seg_name = first_seg(lv)->segtype->name;
segtype = first_seg(lv)->segtype;
if (!strcmp(seg_name, SEG_TYPE_NAME_RAID1)) {
if (segtype_is_raid1(segtype)) {
if (!str_list_add_no_dup_check(mem, layout, _lv_type_names[LV_TYPE_RAID1]))
goto_bad;
} else if (!strcmp(seg_name, SEG_TYPE_NAME_RAID10)) {
} else if (segtype_is_raid10(segtype)) {
if (!str_list_add_no_dup_check(mem, layout, _lv_type_names[LV_TYPE_RAID10]))
goto_bad;
} else if (!strcmp(seg_name, SEG_TYPE_NAME_RAID4)) {
} else if (segtype_is_raid4(segtype)) {
if (!str_list_add_no_dup_check(mem, layout, _lv_type_names[LV_TYPE_RAID4]))
goto_bad;
} else if (!strncmp(seg_name, SEG_TYPE_NAME_RAID5, strlen(SEG_TYPE_NAME_RAID5))) {
} else if (segtype_is_any_raid5(segtype)) {
if (!str_list_add_no_dup_check(mem, layout, _lv_type_names[LV_TYPE_RAID5]))
goto_bad;
if (!strcmp(seg_name, SEG_TYPE_NAME_RAID5_LA)) {
if (segtype_is_raid5_la(segtype)) {
if (!str_list_add_no_dup_check(mem, layout, _lv_type_names[LV_TYPE_RAID5_LA]))
goto_bad;
} else if (!strcmp(seg_name, SEG_TYPE_NAME_RAID5_RA)) {
} else if (segtype_is_raid5_ra(segtype)) {
if (!str_list_add_no_dup_check(mem, layout, _lv_type_names[LV_TYPE_RAID5_RA]))
goto_bad;
} else if (!strcmp(seg_name, SEG_TYPE_NAME_RAID5_LS)) {
} else if (segtype_is_raid5_ls(segtype)) {
if (!str_list_add_no_dup_check(mem, layout, _lv_type_names[LV_TYPE_RAID5_LS]))
goto_bad;
} else if (!strcmp(seg_name, SEG_TYPE_NAME_RAID5_RS)) {
} else if (segtype_is_raid5_rs(segtype)) {
if (!str_list_add_no_dup_check(mem, layout, _lv_type_names[LV_TYPE_RAID5_RS]))
goto_bad;
}
} else if (!strncmp(seg_name, SEG_TYPE_NAME_RAID6, strlen(SEG_TYPE_NAME_RAID6))) {
} else if (segtype_is_any_raid6(segtype)) {
if (!str_list_add_no_dup_check(mem, layout, _lv_type_names[LV_TYPE_RAID6]))
goto_bad;
if (!strcmp(seg_name, SEG_TYPE_NAME_RAID6_ZR)) {
if (segtype_is_raid6_zr(segtype)) {
if (!str_list_add_no_dup_check(mem, layout, _lv_type_names[LV_TYPE_RAID6_ZR]))
goto_bad;
} else if (!strcmp(seg_name, SEG_TYPE_NAME_RAID6_NR)) {
} else if (segtype_is_raid6_nr(segtype)) {
if (!str_list_add_no_dup_check(mem, layout, _lv_type_names[LV_TYPE_RAID6_NR]))
goto_bad;
} else if (!strcmp(seg_name, SEG_TYPE_NAME_RAID6_NC)) {
} else if (segtype_is_raid6_nc(segtype)) {
if (!str_list_add_no_dup_check(mem, layout, _lv_type_names[LV_TYPE_RAID6_NC]))
goto_bad;
}
@@ -505,6 +509,13 @@ int lv_layout_and_role(struct dm_pool *mem, const struct logical_volume *lv,
if (!_lv_layout_and_role_thick_origin_snapshot(mem, lv, *layout, *role, &public_lv))
goto_bad;
if (lv_is_lockd_sanlock_lv(lv)) {
if (!str_list_add_no_dup_check(mem, *role, _lv_type_names[LV_TYPE_LOCKD]) ||
!str_list_add_no_dup_check(mem, *role, _lv_type_names[LV_TYPE_SANLOCK]))
goto_bad;
public_lv = 0;
}
/*
* If layout not yet determined, it must be either
* linear or striped or mixture of these two.
@@ -780,7 +791,7 @@ int get_default_region_size(struct cmd_context *cmd)
if (region_size & (region_size - 1)) {
region_size = _round_down_pow2(region_size);
log_verbose("Reducing mirror region size to %u kiB (power of 2).",
log_verbose("Reducing region size to %u kiB (power of 2).",
region_size / 2);
}
@@ -930,7 +941,7 @@ dm_percent_t copy_percent(const struct logical_volume *lv)
dm_list_iterate_items(seg, &lv->segments) {
denominator += seg->area_len;
/* FIXME Generalise name of 'extents_copied' field */
/* FIXME Generalise name of 'extents_copied' field */
if ((seg_is_raid(seg) || seg_is_mirrored(seg)) &&
(seg->area_count > 1))
numerator += seg->extents_copied;
@@ -938,7 +949,27 @@ dm_percent_t copy_percent(const struct logical_volume *lv)
numerator += seg->area_len;
}
return denominator ? dm_make_percent( numerator, denominator ) : 100.0;
return denominator ? dm_make_percent(numerator, denominator) : 100.0;
}
/* Round up extents to next stripe boundary for number of stripes */
static uint32_t _round_to_stripe_boundary(struct volume_group *vg, uint32_t extents,
uint32_t stripes, int extend)
{
uint32_t size_rest, new_extents = extents;
if (!stripes)
return extents;
/* Round up extents to stripe divisible amount */
if ((size_rest = extents % stripes)) {
new_extents += extend ? stripes - size_rest : -size_rest;
log_print_unless_silent("Rounding size %s (%d extents) up to stripe boundary size %s (%d extents).",
display_size(vg->cmd, extents * vg->extent_size), extents,
display_size(vg->cmd, new_extents * vg->extent_size), new_extents);
}
return new_extents;
}
/*
@@ -1013,7 +1044,7 @@ struct lv_segment *alloc_snapshot_seg(struct logical_volume *lv,
struct lv_segment *seg;
const struct segment_type *segtype;
segtype = get_segtype_from_string(lv->vg->cmd, "snapshot");
segtype = get_segtype_from_string(lv->vg->cmd, SEG_TYPE_NAME_SNAPSHOT);
if (!segtype) {
log_error("Failed to find snapshot segtype");
return NULL;
@@ -1037,6 +1068,7 @@ static int _release_and_discard_lv_segment_area(struct lv_segment *seg, uint32_t
uint32_t area_reduction, int with_discard)
{
struct lv_segment *cache_seg;
struct logical_volume *lv = seg_lv(seg, s);
if (seg_type(seg, s) == AREA_UNASSIGNED)
return 1;
@@ -1054,10 +1086,10 @@ static int _release_and_discard_lv_segment_area(struct lv_segment *seg, uint32_t
return 1;
}
if (lv_is_mirror_image(seg_lv(seg, s)) ||
lv_is_thin_pool_data(seg_lv(seg, s)) ||
lv_is_cache_pool_data(seg_lv(seg, s))) {
if (!lv_reduce(seg_lv(seg, s), area_reduction))
if (lv_is_mirror_image(lv) ||
lv_is_thin_pool_data(lv) ||
lv_is_cache_pool_data(lv)) {
if (!lv_reduce(lv, area_reduction))
return_0; /* FIXME: any upper level reporting */
return 1;
}
@@ -1071,20 +1103,20 @@ static int _release_and_discard_lv_segment_area(struct lv_segment *seg, uint32_t
return_0;
}
if (lv_is_raid_image(seg_lv(seg, s))) {
if (lv_is_raid_image(lv)) {
/*
* FIXME: Use lv_reduce not lv_remove
* We use lv_remove for now, because I haven't figured out
* why lv_reduce won't remove the LV.
lv_reduce(seg_lv(seg, s), area_reduction);
lv_reduce(lv, area_reduction);
*/
if (area_reduction != seg->area_len) {
log_error("Unable to reduce RAID LV - operation not implemented.");
return_0;
} else {
if (!lv_remove(seg_lv(seg, s))) {
if (!lv_remove(lv)) {
log_error("Failed to remove RAID image %s",
seg_lv(seg, s)->name);
lv->name);
return 0;
}
}
@@ -1105,9 +1137,9 @@ static int _release_and_discard_lv_segment_area(struct lv_segment *seg, uint32_t
log_very_verbose("Remove %s:%" PRIu32 "[%" PRIu32 "] from "
"the top of LV %s:%" PRIu32,
seg->lv->name, seg->le, s,
seg_lv(seg, s)->name, seg_le(seg, s));
lv->name, seg_le(seg, s));
if (!remove_seg_from_segs_using_this_lv(seg_lv(seg, s), seg))
if (!remove_seg_from_segs_using_this_lv(lv, seg))
return_0;
seg_lv(seg, s) = NULL;
seg_le(seg, s) = 0;
@@ -1243,6 +1275,51 @@ static int _lv_segment_add_areas(struct logical_volume *lv,
return 1;
}
static uint32_t _calc_area_multiple(const struct segment_type *segtype,
const uint32_t area_count,
const uint32_t stripes)
{
if (!area_count)
return 1;
/* Striped */
if (segtype_is_striped(segtype))
return area_count;
/* Parity RAID (e.g. RAID 4/5/6) */
if (segtype_is_raid(segtype) && segtype->parity_devs) {
/*
* As articulated in _alloc_init, we can tell by
* the area_count whether a replacement drive is
* being allocated; and if this is the case, then
* there is no area_multiple that should be used.
*/
if (area_count <= segtype->parity_devs)
return 1;
return area_count - segtype->parity_devs;
}
/*
* RAID10 - only has 2-way mirror right now.
* If we are to move beyond 2-way RAID10, then
* the 'stripes' argument will always need to
* be given.
*/
if (!strcmp(segtype->name, _lv_type_names[LV_TYPE_RAID10])) {
if (!stripes)
return area_count / 2;
return stripes;
}
/* Mirrored stripes */
if (stripes)
return stripes;
/* Mirrored */
return 1;
}
/*
* Reduce the size of an lv_segment. New size can be zero.
*/
@@ -1393,7 +1470,7 @@ int replace_lv_with_error_segment(struct logical_volume *lv)
/* FIXME Check for any attached LVs that will become orphans e.g. mirror logs */
if (!lv_add_virtual_segment(lv, 0, len, get_segtype_from_string(lv->vg->cmd, "error")))
if (!lv_add_virtual_segment(lv, 0, len, get_segtype_from_string(lv->vg->cmd, SEG_TYPE_NAME_ERROR)))
return_0;
return 1;
@@ -1460,10 +1537,10 @@ struct alloc_handle {
struct dm_pool *mem;
alloc_policy_t alloc; /* Overall policy */
int approx_alloc; /* get as much as possible up to new_extents */
int approx_alloc; /* get as much as possible up to new_extents */
uint32_t new_extents; /* Number of new extents required */
uint32_t area_count; /* Number of parallel areas */
uint32_t parity_count; /* Adds to area_count, but not area_multiple */
uint32_t parity_count; /* Adds to area_count, but not area_multiple */
uint32_t area_multiple; /* seg->len = area_len * area_multiple */
uint32_t log_area_count; /* Number of parallel logs */
uint32_t metadata_area_count; /* Number of parallel metadata areas */
@@ -1498,50 +1575,6 @@ struct alloc_handle {
struct dm_list alloced_areas[0];
};
static uint32_t _calc_area_multiple(const struct segment_type *segtype,
const uint32_t area_count,
const uint32_t stripes)
{
if (!area_count)
return 1;
/* Striped */
if (segtype_is_striped(segtype))
return area_count;
/* Parity RAID (e.g. RAID 4/5/6) */
if (segtype_is_raid(segtype) && segtype->parity_devs) {
/*
* As articulated in _alloc_init, we can tell by
* the area_count whether a replacement drive is
* being allocated; and if this is the case, then
* there is no area_multiple that should be used.
*/
if (area_count <= segtype->parity_devs)
return 1;
return area_count - segtype->parity_devs;
}
/*
* RAID10 - only has 2-way mirror right now.
* If we are to move beyond 2-way RAID10, then
* the 'stripes' argument will always need to
* be given.
*/
if (!strcmp(segtype->name, _lv_type_names[LV_TYPE_RAID10])) {
if (!stripes)
return area_count / 2;
return stripes;
}
/* Mirrored stripes */
if (stripes)
return stripes;
/* Mirrored */
return 1;
}
/*
* Returns log device size in extents, algorithm from kernel code
*/
@@ -1583,7 +1616,7 @@ static int _sufficient_pes_free(struct alloc_handle *ah, struct dm_list *pvms,
{
uint32_t area_extents_needed = (extents_still_needed - allocated) * ah->area_count / ah->area_multiple;
uint32_t parity_extents_needed = (extents_still_needed - allocated) * ah->parity_count / ah->area_multiple;
uint32_t metadata_extents_needed = (ah->alloc_and_split_meta) ? 0 : ah->metadata_area_count * RAID_METADATA_AREA_LEN; /* One each */
uint32_t metadata_extents_needed = ah->alloc_and_split_meta ? 0 : ah->metadata_area_count * RAID_METADATA_AREA_LEN; /* One each */
uint32_t total_extents_needed = area_extents_needed + parity_extents_needed + metadata_extents_needed;
uint32_t free_pes = pv_maps_size(pvms);
@@ -1726,9 +1759,9 @@ static int _setup_alloced_segment(struct logical_volume *lv, uint64_t status,
struct lv_segment *seg;
area_multiple = _calc_area_multiple(segtype, area_count, 0);
extents = aa[0].len * area_multiple;
if (!(seg = alloc_lv_segment(segtype, lv, lv->le_count,
aa[0].len * area_multiple,
if (!(seg = alloc_lv_segment(segtype, lv, lv->le_count, extents,
status, stripe_size, NULL,
area_count,
aa[0].len, 0u, region_size, 0u, NULL))) {
@@ -1744,7 +1777,7 @@ static int _setup_alloced_segment(struct logical_volume *lv, uint64_t status,
extents = aa[0].len * area_multiple;
lv->le_count += extents;
lv->size += (uint64_t) extents *lv->vg->extent_size;
lv->size += (uint64_t) extents * lv->vg->extent_size;
return 1;
}
@@ -1910,7 +1943,7 @@ static int _for_each_pv(struct cmd_context *cmd, struct logical_volume *lv,
*max_seg_len = remaining_seg_len;
area_multiple = _calc_area_multiple(seg->segtype, seg->area_count, 0);
area_len = remaining_seg_len / area_multiple ? : 1;
area_len = (remaining_seg_len / area_multiple) ? : 1;
/* For striped mirrors, all the areas are counted, through the mirror layer */
if (top_level_area_index == -1)
@@ -2956,7 +2989,7 @@ static int _allocate(struct alloc_handle *ah,
if (ah->area_multiple > 1 &&
(ah->new_extents - alloc_state.allocated) % ah->area_multiple) {
log_error("Number of extents requested (%d) needs to be divisible by %d.",
log_error("Number of extents requested (" FMTu32 ") needs to be divisible by " FMTu32 ".",
ah->new_extents - alloc_state.allocated,
ah->area_multiple);
return 0;
@@ -3401,7 +3434,7 @@ static struct lv_segment *_convert_seg_to_mirror(struct lv_segment *seg,
return NULL;
}
if (!(newseg = alloc_lv_segment(get_segtype_from_string(seg->lv->vg->cmd, "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->status, seg->stripe_size,
log_lv,
@@ -3494,7 +3527,7 @@ int lv_add_segmented_mirror_image(struct alloc_handle *ah,
if (!lv_add_mirror_lvs(lv, &copy_lv, 1, MIRROR_IMAGE, region_size))
return_0;
if (!(segtype = get_segtype_from_string(lv->vg->cmd, "striped")))
if (!(segtype = get_segtype_from_string(lv->vg->cmd, SEG_TYPE_NAME_STRIPED)))
return_0;
dm_list_iterate_items(aa, &ah->alloced_areas[0]) {
@@ -3608,7 +3641,7 @@ int lv_add_mirror_lvs(struct logical_volume *lv,
return 0;
}
mirror_segtype = get_segtype_from_string(lv->vg->cmd, "mirror");
mirror_segtype = get_segtype_from_string(lv->vg->cmd, SEG_TYPE_NAME_MIRROR);
if (seg->segtype != mirror_segtype)
if (!(seg = _convert_seg_to_mirror(seg, region_size, NULL)))
return_0;
@@ -3667,8 +3700,7 @@ int lv_add_log_segment(struct alloc_handle *ah, uint32_t first_area,
{
return lv_add_segment(ah, ah->area_count + first_area, 1, log_lv,
get_segtype_from_string(log_lv->vg->cmd,
"striped"),
get_segtype_from_string(log_lv->vg->cmd, SEG_TYPE_NAME_STRIPED),
0, status, 0);
}
@@ -3765,23 +3797,23 @@ static int _lv_extend_layered_lv(struct alloc_handle *ah,
{
const struct segment_type *segtype;
struct logical_volume *sub_lv, *meta_lv;
struct lv_segment *seg;
struct lv_segment *seg = first_seg(lv);
uint32_t fa, s;
int clear_metadata = 0;
segtype = get_segtype_from_string(lv->vg->cmd, "striped");
if (!(segtype = get_segtype_from_string(lv->vg->cmd, SEG_TYPE_NAME_STRIPED)))
return_0;
/*
* The component devices of a "striped" LV all go in the same
* LV. However, RAID has an LV for each device - making the
* 'stripes' and 'stripe_size' parameters meaningless.
*/
if (seg_is_raid(first_seg(lv))) {
if (seg_is_raid(seg)) {
stripes = 1;
stripe_size = 0;
}
seg = first_seg(lv);
for (fa = first_area, s = 0; s < seg->area_count; s++) {
if (is_temporary_mirror_layer(seg_lv(seg, s))) {
if (!_lv_extend_layered_lv(ah, seg_lv(seg, s), extents,
@@ -4392,6 +4424,25 @@ static int _fsadm_cmd(struct cmd_context *cmd,
return exec_cmd(cmd, argv, status, 1);
}
static int _adjust_amount(dm_percent_t percent, int policy_threshold, int *policy_amount)
{
if (!(DM_PERCENT_0 < percent && percent <= DM_PERCENT_100) ||
percent <= (policy_threshold * DM_PERCENT_1))
return 0;
/*
* Evaluate the minimal amount needed to get bellow threshold.
* Keep using DM_PERCENT_1 units for better precision.
* Round-up to needed percentage value
*/
percent = (percent/policy_threshold + (DM_PERCENT_1 - 1) / 100) / (DM_PERCENT_1 / 100) - 100;
/* Use it if current policy amount is smaller */
if (*policy_amount < percent)
*policy_amount = percent;
return 1;
}
static int _adjust_policy_params(struct cmd_context *cmd,
struct logical_volume *lv, struct lvresize_params *lp)
{
@@ -4401,23 +4452,34 @@ static int _adjust_policy_params(struct cmd_context *cmd,
if (lv_is_thin_pool(lv)) {
policy_threshold =
find_config_tree_int(cmd, activation_thin_pool_autoextend_threshold_CFG,
lv_config_profile(lv)) * DM_PERCENT_1;
lv_config_profile(lv));
policy_amount =
find_config_tree_int(cmd, activation_thin_pool_autoextend_percent_CFG,
lv_config_profile(lv));
if (!policy_amount && policy_threshold < DM_PERCENT_100) {
log_error("Can't extend thin pool %s, autoextend is set to 0%%.",
display_lvname(lv));
return 0;
if (policy_threshold < 50) {
log_warn("WARNING: Thin pool autoextend threshold %d%% is set below "
"minimum supported 50%%.", policy_threshold);
policy_threshold = 50;
}
} else {
policy_threshold =
find_config_tree_int(cmd, activation_snapshot_autoextend_threshold_CFG, NULL) * DM_PERCENT_1;
find_config_tree_int(cmd, activation_snapshot_autoextend_threshold_CFG, NULL);
policy_amount =
find_config_tree_int(cmd, activation_snapshot_autoextend_percent_CFG, NULL);
if (policy_threshold < 50) {
log_warn("WARNING: Snapshot autoextend threshold %d%% is set bellow "
"minimal supported value 50%%.", policy_threshold);
policy_threshold = 50;
}
}
if (policy_threshold >= DM_PERCENT_100)
if (!policy_amount && policy_threshold < 100) {
log_error("Can't extend %s with %s autoextend percent set to 0%%.",
display_lvname(lv), first_seg(lv)->segtype->name);
return 0;
}
if (policy_threshold >= 100)
return 1; /* nothing to do */
if (!lv_is_active_locally(lv)) {
@@ -4429,30 +4491,26 @@ static int _adjust_policy_params(struct cmd_context *cmd,
if (lv_is_thin_pool(lv)) {
if (!lv_thin_pool_percent(lv, 1, &percent))
return_0;
if ((DM_PERCENT_0 < percent && percent <= DM_PERCENT_100) &&
(percent > policy_threshold)) {
if (_adjust_amount(percent, policy_threshold, &policy_amount)) {
if (!thin_pool_feature_supported(lv, THIN_FEATURE_METADATA_RESIZE)) {
log_error_once("Online metadata resize for %s/%s is not supported.",
lv->vg->name, lv->name);
log_error_once("Online metadata resize for %s is not supported.",
display_lvname(lv));
return 0;
}
lp->poolmetadatasize = (first_seg(lv)->metadata_lv->size *
policy_amount + 99) / 100;
lp->poolmetadatasign = SIGN_PLUS;
}
if (!lv_thin_pool_percent(lv, 0, &percent))
return_0;
if (!(DM_PERCENT_0 < percent && percent <= DM_PERCENT_100) ||
percent <= policy_threshold)
return 1;
} else {
if (!lv_snapshot_percent(lv, &percent))
return_0;
if (!(DM_PERCENT_0 < percent && percent <= DM_PERCENT_100) || percent <= policy_threshold)
return 1; /* nothing to do */
}
if (!_adjust_amount(percent, policy_threshold, &policy_amount))
return 1; /* nothing to do */
lp->extents = policy_amount;
lp->sizeargs = (lp->extents) ? 1 : 0;
@@ -4547,7 +4605,7 @@ static int _lvresize_poolmetadata(struct cmd_context *cmd, struct volume_group *
struct dm_list *pvh)
{
struct logical_volume *lv = first_seg(pool_lv)->metadata_lv;
alloc_policy_t alloc = lp->ac_alloc ?: lv->alloc;
alloc_policy_t alloc = lp->ac_alloc ? : lv->alloc;
struct lv_segment *mseg = last_seg(lv);
uint32_t seg_mirrors = lv_mirror_count(lv);
@@ -5156,7 +5214,7 @@ static struct logical_volume *_lvresize_volume(struct cmd_context *cmd,
/* Switch to layered LV resizing */
lv = seg_lv(seg, 0);
}
alloc = lp->ac_alloc ?: lv->alloc;
alloc = lp->ac_alloc ? : lv->alloc;
if ((lp->resize == LV_REDUCE) && lp->argc)
log_print_unless_silent("Ignoring PVs on command line when reducing.");
@@ -5173,7 +5231,7 @@ static struct logical_volume *_lvresize_volume(struct cmd_context *cmd,
log_error("Filesystem check failed.");
return NULL;
}
/* some filesystems supports online resize */
/* some filesystems support online resize */
}
/* FIXME forks here */
@@ -6209,7 +6267,7 @@ int remove_layers_for_segments(struct cmd_context *cmd,
/* Replace mirror with error segment */
if (!(lseg->segtype =
get_segtype_from_string(lv->vg->cmd, "error"))) {
get_segtype_from_string(lv->vg->cmd, SEG_TYPE_NAME_ERROR))) {
log_error("Missing error segtype");
return 0;
}
@@ -6343,7 +6401,7 @@ int remove_layer_from_lv(struct logical_volume *lv,
return_0;
/* Replace the empty layer with error segment */
if (!(segtype = get_segtype_from_string(lv->vg->cmd, "error")))
if (!(segtype = get_segtype_from_string(lv->vg->cmd, SEG_TYPE_NAME_ERROR)))
return_0;
if (!lv_add_virtual_segment(layer_lv, 0, parent_lv->le_count, segtype))
return_0;
@@ -6407,7 +6465,7 @@ struct logical_volume *insert_layer_for_lv(struct cmd_context *cmd,
if (lv_is_active(lv_where) && strstr(name, "_mimagetmp")) {
log_very_verbose("Creating transient LV %s for mirror conversion in VG %s.", name, lv_where->vg->name);
segtype = get_segtype_from_string(cmd, "error");
segtype = get_segtype_from_string(cmd, SEG_TYPE_NAME_ERROR);
if (!lv_add_virtual_segment(layer_lv, 0, lv_where->le_count, segtype)) {
log_error("Creation of transient LV %s for mirror conversion in VG %s failed.", name, lv_where->vg->name);
@@ -6455,7 +6513,7 @@ struct logical_volume *insert_layer_for_lv(struct cmd_context *cmd,
if (!move_lv_segments(layer_lv, lv_where, 0, 0))
return_NULL;
if (!(segtype = get_segtype_from_string(cmd, "striped")))
if (!(segtype = get_segtype_from_string(cmd, SEG_TYPE_NAME_STRIPED)))
return_NULL;
/* allocate a new linear segment */
@@ -6505,7 +6563,7 @@ static int _extend_layer_lv_for_segment(struct logical_volume *layer_lv,
if (seg_type(seg, s) != AREA_PV && seg_type(seg, s) != AREA_LV)
return_0;
if (!(segtype = get_segtype_from_string(layer_lv->vg->cmd, "striped")))
if (!(segtype = get_segtype_from_string(layer_lv->vg->cmd, SEG_TYPE_NAME_STRIPED)))
return_0;
/* FIXME Incomplete message? Needs more context */
@@ -6778,7 +6836,7 @@ static struct logical_volume *_create_virtual_origin(struct cmd_context *cmd,
char vorigin_name[NAME_LEN];
struct logical_volume *lv;
if (!(segtype = get_segtype_from_string(cmd, "zero"))) {
if (!(segtype = get_segtype_from_string(cmd, SEG_TYPE_NAME_ZERO))) {
log_error("Zero segment type for virtual origin not found");
return NULL;
}
@@ -6932,7 +6990,7 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
const char *new_lv_name)
{
struct cmd_context *cmd = vg->cmd;
uint32_t size_rest, size;
uint32_t size;
uint64_t status = lp->permission | VISIBLE_LV;
const struct segment_type *create_segtype = lp->segtype;
struct logical_volume *lv, *origin_lv = NULL;
@@ -6997,12 +7055,7 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
lp->stripe_size = vg->extent_size;
}
if ((size_rest = lp->extents % lp->stripes)) {
log_print_unless_silent("Rounding size (%d extents) up to stripe boundary "
"size (%d extents).", lp->extents,
lp->extents - size_rest + lp->stripes);
lp->extents = lp->extents - size_rest + lp->stripes;
}
lp->extents = _round_to_stripe_boundary(vg, lp->extents, lp->stripes, 1);
if (!lp->extents && !seg_is_thin_volume(lp)) {
log_error(INTERNAL_ERROR "Unable to create new logical volume with no extents.");
@@ -7060,12 +7113,25 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
}
}
if (seg_is_thin_volume(lp) &&
lv_is_new_thin_pool(pool_lv)) {
if (seg_is_thin_volume(lp)) {
thin_pool_was_active = lv_is_active(pool_lv);
if (!check_new_thin_pool(pool_lv))
return_NULL;
/* New pool is now inactive */
if (lv_is_new_thin_pool(pool_lv)) {
if (!check_new_thin_pool(pool_lv))
return_NULL;
/* New pool is now inactive */
} else {
if (!activate_lv_excl_local(cmd, pool_lv)) {
log_error("Aborting. Failed to locally activate thin pool %s.",
display_lvname(pool_lv));
return 0;
}
if (!pool_below_threshold(first_seg(pool_lv))) {
log_error("Cannot create new thin volume, free space in "
"thin pool %s reached threshold.",
display_lvname(pool_lv));
return NULL;
}
}
}
if (seg_is_cache(lp) &&
@@ -7113,7 +7179,7 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
}
/* Create cache origin for cache pool */
/* FIXME Eventually support raid/mirrors with -m */
if (!(create_segtype = get_segtype_from_string(vg->cmd, "striped")))
if (!(create_segtype = get_segtype_from_string(vg->cmd, SEG_TYPE_NAME_STRIPED)))
return_0;
} else if (seg_is_mirrored(lp) || seg_is_raid(lp)) {
if (is_change_activating(lp->activate) && (lp->activate != CHANGE_AEY) &&
@@ -7182,8 +7248,7 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
return NULL;
}
if (lv_is_cow(origin_lv)) {
log_error("Snapshots of snapshots are not "
"supported yet.");
log_error("Snapshots of snapshots are not supported.");
return NULL;
}
if (lv_is_locked(origin_lv)) {
@@ -7229,7 +7294,7 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
return_NULL;
/* The snapshot segment gets created later */
if (!(create_segtype = get_segtype_from_string(cmd, "striped")))
if (!(create_segtype = get_segtype_from_string(cmd, SEG_TYPE_NAME_STRIPED)))
return_NULL;
/* Must zero cow */
@@ -7323,8 +7388,6 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
first_seg(lv)->chunk_size = lp->chunk_size;
first_seg(lv)->zero_new_blocks = lp->zero ? 1 : 0;
first_seg(lv)->discards = lp->discards;
/* FIXME: use lowwatermark via lvm.conf global for all thinpools ? */
first_seg(lv)->low_water_mark = 0;
if (!recalculate_pool_chunk_size_with_dev_hints(lv, lp->passed_args,
lp->thin_chunk_size_calc_policy)) {
stack;
@@ -7626,7 +7689,7 @@ struct logical_volume *lv_create_single(struct volume_group *vg,
if (lp->create_pool && !seg_is_pool(lp)) {
segtype = lp->segtype;
if (seg_is_thin_volume(lp)) {
if (!(lp->segtype = get_segtype_from_string(vg->cmd, "thin-pool")))
if (!(lp->segtype = get_segtype_from_string(vg->cmd, SEG_TYPE_NAME_THIN_POOL)))
return_NULL;
if (!(lv = _lv_create_an_lv(vg, lp, lp->pool_name)))
@@ -7638,7 +7701,7 @@ struct logical_volume *lv_create_single(struct volume_group *vg,
return NULL;
}
/* origin_name is defined -> creates cache LV with new cache pool */
if (!(lp->segtype = get_segtype_from_string(vg->cmd, "cache-pool")))
if (!(lp->segtype = get_segtype_from_string(vg->cmd, SEG_TYPE_NAME_CACHE_POOL)))
return_NULL;
if (!(lv = _lv_create_an_lv(vg, lp, lp->pool_name)))

View File

@@ -163,10 +163,9 @@
/* vg_read and vg_read_for_update flags */
#define READ_ALLOW_INCONSISTENT 0x00010000U
#define READ_ALLOW_EXPORTED 0x00020000U
#define READ_OK_NOTFOUND 0x00040000U
#define READ_WARN_INCONSISTENT 0x00080000U
/* A meta-flag, useful with toollib for_each_* functions. */
#define READ_FOR_UPDATE 0x00100000U
#define READ_FOR_UPDATE 0x00100000U /* A meta-flag, useful with toollib for_each_* functions. */
/* vg's "read_status" field */
#define FAILED_INCONSISTENT 0x00000001U
@@ -455,7 +454,6 @@ struct lv_segment {
struct lv_segment_area *meta_areas; /* For RAID */
struct logical_volume *metadata_lv; /* For thin_pool */
uint64_t transaction_id; /* For thin_pool, thin */
uint64_t low_water_mark; /* For thin_pool */
unsigned zero_new_blocks; /* For thin_pool */
thin_discards_t discards; /* For thin_pool */
struct dm_list thin_messages; /* For thin_pool */
@@ -650,9 +648,9 @@ int lv_resize(struct cmd_context *cmd, struct logical_volume *lv,
* Return a handle to VG metadata.
*/
struct volume_group *vg_read(struct cmd_context *cmd, const char *vg_name,
const char *vgid, uint32_t flags, uint32_t lockd_state);
const char *vgid, uint32_t read_flags, uint32_t lockd_state);
struct volume_group *vg_read_for_update(struct cmd_context *cmd, const char *vg_name,
const char *vgid, uint32_t flags, uint32_t lockd_state);
const char *vgid, uint32_t read_flags, uint32_t lockd_state);
/*
* Test validity of a VG handle.

View File

@@ -4925,7 +4925,7 @@ static int _vg_access_permitted(struct cmd_context *cmd, struct volume_group *vg
* Consolidated locking, reading, and status flag checking.
*
* If the metadata is inconsistent, setting READ_ALLOW_INCONSISTENT in
* misc_flags will return it with FAILED_INCONSISTENT set instead of
* read_flags will return it with FAILED_INCONSISTENT set instead of
* giving you nothing.
*
* Use vg_read_error(vg) to determine the result. Nonzero means there were
@@ -4933,8 +4933,10 @@ static int _vg_access_permitted(struct cmd_context *cmd, struct volume_group *vg
* Zero value means that the VG is open and appropriate locks are held.
*/
static struct volume_group *_vg_lock_and_read(struct cmd_context *cmd, const char *vg_name,
const char *vgid, uint32_t lock_flags,
uint64_t status_flags, uint32_t misc_flags,
const char *vgid,
uint32_t lock_flags,
uint64_t status_flags,
uint32_t read_flags,
uint32_t lockd_state)
{
struct volume_group *vg = NULL;
@@ -4944,7 +4946,7 @@ static struct volume_group *_vg_lock_and_read(struct cmd_context *cmd, const cha
uint32_t warn_flags = 0;
int already_locked;
if (misc_flags & READ_ALLOW_INCONSISTENT || lock_flags != LCK_VG_WRITE)
if ((read_flags & READ_ALLOW_INCONSISTENT) || (lock_flags != LCK_VG_WRITE))
consistent = 0;
if (!validate_name(vg_name) && !is_orphan_vg(vg_name)) {
@@ -4967,7 +4969,7 @@ static struct volume_group *_vg_lock_and_read(struct cmd_context *cmd, const cha
consistent_in = consistent;
warn_flags = WARN_PV_READ;
if (consistent || (misc_flags & READ_WARN_INCONSISTENT))
if (consistent || (read_flags & READ_WARN_INCONSISTENT))
warn_flags |= WARN_INCONSISTENT;
/* If consistent == 1, we get NULL here if correction fails. */
@@ -4976,7 +4978,8 @@ static struct volume_group *_vg_lock_and_read(struct cmd_context *cmd, const cha
failure |= FAILED_INCONSISTENT;
goto bad;
}
log_error("Volume group \"%s\" not found", vg_name);
if (!(read_flags & READ_OK_NOTFOUND))
log_error("Volume group \"%s\" not found", vg_name);
failure |= FAILED_NOTFOUND;
goto bad;
}
@@ -5057,20 +5060,20 @@ bad_no_unlock:
* *consistent = 1.
*/
struct volume_group *vg_read(struct cmd_context *cmd, const char *vg_name,
const char *vgid, uint32_t flags, uint32_t lockd_state)
const char *vgid, uint32_t read_flags, uint32_t lockd_state)
{
uint64_t status = UINT64_C(0);
uint64_t status_flags = UINT64_C(0);
uint32_t lock_flags = LCK_VG_READ;
if (flags & READ_FOR_UPDATE) {
status |= EXPORTED_VG | LVM_WRITE;
if (read_flags & READ_FOR_UPDATE) {
status_flags |= EXPORTED_VG | LVM_WRITE;
lock_flags = LCK_VG_WRITE;
}
if (flags & READ_ALLOW_EXPORTED)
status &= ~EXPORTED_VG;
if (read_flags & READ_ALLOW_EXPORTED)
status_flags &= ~EXPORTED_VG;
return _vg_lock_and_read(cmd, vg_name, vgid, lock_flags, status, flags, lockd_state);
return _vg_lock_and_read(cmd, vg_name, vgid, lock_flags, status_flags, read_flags, lockd_state);
}
/*
@@ -5079,9 +5082,9 @@ struct volume_group *vg_read(struct cmd_context *cmd, const char *vg_name,
* request the new metadata to be written and committed).
*/
struct volume_group *vg_read_for_update(struct cmd_context *cmd, const char *vg_name,
const char *vgid, uint32_t flags, uint32_t lockd_state)
const char *vgid, uint32_t read_flags, uint32_t lockd_state)
{
return vg_read(cmd, vg_name, vgid, flags | READ_FOR_UPDATE, lockd_state);
return vg_read(cmd, vg_name, vgid, read_flags | READ_FOR_UPDATE, lockd_state);
}
/*

View File

@@ -83,7 +83,7 @@ int cluster_mirror_is_available(struct cmd_context *cmd)
unsigned attr = 0;
const struct segment_type *segtype;
if (!(segtype = get_segtype_from_string(cmd, "mirror")))
if (!(segtype = get_segtype_from_string(cmd, SEG_TYPE_NAME_MIRROR)))
return_0;
if (!segtype->ops->target_present)
@@ -112,7 +112,7 @@ uint32_t lv_mirror_count(const struct logical_volume *lv)
seg = first_seg(lv);
/* FIXME: RAID10 only supports 2 copies right now */
if (!strcmp(seg->segtype->name, "raid10"))
if (seg_is_raid10(seg))
return 2;
if (lv_is_pvmove(lv))
@@ -1493,8 +1493,7 @@ static int _create_mimage_lvs(struct alloc_handle *ah,
}
} else {
if (!lv_add_segment(ah, m * stripes, stripes, img_lvs[m],
get_segtype_from_string(lv->vg->cmd,
"striped"),
get_segtype_from_string(lv->vg->cmd, SEG_TYPE_NAME_STRIPED),
stripe_size, 0, 0)) {
log_error("Aborting. Failed to add mirror image segment "
"to %s. Remove new LV and retry.",
@@ -1547,8 +1546,7 @@ int remove_mirrors_from_segments(struct logical_volume *lv,
seg->area_count = new_mirrors + 1;
if (!new_mirrors)
seg->segtype = get_segtype_from_string(lv->vg->cmd,
"striped");
seg->segtype = get_segtype_from_string(lv->vg->cmd, SEG_TYPE_NAME_STRIPED);
}
return 1;
@@ -1720,7 +1718,7 @@ int fixup_imported_mirrors(struct volume_group *vg)
dm_list_iterate_items(lvl, &vg->lvs) {
dm_list_iterate_items(seg, &lvl->lv->segments) {
if (seg->segtype !=
get_segtype_from_string(vg->cmd, "mirror"))
get_segtype_from_string(vg->cmd, SEG_TYPE_NAME_MIRROR))
continue;
if (seg->log_lv && !add_seg_to_segs_using_this_lv(seg->log_lv, seg))
@@ -1748,7 +1746,7 @@ static int _add_mirrors_that_preserve_segments(struct logical_volume *lv,
if (!(parallel_areas = build_parallel_areas_from_lv(lv, 1, 0)))
return_0;
if (!(segtype = get_segtype_from_string(cmd, "mirror")))
if (!(segtype = get_segtype_from_string(cmd, SEG_TYPE_NAME_MIRROR)))
return_0;
adjusted_region_size = adjusted_mirror_region_size(lv->vg->extent_size,
@@ -2033,7 +2031,7 @@ int add_mirror_log(struct cmd_context *cmd, struct logical_volume *lv,
if (!(parallel_areas = build_parallel_areas_from_lv(lv, 0, 0)))
return_0;
if (!(segtype = get_segtype_from_string(cmd, "mirror")))
if (!(segtype = get_segtype_from_string(cmd, SEG_TYPE_NAME_MIRROR)))
return_0;
if (activation() && segtype->ops->target_present &&
@@ -2106,7 +2104,7 @@ int add_mirror_images(struct cmd_context *cmd, struct logical_volume *lv,
if (!(parallel_areas = build_parallel_areas_from_lv(lv, 0, 0)))
return_0;
if (!(segtype = get_segtype_from_string(cmd, "mirror")))
if (!(segtype = get_segtype_from_string(cmd, SEG_TYPE_NAME_MIRROR)))
return_0;
ah = allocate_extents(lv->vg, NULL, segtype,

View File

@@ -438,7 +438,7 @@ int create_pool(struct logical_volume *pool_lv,
}
/* LV is not yet a pool, so it's extension from lvcreate */
if (!(striped = get_segtype_from_string(pool_lv->vg->cmd, "striped")))
if (!(striped = get_segtype_from_string(pool_lv->vg->cmd, SEG_TYPE_NAME_STRIPED)))
return_0;
if (activation() && striped->ops->target_present &&
@@ -561,7 +561,7 @@ struct logical_volume *alloc_pool_metadata(struct logical_volume *pool_lv,
.zero = 1,
};
if (!(lvc.segtype = get_segtype_from_string(pool_lv->vg->cmd, "striped")))
if (!(lvc.segtype = get_segtype_from_string(pool_lv->vg->cmd, SEG_TYPE_NAME_STRIPED)))
return_0;
/* FIXME: allocate properly space for metadata_lv */
@@ -597,7 +597,7 @@ static struct logical_volume *_alloc_pool_metadata_spare(struct volume_group *vg
.zero = 1,
};
if (!(lp.segtype = get_segtype_from_string(vg->cmd, "striped")))
if (!(lp.segtype = get_segtype_from_string(vg->cmd, SEG_TYPE_NAME_STRIPED)))
return_0;
/* FIXME: Maybe using silent mode ? */

View File

@@ -781,7 +781,7 @@ int pvremove_single(struct cmd_context *cmd, const char *pv_name,
goto out;
}
info = lvmcache_info_from_pvid(dev->pvid, 1);
info = lvmcache_info_from_pvid(dev->pvid, 0);
if (!dev_test_excl(dev)) {
/* FIXME Detect whether device-mapper is still using the device */

View File

@@ -408,7 +408,7 @@ static struct logical_volume *_alloc_image_component(struct logical_volume *lv,
return 0;
}
if (!(segtype = get_segtype_from_string(lv->vg->cmd, "striped")))
if (!(segtype = get_segtype_from_string(lv->vg->cmd, SEG_TYPE_NAME_STRIPED)))
return_0;
if (!lv_add_segment(ah, first_area, 1, tmp_lv, segtype, 0, status, 0)) {
@@ -460,9 +460,12 @@ static int _alloc_image_components(struct logical_volume *lv,
* individual devies, we must specify how large the individual device
* is along with the number we want ('count').
*/
extents = (segtype->parity_devs) ?
(lv->le_count / (seg->area_count - segtype->parity_devs)) :
lv->le_count;
if (segtype_is_raid10(segtype))
extents = lv->le_count / (seg->area_count / 2); /* we enforce 2 mirrors right now */
else
extents = (segtype->parity_devs) ?
(lv->le_count / (seg->area_count - segtype->parity_devs)) :
lv->le_count;
if (!(ah = allocate_extents(lv->vg, NULL, segtype, 0, count, count,
region_size, extents, pvs,
@@ -867,7 +870,7 @@ static int _raid_extract_images(struct logical_volume *lv, uint32_t new_count,
sizeof(*lvl_array) * extract * 2)))
return_0;
if (!(error_segtype = get_segtype_from_string(lv->vg->cmd, "error")))
if (!(error_segtype = get_segtype_from_string(lv->vg->cmd, SEG_TYPE_NAME_ERROR)))
return_0;
/*
@@ -1102,7 +1105,7 @@ int lv_raid_split(struct logical_volume *lv, const char *split_name,
}
if (!seg_is_mirrored(first_seg(lv)) ||
!strcmp(first_seg(lv)->segtype->name, SEG_TYPE_NAME_RAID10)) {
seg_is_raid10(first_seg(lv))) {
log_error("Unable to split logical volume of segment type, %s",
lvseg_name(first_seg(lv)));
return 0;
@@ -1475,13 +1478,11 @@ int lv_raid_reshape(struct logical_volume *lv,
return 0;
}
if (!strcmp(seg->segtype->name, "mirror") &&
(!strcmp(new_segtype->name, SEG_TYPE_NAME_RAID1)))
return _convert_mirror_to_raid1(lv, new_segtype);
if (seg_is_mirror(seg) && segtype_is_raid1(new_segtype))
return _convert_mirror_to_raid1(lv, new_segtype);
log_error("Converting the segment type for %s/%s from %s to %s"
" is not yet supported.", lv->vg->name, lv->name,
lvseg_name(seg), new_segtype->name);
log_error("Converting the segment type for %s/%s from %s to %s is not yet supported.",
lv->vg->name, lv->name, lvseg_name(seg), new_segtype->name);
return 0;
}
@@ -1663,7 +1664,7 @@ int lv_raid_replace(struct logical_volume *lv,
lvseg_name(raid_seg),
lv->vg->name, lv->name);
return 0;
} else if (!strcmp(raid_seg->segtype->name, SEG_TYPE_NAME_RAID10)) {
} else if (seg_is_raid10(raid_seg)) {
uint32_t i, rebuilds_per_group = 0;
/* FIXME: We only support 2-way mirrors in RAID10 currently */
uint32_t copies = 2;
@@ -1895,7 +1896,7 @@ static int _partial_raid_lv_is_redundant(const struct logical_volume *lv)
uint32_t i, s, rebuilds_per_group = 0;
uint32_t failed_components = 0;
if (!strcmp(raid_seg->segtype->name, SEG_TYPE_NAME_RAID10)) {
if (seg_is_raid10(raid_seg)) {
/* FIXME: We only support 2-way mirrors in RAID10 currently */
copies = 2;
for (i = 0; i < raid_seg->area_count * copies; i++) {

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004-2010 Red Hat, Inc. All rights reserved.
* Copyright (C) 2004-2015 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
@@ -28,32 +28,95 @@ struct dm_config_node;
struct dev_manager;
/* Feature flags */
#define SEG_CAN_SPLIT 0x00000001U
#define SEG_AREAS_STRIPED 0x00000002U
#define SEG_AREAS_MIRRORED 0x00000004U
#define SEG_SNAPSHOT 0x00000008U
#define SEG_FORMAT1_SUPPORT 0x00000010U
#define SEG_VIRTUAL 0x00000020U
#define SEG_CANNOT_BE_ZEROED 0x00000040U
#define SEG_MONITORED 0x00000080U
#define SEG_REPLICATOR 0x00000100U
#define SEG_REPLICATOR_DEV 0x00000200U
#define SEG_RAID 0x00000400U
#define SEG_THIN_POOL 0x00000800U
#define SEG_THIN_VOLUME 0x00001000U
#define SEG_CACHE 0x00002000U
#define SEG_CACHE_POOL 0x00004000U
#define SEG_MIRROR 0x00008000U
#define SEG_ONLY_EXCLUSIVE 0x00010000U /* In cluster only exlusive activation */
#define SEG_CAN_ERROR_WHEN_FULL 0x00020000U
#define SEG_UNKNOWN 0x80000000U
#define SEG_CAN_SPLIT 0x0000000000000001ULL
#define SEG_AREAS_STRIPED 0x0000000000000002ULL
#define SEG_AREAS_MIRRORED 0x0000000000000004ULL
#define SEG_SNAPSHOT 0x0000000000000008ULL
#define SEG_FORMAT1_SUPPORT 0x0000000000000010ULL
#define SEG_VIRTUAL 0x0000000000000020ULL
#define SEG_CANNOT_BE_ZEROED 0x0000000000000040ULL
#define SEG_MONITORED 0x0000000000000080ULL
#define SEG_REPLICATOR 0x0000000000000100ULL
#define SEG_REPLICATOR_DEV 0x0000000000000200ULL
#define SEG_RAID 0x0000000000000400ULL
#define SEG_THIN_POOL 0x0000000000000800ULL
#define SEG_THIN_VOLUME 0x0000000000001000ULL
#define SEG_CACHE 0x0000000000002000ULL
#define SEG_CACHE_POOL 0x0000000000004000ULL
#define SEG_MIRROR 0x0000000000008000ULL
#define SEG_ONLY_EXCLUSIVE 0x0000000000010000ULL /* In cluster only exlusive activation */
#define SEG_CAN_ERROR_WHEN_FULL 0x0000000000020000ULL
#define SEG_RAID1 0x0000000000100000ULL
#define SEG_RAID10 0x0000000000200000ULL
#define SEG_RAID4 0x0000000000400000ULL
#define SEG_RAID5_N 0x0000000000800000ULL
#define SEG_RAID5_LA 0x0000000001000000ULL
#define SEG_RAID5_LS 0x0000000002000000ULL
#define SEG_RAID5_RA 0x0000000004000000ULL
#define SEG_RAID5_RS 0x0000000008000000ULL
#define SEG_RAID5 SEG_RAID5_LS
#define SEG_RAID6_NC 0x0000000010000000ULL
#define SEG_RAID6_NR 0x0000000020000000ULL
#define SEG_RAID6_ZR 0x0000000040000000ULL
#define SEG_RAID6_LA_6 0x0000000080000000ULL
#define SEG_RAID6_LS_6 0x0000000100000000ULL
#define SEG_RAID6_RA_6 0x0000000200000000ULL
#define SEG_RAID6_RS_6 0x0000000400000000ULL
#define SEG_RAID6_N_6 0x0000000800000000ULL
#define SEG_RAID6 SEG_RAID6_ZR
#define SEG_UNKNOWN 0x8000000000000000ULL
#define SEG_TYPE_NAME_LINEAR "linear"
#define SEG_TYPE_NAME_STRIPED "striped"
#define SEG_TYPE_NAME_MIRROR "mirror"
#define SEG_TYPE_NAME_SNAPSHOT "snapshot"
#define SEG_TYPE_NAME_THIN "thin"
#define SEG_TYPE_NAME_THIN_POOL "thin-pool"
#define SEG_TYPE_NAME_CACHE "cache"
#define SEG_TYPE_NAME_CACHE_POOL "cache-pool"
#define SEG_TYPE_NAME_ERROR "error"
#define SEG_TYPE_NAME_FREE "free"
#define SEG_TYPE_NAME_ZERO "zero"
#define SEG_TYPE_NAME_RAID "raid"
#define SEG_TYPE_NAME_RAID0 "raid0"
#define SEG_TYPE_NAME_RAID1 "raid1"
#define SEG_TYPE_NAME_RAID10 "raid10"
#define SEG_TYPE_NAME_RAID4 "raid4"
#define SEG_TYPE_NAME_RAID5 "raid5"
#define SEG_TYPE_NAME_RAID5_LA "raid5_la"
#define SEG_TYPE_NAME_RAID5_LS "raid5_ls"
#define SEG_TYPE_NAME_RAID5_RA "raid5_ra"
#define SEG_TYPE_NAME_RAID5_RS "raid5_rs"
#define SEG_TYPE_NAME_RAID6 "raid6"
#define SEG_TYPE_NAME_RAID6_NC "raid6_nc"
#define SEG_TYPE_NAME_RAID6_NR "raid6_nr"
#define SEG_TYPE_NAME_RAID6_ZR "raid6_zr"
#define segtype_is_linear(segtype) (!strcmp(segtype->name, SEG_TYPE_NAME_LINEAR))
#define segtype_is_cache(segtype) ((segtype)->flags & SEG_CACHE ? 1 : 0)
#define segtype_is_cache_pool(segtype) ((segtype)->flags & SEG_CACHE_POOL ? 1 : 0)
#define segtype_is_mirrored(segtype) ((segtype)->flags & SEG_AREAS_MIRRORED ? 1 : 0)
#define segtype_is_mirror(segtype) ((segtype)->flags & SEG_MIRROR ? 1 : 0)
#define segtype_is_pool(segtype) ((segtype)->flags & (SEG_CACHE_POOL | SEG_THIN_POOL) ? 1 : 0)
#define segtype_is_raid(segtype) ((segtype)->flags & SEG_RAID ? 1 : 0)
#define segtype_is_raid1(segtype) ((segtype)->flags & SEG_RAID1 ? 1 : 0)
#define segtype_is_raid4(segtype) ((segtype)->flags & SEG_RAID4 ? 1 : 0)
#define segtype_is_any_raid5(segtype) ((segtype)->flags & \
(SEG_RAID5_LS|SEG_RAID5_LA|SEG_RAID5_RS|SEG_RAID5_RA|SEG_RAID5_N) ? 1 : 0)
#define segtype_is_raid5_la(segtype) ((segtype)->flags & SEG_RAID5_LA ? 1 : 0)
#define segtype_is_raid5_ra(segtype) ((segtype)->flags & SEG_RAID5_RA ? 1 : 0)
#define segtype_is_raid5_ls(segtype) ((segtype)->flags & SEG_RAID5_LS ? 1 : 0)
#define segtype_is_raid5_rs(segtype) ((segtype)->flags & SEG_RAID5_RS ? 1 : 0)
#define segtype_is_any_raid6(segtype) ((segtype)->flags & \
(SEG_RAID6_ZR|SEG_RAID6_NC|SEG_RAID6_NR| \
SEG_RAID6_LA_6|SEG_RAID6_LS_6|SEG_RAID6_RA_6|SEG_RAID6_RS_6|SEG_RAID6_N_6) ? 1 : 0)
#define segtype_is_raid6_nc(segtype) ((segtype)->flags & SEG_RAID6_NC ? 1 : 0)
#define segtype_is_raid6_nr(segtype) ((segtype)->flags & SEG_RAID6_NR ? 1 : 0)
#define segtype_is_raid6_zr(segtype) ((segtype)->flags & SEG_RAID6_ZR ? 1 : 0)
#define segtype_is_raid10(segtype) ((segtype)->flags & SEG_RAID10 ? 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_thin(segtype) ((segtype)->flags & (SEG_THIN_POOL|SEG_THIN_VOLUME) ? 1 : 0)
#define segtype_is_thin_pool(segtype) ((segtype)->flags & SEG_THIN_POOL ? 1 : 0)
@@ -68,9 +131,21 @@ struct dev_manager;
#define seg_is_mirrored(seg) segtype_is_mirrored((seg)->segtype)
#define seg_is_pool(seg) segtype_is_pool((seg)->segtype)
#define seg_is_raid(seg) segtype_is_raid((seg)->segtype)
#define seg_is_raid1(seg) segtype_is_raid1((seg)->segtype)
#define seg_is_raid4(seg) segtype_is_raid4((seg)->segtype)
#define seg_is_any_raid5(seg) segtype_is_any_raid5((seg)->segtype)
#define seg_is_raid5_la(seg) segtype_is_raid5_la((seg)->segtype)
#define seg_is_raid5_ra(seg) segtype_is_raid5_ra((seg)->segtype)
#define seg_is_raid5_ls(seg) segtype_is_raid5_ls((seg)->segtype)
#define seg_is_raid5_rs(seg) segtype_is_raid5_rs((seg)->segtype)
#define seg_is_any_raid6(seg) segtype_is_any_raid6((seg)->segtype)
#define seg_is_raid6_zr(seg) segtype_is_raid6_zr((seg)->segtype)
#define seg_is_raid6_nr(seg) segtype_is_raid6_nr((seg)->segtype)
#define seg_is_raid6_nc(seg) segtype_is_raid6_nc((seg)->segtype)
#define seg_is_raid10(seg) segtype_is_raid10((seg)->segtype)
#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_snapshot(seg) ((seg)->segtype->flags & SEG_SNAPSHOT ? 1 : 0)
#define seg_is_snapshot(seg) segtype_is_snapshot((seg)->segtype)
#define seg_is_striped(seg) segtype_is_striped((seg)->segtype)
#define seg_is_thin(seg) segtype_is_thin((seg)->segtype)
#define seg_is_thin_pool(seg) segtype_is_thin_pool((seg)->segtype)
@@ -86,8 +161,8 @@ struct dev_manager;
struct segment_type {
struct dm_list list; /* Internal */
uint32_t flags;
uint32_t parity_devs; /* Parity drives required by segtype */
uint64_t flags;
uint32_t parity_devs; /* Parity drives required by segtype */
struct segtype_handler *ops;
const char *name;
@@ -152,24 +227,13 @@ struct segment_type *init_unknown_segtype(struct cmd_context *cmd,
const char *name);
#define RAID_FEATURE_RAID10 (1U << 0) /* version 1.3 */
#define RAID_FEATURE_RAID0 (1U << 1) /* version 1.7 */
#define RAID_FEATURE_RESHAPING (1U << 2) /* version 1.8 */
#ifdef RAID_INTERNAL
int init_raid_segtypes(struct cmd_context *cmd, struct segtype_library *seglib);
#endif
#define SEG_TYPE_NAME_RAID1 "raid1"
#define SEG_TYPE_NAME_RAID10 "raid10"
#define SEG_TYPE_NAME_RAID4 "raid4"
#define SEG_TYPE_NAME_RAID5 "raid5"
#define SEG_TYPE_NAME_RAID5_LA "raid5_la"
#define SEG_TYPE_NAME_RAID5_LS "raid5_ls"
#define SEG_TYPE_NAME_RAID5_RA "raid5_ra"
#define SEG_TYPE_NAME_RAID5_RS "raid5_rs"
#define SEG_TYPE_NAME_RAID6 "raid6"
#define SEG_TYPE_NAME_RAID6_NC "raid6_nc"
#define SEG_TYPE_NAME_RAID6_NR "raid6_nr"
#define SEG_TYPE_NAME_RAID6_ZR "raid6_zr"
#ifdef REPLICATOR_INTERNAL
int init_replicator_segtype(struct cmd_context *cmd, struct segtype_library *seglib);
#endif

View File

@@ -44,7 +44,7 @@ static uint64_t _cow_extra_chunks(struct cmd_context *cmd, uint64_t n_chunks)
unsigned attrs = 0;
if (activation() &&
(segtype = get_segtype_from_string(cmd, "snapshot")) &&
(segtype = get_segtype_from_string(cmd, SEG_TYPE_NAME_SNAPSHOT)) &&
segtype->ops->target_present &&
segtype->ops->target_present(cmd, NULL, &attrs) &&
(attrs & SNAPSHOT_FEATURE_FIXED_LEAK))

View File

@@ -216,7 +216,7 @@ int thin_pool_feature_supported(const struct logical_volume *lv, int feature)
int pool_below_threshold(const struct lv_segment *pool_seg)
{
dm_percent_t percent;
int threshold = DM_PERCENT_1 *
dm_percent_t threshold = DM_PERCENT_1 *
find_config_tree_int(pool_seg->lv->vg->cmd, activation_thin_pool_autoextend_threshold_CFG,
lv_config_profile(pool_seg->lv));
@@ -224,15 +224,27 @@ int pool_below_threshold(const struct lv_segment *pool_seg)
if (!lv_thin_pool_percent(pool_seg->lv, 0, &percent))
return_0;
if (percent >= threshold)
if (percent > threshold) {
log_debug("Threshold configured for free data space in "
"thin pool %s has been reached (%.2f%% >= %.2f%%).",
display_lvname(pool_seg->lv),
dm_percent_to_float(percent),
dm_percent_to_float(threshold));
return 0;
}
/* Metadata */
if (!lv_thin_pool_percent(pool_seg->lv, 1, &percent))
return_0;
if (percent >= threshold)
if (percent > threshold) {
log_debug("Threshold configured for free metadata space in "
"thin pool %s has been reached (%.2f%% > %.2f%%).",
display_lvname(pool_seg->lv),
dm_percent_to_float(percent),
dm_percent_to_float(threshold));
return 0;
}
return 1;
}

View File

@@ -620,7 +620,7 @@ struct segment_type *init_segtype(struct cmd_context *cmd)
return_NULL;
segtype->ops = &_mirrored_ops;
segtype->name = "mirror";
segtype->name = SEG_TYPE_NAME_MIRROR;
segtype->flags = SEG_MIRROR | SEG_AREAS_MIRRORED;
#ifdef DEVMAPPER_SUPPORT

View File

@@ -40,6 +40,8 @@ static int _security_level = SECURITY_LEVEL;
static char _cmd_name[30] = "";
static int _mirror_in_sync = 0;
static int _dmeventd_monitor = DEFAULT_DMEVENTD_MONITOR;
/* When set, disables update of _dmeventd_monitor & _ignore_suspended_devices */
static int _disable_dmeventd_monitoring = 0;
static int _background_polling = DEFAULT_BACKGROUND_POLLING;
static int _ignore_suspended_devices = 0;
static int _ignore_lvm_mirrors = DEFAULT_IGNORE_LVM_MIRRORS;
@@ -123,7 +125,13 @@ void init_mirror_in_sync(int in_sync)
void init_dmeventd_monitor(int reg)
{
_dmeventd_monitor = reg;
if (!_disable_dmeventd_monitoring)
_dmeventd_monitor = reg;
}
void init_disable_dmeventd_monitoring(int reg)
{
_disable_dmeventd_monitoring = reg;
}
void init_background_polling(int polling)
@@ -133,7 +141,8 @@ void init_background_polling(int polling)
void init_ignore_suspended_devices(int ignore)
{
_ignore_suspended_devices = ignore;
if (!_disable_dmeventd_monitoring)
_ignore_suspended_devices = ignore;
}
void init_ignore_lvm_mirrors(int scan)

View File

@@ -38,6 +38,7 @@ void init_lockingfailed(int level);
void init_security_level(int level);
void init_mirror_in_sync(int in_sync);
void init_dmeventd_monitor(int reg);
void init_disable_dmeventd_monitoring(int disable);
void init_background_polling(int polling);
void init_ignore_suspended_devices(int ignore);
void init_ignore_lvm_mirrors(int scan);

View File

@@ -15,6 +15,7 @@
#include "lib.h"
#include "lvm-signal.h"
#include "memlock.h"
#include <signal.h>
@@ -60,6 +61,8 @@ void sigint_allow(void)
struct sigaction handler;
sigset_t sigs;
if (memlock_count_daemon())
return;
/*
* Do not overwrite the backed-up handler data -
* just increase nesting count.
@@ -91,6 +94,9 @@ void sigint_allow(void)
void sigint_restore(void)
{
if (memlock_count_daemon())
return;
if (!_handler_installed ||
--_handler_installed >= MAX_SIGINTS)
return;
@@ -112,6 +118,9 @@ void block_signals(uint32_t flags __attribute__((unused)))
{
sigset_t set;
if (memlock_count_daemon())
return;
if (_signals_blocked)
return;
@@ -130,6 +139,9 @@ void block_signals(uint32_t flags __attribute__((unused)))
void unblock_signals(void)
{
if (memlock_count_daemon())
return;
/* Don't unblock signals while any locks are held */
if (!_signals_blocked)
return;

View File

@@ -638,3 +638,8 @@ void memlock_unlock(struct cmd_context *cmd)
}
#endif
int memlock_count_daemon(void)
{
return _memlock_count_daemon;
}

View File

@@ -36,6 +36,7 @@ void critical_section_dec(struct cmd_context *cmd, const char *reason);
int critical_section(void);
void memlock_inc_daemon(struct cmd_context *cmd);
void memlock_dec_daemon(struct cmd_context *cmd);
int memlock_count_daemon(void);
void memlock_init(struct cmd_context *cmd);
void memlock_reset(void);
void memlock_unlock(struct cmd_context *cmd);

View File

@@ -55,7 +55,7 @@ static int _raid_text_import_areas(struct lv_segment *seg,
const struct dm_config_value *cv)
{
unsigned int s;
struct logical_volume *lv1;
struct logical_volume *lv;
const char *seg_name = dm_config_parent_name(sn);
if (!seg->area_count) {
@@ -75,23 +75,23 @@ static int _raid_text_import_areas(struct lv_segment *seg,
}
/* Metadata device comes first */
if (!(lv1 = find_lv(seg->lv->vg, cv->v.str))) {
if (!(lv = find_lv(seg->lv->vg, cv->v.str))) {
log_error("Couldn't find volume '%s' for segment '%s'.",
cv->v.str ? : "NULL", seg_name);
return 0;
}
if (!set_lv_segment_area_lv(seg, s, lv1, 0, RAID_META))
return_0;
if (!set_lv_segment_area_lv(seg, s, lv, 0, RAID_META))
return_0;
/* Data device comes second */
cv = cv->next;
if (!(lv1 = find_lv(seg->lv->vg, cv->v.str))) {
if (!(lv = find_lv(seg->lv->vg, cv->v.str))) {
log_error("Couldn't find volume '%s' for segment '%s'.",
cv->v.str ? : "NULL", seg_name);
return 0;
}
if (!set_lv_segment_area_lv(seg, s, lv1, 0, RAID_IMAGE))
return_0;
if (!set_lv_segment_area_lv(seg, s, lv, 0, RAID_IMAGE))
return_0;
}
/*
@@ -111,49 +111,28 @@ static int _raid_text_import(struct lv_segment *seg,
struct dm_hash_table *pv_hash)
{
const struct dm_config_value *cv;
const struct {
const char *name;
uint32_t *var;
} raid_attr_import[] = {
{ "region_size", &seg->region_size },
{ "stripe_size", &seg->stripe_size },
{ "writebehind", &seg->writebehind },
{ "min_recovery_rate", &seg->min_recovery_rate },
{ "max_recovery_rate", &seg->max_recovery_rate },
}, *aip = raid_attr_import;
int i;
if (dm_config_has_node(sn, "region_size")) {
if (!dm_config_get_uint32(sn, "region_size", &seg->region_size)) {
log_error("Couldn't read 'region_size' for "
"segment %s of logical volume %s.",
dm_config_parent_name(sn), seg->lv->name);
return 0;
}
}
if (dm_config_has_node(sn, "stripe_size")) {
if (!dm_config_get_uint32(sn, "stripe_size", &seg->stripe_size)) {
log_error("Couldn't read 'stripe_size' for "
"segment %s of logical volume %s.",
dm_config_parent_name(sn), seg->lv->name);
return 0;
}
}
if (dm_config_has_node(sn, "writebehind")) {
if (!dm_config_get_uint32(sn, "writebehind", &seg->writebehind)) {
log_error("Couldn't read 'writebehind' for "
"segment %s of logical volume %s.",
dm_config_parent_name(sn), seg->lv->name);
return 0;
}
}
if (dm_config_has_node(sn, "min_recovery_rate")) {
if (!dm_config_get_uint32(sn, "min_recovery_rate",
&seg->min_recovery_rate)) {
log_error("Couldn't read 'min_recovery_rate' for "
"segment %s of logical volume %s.",
dm_config_parent_name(sn), seg->lv->name);
return 0;
}
}
if (dm_config_has_node(sn, "max_recovery_rate")) {
if (!dm_config_get_uint32(sn, "max_recovery_rate",
&seg->max_recovery_rate)) {
log_error("Couldn't read 'max_recovery_rate' for "
"segment %s of logical volume %s.",
dm_config_parent_name(sn), seg->lv->name);
return 0;
for (i = 0; i < DM_ARRAY_SIZE(raid_attr_import); i++, aip++) {
if (dm_config_has_node(sn, aip->name)) {
if (!dm_config_get_uint32(sn, aip->name, aip->var)) {
log_error("Couldn't read '%s' for segment %s of logical volume %s.",
aip->name, dm_config_parent_name(sn), seg->lv->name);
return 0;
}
}
}
if (!dm_config_get_list(sn, "raids", &cv)) {
log_error("Couldn't find RAID array for "
"segment %s of logical volume %s.",
@@ -162,7 +141,7 @@ static int _raid_text_import(struct lv_segment *seg,
}
if (!_raid_text_import_areas(seg, sn, cv)) {
log_error("Failed to import RAID images");
log_error("Failed to import RAID component pairs.");
return 0;
}
@@ -242,7 +221,7 @@ static int _raid_add_target_line(struct dev_manager *dm __attribute__((unused)),
/* RAID 4/5/6 */
params.mirrors = 1;
params.stripes = seg->area_count - seg->segtype->parity_devs;
} else if (strcmp(seg->segtype->name, SEG_TYPE_NAME_RAID10)) {
} else if (seg_is_raid10(seg)) {
/* RAID 10 only supports 2 mirrors now */
params.mirrors = 2;
params.stripes = seg->area_count / 2;
@@ -301,8 +280,8 @@ static int _raid_target_percent(void **target_state,
else
break;
}
if (!pos || (sscanf(pos, FMTu64 "/" FMTu64 "%n",
&numerator, &denominator, &i) != 2)) {
if (!pos || (sscanf(pos, FMTu64 "/" FMTu64 "%n", &numerator, &denominator, &i) != 2) ||
!denominator) {
log_error("Failed to parse %s status fraction: %s",
(seg) ? seg->segtype->name : "segment", params);
return 0;
@@ -331,6 +310,7 @@ static int _raid_target_present(struct cmd_context *cmd,
const char *feature;
} _features[] = {
{ 1, 3, RAID_FEATURE_RAID10, SEG_TYPE_NAME_RAID10 },
{ 1, 7, RAID_FEATURE_RAID0, SEG_TYPE_NAME_RAID0 },
};
static int _raid_checked = 0;
@@ -434,25 +414,25 @@ static struct segtype_handler _raid_ops = {
static const struct raid_type {
const char name[12];
unsigned parity;
int extra_flags;
uint64_t extra_flags;
} _raid_types[] = {
{ SEG_TYPE_NAME_RAID1, 0, SEG_AREAS_MIRRORED },
{ SEG_TYPE_NAME_RAID10, 0, SEG_AREAS_MIRRORED },
{ SEG_TYPE_NAME_RAID4, 1 },
{ SEG_TYPE_NAME_RAID5, 1 },
{ SEG_TYPE_NAME_RAID5_LA, 1 },
{ SEG_TYPE_NAME_RAID5_LS, 1 },
{ SEG_TYPE_NAME_RAID5_RA, 1 },
{ SEG_TYPE_NAME_RAID5_RS, 1 },
{ SEG_TYPE_NAME_RAID6, 2 },
{ SEG_TYPE_NAME_RAID6_NC, 2 },
{ SEG_TYPE_NAME_RAID6_NR, 2 },
{ SEG_TYPE_NAME_RAID6_ZR, 2 }
{ SEG_TYPE_NAME_RAID1, 0, SEG_RAID1 | SEG_AREAS_MIRRORED },
{ SEG_TYPE_NAME_RAID10, 0, SEG_RAID10 | SEG_AREAS_MIRRORED },
{ SEG_TYPE_NAME_RAID4, 1, SEG_RAID4 },
{ SEG_TYPE_NAME_RAID5, 1, SEG_RAID5 },
{ SEG_TYPE_NAME_RAID5_LA, 1, SEG_RAID5_LA },
{ SEG_TYPE_NAME_RAID5_LS, 1, SEG_RAID5_LS },
{ SEG_TYPE_NAME_RAID5_RA, 1, SEG_RAID5_RA },
{ SEG_TYPE_NAME_RAID5_RS, 1, SEG_RAID5_RS },
{ SEG_TYPE_NAME_RAID6, 2, SEG_RAID6 },
{ SEG_TYPE_NAME_RAID6_NC, 2, SEG_RAID6_NC },
{ SEG_TYPE_NAME_RAID6_NR, 2, SEG_RAID6_NR },
{ SEG_TYPE_NAME_RAID6_ZR, 2, SEG_RAID6_ZR }
};
static struct segment_type *_init_raid_segtype(struct cmd_context *cmd,
const struct raid_type *rt,
int monitored)
uint64_t monitored)
{
struct segment_type *segtype = dm_zalloc(sizeof(*segtype));
@@ -482,7 +462,7 @@ int init_multiple_segtypes(struct cmd_context *cmd, struct segtype_library *segl
{
struct segment_type *segtype;
unsigned i;
int monitored = 0;
uint64_t monitored = 0;
#ifdef DEVMAPPER_SUPPORT
# ifdef DMEVENTD

View File

@@ -158,7 +158,8 @@ FIELD(VGS, vg, NUM, "#Ext", extent_count, 4, uint32, vg_extent_count, "Total num
FIELD(VGS, vg, NUM, "Free", free_count, 4, uint32, vg_free_count, "Total number of unallocated Physical Extents.", 0)
FIELD(VGS, vg, NUM, "MaxLV", max_lv, 5, uint32, max_lv, "Maximum number of LVs allowed in VG or 0 if unlimited.", 0)
FIELD(VGS, vg, NUM, "MaxPV", max_pv, 5, uint32, max_pv, "Maximum number of PVs allowed in VG or 0 if unlimited.", 0)
FIELD(VGS, vg, NUM, "#PV", pv_count, 3, uint32, pv_count, "Number of PVs.", 0)
FIELD(VGS, vg, NUM, "#PV", pv_count, 3, uint32, pv_count, "Number of PVs in VG.", 0)
FIELD(VGS, vg, NUM, "#PV Missing", cmd, 11, vgmissingpvcount, vg_missing_pv_count, "Number of PVs in VG which are missing.", 0)
FIELD(VGS, vg, NUM, "#LV", cmd, 3, lvcount, lv_count, "Number of LVs.", 0)
FIELD(VGS, vg, NUM, "#SN", cmd, 3, snapcount, snap_count, "Number of snapshots.", 0)
FIELD(VGS, vg, NUM, "Seq", seqno, 3, uint32, vg_seqno, "Revision number of internal metadata. Incremented whenever it changes.", 0)
@@ -190,7 +191,9 @@ FIELD(SEGS, seg, SIZ, "SSize", list, 5, segsize, seg_size, "Size of segment in c
FIELD(SEGS, seg, SIZ, "SSize", list, 5, segsizepe, seg_size_pe, "Size of segment in physical extents.", 0)
FIELD(SEGS, seg, STR_LIST, "Seg Tags", tags, 8, tags, seg_tags, "Tags, if any.", 0)
FIELD(SEGS, seg, STR, "PE Ranges", list, 9, peranges, seg_pe_ranges, "Ranges of Physical Extents of underlying devices in command line format.", 0)
FIELD(SEGS, seg, STR, "Metadata LE Ranges", list, 18, metadataleranges, seg_metadata_le_ranges, "Ranges of Logical Extents of underlying metadata devices in command line format.", 0)
FIELD(SEGS, seg, STR, "Devices", list, 7, devices, devices, "Underlying devices used with starting extent numbers.", 0)
FIELD(SEGS, seg, STR, "Metadata Devs", list, 13, metadatadevices, metadata_devices, "Underlying metadata devices used with starting extent numbers.", 0)
FIELD(SEGS, seg, STR, "Monitor", list, 7, segmonitor, seg_monitor, "Dmeventd monitoring status of the segment.", 0)
FIELD(SEGS, seg, STR, "Cache Policy", list, 12, cache_policy, cache_policy, "The cache policy (cached segments only).", 0)
FIELD(SEGS, seg, STR_LIST, "Cache Settings", list, 14, cache_settings, cache_settings, "Cache settings/parameters (cached segments only).", 0)

View File

@@ -420,6 +420,8 @@ GET_VG_NUM_PROPERTY_FN(vg_mda_copies, (vg_mda_copies(vg)))
SET_VG_NUM_PROPERTY_FN(vg_mda_copies, vg_set_mda_copies)
GET_VG_STR_PROPERTY_FN(vg_profile, vg_profile_dup(vg))
#define _vg_profile_set prop_not_implemented_set
GET_VG_NUM_PROPERTY_FN(vg_missing_pv_count, vg_missing_pv_count(vg))
#define _vg_missing_pv_count_set prop_not_implemented_set
/* LVSEG */
GET_LVSEG_STR_PROPERTY_FN(segtype, lvseg_segtype_dup(lvseg->lv->vg->vgmem, lvseg))
@@ -463,8 +465,13 @@ GET_LVSEG_STR_PROPERTY_FN(seg_tags, lvseg_tags_dup(lvseg))
GET_LVSEG_STR_PROPERTY_FN(seg_pe_ranges,
lvseg_seg_pe_ranges(lvseg->lv->vg->vgmem, lvseg))
#define _seg_pe_ranges_set prop_not_implemented_set
GET_LVSEG_STR_PROPERTY_FN(seg_metadata_le_ranges,
lvseg_seg_metadata_le_ranges(lvseg->lv->vg->vgmem, lvseg))
#define _seg_metadata_le_ranges_set prop_not_implemented_set
GET_LVSEG_STR_PROPERTY_FN(devices, lvseg_devices(lvseg->lv->vg->vgmem, lvseg))
#define _devices_set prop_not_implemented_set
GET_LVSEG_STR_PROPERTY_FN(metadata_devices, lvseg_metadata_devices(lvseg->lv->vg->vgmem, lvseg))
#define _metadata_devices_set prop_not_implemented_set
GET_LVSEG_STR_PROPERTY_FN(seg_monitor, lvseg_monitor_dup(lvseg->lv->vg->vgmem, lvseg))
#define _seg_monitor_set prop_not_implemented_set

View File

@@ -1304,6 +1304,18 @@ static int _devices_disp(struct dm_report *rh __attribute__((unused)), struct dm
return _field_set_value(field, str, NULL);
}
static int _metadatadevices_disp(struct dm_report *rh __attribute__((unused)), struct dm_pool *mem,
struct dm_report_field *field,
const void *data, void *private __attribute__((unused)))
{
char *str;
if (!(str = lvseg_metadata_devices(mem, (const struct lv_segment *) data)))
return_0;
return _field_set_value(field, str, NULL);
}
static int _peranges_disp(struct dm_report *rh __attribute__((unused)), struct dm_pool *mem,
struct dm_report_field *field,
const void *data, void *private __attribute__((unused)))
@@ -1316,6 +1328,18 @@ static int _peranges_disp(struct dm_report *rh __attribute__((unused)), struct d
return _field_set_value(field, str, NULL);
}
static int _metadataleranges_disp(struct dm_report *rh __attribute__((unused)), struct dm_pool *mem,
struct dm_report_field *field,
const void *data, void *private __attribute__((unused)))
{
char *str;
if (!(str = lvseg_seg_metadata_le_ranges(mem, (const struct lv_segment *) data)))
return_0;
return _field_set_value(field, str, NULL);
}
static int _tags_disp(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field,
const void *data, void *private)
@@ -2414,6 +2438,17 @@ static int _vgprofile_disp(struct dm_report *rh, struct dm_pool *mem,
return _field_set_value(field, "", NULL);
}
static int _vgmissingpvcount_disp(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field,
const void *data, void *private)
{
const struct volume_group *vg = (const struct volume_group *) data;
uint32_t count = vg_missing_pv_count(vg);
return _uint32_disp(rh, mem, field, &count, private);
}
static int _pvmdafree_disp(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field,
const void *data, void *private)
@@ -3361,6 +3396,21 @@ void *report_init_for_selection(struct cmd_context *cmd,
cmd);
}
const char *report_get_field_prefix(report_type_t report_type_id)
{
const struct dm_report_object_type *report_types, *report_type;
report_types = report_type_id & DEVTYPES ? _devtypes_report_types
: _report_types;
for (report_type = report_types; report_type->id; report_type++) {
if (report_type_id & report_type->id)
return report_type->prefix;
}
return "";
}
/*
* Create a row of data for an object
*/

View File

@@ -71,6 +71,7 @@ void *report_init(struct cmd_context *cmd, const char *format, const char *keys,
int quoted, int columns_as_rows, const char *selection);
void *report_init_for_selection(struct cmd_context *cmd, report_type_t *report_type,
const char *selection);
const char *report_get_field_prefix(report_type_t report_type);
int report_for_selection(struct cmd_context *cmd,
struct selection_handle *sh,
struct physical_volume *pv,

View File

@@ -259,7 +259,7 @@ struct segment_type *init_segtype(struct cmd_context *cmd)
return_NULL;
segtype->ops = &_snapshot_ops;
segtype->name = "snapshot";
segtype->name = SEG_TYPE_NAME_SNAPSHOT;
segtype->flags = SEG_SNAPSHOT | SEG_CANNOT_BE_ZEROED | SEG_ONLY_EXCLUSIVE;
#ifdef DEVMAPPER_SUPPORT

View File

@@ -29,7 +29,7 @@
static const char *_striped_name(const struct lv_segment *seg)
{
return (seg->area_count == 1) ? "linear" : seg->segtype->name;
return (seg->area_count == 1) ? SEG_TYPE_NAME_LINEAR : seg->segtype->name;
}
static void _striped_display(const struct lv_segment *seg)
@@ -229,7 +229,7 @@ struct segment_type *init_striped_segtype(struct cmd_context *cmd)
return_NULL;
segtype->ops = &_striped_ops;
segtype->name = "striped";
segtype->name = SEG_TYPE_NAME_STRIPED;
segtype->flags =
SEG_CAN_SPLIT | SEG_AREAS_STRIPED | SEG_FORMAT1_SUPPORT;

View File

@@ -118,10 +118,6 @@ static int _thin_pool_text_import(struct lv_segment *seg,
else if (!set_pool_discards(&seg->discards, discards_str))
return SEG_LOG_ERROR("Discards option unsupported for");
if (dm_config_has_node(sn, "low_water_mark") &&
!dm_config_get_uint64(sn, "low_water_mark", &seg->low_water_mark))
return SEG_LOG_ERROR("Could not read low_water_mark");
if ((seg->chunk_size < DM_THIN_MIN_DATA_BLOCK_SIZE) ||
(seg->chunk_size > DM_THIN_MAX_DATA_BLOCK_SIZE))
return SEG_LOG_ERROR("Unsupported value %u for chunk_size",
@@ -169,9 +165,6 @@ static int _thin_pool_text_export(const struct lv_segment *seg, struct formatter
return 0;
}
if (seg->low_water_mark)
outf(f, "low_water_mark = %" PRIu64, seg->low_water_mark);
if (seg->zero_new_blocks)
outf(f, "zero_new_blocks = 1");
@@ -266,6 +259,8 @@ static int _thin_pool_add_target_line(struct dev_manager *dm,
struct lvinfo info;
uint64_t transaction_id = 0;
unsigned attr;
uint64_t low_water_mark;
int threshold;
if (!_thin_target_present(cmd, NULL, &attr))
return_0;
@@ -277,27 +272,37 @@ static int _thin_pool_add_target_line(struct dev_manager *dm,
if (!(attr & THIN_FEATURE_BLOCK_SIZE) &&
(seg->chunk_size & (seg->chunk_size - 1))) {
log_error("Thin pool target does not support %uKiB chunk size "
"(needs kernel >= 3.6).", seg->chunk_size / 2);
log_error("Thin pool target does not support %s chunk size (needs"
" kernel >= 3.6).", display_size(cmd, seg->chunk_size));
return 0;
}
if (!(metadata_dlid = build_dm_uuid(mem, seg->metadata_lv, NULL))) {
log_error("Failed to build uuid for metadata LV %s.",
seg->metadata_lv->name);
display_lvname(seg->metadata_lv));
return 0;
}
if (!(pool_dlid = build_dm_uuid(mem, seg_lv(seg, 0), NULL))) {
log_error("Failed to build uuid for pool LV %s.",
seg_lv(seg, 0)->name);
display_lvname(seg_lv(seg, 0)));
return 0;
}
threshold = find_config_tree_int(seg->lv->vg->cmd,
activation_thin_pool_autoextend_threshold_CFG,
lv_config_profile(seg->lv));
if (threshold < 50)
threshold = 50;
if (threshold < 100)
low_water_mark = (len * threshold + 99) / 100;
else
low_water_mark = len;
if (!dm_tree_node_add_thin_pool_target(node, len,
seg->transaction_id,
metadata_dlid, pool_dlid,
seg->chunk_size, seg->low_water_mark,
seg->chunk_size, low_water_mark,
seg->zero_new_blocks ? 0 : 1))
return_0;

View File

@@ -89,7 +89,7 @@ struct segment_type *init_zero_segtype(struct cmd_context *cmd)
return_NULL;
segtype->ops = &_zero_ops;
segtype->name = "zero";
segtype->name = SEG_TYPE_NAME_ZERO;
segtype->flags = SEG_CAN_SPLIT | SEG_VIRTUAL | SEG_CANNOT_BE_ZEROED;
log_very_verbose("Initialised segtype: %s", segtype->name);

View File

@@ -289,7 +289,7 @@ static int close_enough(double d1, double d2)
return fabs(d1 - d2) < DBL_EPSILON;
}
static int compare_value(struct dm_config_value *a, struct dm_config_value *b)
int compare_value(struct dm_config_value *a, struct dm_config_value *b)
{
int r = 0;

View File

@@ -42,6 +42,7 @@ struct dm_config_node *make_config_node(struct dm_config_tree *cft,
struct dm_config_node *parent,
struct dm_config_node *pre_sib);
int compare_value(struct dm_config_value *a, struct dm_config_value *b);
int compare_config(struct dm_config_node *a, struct dm_config_node *b);
struct dm_config_node *make_text_node(struct dm_config_tree *cft,

View File

@@ -160,12 +160,18 @@ static int _parse_one(log_state *s, int outlet, const char *type, int enable)
if (!strcmp(type, "all"))
for (i = 0; i < 32; ++i)
daemon_log_enable(s, outlet, i, enable);
else if (!strcmp(type, "fatal"))
daemon_log_enable(s, outlet, DAEMON_LOG_FATAL, enable);
else if (!strcmp(type, "error"))
daemon_log_enable(s, outlet, DAEMON_LOG_ERROR, enable);
else if (!strcmp(type, "warn"))
daemon_log_enable(s, outlet, DAEMON_LOG_WARN, enable);
else if (!strcmp(type, "info"))
daemon_log_enable(s, outlet, DAEMON_LOG_INFO, enable);
else if (!strcmp(type, "wire"))
daemon_log_enable(s, outlet, DAEMON_LOG_WIRE, enable);
else if (!strcmp(type, "debug"))
daemon_log_enable(s, outlet, DAEMON_LOG_DEBUG, enable);
else
return 0;
return 1;
}

View File

@@ -262,7 +262,6 @@ dm_tree_node_set_thin_external_origin
dm_tree_node_set_thin_pool_discard
dm_tree_node_set_thin_pool_error_if_no_space
dm_tree_node_set_udev_flags
dm_tree_node_size_changed
dm_tree_preload_children
dm_tree_retry_remove
dm_tree_set_cookie

View File

@@ -0,0 +1,3 @@
dm_report_compact_given_fields
dm_hold_control_dev
dm_tree_node_size_changed

View File

@@ -21,13 +21,14 @@ SOURCES =\
datastruct/hash.c \
datastruct/list.c \
libdm-common.c \
libdm-file.c \
libdm-deptree.c \
libdm-string.c \
libdm-report.c \
libdm-timestamp.c \
libdm-stats.c \
libdm-config.c \
libdm-deptree.c \
libdm-file.c \
libdm-report.c \
libdm-stats.c \
libdm-string.c \
libdm-targets.c \
libdm-timestamp.c \
mm/dbg_malloc.c \
mm/pool.c \
regex/matcher.c \

View File

@@ -81,6 +81,7 @@ static dm_bitset_t _dm_bitset = NULL;
static uint32_t _dm_device_major = 0;
static int _control_fd = -1;
static int _hold_control_fd_open = 0;
static int _version_checked = 0;
static int _version_ok = 1;
static unsigned _ioctl_buffer_double_factor = 0;
@@ -1201,8 +1202,13 @@ static struct dm_ioctl *_flatten(struct dm_task *dmt, unsigned repeat_count)
if (dmt->type == DM_DEVICE_SUSPEND)
dmi->flags |= DM_SUSPEND_FLAG;
if (dmt->no_flush)
dmi->flags |= DM_NOFLUSH_FLAG;
if (dmt->no_flush) {
if (_dm_version_minor < 12)
log_verbose("No flush flag unsupported by kernel. "
"Buffers will be flushed.");
else
dmi->flags |= DM_NOFLUSH_FLAG;
}
if (dmt->read_only)
dmi->flags |= DM_READONLY_FLAG;
if (dmt->skip_lockfs)
@@ -2079,9 +2085,18 @@ repeat_ioctl:
return 0;
}
void dm_hold_control_dev(int hold_open)
{
_hold_control_fd_open = hold_open ? 1 : 0;
log_debug("Hold of control device is now %sset.",
_hold_control_fd_open ? "" : "un");
}
void dm_lib_release(void)
{
_close_control_fd();
if (!_hold_control_fd_open)
_close_control_fd();
dm_timestamp_destroy(_dm_ioctl_timestamp);
_dm_ioctl_timestamp = NULL;
update_devs();

View File

@@ -1168,6 +1168,9 @@ void dm_lib_init(void) __attribute__((constructor));
void dm_lib_release(void);
void dm_lib_exit(void) __attribute__((destructor));
/* An optimisation for clients making repeated calls involving dm ioctls */
void dm_hold_control_dev(int hold_open);
/*
* Use NULL for all devices.
*/
@@ -1253,6 +1256,11 @@ const char *dm_tree_node_get_name(const struct dm_tree_node *node);
const char *dm_tree_node_get_uuid(const struct dm_tree_node *node);
const struct dm_info *dm_tree_node_get_info(const struct dm_tree_node *node);
void *dm_tree_node_get_context(const struct dm_tree_node *node);
/*
* Returns 0 when node size and its children is unchanged.
* Returns 1 when node or any of its children has increased size.
* Rerurns -1 when node or any of its children has reduced size.
*/
int dm_tree_node_size_changed(const struct dm_tree_node *dnode);
/*
@@ -2548,6 +2556,13 @@ int dm_report_object_is_selected(struct dm_report *rh, void *object, int do_outp
*/
int dm_report_compact_fields(struct dm_report *rh);
/*
* The same as dm_report_compact_fields, but for selected fields only.
* The "fields" arg is comma separated list of field names (the same format
* as used for "output_fields" arg in dm_report_init fn).
*/
int dm_report_compact_given_fields(struct dm_report *rh, const char *fields);
/*
* Returns 1 if there is no data waiting to be output.
*/

View File

@@ -51,4 +51,6 @@ void selinux_release(void);
void inc_suspended(void);
void dec_suspended(void);
int parse_thin_pool_status(const char *params, struct dm_status_thin_pool *s);
#endif

View File

@@ -157,21 +157,18 @@ struct dm_config_tree *dm_config_insert_cascaded_tree(struct dm_config_tree *fir
static struct dm_config_node *_config_reverse(struct dm_config_node *head)
{
if (!head)
return NULL;
struct dm_config_node *left = head, *middle = NULL, *right = NULL;
do {
while (left) {
right = middle;
middle = left;
left = left->sib;
middle->sib = right;
middle->child = _config_reverse(middle->child);
} while (left);
}
return middle;
};
}
int dm_config_parse(struct dm_config_tree *cft, const char *start, const char *end)
{

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2005-2014 Red Hat, Inc. All rights reserved.
* Copyright (C) 2005-2015 Red Hat, Inc. All rights reserved.
*
* This file is part of the device-mapper userspace tools.
*
@@ -86,7 +86,7 @@ static const struct {
{ SEG_RAID6_NC, "raid6_nc"},
/*
*WARNING: Since 'raid' target overloads this 1:1 mapping table
* WARNING: Since 'raid' target overloads this 1:1 mapping table
* for search do not add new enum elements past them!
*/
{ SEG_RAID5_LS, "raid5"}, /* same as "raid5_ls" (default for MD also) */
@@ -220,7 +220,7 @@ struct load_properties {
uint32_t read_ahead_flags;
unsigned segment_count;
unsigned size_changed;
int size_changed;
struct dm_list segs;
const char *new_name;
@@ -1427,48 +1427,6 @@ static int _suspend_node(const char *name, uint32_t major, uint32_t minor,
return r;
}
static int _thin_pool_parse_status(const char *params,
struct dm_status_thin_pool *s)
{
int pos;
if (!params) {
log_error("Failed to parse invalid thin params.");
return 0;
}
/* FIXME: add support for held metadata root */
if (sscanf(params, FMTu64 " " FMTu64 "/" FMTu64 " " FMTu64 "/" FMTu64 "%n",
&s->transaction_id,
&s->used_metadata_blocks,
&s->total_metadata_blocks,
&s->used_data_blocks,
&s->total_data_blocks, &pos) < 5) {
log_error("Failed to parse thin pool params: %s.", params);
return 0;
}
/* New status flags */
if (strstr(params + pos, "no_discard_passdown"))
s->discards = DM_THIN_DISCARDS_NO_PASSDOWN;
else if (strstr(params + pos, "ignore_discard"))
s->discards = DM_THIN_DISCARDS_IGNORE;
else /* default discard_passdown */
s->discards = DM_THIN_DISCARDS_PASSDOWN;
if (strstr(params + pos, "ro "))
s->read_only = 1;
else if (strstr(params + pos, "fail"))
s->fail = 1;
else if (strstr(params + pos, "out_of_data_space"))
s->out_of_data_space = 1;
if (strstr(params + pos, "error_if_no_space"))
s->error_if_no_space = 1;
return 1;
}
static int _thin_pool_get_status(struct dm_tree_node *dnode,
struct dm_status_thin_pool *s)
{
@@ -1501,7 +1459,7 @@ static int _thin_pool_get_status(struct dm_tree_node *dnode,
goto out;
}
if (!_thin_pool_parse_status(params, s))
if (!parse_thin_pool_status(params, s))
goto_out;
log_debug_activation("Found transaction id %" PRIu64 " for thin pool %s "
@@ -2370,6 +2328,20 @@ static int _mirror_emit_segment_line(struct dm_task *dmt, struct load_segment *s
return 1;
}
/* Is parameter non-zero? */
#define PARAM_IS_SET(p) ((p) ? 1 : 0)
/* Return number of bits assuming 4 * 64 bit size */
static int _get_params_count(uint64_t bits)
{
int r = 0;
r += 2 * hweight32(bits & 0xFFFFFFFF);
r += 2 * hweight32(bits >> 32);
return r;
}
static int _raid_emit_segment_line(struct dm_task *dmt, uint32_t major,
uint32_t minor, struct load_segment *seg,
uint64_t *seg_start, char *params,
@@ -2382,25 +2354,14 @@ static int _raid_emit_segment_line(struct dm_task *dmt, uint32_t major,
if ((seg->flags & DM_NOSYNC) || (seg->flags & DM_FORCESYNC))
param_count++;
if (seg->region_size)
param_count += 2;
param_count += 2 * (PARAM_IS_SET(seg->region_size) +
PARAM_IS_SET(seg->writebehind) +
PARAM_IS_SET(seg->min_recovery_rate) +
PARAM_IS_SET(seg->max_recovery_rate));
if (seg->writebehind)
param_count += 2;
if (seg->min_recovery_rate)
param_count += 2;
if (seg->max_recovery_rate)
param_count += 2;
/* rebuilds is 64-bit */
param_count += 2 * hweight32(seg->rebuilds & 0xFFFFFFFF);
param_count += 2 * hweight32(seg->rebuilds >> 32);
/* rebuilds is 64-bit */
param_count += 2 * hweight32(seg->writemostly & 0xFFFFFFFF);
param_count += 2 * hweight32(seg->writemostly >> 32);
/* rebuilds and writemostly are 64 bits */
param_count += _get_params_count(seg->rebuilds);
param_count += _get_params_count(seg->writemostly);
if ((seg->type == SEG_RAID1) && seg->stripe_size)
log_error("WARNING: Ignoring RAID1 stripe size");
@@ -2420,13 +2381,6 @@ static int _raid_emit_segment_line(struct dm_task *dmt, uint32_t major,
if (seg->rebuilds & (1ULL << i))
EMIT_PARAMS(pos, " rebuild %u", i);
for (i = 0; i < (seg->area_count / 2); i++)
if (seg->writemostly & (1ULL << i))
EMIT_PARAMS(pos, " write_mostly %u", i);
if (seg->writebehind)
EMIT_PARAMS(pos, " writebehind %u", seg->writebehind);
if (seg->min_recovery_rate)
EMIT_PARAMS(pos, " min_recovery_rate %u",
seg->min_recovery_rate);
@@ -2435,6 +2389,13 @@ static int _raid_emit_segment_line(struct dm_task *dmt, uint32_t major,
EMIT_PARAMS(pos, " max_recovery_rate %u",
seg->max_recovery_rate);
for (i = 0; i < (seg->area_count / 2); i++)
if (seg->writemostly & (1ULL << i))
EMIT_PARAMS(pos, " write_mostly %u", i);
if (seg->writebehind)
EMIT_PARAMS(pos, " max_write_behind %u", seg->writebehind);
/* Print number of metadata/data device pairs */
EMIT_PARAMS(pos, " %u", seg->area_count/2);
@@ -2768,7 +2729,8 @@ static int _load_node(struct dm_tree_node *dnode)
existing_table_size = dm_task_get_existing_table_size(dmt);
if ((dnode->props.size_changed =
(existing_table_size == seg_start) ? 0 : 1)) {
(existing_table_size == seg_start) ? 0 :
(existing_table_size > seg_start) ? -1 : 1)) {
/*
* Kernel usually skips size validation on zero-length devices
* now so no need to preload them.
@@ -2864,8 +2826,10 @@ int dm_tree_preload_children(struct dm_tree_node *dnode,
}
/* Propagate device size change change */
if (child->props.size_changed)
if (child->props.size_changed > 0 && !dnode->props.size_changed)
dnode->props.size_changed = 1;
else if (child->props.size_changed < 0)
dnode->props.size_changed = -1;
/* Resume device immediately if it has parents and its size changed */
if (!dm_tree_node_num_children(child, 1) || !child->props.size_changed)
@@ -3100,45 +3064,6 @@ int dm_tree_node_add_snapshot_merge_target(struct dm_tree_node *node,
merge_uuid, 1, chunk_size);
}
int dm_get_status_snapshot(struct dm_pool *mem, const char *params,
struct dm_status_snapshot **status)
{
struct dm_status_snapshot *s;
int r;
if (!params) {
log_error("Failed to parse invalid snapshot params.");
return 0;
}
if (!(s = dm_pool_zalloc(mem, sizeof(*s)))) {
log_error("Failed to allocate snapshot status structure.");
return 0;
}
r = sscanf(params, FMTu64 "/" FMTu64 " " FMTu64,
&s->used_sectors, &s->total_sectors,
&s->metadata_sectors);
if (r == 3 || r == 2)
s->has_metadata_sectors = (r == 3);
else if (!strcmp(params, "Invalid"))
s->invalid = 1;
else if (!strcmp(params, "Merge failed"))
s->merge_failed = 1;
else if (!strcmp(params, "Overflow"))
s->overflow = 1;
else {
dm_pool_free(mem, s);
log_error("Failed to parse snapshot params: %s.", params);
return 0;
}
*status = s;
return 1;
}
int dm_tree_node_add_error_target(struct dm_tree_node *node,
uint64_t size)
{
@@ -3310,84 +3235,6 @@ int dm_tree_node_add_raid_target(struct dm_tree_node *node,
return dm_tree_node_add_raid_target_with_params(node, size, &params);
}
/*
* Various RAID status versions include:
* Versions < 1.5.0 (4 fields):
* <raid_type> <#devs> <health_str> <sync_ratio>
* Versions 1.5.0+ (6 fields):
* <raid_type> <#devs> <health_str> <sync_ratio> <sync_action> <mismatch_cnt>
*/
int dm_get_status_raid(struct dm_pool *mem, const char *params,
struct dm_status_raid **status)
{
int i;
const char *pp, *p;
struct dm_status_raid *s;
if (!params || !(p = strchr(params, ' '))) {
log_error("Failed to parse invalid raid params.");
return 0;
}
p++;
/* second field holds the device count */
if (sscanf(p, "%d", &i) != 1)
return_0;
if (!(s = dm_pool_zalloc(mem, sizeof(struct dm_status_raid))))
return_0;
if (!(s->raid_type = dm_pool_zalloc(mem, p - params)))
goto_bad; /* memory is freed went pool is destroyed */
if (!(s->dev_health = dm_pool_zalloc(mem, i + 1)))
goto_bad;
if (sscanf(params, "%s %u %s %" PRIu64 "/%" PRIu64,
s->raid_type,
&s->dev_count,
s->dev_health,
&s->insync_regions,
&s->total_regions) != 5) {
log_error("Failed to parse raid params: %s", params);
goto bad;
}
*status = s;
/*
* All pre-1.5.0 version parameters are read. Now we check
* for additional 1.5.0+ parameters.
*
* Note that 'sync_action' will be NULL (and mismatch_count
* will be 0) if the kernel returns a pre-1.5.0 status.
*/
for (p = params, i = 0; i < 4; i++, p++)
if (!(p = strchr(p, ' ')))
return 1; /* return pre-1.5.0 status */
pp = p;
if (!(p = strchr(p, ' '))) {
log_error(INTERNAL_ERROR "Bad RAID status received.");
goto bad;
}
p++;
if (!(s->sync_action = dm_pool_zalloc(mem, p - pp)))
goto_bad;
if (sscanf(pp, "%s %" PRIu64, s->sync_action, &s->mismatch_count) != 2) {
log_error("Failed to parse raid params: %s", params);
goto bad;
}
return 1;
bad:
dm_pool_free(mem, s);
return 0;
}
int dm_tree_node_add_cache_target(struct dm_tree_node *node,
uint64_t size,
uint64_t feature_flags, /* DM_CACHE_FEATURE_* */
@@ -3458,7 +3305,8 @@ int dm_tree_node_add_cache_target(struct dm_tree_node *node,
return_0;
seg->data_block_size = data_block_size;
seg->flags = feature_flags;
/* Enforce WriteThough mode for cleaner policy */
seg->flags = (strcmp(policy_name, "cleaner") == 0) ? DM_CACHE_FEATURE_WRITETHROUGH : feature_flags;
seg->policy_name = policy_name;
/* FIXME: better validation missing */
@@ -3479,143 +3327,6 @@ int dm_tree_node_add_cache_target(struct dm_tree_node *node,
return 1;
}
static const char *advance_to_next_word(const char *str, int count)
{
int i;
const char *p;
for (p = str, i = 0; i < count; i++, p++)
if (!(p = strchr(p, ' ')))
return NULL;
return p;
}
/*
* <metadata block size> <#used metadata blocks>/<#total metadata blocks>
* <cache block size> <#used cache blocks>/<#total cache blocks>
* <#read hits> <#read misses> <#write hits> <#write misses>
* <#demotions> <#promotions> <#dirty> <#features> <features>*
* <#core args> <core args>* <policy name> <#policy args> <policy args>*
*
* metadata block size : Fixed block size for each metadata block in
* sectors
* #used metadata blocks : Number of metadata blocks used
* #total metadata blocks : Total number of metadata blocks
* cache block size : Configurable block size for the cache device
* in sectors
* #used cache blocks : Number of blocks resident in the cache
* #total cache blocks : Total number of cache blocks
* #read hits : Number of times a READ bio has been mapped
* to the cache
* #read misses : Number of times a READ bio has been mapped
* to the origin
* #write hits : Number of times a WRITE bio has been mapped
* to the cache
* #write misses : Number of times a WRITE bio has been
* mapped to the origin
* #demotions : Number of times a block has been removed
* from the cache
* #promotions : Number of times a block has been moved to
* the cache
* #dirty : Number of blocks in the cache that differ
* from the origin
* #feature args : Number of feature args to follow
* feature args : 'writethrough' (optional)
* #core args : Number of core arguments (must be even)
* core args : Key/value pairs for tuning the core
* e.g. migration_threshold
* *policy name : Name of the policy
* #policy args : Number of policy arguments to follow (must be even)
* policy args : Key/value pairs
* e.g. sequential_threshold
*/
int dm_get_status_cache(struct dm_pool *mem, const char *params,
struct dm_status_cache **status)
{
int i, feature_argc;
char *str;
const char *p, *pp;
struct dm_status_cache *s;
if (!(s = dm_pool_zalloc(mem, sizeof(struct dm_status_cache))))
return_0;
/* Read in args that have definitive placement */
if (sscanf(params,
" %" PRIu32
" %" PRIu64 "/%" PRIu64
" %" PRIu32
" %" PRIu64 "/%" PRIu64
" %" PRIu64 " %" PRIu64
" %" PRIu64 " %" PRIu64
" %" PRIu64 " %" PRIu64
" %" PRIu64
" %d",
&s->metadata_block_size,
&s->metadata_used_blocks, &s->metadata_total_blocks,
&s->block_size, /* AKA, chunk_size */
&s->used_blocks, &s->total_blocks,
&s->read_hits, &s->read_misses,
&s->write_hits, &s->write_misses,
&s->demotions, &s->promotions,
&s->dirty_blocks,
&feature_argc) != 14)
goto bad;
/* Now jump to "features" section */
if (!(p = advance_to_next_word(params, 12)))
goto bad;
/* Read in features */
for (i = 0; i < feature_argc; i++) {
if (!strncmp(p, "writethrough ", 13))
s->feature_flags |= DM_CACHE_FEATURE_WRITETHROUGH;
else if (!strncmp(p, "writeback ", 10))
s->feature_flags |= DM_CACHE_FEATURE_WRITEBACK;
else
log_error("Unknown feature in status: %s", params);
if (!(p = advance_to_next_word(p, 1)))
goto bad;
}
/* Read in core_args. */
if (sscanf(p, "%d ", &s->core_argc) != 1)
goto bad;
if (s->core_argc &&
(!(s->core_argv = dm_pool_zalloc(mem, sizeof(char *) * s->core_argc)) ||
!(p = advance_to_next_word(p, 1)) ||
!(str = dm_pool_strdup(mem, p)) ||
!(p = advance_to_next_word(p, s->core_argc)) ||
(dm_split_words(str, s->core_argc, 0, s->core_argv) != s->core_argc)))
goto bad;
/* Read in policy args */
pp = p;
if (!(p = advance_to_next_word(p, 1)) ||
!(s->policy_name = dm_pool_zalloc(mem, (p - pp))))
goto bad;
if (sscanf(pp, "%s %d", s->policy_name, &s->policy_argc) != 2)
goto bad;
if (s->policy_argc &&
(!(s->policy_argv = dm_pool_zalloc(mem, sizeof(char *) * s->policy_argc)) ||
!(p = advance_to_next_word(p, 1)) ||
!(str = dm_pool_strdup(mem, p)) ||
(dm_split_words(str, s->policy_argc, 0, s->policy_argv) != s->policy_argc)))
goto bad;
*status = s;
return 1;
bad:
log_error("Failed to parse cache params: %s", params);
dm_pool_free(mem, s);
*status = NULL;
return 0;
}
int dm_tree_node_add_replicator_target(struct dm_tree_node *node,
uint64_t size,
const char *rlog_uuid,
@@ -4042,52 +3753,6 @@ int dm_tree_node_set_thin_external_origin(struct dm_tree_node *node,
return 1;
}
int dm_get_status_thin_pool(struct dm_pool *mem, const char *params,
struct dm_status_thin_pool **status)
{
struct dm_status_thin_pool *s;
if (!(s = dm_pool_zalloc(mem, sizeof(struct dm_status_thin_pool)))) {
log_error("Failed to allocate thin_pool status structure.");
return 0;
}
if (!_thin_pool_parse_status(params, s)) {
dm_pool_free(mem, s);
return_0;
}
*status = s;
return 1;
}
int dm_get_status_thin(struct dm_pool *mem, const char *params,
struct dm_status_thin **status)
{
struct dm_status_thin *s;
if (!(s = dm_pool_zalloc(mem, sizeof(struct dm_status_thin)))) {
log_error("Failed to allocate thin status structure.");
return 0;
}
if (strchr(params, '-')) {
s->mapped_sectors = 0;
s->highest_mapped_sector = 0;
} else if (sscanf(params, FMTu64 " " FMTu64,
&s->mapped_sectors,
&s->highest_mapped_sector) != 2) {
dm_pool_free(mem, s);
log_error("Failed to parse thin params: %s.", params);
return 0;
}
*status = s;
return 1;
}
static int _add_area(struct dm_tree_node *node, struct load_segment *seg, struct dm_tree_node *dev_node, uint64_t offset)
{
struct seg_area *area;
@@ -4191,3 +3856,19 @@ void dm_tree_node_set_callback(struct dm_tree_node *dnode,
dnode->callback = cb;
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__)
int dm_tree_node_size_changed_base(const struct dm_tree_node *dnode);
DM_EXPORT_SYMBOL_BASE(dm_tree_node_size_changed);
int dm_tree_node_size_changed_base(const struct dm_tree_node *dnode)
{
/* Base does not make difference between smaller and bigger */
return dm_tree_node_size_changed(dnode) ? 1 : 0;
}
#endif

View File

@@ -81,6 +81,7 @@ struct dm_report {
#define FLD_ASCENDING 0x00004000
#define FLD_DESCENDING 0x00008000
#define FLD_COMPACTED 0x00010000
#define FLD_COMPACT_ONE 0x00020000
struct field_properties {
struct dm_list list;
@@ -2013,7 +2014,7 @@ out:
return r;
}
int dm_report_compact_fields(struct dm_report *rh)
static int _do_report_compact_fields(struct dm_report *rh, int global)
{
struct dm_report_field *field;
struct field_properties *fp;
@@ -2036,7 +2037,9 @@ int dm_report_compact_fields(struct dm_report *rh)
* in next step...
*/
dm_list_iterate_items(fp, &rh->field_props) {
if (!(fp->flags & FLD_HIDDEN))
if (fp->flags & FLD_HIDDEN)
continue;
if (global || (fp->flags & FLD_COMPACT_ONE))
fp->flags |= (FLD_COMPACTED | FLD_HIDDEN);
}
@@ -2065,6 +2068,61 @@ int dm_report_compact_fields(struct dm_report *rh)
return 1;
}
int dm_report_compact_fields(struct dm_report *rh)
{
return _do_report_compact_fields(rh, 1);
}
static int _field_to_compact_match(struct dm_report *rh, const char *field, size_t flen)
{
struct field_properties *fp;
uint32_t f;
int implicit;
if ((_get_field(rh, field, flen, &f, &implicit))) {
dm_list_iterate_items(fp, &rh->field_props) {
if ((fp->implicit == implicit) && (fp->field_num == f)) {
fp->flags |= FLD_COMPACT_ONE;
break;
}
}
return 1;
}
return 0;
}
static int _parse_fields_to_compact(struct dm_report *rh, const char *fields)
{
const char *ws; /* Word start */
const char *we = fields; /* Word end */
if (!fields)
return 1;
while (*we) {
while (*we && *we == ',')
we++;
ws = we;
while (*we && *we != ',')
we++;
if (!_field_to_compact_match(rh, ws, (size_t) (we - ws))) {
log_error("dm_report: Unrecognized field: %.*s", (int) (we - ws), ws);
return 0;
}
}
return 1;
}
int dm_report_compact_given_fields(struct dm_report *rh, const char *fields)
{
if (!_parse_fields_to_compact(rh, fields))
return_0;
return _do_report_compact_fields(rh, 0);
}
int dm_report_object(struct dm_report *rh, void *object)
{
return _do_report_object(rh, object, 1, NULL);

357
libdm/libdm-targets.c Normal file
View File

@@ -0,0 +1,357 @@
/*
* Copyright (C) 2005-2015 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "dmlib.h"
#include "libdm-common.h"
int dm_get_status_snapshot(struct dm_pool *mem, const char *params,
struct dm_status_snapshot **status)
{
struct dm_status_snapshot *s;
int r;
if (!params) {
log_error("Failed to parse invalid snapshot params.");
return 0;
}
if (!(s = dm_pool_zalloc(mem, sizeof(*s)))) {
log_error("Failed to allocate snapshot status structure.");
return 0;
}
r = sscanf(params, FMTu64 "/" FMTu64 " " FMTu64,
&s->used_sectors, &s->total_sectors,
&s->metadata_sectors);
if (r == 3 || r == 2)
s->has_metadata_sectors = (r == 3);
else if (!strcmp(params, "Invalid"))
s->invalid = 1;
else if (!strcmp(params, "Merge failed"))
s->merge_failed = 1;
else if (!strcmp(params, "Overflow"))
s->overflow = 1;
else {
dm_pool_free(mem, s);
log_error("Failed to parse snapshot params: %s.", params);
return 0;
}
*status = s;
return 1;
}
/*
* Various RAID status versions include:
* Versions < 1.5.0 (4 fields):
* <raid_type> <#devs> <health_str> <sync_ratio>
* Versions 1.5.0+ (6 fields):
* <raid_type> <#devs> <health_str> <sync_ratio> <sync_action> <mismatch_cnt>
*/
int dm_get_status_raid(struct dm_pool *mem, const char *params,
struct dm_status_raid **status)
{
int i;
const char *pp, *p;
struct dm_status_raid *s;
if (!params || !(p = strchr(params, ' '))) {
log_error("Failed to parse invalid raid params.");
return 0;
}
p++;
/* second field holds the device count */
if (sscanf(p, "%d", &i) != 1)
return_0;
if (!(s = dm_pool_zalloc(mem, sizeof(struct dm_status_raid))))
return_0;
if (!(s->raid_type = dm_pool_zalloc(mem, p - params)))
goto_bad; /* memory is freed when pool is destroyed */
if (!(s->dev_health = dm_pool_zalloc(mem, i + 1)))
goto_bad;
if (sscanf(params, "%s %u %s %" PRIu64 "/%" PRIu64,
s->raid_type,
&s->dev_count,
s->dev_health,
&s->insync_regions,
&s->total_regions) != 5) {
log_error("Failed to parse raid params: %s", params);
goto bad;
}
*status = s;
/*
* All pre-1.5.0 version parameters are read. Now we check
* for additional 1.5.0+ parameters.
*
* Note that 'sync_action' will be NULL (and mismatch_count
* will be 0) if the kernel returns a pre-1.5.0 status.
*/
for (p = params, i = 0; i < 4; i++, p++)
if (!(p = strchr(p, ' ')))
return 1; /* return pre-1.5.0 status */
pp = p;
if (!(p = strchr(p, ' '))) {
log_error(INTERNAL_ERROR "Bad RAID status received.");
goto bad;
}
p++;
if (!(s->sync_action = dm_pool_zalloc(mem, p - pp)))
goto_bad;
if (sscanf(pp, "%s %" PRIu64, s->sync_action, &s->mismatch_count) != 2) {
log_error("Failed to parse raid params: %s", params);
goto bad;
}
return 1;
bad:
dm_pool_free(mem, s);
return 0;
}
static const char *_advance_to_next_word(const char *str, int count)
{
int i;
const char *p;
for (p = str, i = 0; i < count; i++, p++)
if (!(p = strchr(p, ' ')))
return NULL;
return p;
}
/*
* <metadata block size> <#used metadata blocks>/<#total metadata blocks>
* <cache block size> <#used cache blocks>/<#total cache blocks>
* <#read hits> <#read misses> <#write hits> <#write misses>
* <#demotions> <#promotions> <#dirty> <#features> <features>*
* <#core args> <core args>* <policy name> <#policy args> <policy args>*
*
* metadata block size : Fixed block size for each metadata block in
* sectors
* #used metadata blocks : Number of metadata blocks used
* #total metadata blocks : Total number of metadata blocks
* cache block size : Configurable block size for the cache device
* in sectors
* #used cache blocks : Number of blocks resident in the cache
* #total cache blocks : Total number of cache blocks
* #read hits : Number of times a READ bio has been mapped
* to the cache
* #read misses : Number of times a READ bio has been mapped
* to the origin
* #write hits : Number of times a WRITE bio has been mapped
* to the cache
* #write misses : Number of times a WRITE bio has been
* mapped to the origin
* #demotions : Number of times a block has been removed
* from the cache
* #promotions : Number of times a block has been moved to
* the cache
* #dirty : Number of blocks in the cache that differ
* from the origin
* #feature args : Number of feature args to follow
* feature args : 'writethrough' (optional)
* #core args : Number of core arguments (must be even)
* core args : Key/value pairs for tuning the core
* e.g. migration_threshold
* *policy name : Name of the policy
* #policy args : Number of policy arguments to follow (must be even)
* policy args : Key/value pairs
* e.g. sequential_threshold
*/
int dm_get_status_cache(struct dm_pool *mem, const char *params,
struct dm_status_cache **status)
{
int i, feature_argc;
char *str;
const char *p, *pp;
struct dm_status_cache *s;
if (!(s = dm_pool_zalloc(mem, sizeof(struct dm_status_cache))))
return_0;
/* Read in args that have definitive placement */
if (sscanf(params,
" %" PRIu32
" %" PRIu64 "/%" PRIu64
" %" PRIu32
" %" PRIu64 "/%" PRIu64
" %" PRIu64 " %" PRIu64
" %" PRIu64 " %" PRIu64
" %" PRIu64 " %" PRIu64
" %" PRIu64
" %d",
&s->metadata_block_size,
&s->metadata_used_blocks, &s->metadata_total_blocks,
&s->block_size, /* AKA, chunk_size */
&s->used_blocks, &s->total_blocks,
&s->read_hits, &s->read_misses,
&s->write_hits, &s->write_misses,
&s->demotions, &s->promotions,
&s->dirty_blocks,
&feature_argc) != 14)
goto bad;
/* Now jump to "features" section */
if (!(p = _advance_to_next_word(params, 12)))
goto bad;
/* Read in features */
for (i = 0; i < feature_argc; i++) {
if (!strncmp(p, "writethrough ", 13))
s->feature_flags |= DM_CACHE_FEATURE_WRITETHROUGH;
else if (!strncmp(p, "writeback ", 10))
s->feature_flags |= DM_CACHE_FEATURE_WRITEBACK;
else
log_error("Unknown feature in status: %s", params);
if (!(p = _advance_to_next_word(p, 1)))
goto bad;
}
/* Read in core_args. */
if (sscanf(p, "%d ", &s->core_argc) != 1)
goto bad;
if (s->core_argc &&
(!(s->core_argv = dm_pool_zalloc(mem, sizeof(char *) * s->core_argc)) ||
!(p = _advance_to_next_word(p, 1)) ||
!(str = dm_pool_strdup(mem, p)) ||
!(p = _advance_to_next_word(p, s->core_argc)) ||
(dm_split_words(str, s->core_argc, 0, s->core_argv) != s->core_argc)))
goto bad;
/* Read in policy args */
pp = p;
if (!(p = _advance_to_next_word(p, 1)) ||
!(s->policy_name = dm_pool_zalloc(mem, (p - pp))))
goto bad;
if (sscanf(pp, "%s %d", s->policy_name, &s->policy_argc) != 2)
goto bad;
if (s->policy_argc &&
(!(s->policy_argv = dm_pool_zalloc(mem, sizeof(char *) * s->policy_argc)) ||
!(p = _advance_to_next_word(p, 1)) ||
!(str = dm_pool_strdup(mem, p)) ||
(dm_split_words(str, s->policy_argc, 0, s->policy_argv) != s->policy_argc)))
goto bad;
*status = s;
return 1;
bad:
log_error("Failed to parse cache params: %s", params);
dm_pool_free(mem, s);
*status = NULL;
return 0;
}
int parse_thin_pool_status(const char *params, struct dm_status_thin_pool *s)
{
int pos;
if (!params) {
log_error("Failed to parse invalid thin params.");
return 0;
}
/* FIXME: add support for held metadata root */
if (sscanf(params, FMTu64 " " FMTu64 "/" FMTu64 " " FMTu64 "/" FMTu64 "%n",
&s->transaction_id,
&s->used_metadata_blocks,
&s->total_metadata_blocks,
&s->used_data_blocks,
&s->total_data_blocks, &pos) < 5) {
log_error("Failed to parse thin pool params: %s.", params);
return 0;
}
/* New status flags */
if (strstr(params + pos, "no_discard_passdown"))
s->discards = DM_THIN_DISCARDS_NO_PASSDOWN;
else if (strstr(params + pos, "ignore_discard"))
s->discards = DM_THIN_DISCARDS_IGNORE;
else /* default discard_passdown */
s->discards = DM_THIN_DISCARDS_PASSDOWN;
if (strstr(params + pos, "ro "))
s->read_only = 1;
else if (strstr(params + pos, "fail"))
s->fail = 1;
else if (strstr(params + pos, "out_of_data_space"))
s->out_of_data_space = 1;
if (strstr(params + pos, "error_if_no_space"))
s->error_if_no_space = 1;
return 1;
}
int dm_get_status_thin_pool(struct dm_pool *mem, const char *params,
struct dm_status_thin_pool **status)
{
struct dm_status_thin_pool *s;
if (!(s = dm_pool_zalloc(mem, sizeof(struct dm_status_thin_pool)))) {
log_error("Failed to allocate thin_pool status structure.");
return 0;
}
if (!parse_thin_pool_status(params, s)) {
dm_pool_free(mem, s);
return_0;
}
*status = s;
return 1;
}
int dm_get_status_thin(struct dm_pool *mem, const char *params,
struct dm_status_thin **status)
{
struct dm_status_thin *s;
if (!(s = dm_pool_zalloc(mem, sizeof(struct dm_status_thin)))) {
log_error("Failed to allocate thin status structure.");
return 0;
}
if (strchr(params, '-')) {
s->mapped_sectors = 0;
s->highest_mapped_sector = 0;
} else if (sscanf(params, FMTu64 " " FMTu64,
&s->mapped_sectors,
&s->highest_mapped_sector) != 2) {
dm_pool_free(mem, s);
log_error("Failed to parse thin params: %s.", params);
return 0;
}
*status = s;
return 1;
}

View File

@@ -205,7 +205,7 @@ static void _lv_set_default_params(struct lvcreate_params *lp,
}
static struct segment_type * _get_segtype(struct cmd_context *cmd) {
struct segment_type *rc = get_segtype_from_string(cmd, "striped");
struct segment_type *rc = get_segtype_from_string(cmd, SEG_TYPE_NAME_STRIPED);
if (!rc) {
log_error(INTERNAL_ERROR "Segtype striped not found.");
}
@@ -503,7 +503,7 @@ static int _lv_set_pool_params(struct lvcreate_params *lp,
_lv_set_default_params(lp, vg, pool_name, extents);
lp->create_pool = 1;
lp->segtype = get_segtype_from_string(vg->cmd, "thin-pool");
lp->segtype = get_segtype_from_string(vg->cmd, SEG_TYPE_NAME_THIN_POOL);
lp->stripes = 1;
if (!meta_size) {
@@ -611,7 +611,7 @@ static int _lv_set_thin_params(struct lvcreate_params *lp,
_lv_set_default_params(lp, vg, lvname, 0);
lp->pool_name = pool_name;
lp->segtype = get_segtype_from_string(vg->cmd, "thin");
lp->segtype = get_segtype_from_string(vg->cmd, SEG_TYPE_NAME_THIN);
lp->virtual_extents = extents;
lp->stripes = 1;
@@ -655,14 +655,14 @@ static lv_create_params_t _lvm_lv_params_create_snapshot(const lv_t lv,
_lv_set_default_params(&lvcp->lvp, lv->vg, snap_name, extents);
if (size) {
if (!(lvcp->lvp.segtype = get_segtype_from_string(lv->vg->cmd, "snapshot"))) {
if (!(lvcp->lvp.segtype = get_segtype_from_string(lv->vg->cmd, SEG_TYPE_NAME_SNAPSHOT))) {
log_error("Segtype snapshot not found.");
return NULL;
}
lvcp->lvp.chunk_size = 8;
lvcp->lvp.snapshot = 1;
} else {
if (!(lvcp->lvp.segtype = get_segtype_from_string(lv->vg->cmd, "thin"))) {
if (!(lvcp->lvp.segtype = get_segtype_from_string(lv->vg->cmd, SEG_TYPE_NAME_THIN))) {
log_error("Segtype thin not found.");
return NULL;
}

View File

@@ -497,7 +497,9 @@ EXPORTED_SYMBOLS := $(wildcard $(srcdir)/.exported_symbols.Base $(srcdir)/.expor
ifeq (,$(firstword $(EXPORTED_SYMBOLS)))
set -e; (echo "Base {"; echo " global:";\
$(SED) "s/^/ /;s/$$/;/" $<;\
echo " local:"; echo " *;"; echo "};") > $@
echo "};";\
echo "Local {"; echo " local:"; echo " *;"; echo "};";\
) > $@
else
set -e;\
R=$$(sort $^ | uniq -u);\

View File

@@ -14,10 +14,11 @@ blkdeactivate \(em utility to deactivate block devices
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, including LVM volumes.
LVM volumes are handled directly using the \fBlvm\fP(8) command.
Other device-mapper based devices are handled using the
\fBdmsetup\fP(8) command.
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
@@ -88,4 +89,5 @@ of device-mapper devices in case the deactivation fails and force removal.
.BR dmsetup (8),
.BR lsblk (8),
.BR lvm (8),
.BR mdadm (8),
.BR umount (8)

View File

@@ -1,125 +1,159 @@
.TH CLVMD 8 "LVM TOOLS #VERSION#" "Red Hat Inc" \" -*- nroff -*-
.
.SH NAME
.
clvmd \(em cluster LVM daemon
.
.SH SYNOPSIS
.
.ad l
.B clvmd
.RB [ \-C ]
.RB [ \-d
.RI [ value ]]
.RB [ \-E
.IR "lock uuid" ]
.IR lock_uuid ]
.RB [ \-f ]
.RB [ \-h ]
.RB [ \-I
.IR "cluster manager" ]
.IR cluster_manager ]
.RB [ \-R ]
.RB [ \-S ]
.RB [ \-t
.IR timeout ]
.RB [ \-T
.IR "start timeout" ]
.IR start_timeout ]
.RB [ \-V ]
.ad b
.
.SH DESCRIPTION
.
clvmd is the daemon that distributes LVM metadata updates around a cluster.
It must be running on all nodes in the cluster and will give an error
if a node in the cluster does not have this daemon running.
.
.SH OPTIONS
.TP
.BR \-d \ [ \fIvalue ]
.
.HP
.BR \-C
.br
Only valid if \fB\-d\fP is also specified.
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
given with \fB\-d\fP.
.br
This does not work correctly if specified on the command-line that starts clvmd.
If you want to start clvmd \fBand\fP
enable cluster-wide logging then the command needs to be issued twice, eg:
.br
.BR clvmd
.br
.BR clvmd\ \-d2
.
.HP
.BR \-d
.RI [ value ]
.br
Set debug logging level.
If \fB\-d\fP is specified without a \fIvalue\fP
then 1 is assumed. \fIValue\fP can be:
.PD 0
.IP
.B 0
.BR 0
\(em Disabled
.IP
.B 1
.BR 1
\(em Sends debug logs to stderr (implies \fB\-f\fP)
.IP
.B 2
.BR 2
\(em Sends debug logs to \fBsyslog\fP(3)
.PD
.TP
.B \-C
Only valid if
.B \-d
is also specified. 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
given with
.B \-d
.
.HP
.BR \-E
.IR lock_uuid
.br
This does not work correctly if specified on the command-line that starts clvmd.
If you want to start clvmd
.B and
enable cluster-wide logging then the command needs to be issued twice, eg:
Pass lock uuid to be reacquired exclusively when clvmd is restarted.
.
.HP
.BR \-f
.br
.B clvmd
.br
.B clvmd \-d2
.br
.TP
.BR \-E "\fI lock uuid"
Pass \fIlock uuid\fP to be reacquired exclusively when clvmd is restarted.
.TP
.B \-f
Don't fork, run in the foreground.
.TP
.B \-h
.
.HP
.BR \-h
.br
Show help information.
.TP
.BR \-I "\fI cluster manager"
Selects the \fIcluster manager\fP to use for locking and internal
.
.HP
.BR \-I
.IR cluster_manager
.br
Selects the cluster manager to use for locking and internal
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
search.
By default, omit \fB-I\fP is equivalent to \fB\-Iauto\fP. \fBClvmd\fP
will use the first cluster manager that succeeds, and it checks them in a
predefined order cman,corosync,openais.
By default, omit \fB-I\fP is equivalent to \fB\-Iauto\fP.
Clvmd will use the first cluster manager that succeeds,
and it checks them in a predefined order
.BR cman ,
.BR corosync ,
.BR openais .
The available managers will be listed by order as part of the
\fBclvmd \-h\fP output.
.TP
.B \-R
.
.HP
.BR \-R
.br
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
devices on a cluster system are changed.
.TP
.B \-S
.
.HP
.BR \-S
.br
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
any locks in the same state as they were previously held. (Alternative
methods of restarting the daemon have the side effect of changing
exclusive LV locks into shared locks.)
.TP
.BR \-t "\fI timeout"
.
.HP
.BR \-t
.IR timeout
.br
Specifies the \fItimeout\fP for commands to run around the cluster. This should not
be so small that commands with many disk updates to do will fail, so you
may need to increase this on systems with very large disk farms.
The default is 60 seconds.
.TP
.BR \-T "\fI start timeout"
Specifies the \fIstart timeout\fP for \fBclvmd\fP daemon startup. If the
.
.HP
.BR \-T
.IR start_timeout
.br
Specifies the start timeout for \fBclvmd\fP daemon startup. If the
daemon does not report that it has started up within this time then the parent
command will exit with status of 5. This does NOT mean that \fBclvmd\fP has
not started! What it means is that the startup has been delayed for some
reason; the most likely cause of this is an inquorate cluster though it
could be due to locking latencies on a cluster with large numbers of logical
volumes. If you get the return code of 5 it is usually not necessary to
restart \fBclvmd\fP it will start as soon as that blockage has cleared.
restart \fBclvmd\fP it will start as soon as that blockage has cleared.
This flag is to allow startup scripts to exit in a timely fashion even if the
cluster is stalled for some reason.
The default is 0 (no timeout) and the value is in seconds. Don't set this too
The default is \fB0\fP (no timeout) and the value is in seconds. Don't set this too
small or you will experience spurious errors. 10 or 20 seconds might be
sensible.
This timeout will be ignored if you start \fBclvmd\fP with the \fB\-d\fP.
.TP
.B \-V
.
.HP
.BR \-V
.br
Display the version of the cluster LVM daemon.
.
.SH ENVIRONMENT VARIABLES
.TP
.B LVM_CLVMD_BINARY
@@ -129,7 +163,10 @@ Defaults to \fI#CLVMD_PATH#\fP.
.B LVM_BINARY
The LVM2 binary to use.
Defaults to \fI#LVM_PATH#\fP.
.SH FILES
.I #CLVMD_PATH#
.br
.I #LVM_PATH#
.SH SEE ALSO
.BR syslog (3),
.BR lvm.conf (5),

View File

@@ -1,43 +1,68 @@
.TH DMEVENTD 8 "DM TOOLS #VERSION#" "Red Hat Inc" \" -*- nroff -*-
.
.SH NAME
.
dmeventd \(em Device-mapper event daemon
.
.SH SYNOPSIS
.
.B dmeventd
.RB [ \-d
.RB [ \-d
.RB [ \-d ]]]
.RB [ \-f ]
.RB [ \-h ]
.RB [ \-l ]
.RB [ \-R ]
.RB [ \-V ]
.RB [ \-? ]
.
.SH DESCRIPTION
.
dmeventd is the event monitoring daemon for device-mapper devices.
Library plugins can register and carry out actions triggered when
particular events occur.
.SH
LVM PLUGINS
.TP
.I Mirror
Attempts to handle device failure automatically. See \fBlvm.conf\fP(5).
.TP
.I Raid
Attempts to handle device failure automatically. See \fBlvm.conf\fP(5).
.TP
.I Snapshot
.
.SH LVM PLUGINS
.
.HP
.IR Mirror
.br
Attempts to handle device failure automatically. See
.BR lvm.conf (5).
.
.HP
.IR Raid
.br
Attempts to handle device failure automatically. See
.BR lvm.conf (5).
.
.HP
.IR Snapshot
.br
Monitors how full a snapshot is becoming and emits a warning to
syslog when it exceeds 80% full.
The warning is repeated when 85%, 90% and 95% of the snapshot is filled.
See \fBlvm.conf\fP(5).
.TP
.I Thin
Monitors how full a thin pool is becoming and emits a warning to
syslog when it exceeds 80% full.
See
.BR lvm.conf (5).
Snapshot which runs out of space gets invalid and when it is mounted,
it gets umounted if possible.
.
.HP
.IR Thin
.br
Monitors how full a thin pool data and metadata is becoming and emits
a warning to syslog when it exceeds 80% full.
The warning is repeated when 85%, 90% and 95% of the thin pool is filled.
See \fBlvm.conf\fP(5).
See
.BR lvm.conf (5).
If the thin-pool runs out of space, thin volumes are umounted if possible.
.
.SH OPTIONS
.TP
.B \-d
.
.HP
.BR \-d
.br
Repeat from 1 to 3 times (
.BR \-d ,
.BR \-dd ,
@@ -45,21 +70,41 @@ Repeat from 1 to 3 times (
) to increase the detail of
debug messages sent to syslog.
Each extra d adds more debugging information.
.TP
.B \-f
.
.HP
.BR \-f
.br
Don't fork, run in the foreground.
.TP
.BR \-h ", " \-?
.
.HP
.BR \-h
.br
Show help information.
.TP
.B \-R
.
.HP
.BR \-l
.br
Log through stdout and stderr instead of syslog.
This option works only with option \-f, otherwise it is ignored.
.
.HP
.BR \-?
.br
Show help information on stderr.
.
.HP
.BR \-R
.br
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
events to monitor from the currently running daemon.
.TP
.B \-V
.
.HP
.BR \-V
.br
Show version of dmeventd.
.
.SH SEE ALSO
.
.BR lvm (8),
.BR lvm.conf (5)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -2,72 +2,105 @@
.SH "NAME"
fsadm \(em utility to resize or check filesystem on a device
.SH SYNOPSIS
.
.PD 0
.ad l
.HP 5
.B fsadm
.RI [ options ]
.B check
.I device
.sp
.BR check
.IR device
.
.HP
.B fsadm
.RI [ options ]
.B resize
.I device
.RI [ new_size [ BKMGTEP ]]
.sp
.BR resize
.IR device
.RI [ new_size ]
.PD
.ad b
.
.SH DESCRIPTION
.
fsadm utility checks or resizes the filesystem on a device.
It tries to use the same API for
.IR ext2 ", " ext3 ", " ext4 ", " ReiserFS " and " XFS
It tries to use the same API for
.BR ext2 ,
.BR ext3 ,
.BR ext4 ,
.BR ReiserFS
.RB and
.BR XFS
filesystem.
.
.SH OPTIONS
.TP
.BR \-e ", " \-\-ext\-offline
.
.HP
.BR \-e | \-\-ext\-offline
.br
Unmount ext2/ext3/ext4 filesystem before doing resize.
.TP
.BR \-f ", " \-\-force
.
.HP
.BR \-f | \-\-force
.br
Bypass some sanity checks.
.TP
.BR \-h ", " \-\-help
.
.HP
.BR \-h | \-\-help
.br
Display the help text.
.TP
.BR \-n ", " \-\-dry\-run
.
.HP
.BR \-n | \-\-dry\-run
.br
Print commands without running them.
.TP
.BR \-v ", " \-\-verbose
.
.HP
.BR \-v | \-\-verbose
.br
Be more verbose.
.TP
.BR \-y ", " \-\-yes
.
.HP
.BR \-y | \-\-yes
.br
Answer "yes" at any prompts.
.TP
.I new_size
.
.HP
.BR \fInew_size [ B | K | M | G | T | P | E ]
.br
Absolute number of filesystem blocks to be in the filesystem,
or an absolute size using a suffix (in powers of 1024).
If new_size is not supplied, the whole device is used.
.
.SH DIAGNOSTICS
.
On successful completion, the status code is 0.
A status code of 2 indicates the operation was interrupted by the user.
A status code of 3 indicates the requested check operation could not be performed
because the filesystem is mounted and does not support an online
because the filesystem is mounted and does not support an online
.BR fsck (8).
A status code of 1 is used for other failures.
.
.SH EXAMPLES
Resize the filesystem on logical volume /dev/vg/test to 1000 megabytes.
If /dev/vg/test contains ext2/ext3/ext4
.
Resize the filesystem on logical volume \fI/dev/vg/test\fP to 1000 megabytes.
If \fI/dev/vg/test\fP contains ext2/ext3/ext4
filesystem it will be unmounted prior the resize.
All [y/n] questions will be answered 'y'.
.sp
.B fsadm \-e \-y resize /dev/vg/test 1000M
.
.SH ENVIRONMENT VARIABLES
.
.TP
.B TMPDIR
The temporary directory name for mount points. Defaults to "/tmp".
.B "TMPDIR "
The temporary directory name for mount points. Defaults to "\fI/tmp\fP".
.TP
.B DM_DEV_DIR
The device directory name.
Defaults to "/dev" and must be an absolute path.
Defaults to "\fI/dev\fP" and must be an absolute path.
.SH SEE ALSO
.nh
.BR lvm (8),
.BR lvresize (8),
.BR lvm.conf (5),

View File

@@ -1,21 +1,30 @@
.TH LVCHANGE 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
.de UNITS
..
.
.SH NAME
.
lvchange \(em change attributes of a logical volume
.
.SH SYNOPSIS
.
.ad l
.B lvchange
.RB [ \-\-addtag
.IR Tag ]
.RB [ \-A | \-\-autobackup
.RB { y | n }]
.RB [ \-a | \-\-activate
.RB [ a ][ e | s | l ]{ y | n }]
.RB [ \-\-activationmode
.RB { complete | degraded | partial }]
.RB [ \-\-addtag
.IR Tag ]
.RB [ \-K | \-\-ignoreactivationskip ]
.RB [ \-k | \-\-setactivationskip
.RB { y | n }]
.RB [ \-K | \-\-ignoreactivationskip ]
.RB [ \-\-alloc
.IR AllocationPolicy ]
.RB [ \-A | \-\-autobackup
.RB { y | n }]
.RB [ \-\-cachepolicy
.IR policy ]
.RB [ \-\-cachesettings
@@ -33,13 +42,24 @@ lvchange \(em change attributes of a logical volume
.RB { ignore | nopassdown | passdown }]
.RB [ \-\-errorwhenfull
.RB { y | n }]
.RB [ \-\-resync ]
.RB [ \-h | \-? | \-\-help ]
.RB [ \-\-ignorelockingfailure ]
.RB [ \-\-ignoremonitoring ]
.RB [ \-\-ignoreskippedcluster ]
.RB \%[ \-\-ignorelockingfailure ]
.RB \%[ \-\-ignoremonitoring ]
.RB \%[ \-\-ignoreskippedcluster ]
.RB \%[ \-\-metadataprofile
.IR ProfileName ]
.RB [ \-\-monitor
.RB { y | n }]
.RB [ \-\-noudevsync ]
.RB [ \-P | \-\-partial ]
.RB [ \-p | \-\-permission
.RB { r | rw }]
.RB [ \-M | \-\-persistent
.RB { y | n }
.RB [ \-\-major
.IR major ]
.RB [ \-\-minor
.IR minor ]]
.RB [ \-\-poll
.RB { y | n }]
.RB [ \-\- [ raid ] maxrecoveryrate
@@ -52,41 +72,38 @@ lvchange \(em change attributes of a logical volume
.IR IOCount ]
.RB [ \-\- [ raid ] writemostly
.BR \fIPhysicalVolume [ : { y | n | t }]]
.RB [ \-\-sysinit ]
.RB [ \-\-noudevsync ]
.RB [ \-\-metadataprofile
.IR ProfileName ]
.RB [ \-M | \-\-persistent
.RB { y | n }
.RB [ \-\-minor
.IR minor ]
.RB [ \-\-major
.IR major ]]
.RB [ \-P | \-\-partial ]
.RB [ \-p | \-\-permission
.RB { r | rw }]
.RB [ \-r | \-\-readahead
.RB { \fIReadAheadSectors | auto | none }]
.RB [ \-\-refresh ]
.RB [ \-\-resync ]
.RB [ \-S | \-\-select
.IR Selection ]
.RB [ \-\-sysinit ]
.RB [ \-t | \-\-test ]
.RB [ \-v | \-\-verbose ]
.RB [ \-Z | \-\-zero
.RB { y | n }]
.RI [ LogicalVolumePath ...]
.ad b
.
.SH DESCRIPTION
.
lvchange allows you to change the attributes of a logical volume
including making them known to the kernel ready for use.
.
.SH OPTIONS
.
See \fBlvm\fP(8) for common options.
.TP
.BR \-a ", " \-\-activate " [" a ][ e | s | l ]{ y | n }
.
.HP
.BR \-a | \-\-activate
.RB [ a ][ e | s | l ]{ y | n }
.br
Controls the availability of the logical volumes for use.
Communicates with the kernel device-mapper driver via
libdevmapper to activate (\fB\-ay\fP) or deactivate (\fB\-an\fP) the
logical volumes.
.IP
.br
Activation of a logical volume creates a symbolic link
\fI/dev/VolumeGroupName/LogicalVolumeName\fP pointing to the device node.
This link is removed on deactivation.
@@ -95,19 +112,16 @@ this symbolic link and present this as the name of the device.
The location and name of the underlying device node may depend on
the distribution and configuration (e.g. udev) and might change
from release to release.
.IP
.br
If autoactivation option is used (\fB\-aay\fP),
the logical volume is activated only if it matches an item in
the
.B activation/auto_activation_volume_list
the \fBactivation/auto_activation_volume_list\fP
set in \fBlvm.conf\fP(5).
If this list is not set, then all volumes are considered for
activation. The \fB\-aay\fP option should be also used during system
boot so it's possible to select which volumes to activate using
the
.B activation/auto_activation_volume_list
setting.
.IP
the \fBactivation/auto_activation_volume_list\fP setting.
.br
In a clustered VG, clvmd is used for activation, and the
following options are possible:
@@ -137,9 +151,11 @@ LVs with snapshots are always activated exclusively because they can only
be used on one node at once.
For local VGs \fB\-ay\fP, \fB\-aey\fP, and \fB\-asy\fP are all equivalent.
.TP
.BR \-\-activationmode " {" complete | degraded | partial }
.
.HP
.BR \-\-activationmode
.RB { complete | degraded | partial }
.br
The activation mode determines whether logical volumes are allowed to
activate when there are physical volumes missing (e.g. due to a device
failure). \fBcomplete\fP is the most restrictive; allowing only those
@@ -150,106 +166,168 @@ considered a RAID logical volume. The "\fIraid1\fP" segment type should
be used instead.) Finally, \fBpartial\fP allows any logical volume to
be activated even if portions are missing due to a missing or failed
PV. This last option should only be used when performing recovery or
repair operations. \fBdegraded\fP is the default mode. To change it, modify
.B activation_mode
in
.BR lvm.conf (5).
.TP
.BR \-k ", " \-\-setactivationskip " {" y | n }
repair operations. \fBdegraded\fP is the default mode. To change it,
modify \fBactivation_mode\fP in \fBlvm.conf\fP(5).
.
.HP
.BR \-K | \-\-ignoreactivationskip
.br
Ignore the flag to skip Logical Volumes during activation.
.
.HP
.BR \-k | \-\-setactivationskip
.RB { y | n }
.br
Controls whether Logical Volumes are persistently flagged to be
skipped during activation. By default, thin snapshot volumes are
flagged for activation skip. To activate such volumes,
an extra
.BR \-K / \-\-ignoreactivationskip
option must be used.
an extra \fB\-\-ignoreactivationskip\fP option must be used.
The flag is not applied during deactivation. To see whether
the flag is attached, use \fBlvs\fP(8) command where the state
of the flag is reported within \fBlv_attr\fP bits.
.TP
.BR \-K ", " \-\-ignoreactivationskip
Ignore the flag to skip Logical Volumes during activation.
.TP
.BR \-\-cachepolicy " " \fIpolicy ", " \-\-cachesettings " " \fIkey = \fIvalue
.
.HP
.BR \-\-cachepolicy
.IR policy ,
.BR \-\-cachesettings
.IR key \fB= value
.br
Only applicable to cached LVs; see also \fBlvmcache(7)\fP. Sets
the cache policy and its associated tunable settings. In most use-cases,
default values should be adequate.
.TP
.BR \-C ", " \-\-contiguous " {" y | n }
.
.HP
.BR \-C | \-\-contiguous
.RB { y | n }
.br
Tries to set or reset the contiguous allocation policy for
logical volumes. It's only possible to change a non-contiguous
logical volume's allocation policy to contiguous, if all of the
allocated physical extents are already contiguous.
.TP
.
.HP
.BR \-\-detachprofile
.br
Detach any metadata configuration profiles attached to given
Logical Volumes. See \fBlvm.conf\fP(5) for more information
about metadata profiles.
.TP
.BR \-\-discards " {" ignore | nopassdown | passdown }
.
.HP
.BR \-\-discards
.RB { ignore | nopassdown | passdown }
.br
Set this to \fBignore\fP to ignore any discards received by a
thin pool Logical Volume. Set to \fBnopassdown\fP to process such
discards within the thin pool itself and allow the no-longer-needed
extents to be overwritten by new data. Set to \fBpassdown\fP (the
default) to process them both within the thin pool itself and to
pass them down the underlying device.
.TP
.BR \-\-errorwhenfull " {" y | n }
.
.HP
.BR \-\-errorwhenfull
.RB { y | n }
.br
Sets thin pool behavior when data space is exhaused. See
.BR lvcreate (8)
for information.
.TP
.B \-\-resync
Forces the complete resynchronization of a mirror. In normal
circumstances you should not need this option because synchronization
happens automatically. Data is read from the primary mirror device
and copied to the others, so this can take a considerable amount of
time - and during this time you are without a complete redundant copy
of your data.
.TP
.B \-\-metadataprofile " " \fIProfileName
.
.HP
.BR \-\-ignoremonitoring
.br
Make no attempt to interact with dmeventd unless \fB\-\-monitor\fP
is specified.
Do not use this if dmeventd is already monitoring a device.
.
.HP
.BR \-\-major
.IR major
.br
Sets the major number. This option is supported only on older systems
(kernel version 2.4) and is ignored on modern Linux systems where major
numbers are dynamically assigned.
.
.HP
.BR \-\-minor
.IR minor
.br
Set the minor number.
.
.HP
.BR \-\-metadataprofile
.IR ProfileName
.br
Uses and attaches \fIProfileName\fP configuration profile to the logical
volume metadata. Whenever the logical volume is processed next time,
the profile is automatically applied. If the volume group has another
profile attached, the logical volume profile is preferred.
See \fBlvm.conf\fP(5) for more information about metadata profiles.
.TP
.B \-\-minor \fIminor
Set the minor number.
.TP
.B \-\-major \fImajor
Sets the major number. This option is supported only on older systems
(kernel version 2.4) and is ignored on modern Linux systems where major
numbers are dynamically assigned.
.TP
.BR \-\-monitor " {" y | n }
.
.HP
.BR \-\-monitor
.RB { y | n }
.br
Start or stop monitoring a mirrored or snapshot logical volume with
dmeventd, if it is installed.
If a device used by a monitored mirror reports an I/O error,
the failure is handled according to
\fBmirror_image_fault_policy\fP and \fBmirror_log_fault_policy\fP
\%\fBmirror_image_fault_policy\fP and \fBmirror_log_fault_policy\fP
set in \fBlvm.conf\fP(5).
.TP
.BR \-\-poll " {" y | n }
.
.HP
.BR \-\-noudevsync
.br
Disable udev synchronisation. The
process will not wait for notification from udev.
It will continue irrespective of any possible udev processing
in the background. You should only use this if udev is not running
or has rules that ignore the devices LVM2 creates.
.
.HP
.BR \-p | \-\-permission
.RB { r | rw }
.br
Change access permission to read-only or read/write.
.
.HP
.BR \-M | \-\-persistent
.RB { y | n }
.br
Set to \fBy\fP to make the minor number specified persistent.
Change of persistent numbers is not supported for pool volumes.
.
.HP
.BR \-\-poll
.RB { y | n }
.br
Without polling a logical volume's backgrounded transformation process
will never complete. If there is an incomplete pvmove or lvconvert (for
example, on rebooting after a crash), use \fB\-\-poll y\fP to restart the
process from its last checkpoint. However, it may not be appropriate to
immediately poll a logical volume when it is activated, use
\fB\-\-poll n\fP to defer and then \fB\-\-poll y\fP to restart the process.
.TP
.BR \-\- [ raid ] maxrecoveryrate " " \fIRate [ bBsSkKmMgG ]
.
.HP
.BR \-\- [ raid ] maxrecoveryrate
.BR \fIRate [ b | B | s | S | k | K | m | M | g | G ]
.br
Sets the maximum recovery rate for a RAID logical volume. \fIRate\fP
is specified as an amount per second for each device in the array.
If no suffix is given, then KiB/sec/device is assumed. Setting the
recovery rate to \fB0\fP means it will be unbounded.
.TP
.BR \-\- [ raid ] minrecoveryrate " " \fIRate [ bBsSkKmMgG ]
.
.HP
.BR \-\- [ raid ] minrecoveryrate
.BR \fIRate [ b | B | s | S | k | K | m | M | g | G ]
.br
Sets the minimum recovery rate for a RAID logical volume. \fIRate\fP
is specified as an amount per second for each device in the array.
If no suffix is given, then KiB/sec/device is assumed. Setting the
recovery rate to \fB0\fP means it will be unbounded.
.TP
.BR \-\- [ raid ] syncaction " {" check | repair }
.
.HP
.BR \-\- [ raid ] syncaction
.RB { check | repair }
.br
This argument is used to initiate various RAID synchronization operations.
The \fBcheck\fP and \fBrepair\fP options provide a way to check the
integrity of a RAID logical volume (often referred to as "scrubbing").
@@ -260,16 +338,22 @@ If \fBcheck\fP is used, the discrepancies will be counted but not repaired.
If \fBrepair\fP is used, the discrepancies will be corrected as they are
encountered. The \fBlvs\fP(8) command can be used to show the number of
discrepancies found or repaired.
.TP
.BR \-\- [ raid ] writebehind " " \fIIOCount
.
.HP
.BR \-\- [ raid ] writebehind
.IR IOCount
.br
Specify the maximum number of outstanding writes that are allowed to
devices in a RAID1 logical volume that are marked as write-mostly.
Once this value is exceeded, writes become synchronous (i.e. all writes
to the constituent devices must complete before the array signals the
write has completed). Setting the value to zero clears the preference
and allows the system to choose the value arbitrarily.
.TP
.BR \-\- [ raid ] writemostly " " \fIPhysicalVolume [ : { y | n | t }]
.
.HP
.BR \-\- [ raid ] writemostly
.BR \fIPhysicalVolume [ : { y | n | t }]
.br
Mark a device in a RAID1 logical volume as write-mostly. All reads
to these drives will be avoided unless absolutely necessary. This keeps
the number of I/Os to the drive to a minimum. The default behavior is to
@@ -279,8 +363,39 @@ appending a "\fB:n\fP" to the physical volume or to toggle the value by specifyi
"\fB:t\fP". The \fB\-\-writemostly\fP argument can be specified more than one time
in a single command; making it possible to toggle the write-mostly attributes
for all the physical volumes in a logical volume at once.
.TP
.B \-\-sysinit
.
.HP
.BR \-r | \-\-readahead
.RB { \fIReadAheadSectors | auto | none }
.br
Set read ahead sector count of this logical volume.
For volume groups with metadata in lvm1 format, this must
be a value between 2 and 120 sectors.
The default value is "\fBauto\fP" which allows the kernel to choose
a suitable value automatically.
"\fBnone\fP" is equivalent to specifying zero.
.
.HP
.BR \-\-refresh
.br
If the logical volume is active, reload its metadata.
This is not necessary in normal operation, but may be useful
if something has gone wrong or if you're doing clustering
manually without a clustered lock manager.
.
.HP
.BR \-\-resync
.br
Forces the complete resynchronization of a mirror. In normal
circumstances you should not need this option because synchronization
happens automatically. Data is read from the primary mirror device
and copied to the others, so this can take a considerable amount of
time - and during this time you are without a complete redundant copy
of your data.
.
.HP
.BR \-\-sysinit
.br
Indicates that \fBlvchange\fP(8) is being invoked from early system
initialisation scripts (e.g. rc.sysinit or an initrd),
before writeable filesystems are available. As such,
@@ -295,55 +410,31 @@ If \fB\-\-sysinit\fP is used in conjunction with
\fBlvmetad\fP(8) enabled and running,
autoactivation is preferred over manual activation via direct lvchange call.
Logical volumes are autoactivated according to
.B auto_activation_volume_list
set in \fBlvm.conf\fP(5).
.TP
.B \-\-noudevsync
Disable udev synchronisation. The
process will not wait for notification from udev.
It will continue irrespective of any possible udev processing
in the background. You should only use this if udev is not running
or has rules that ignore the devices LVM2 creates.
.TP
.B \-\-ignoremonitoring
Make no attempt to interact with dmeventd unless \fB\-\-monitor\fP
is specified.
Do not use this if dmeventd is already monitoring a device.
.TP
.BR \-M ", " \-\-persistent " {" y | n }
Set to \fBy\fP to make the minor number specified persistent.
Change of persistent numbers is not supported for pool volumes.
.TP
.BR \-p ", " \-\-permission " {" r | rw }
Change access permission to read-only or read/write.
.TP
.BR \-r ", " \-\-readahead " {" \fIReadAheadSectors | auto | none }
Set read ahead sector count of this logical volume.
For volume groups with metadata in lvm1 format, this must
be a value between 2 and 120 sectors.
The default value is "\fBauto\fP" which allows the kernel to choose
a suitable value automatically.
"\fBnone\fP" is equivalent to specifying zero.
.TP
.B \-\-refresh
If the logical volume is active, reload its metadata.
This is not necessary in normal operation, but may be useful
if something has gone wrong or if you're doing clustering
manually without a clustered lock manager.
.TP
.BR \-Z ", " \-\-zero " {" y | n }
\fB auto_activation_volume_list\fP set in \fBlvm.conf\fP(5).
.
.HP
.BR \-Z | \-\-zero
.RB { y | n }
.br
Set zeroing mode for thin pool. Note: already provisioned blocks from pool
in non-zero mode are not cleared in unwritten parts when setting zero to
\fBy\fP.
.
.SH ENVIRONMENT VARIABLES
.
.TP
.B LVM_SUPPRESS_LOCKING_FAILURE_MESSAGES
Suppress locking failure messages.
.
.SH Examples
.
Changes the permission on volume lvol1 in volume group vg00 to be read-only:
.sp
.B lvchange \-pr vg00/lvol1
.
.SH SEE ALSO
.
.nh
.BR lvm (8),
.BR lvmetad (8),
.BR lvs (8),

View File

@@ -1,41 +1,57 @@
.TH LVCREATE 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
.
.\" Use 1st. parameter with \% to fix 'man2html' rendeing on same line!
.de SIZE_G
. IR \\$1 \c
. RB [ b | B | s | S | k | K | m | M | g | G ]
..
.de SIZE_E
. IR \\$1 \c
. RB [ b | B | s | S | k | K | m | M | \c
. BR g | G | t | T | p | P | e | E ]
..
.
.SH NAME
.
lvcreate \- create a logical volume in an existing volume group
.
.SH SYNOPSIS
.
.ad l
.B lvcreate
.RB [ \-a | \-\-activate
.RI [ a | e | l ]{ y | n }]
.RB [ a ][ e | l | s ]{ y | n }]
.RB [ \-\-addtag
.IR Tag ]
.RB [ \-\-alloc
.IR AllocationPolicy ]
.IR Allocation\%Policy ]
.RB [ \-A | \-\-autobackup
.RI { y | n }]
.RB { y | n }]
.RB [ \-H | \-\-cache ]
.RB [ \-\-cachemode
.RI { passthrough | writeback | writethrough }]
.RB { passthrough | writeback | writethrough }]
.RB [ \-\-cachepolicy
.IR policy ]
.RB [ \-\-cachepool
.IR CachePoolLogicalVolume { Name | Path }
.RB \%[ \-\-cachepool
.IR CachePoolLogicalVolume ]
.RB [ \-\-cachesettings
.IR key=value ]
.IR key \fB= value ]
.RB [ \-c | \-\-chunksize
.IR ChunkSize [ bBsSkKmMgG ]]
.IR ChunkSize ]
.RB [ \-\-commandprofile
.IR ProfileName ]
.RB [ \-C | \-\-contiguous
.RI { y | n }]
.RB \%[ \-C | \-\-contiguous
.RB { y | n }]
.RB [ \-d | \-\-debug ]
.RB [ \-\-discards
.RI { ignore | nopassdown | passdown }]
.RB \%{ ignore | nopassdown | passdown }]
.RB [ \-\-errorwhenfull
.RI { y | n }]
.RB { y | n }]
.RB [{ \-l | \-\-extents
.IR LogicalExtentsNumber [ % { FREE | PVS | VG }]
|
.BR \fILogicalExtents\%Number [ % { FREE | PVS | VG }]
.RB |
.BR \-L | \-\-size
.IR LogicalVolumeSize [ bBsSkKmMgGtTpPeE ]}
.BR \fILogicalVolumeSize }
.RB [ \-i | \-\-stripes
.IR Stripes
.RB [ \-I | \-\-stripesize
@@ -48,87 +64,83 @@ lvcreate \- create a logical volume in an existing volume group
.RB [ \-j | \-\-major
.IR major ]]
.RB [ \-\-metadataprofile
.IR ProfileName ]
.IR Profile\%Name ]
.RB [ \-m | \-\-mirrors
.IR Mirrors
.RB [{ \-\-corelog
|
.B \-\-mirrorlog
.RI { disk | core | mirrored }}]
.RB [ \-\-corelog | \-\-mirrorlog
.RB { disk | core | mirrored }]
.RB [ \-\-nosync ]
.RB [ \-R | \-\-regionsize
.IR MirrorLogRegionSize [ bBsSkKmMgG ]]]
.BR \fIMirrorLogRegionSize ]]
.RB [ \-\-monitor
.RI { y | n }]
.RB { y | n }]
.RB [ \-n | \-\-name
.IR LogicalVolume { Name | Path }]
.IR Logical\%Volume ]
.RB [ \-\-noudevsync ]
.RB [ \-p | \-\-permission
.RI { r | rw }]
.RB { r | rw }]
.RB [ \-M | \-\-persistent
.RI { y | n }]
.RB { y | n }]
.\" .RB [ \-\-pooldatasize
.\" .IR DataVolumeSize [ bBsSkKmMgGtTpPeE ]]
.RB [ \-\-poolmetadatasize
.IR MetadataVolumeSize [ bBsSkKmMgG ]]
.\" .I DataVolumeSize
.RB \%[ \-\-poolmetadatasize
.IR MetadataVolumeSize ]
.RB [ \-\-poolmetadataspare
.RI { y | n }]
.RB { y | n }]
.RB [ \-\- [ raid ] maxrecoveryrate
.IR Rate ]
.RB [ \-\- [ raid ] minrecoveryrate
.IR Rate ]
.RB [ \-r | \-\-readahead
.RI { ReadAheadSectors | auto | none }]
.RB [ \-k | \-\-setactivationskip
.RI { y | n }]
.RB [ \-s | \-\-snapshot
.RB { \fIReadAheadSectors | auto | none }]
.RB \%[ \-k | \-\-setactivationskip
.RB { y | n }]
.RB [ \-s | \-\-snapshot ]
.RB [ \-V | \-\-virtualsize
.IR VirtualSize [ bBsSkKmMgGtTpPeE ]]
.IR VirtualSize ]
.RB [ \-t | \-\-test ]
.RB [ \-T | \-\-thin ]
.RB [ \-\-thinpool
.IR ThinPoolLogicalVolume { Name | Path }]
.IR ThinPoolLogicalVolume ]
.RB [ \-\-type
.IR SegmentType ]
.RB [ \-v | \-\-verbose ]
.RB [ \-W | \-\-wipesignatures
.RI { y | n }]
.RB { y | n }]
.RB [ \-Z | \-\-zero
.RI { y | n }]
.RI [ VolumeGroup { Name | Path }
.RI [/\{ ExternalOrigin
|
.I Origin
|
.IR Pool } LogicalVolumeName ]
.RI [ PhysicalVolumePath [ :PE [ \-PE ]]...]
.RB { y | n }]
.RI [ VolumeGroup \c
.RB [ / \c
.RI { ExternalOrigin | Origin | Pool } LogicalVolumeName
.RI [ PhysicalVolumePath [ \fB: \fIPE \fR[ \fB\- PE ]]...]]
.LP
.B lvcreate
.RB [ \-l | \-\-extents
.IR LogicalExtentsNumber [ % { FREE | ORIGIN | PVS | VG }]
.BR \fILogicalExtentsNumber [ % { FREE | ORIGIN | PVS | VG }]
|
.BR \-L | \-\-size
.\" | \-\-pooldatasize
.IR LogicalVolumeSize [ bBsSkKmMgGtTpPeE ]]
.IR LogicalVolumeSize ]
.RB [ \-c | \-\-chunksize
.IR ChunkSize [ bBsSkKmMgG ]]
.RB [ \-\-commandprofile
.IR Profilename ]
.IR ChunkSize ]
.RB \%[ \-\-commandprofile
.IR Profile\%Name ]
.RB [ \-\-noudevsync ]
.RB [ \-\-ignoremonitoring ]
.RB [ \-\-metadataProfile
.IR ProfileName ]
.RB [ \-\-monitor
.RI { y | n }]
.RB [ \-\-metadataprofile
.IR Profile\%Name ]
.RB \%[ \-\-monitor
.RB { y | n }]
.RB [ \-n | \-\-name
.IR SnapshotLogicalVolume { Name | Path }]
.IR SnapshotLogicalVolume ]
.BR \-s | \-\-snapshot | \-H | \-\-cache
.RI {[ VolumeGroup { Name | Path }/] OriginalLogicalVolumeName
.BR \-V | \-\-virtualsize
.IR VirtualSize [ bBsSkKmMgGtTpPeE ]}
.br
.RI \%{[ VolumeGroup \fB/\fP] OriginalLogicalVolume
.RB \%[ \-V | \-\-virtualsize
.IR VirtualSize ]}
.ad b
.
.SH DESCRIPTION
.
lvcreate creates a new logical volume in a volume group (see
.BR vgcreate "(8), " vgchange (8))
by allocating logical extents from the free physical extent pool
@@ -144,165 +156,217 @@ extents will be restricted to these volumes.
.br
The second form supports the creation of snapshot logical volumes which
keep the contents of the original logical volume for backup purposes.
.
.SH OPTIONS
.
See
.BR lvm (8)
for common options.
.TP
.IR \fB\-a ", " \fB\-\-activate " {" y | ay | n | ey | en | ly | ln }
.
.HP
.BR \-a | \-\-activate
.RB [ a ][ l | e | s ]{ y | n }
.br
Controls the availability of the Logical Volumes for immediate use after
the command finishes running.
By default, new Logical Volumes are activated (\fB\-a\fIy\fR).
If it is possible technically, \fB\-a\fIn\fR will leave the new Logical
By default, new Logical Volumes are activated (\fB\-ay\fP).
If it is possible technically, \fB\-an\fP will leave the new Logical
Volume inactive. But for example, snapshots of active origin can only be
created in the active state so \fB\-a\fIn\fR cannot be used with
\fB-\-type\fP \fIsnapshot\fP. This does not apply to thin volume snapshots,
created in the active state so \fB\-an\fP cannot be used with
\fB-\-type snapshot\fP. This does not apply to thin volume snapshots,
which are by default created with flag to skip their activation
(\fB-k\fP\fIy\fP).
Normally the \fB\-\-zero\fP \fIn\fP argument has to be supplied too because
(\fB-ky\fP).
Normally the \fB\-\-zero n\fP argument has to be supplied too because
zeroing (the default behaviour) also requires activation.
If autoactivation option is used (\fB\-a\fIay\fR), the logical volume is
If autoactivation option is used (\fB\-aay\fP), the logical volume is
activated only if it matches an item in the
.IR activation / auto_activation_volume_list
\fBactivation/auto_activation_volume_list\fP
set in \fBlvm.conf\fP(5).
For autoactivated logical volumes, \fB\-\-zero\fP \fIn\fP and
\fB\-\-wipesignatures\fP \fIn\fP is always assumed and it can't
For autoactivated logical volumes, \fB\-\-zero n\fP and
\fB\-\-wipesignatures n\fP is always assumed and it can't
be overridden. If the clustered locking is enabled,
\fB\-a\fIey\fR will activate exclusively on one node and
.IR \fB\-a { a | l } y
\fB\-aey\fP will activate exclusively on one node and
.BR \-a { a | l } y
will activate only on the local node.
.TP
.IR \fB\-H ", " \fB\-\-cache
Creates cache or cache pool logical volume or both.
Specifying the optional argument \fB\-\-size\fP will cause the creation of
the cache logical volume.
.
.HP
.BR \-H | \-\-cache
.br
Creates cache or cache pool logical volume.
.\" or both.
Specifying the optional argument \fB\-\-extents\fP or \fB\-\-size\fP
will cause the creation of the cache logical volume.
.\" Specifying the optional argument \fB\-\-pooldatasize\fP will cause
.\" the creation of the cache pool logical volume.
Specifying both arguments will cause the creation of cache with its
cache pool volume.
.\" Specifying both arguments will cause the creation of cache with its
.\" cache pool volume.
When the Volume group name is specified together with existing logical volume
name which is NOT a cache pool name, such volume is treaded
as cache origin volume and cache pool is created. In this case
the \fB\-\-size\fP is used to specify size of cache pool volume.
name which is NOT a cache pool name, such volume is treated
as cache origin volume and cache pool is created. In this case the
\fB\-\-extents\fP or \fB\-\-size\fP is used to specify size of cache pool volume.
See \fBlvmcache\fP(7) for more info about caching support.
Note that the cache segment type requires a dm-cache kernel module version
1.3.0 or greater.
.TP
.IR \fB\-\-cachemode " {" passthrough | writeback | writethrough }
.
.HP
.BR \-\-cachemode
.RB { passthrough | writeback | writethrough }
.br
Specifying a cache mode determines when the writes to a cache LV
are considered complete. When \fIwriteback\fP is specified, a write is
are considered complete. When \fBwriteback\fP is specified, a write is
considered complete as soon as it is stored in the cache pool LV.
If \fIwritethough\fP is specified, a write is considered complete only
If \fBwritethough\fP is specified, a write is considered complete only
when it has been stored in the cache pool LV and on the origin LV.
While \fIwritethrough\fP may be slower for writes, it is more
While \fBwritethrough\fP may be slower for writes, it is more
resilient if something should happen to a device associated with the
cache pool LV.
.TP
.B \-\-cachepolicy \fIpolicy
.
.HP
.BR \-\-cachepolicy
.IR policy
.br
Only applicable to cached LVs; see also \fBlvmcache(7)\fP. Sets
the cache policy. \fImq\fP is the basic policy name. \fIsmq\fP is more advanced
the cache policy. \fBmq\fP is the basic policy name. \fBsmq\fP is more advanced
version available in newer kernels.
.TP
.IR \fB\-\-cachepool " " CachePoolLogicalVolume { Name | Path }
.
.HP
.BR \-\-cachepool
.IR CachePoolLogicalVolume { Name | Path }
.br
Specifies the name of cache pool volume name. The other way to specify pool name
is to append name to Volume group name argument.
.TP
.BR \-\-cachesettings " " \fIkey=value
.
.HP
.BR \-\-cachesettings
.IB key = value
.br
Only applicable to cached LVs; see also \fBlvmcache(7)\fP. Sets
the cache tunable settings. In most use-cases, default values should be adequate.
Special string value \fIdefault\fP switches setting back to its default kernel value
Special string value \fBdefault\fP switches setting back to its default kernel value
and removes it from the list of settings stored in lvm2 metadata.
.TP
.BR \-c ", " \-\-chunksize " " \fIChunkSize [ \fIbBsSkKmMgG ]
.
.HP
.BR \-c | \-\-chunksize
.SIZE_G \%ChunkSize
.br
Gives the size of chunk for snapshot, cache pool and thin pool logical volumes.
Default unit is in kilobytes.
.br
For \fIsnapshots\fP the value must be power of 2 between 4KiB and 512KiB
For snapshots the value must be power of 2 between 4KiB and 512KiB
and the default value is 4KiB.
.br
For \fIcache pools\fP the value must a multiple of 32KiB
For cache pools the value must a multiple of 32KiB
between 32KiB and 1GiB. The default is 64KiB.
.br
For \fIthin pools\fP the value must be a multiple of 64KiB
For thin pools the value must be a multiple of 64KiB
between 64KiB and 1GiB.
Default value starts with 64KiB and grows up to
fit the pool metadata size within 128MiB,
if the pool metadata size is not specified.
See
.BR lvm.conf (5)
setting
.IR allocation / thin_pool_chunk_size_policy
setting \fBallocation/thin_pool_chunk_size_policy\fP
to select different calculation policy.
Thin pool target version <1.4 requires this value to be a power of 2.
For target version <1.5 discard is not supported for non power of 2 values.
.TP
.BR \-C ", " \-\-contiguous " {" \fIy | \fIn }
.
.HP
.BR \-C | \-\-contiguous
.RB { y | n }
.br
Sets or resets the contiguous allocation policy for
logical volumes. Default is no contiguous allocation based
on a next free principle.
.TP
.
.HP
.BR \-\-corelog
This is shortcut for option \fB\-\-mirrorlog\fP \fIcore\fP.
.TP
.BR \-\-discards " {" \fIignore | \fInopassdown | \fIpassdown }
.br
This is shortcut for option \fB\-\-mirrorlog core\fP.
.
.HP
.BR \-\-discards
.RB { ignore | nopassdown | passdown }
.br
Sets discards behavior for thin pool.
Default is \fIpassdown\fP.
.TP
.BR \-\-errorwhenfull " {" \fIy |\fIn }
Default is \fBpassdown\fP.
.
.HP
.BR \-\-errorwhenfull
.RB { y | n }
.br
Configures thin pool behaviour when data space is exhausted.
Default is \fIn\fPo.
Default is \fBn\fPo.
Device will queue I/O operations until target timeout
(see dm-thin-pool kernel module option \fIno_space_timeout\fP)
(see dm-thin-pool kernel module option \fPno_space_timeout\fP)
expires. Thus configured system has a time to i.e. extend
the size of thin pool data device.
When set to \fIy\fPes, the I/O operation is immeditelly errored.
.TP
.BR \-K ", " \-\-ignoreactivationskip
When set to \fBy\fPes, the I/O operation is immeditelly errored.
.
.HP
.BR \-K | \-\-ignoreactivationskip
.br
Ignore the flag to skip Logical Volumes during activation.
Use \fB\-\-setactivationskip\fP option to set or reset
activation skipping flag persistently for logical volume.
.TP
.B \-\-ignoremonitoring
.
.HP
.BR \-\-ignoremonitoring
.br
Make no attempt to interact with dmeventd unless \fB\-\-monitor\fP
is specified.
.TP
.IR \fB\-l ", " \fB\-\-extents " " LogicalExtentsNumber [ % { VG | PVS | FREE | ORIGIN }]
.
.HP
.BR -l | \-\-extents
.IR LogicalExtentsNumber \c
.RB [ % { VG | PVS | FREE | ORIGIN }]
.br
Gives the number of logical extents to allocate for the new
logical volume. The total number of physical extents allocated will be
greater than this, for example, if the volume is mirrored.
The number can also be expressed as a percentage of the total space
in the Volume Group with the suffix \fI%VG\fR, as a percentage of the
remaining free space in the Volume Group with the suffix \fI%FREE\fR, as a
in the Volume Group with the suffix \fB%VG\fP, as a percentage of the
remaining free space in the Volume Group with the suffix \fB%FREE\fP, as a
percentage of the remaining free space for the specified
PhysicalVolume(s) with the suffix \fI%PVS\fR, or (for a snapshot) as a
PhysicalVolume(s) with the suffix \fB%PVS\fP, or (for a snapshot) as a
percentage of the total space in the Origin Logical Volume with the
suffix \fI%ORIGIN\fR (i.e. \fI100%ORIGIN\fR provides space for the whole origin).
suffix \fB%ORIGIN\fP (i.e. \fB100%ORIGIN\fP provides space for the whole origin).
When expressed as a percentage, the number is treated
as an approximate upper limit for the total number of physical extents
as an approximate upper limit for the number of physical extents
to be allocated (including extents used by any mirrors, for example).
.TP
.BR \-j ", " \-\-major " " \fImajor
.
.HP
.BR \-j | \-\-major
.IR major
.br
Sets the major number.
Major numbers are not supported with pool volumes.
This option is supported only on older systems
(kernel version 2.4) and is ignored on modern Linux systems where major
numbers are dynamically assigned.
.TP
.BR \-\-metadataprofile " " \fIProfileName
Uses and attaches the ProfileName configuration profile to the logical
.
.HP
.BR \-\-metadataprofile
.IR ProfileName
.br
Uses and attaches the \fIProfileName\fP configuration profile to the logical
volume metadata. Whenever the logical volume is processed next time,
the profile is automatically applied. If the volume group has another
profile attached, the logical volume profile is preferred.
See \fBlvm.conf\fP(5) for more information about \fBmetadata profiles\fP.
.TP
.B \-\-minor \fIminor
.
.HP
.BR \-\-minor
.IR minor
.br
Sets the minor number.
Minor numbers are not supported with pool volumes.
.TP
.BR \-m ", " \-\-mirrors " " \fIMirrors
Creates a mirrored logical volume with \fIMirrors\fP copies.
For example, specifying
.BI \-m\ 1
.
.HP
.BR \-m | \-\-mirrors
.IR mirrors
.br
Creates a mirrored logical volume with \fImirrors\fP copies.
For example, specifying \fB\-m 1\fP
would result in a mirror with two-sides; that is,
a linear volume plus one copy.
@@ -318,135 +382,178 @@ The default is "\fIraid1\fP". See the
\fB\-\-type\fP option for more information if you would like to use the
legacy "\fImirror\fP" segment type. See
.BR lvm.conf (5)
settings
.IR global / mirror_segtype_default
and
.IR global / raid10_segtype_default
settings \fB global/mirror_segtype_default\fP
and \fBglobal/raid10_segtype_default\fP
to configure default mirror segment type.
The options
\fB\-\-mirrorlog\fP and \fB\-\-corelog\fP apply
to the legacy "\fImirror\fP" segment type only.
.TP
.BR \-\-mirrorlog " {" \fIdisk | \fIcore | \fImirrored }
.
.HP
.BR \-\-mirrorlog
.RB { disk | core | mirrored }
.br
Specifies the type of log to be used for logical volumes utilizing
the legacy "\fImirror\fP" segment type.
.br
The default is \fIdisk\fP, which is persistent and requires
The default is \fBdisk\fP, which is persistent and requires
a small amount of storage space, usually on a separate device from the
data being mirrored.
.br
Using \fIcore\fP means the mirror is regenerated by copying the data
Using \fBcore\fP means the mirror is regenerated by copying the data
from the first device each time the logical volume is activated,
like after every reboot.
.br
Using \fImirrored\fP will create a persistent log that is itself mirrored.
.TP
.BR \-\-monitor " {" \fIy | \fIn }
Using \fBmirrored\fP will create a persistent log that is itself mirrored.
.
.HP
.BR \-\-monitor
.RB { y | n }
.br
Starts or avoids monitoring a mirrored, snapshot or thin pool logical volume with
dmeventd, if it is installed.
If a device used by a monitored mirror reports an I/O error,
the failure is handled according to
.IR activation / mirror_image_fault_policy
and
.IR activation / mirror_log_fault_policy
\fBactivation/mirror_image_fault_policy\fP
and \fBactivation/mirror_log_fault_policy\fP
set in \fBlvm.conf\fP(5).
.TP
.IR \fB\-n ", " \fB\-\-name " " LogicalVolume { Name | Path }
.
.HP
.BR \-n | \-\-name
.IR LogicalVolume { Name | Path }
.br
Sets the name for the new logical volume.
.br
Without this option a default name of "lvol#" will be generated where
# is the LVM internal number of the logical volume.
.TP
.B \-\-nosync
.
.HP
.BR \-\-nosync
.br
Causes the creation of the mirror to skip the initial resynchronization.
.TP
.B \-\-noudevsync
.
.HP
.BR \-\-noudevsync
.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. You should only use this if udev is not running
or has rules that ignore the devices LVM2 creates.
.TP
.BR \-p ", " \-\-permission " {" \fIr | \fIrw }
Sets access permissions to read only (\fIr\fP) or read and write (\fIrw\fP).
.
.HP
.BR \-p | \-\-permission
.RB { r | rw }
.br
Sets access permissions to read only (\fBr\fP) or read and write (\fBrw\fP).
.br
Default is read and write.
.TP
.BR \-M ", " \-\-persistent " {" \fIy | \fIn }
Set to \fIy\fP to make the minor number specified persistent.
.
.HP
.BR \-M | \-\-persistent
.RB { y | n }
.br
Set to \fBy\fP to make the minor number specified persistent.
Pool volumes cannot have persistent major and minor numbers.
Defaults to \fIy\fPes only when major or minor number is specified.
Otherwise it is \fIn\fPo.
.TP
Defaults to \fBy\fPes only when major or minor number is specified.
Otherwise it is \fBn\fPo.
.\" .HP
.\" .IR \fB\-\-pooldatasize " " PoolDataVolumeSize [ bBsSkKmMgGtTpPeE ]
.\" Sets the size of pool's data logical volume.
.\" For thin pools you may also specify the size
.\" with the option \fB\-\-size\fP.
.\" .TP
.IR \fB\-\-poolmetadatasize " " MetadataVolumeSize [ bBsSkKmMgG ]
.\"
.
.HP
.BR \-\-poolmetadatasize
.SIZE_G \%MetadataVolumeSize
.br
Sets the size of pool's metadata logical volume.
Supported values are in range between 2MiB and 16GiB for thin pool,
and upto 16GiB for cache pool. The minimum value is computed from pool's
data size.
Default value for thin pool is (Pool_LV_size / Pool_LV_chunk_size * 64b).
Default unit is megabytes.
.TP
.IR \fB\-\-poolmetadataspare " {" y | n }
.
.HP
.BR \-\-poolmetadataspare
.RB { y | n }
.br
Controls creation and maintanence of pool metadata spare logical volume
that will be used for automated pool recovery.
Only one such volume is maintained within a volume group
with the size of the biggest pool metadata volume.
Default is \fIy\fPes.
.TP
.BR \-\- [ raid ] maxrecoveryrate " " \fIRate [ \fIbBsSkKmMgG ]
Default is \fBy\fPes.
.
.HP
.BR \-\- [ raid ] maxrecoveryrate
.SIZE_G \%Rate
.br
Sets the maximum recovery rate for a RAID logical volume. \fIRate\fP
is specified as an amount per second for each device in the array.
If no suffix is given, then KiB/sec/device is assumed. Setting the
recovery rate to 0 means it will be unbounded.
.TP
.BR \-\- [ raid ] minrecoveryrate " " \fIRate [ \fIbBsSkKmMgG ]
.
.HP
.BR \-\- [ raid ] minrecoveryrate
.SIZE_G \%Rate
.br
Sets the minimum recovery rate for a RAID logical volume. \fIRate\fP
is specified as an amount per second for each device in the array.
If no suffix is given, then KiB/sec/device is assumed. Setting the
recovery rate to 0 means it will be unbounded.
.TP
.IR \fB\-r ", " \fB\-\-readahead " {" ReadAheadSectors | auto | none }
.
.HP
.BR \-r | \-\-readahead
.RB { \fIReadAheadSectors | auto | none }
.br
Sets read ahead sector count of this logical volume.
For volume groups with metadata in lvm1 format, this must
be a value between 2 and 120.
The default value is \fIauto\fP which allows the kernel to choose
The default value is \fBauto\fP which allows the kernel to choose
a suitable value automatically.
\fINone\fP is equivalent to specifying zero.
.TP
.BR \-R ", " \-\-regionsize " " \fIMirrorLogRegionSize [ \fIbBsSkKmMgG ]
\fBnone\fP is equivalent to specifying zero.
.
.HP
.BR \-R | \-\-regionsize
.SIZE_G \%MirrorLogRegionSize
.br
A mirror is divided into regions of this size (in MiB), and the mirror log
uses this granularity to track which regions are in sync.
.TP
.IR \fB\-k ", " \fB\-\-setactivationskip " {" y | n }
.
.HP
.BR \-k | \-\-setactivationskip
.RB { y | n }
.br
Controls whether Logical Volumes are persistently flagged to be skipped during
activation. By default, thin snapshot volumes are flagged for activation skip.
See
.BR lvm.conf (5)
.IR activation / auto_set_activation_skip
\fBactivation/auto_set_activation_skip\fP
how to change its default behaviour.
To activate such volumes, an extra
.BR \-K | \-\-ignoreactivationskip
To activate such volumes, an extra \fB\-\-ignoreactivationskip\fP
option must be used. The flag is not applied during deactivation. Use
.B lvchange \-\-setactivationskip {y|n}
\fBlvchange \-\-setactivationskip\fP
command to change the skip flag for existing volumes.
To see whether the flag is attached, use \fBlvs\fP command
where the state of the flag is reported within \fBlv_attr\fP bits.
.TP
.IR \fB\-L ", " \fB\-\-size " " LogicalVolumeSize [ bBsSkKmMgGtTpPeE ]
.
.HP
.BR \-L | \-\-size
.SIZE_E \%LogicalVolumeSize
.br
Gives the size to allocate for the new logical volume.
A size suffix of \fIB\fR for bytes, \fIS\fR for sectors as 512 bytes,
\fIK\fR for kilobytes, \fIM\fR for megabytes,
\fIG\fR for gigabytes, \fIT\fR for terabytes, \fIP\fR for petabytes
or \fIE\fR for exabytes is optional.
A size suffix of \fBB\fP for bytes, \fBS\fP for sectors as 512 bytes,
\fBK\fP for kilobytes, \fBM\fP for megabytes,
\fBG\fP for gigabytes, \fBT\fP for terabytes, \fBP\fP for petabytes
or \fBE\fP for exabytes is optional.
.br
Default unit is megabytes.
.TP
.IR \fB\-s ", " \fB\-\-snapshot " " OriginalLogicalVolume { Name | Path }
.
.HP
.BR \-s | \fB\-\-snapshot
.IR OriginalLogicalVolume { Name | Path }
.br
Creates a snapshot logical volume (or snapshot) for an existing, so called
original logical volume (or origin).
Snapshots provide a 'frozen image' of the contents of the origin
@@ -479,29 +586,35 @@ External origin volume can be used/shared for many thin volumes
even from different thin pools. See
.BR lvconvert (8)
for online conversion to thin volumes with external origin.
.TP
.BR \-i ", " \-\-stripes " " \fIStripes
.
.HP
.BR \-i | \-\-stripes
.IR Stripes
.br
Gives the number of stripes.
This is equal to the number of physical volumes to scatter
the logical volume. When creating a RAID 4/5/6 logical volume,
the extra devices which are necessary for parity are
internally accounted for. Specifying
.BI \-i 3
internally accounted for. Specifying \fB\-i 3\fP
would use 3 devices for striped logical volumes,
4 devices for RAID 4/5, and 5 devices for RAID 6. Alternatively,
RAID 4/5/6 will stripe across all PVs in the volume group or
all of the PVs specified if the
.B \-i
all of the PVs specified if the \fB\-i\fP
argument is omitted.
.TP
.BR \-I ", " \-\-stripesize " " \fIStripeSize
.
.HP
.BR \-I | \-\-stripesize
.IR StripeSize
.br
Gives the number of kilobytes for the granularity of the stripes.
.br
StripeSize must be 2^n (n = 2 to 9) for metadata in LVM1 format.
For metadata in LVM2 format, the stripe size may be a larger
power of 2 but must not exceed the physical extent size.
.TP
.IR \fB\-T ", " \fB\-\-thin
.
.HP
.BR \-T | \-\-thin
.br
Creates thin pool or thin logical volume or both.
Specifying the optional argument \fB\-\-size\fP or \fB\-\-extents\fP
will cause the creation of the thin pool logical volume.
@@ -512,99 +625,115 @@ thin pool and thin volume using this pool.
See \fBlvmthin\fP(7) for more info about thin provisioning support.
Thin provisioning requires device mapper kernel driver
from kernel 3.2 or greater.
.TP
.IR \fB\-\-thinpool " " ThinPoolLogicalVolume { Name | Path }
.
.HP
.BR \-\-thinpool
.IR ThinPoolLogicalVolume { Name | Path }
.br
Specifies the name of thin pool volume name. The other way to specify pool name
is to append name to Volume group name argument.
.TP
.B \-\-type \fISegmentType
.
.HP
.BR \-\-type
.IR SegmentType
.br
Creates a logical volume with the specified segment type.
Supported types are:
.IR cache ,
.IR cache-pool ,
.IR error ,
.IR linear ,
.IR mirror,
.IR raid1 ,
.IR raid4 ,
.IR raid5_la ,
.IR raid5_ls " (= " raid5 ),
.IR raid5_ra ,
.IR raid5_rs ,
.IR raid6_nc ,
.IR raid6_nr ,
.IR raid6_zr " (= " raid6 ) ,
.IR raid10 ,
.IR snapshot ,
.IR striped,
.IR thin ,
.IR thin-pool
.BR cache ,
.BR cache-pool ,
.BR error ,
.BR linear ,
.BR mirror,
.BR raid1 ,
.BR raid4 ,
.BR raid5_la ,
.BR raid5_ls
.RB (=
.BR raid5 ),
.BR raid5_ra ,
.BR raid5_rs ,
.BR raid6_nc ,
.BR raid6_nr ,
.BR raid6_zr
.RB (=
.BR raid6 ),
.BR raid10 ,
.BR snapshot ,
.BR striped,
.BR thin ,
.BR thin-pool
or
.IR zero .
.BR zero .
Segment type may have a commandline switch alias that will
enable its use.
When the type is not explicitly specified an implicit type
is selected from combination of options:
.BR \-H | \-\-cache | \-\-cachepool " (" \fIcache
or
.IR cachepool ),
.BR \-T | \-\-thin | \-\-thinpool " (" \fIthin
or
.IR thinpool ),
.BR \-m | \-\-mirrors " (" \fIraid1
or
.IR mirror ),
.BR \-s | \-\-snapshot | \-V | \-\-virtualsize " (" \fIsnapshot
or
.IR thin ),
.BR \-i | \-\-stripes " (" \fIstriped ).
Default type is \fIlinear\fP.
.TP
.BR \-V ", " \-\-virtualsize " " \fIVirtualSize [ \fIbBsSkKmMgGtTpPeE ]
.BR \-H | \-\-cache | \-\-cachepool
(cache or cachepool),
.BR \-T | \-\-thin | \-\-thinpool
(thin or thinpool),
.BR \-m | \-\-mirrors
(raid1 or mirror),
.BR \-s | \-\-snapshot | \-V | \-\-virtualsize
(snapshot or thin),
.BR \-i | \-\-stripes
(striped).
Default segment type is \fBlinear\fP.
.
.HP
.BR \-V | \-\-virtualsize
.SIZE_E \%VirtualSize
.br
Creates a thinly provisioned device or a sparse device of the given size (in MiB by default).
See
.BR lvm.conf (5)
settings
.IR global / sparse_segtype_default
settings \fBglobal/sparse_segtype_default\fP
to configure default sparse segment type.
See \fBlvmthin\fP(7) for more info about thin provisioning support.
Anything written to a sparse snapshot will be returned when reading from it.
Reading from other areas of the device will return blocks of zeros.
Virtual snapshot is implemented by creating a hidden virtual device of the
requested size using the zero target. A suffix of _vorigin is used for
this device. Note: using sparse snapshots is not efficient for larger
Virtual snapshot (sparse snapshot) is implemented by creating
a hidden virtual device of the requested size using the zero target.
A suffix of _vorigin is used for this device.
Note: using sparse snapshots is not efficient for larger
device sizes (GiB), thin provisioning should be used for this case.
.TP
.BR \-W ", " \-\-wipesignatures " {" \fIy | \fIn }
.
.HP
.BR \-W | \-\-wipesignatures
.RB { y | n }
.br
Controls wiping of detected signatures on newly created Logical Volume.
If this option is not specified, then by default signature wiping is done
each time the zeroing (\fB\-Z\fP/\fB\-\-zero\fP) is done. This default behaviour
can be controlled by
.IR allocation / wipe_signatures_when_zeroing_new_lvs
each time the zeroing (
.BR \-Z | \-\-zero
) is done. This default behaviour
can be controlled by \fB\%allocation/wipe_signatures_when_zeroing_new_lvs\fP
setting found in
.BR lvm.conf (5).
.br
If blkid wiping is used
.IR allocation / use_blkid_wiping
setting in
If blkid wiping is used \fBallocation/use_blkid_wiping\fP setting in
.BR lvm.conf (5))
and LVM2 is compiled with blkid wiping support, then \fBblkid\fP(8) library is used
to detect the signatures (use \fBblkid -k\fP command to list the signatures that are recognized).
to detect the signatures (use \fBblkid \-k\fP command to list the signatures that are recognized).
Otherwise, native LVM2 code is used to detect signatures (MD RAID, swap and LUKS
signatures are detected only in this case).
.br
Logical volume is not wiped if the read only flag is set.
.TP
.BR \-Z ", " \-\-zero " {" \fIy | \fIn }
.
.HP
.BR \-Z | \-\-zero
.RB { y | n }
.br
Controls zeroing of the first 4KiB of data in the new logical volume.
Default is \fIy\fPes.
Default is \fBy\fPes.
Snapshot COW volumes are always zeroed.
Logical volume is not zeroed if the read only flag is set.
.br
Warning: trying to mount an unzeroed logical volume can cause the system to
hang.
.
.SH Examples
.
Creates a striped logical volume with 3 stripes, a stripe size of 8KiB
and a size of 100MiB in the volume group named vg00.
The logical volume name will be chosen by lvcreate:
@@ -613,8 +742,8 @@ The logical volume name will be chosen by lvcreate:
Creates a mirror logical volume with 2 sides with a useable size of 500 MiB.
This operation would require 3 devices (or option
.BI \-\-alloc \ anywhere
) - two for the mirror devices and one for the disk log:
\fB\-\-alloc \%anywhere\fP) - two for the mirror
devices and one for the disk log:
.sp
.B lvcreate \-m1 \-L 500M vg00
@@ -705,9 +834,11 @@ volume (i.e. the origin LV), creating a cache LV.
.\" Create a 1G cached LV "lvol1" with 10M cache pool "vg00/pool".
.\" .sp
.\" .B lvcreate \-\-cache \-L 1G \-n lv --pooldatasize 10M vg00/pool
.\" .B lvcreate \-\-cache \-L 1G \-n lv \-\-pooldatasize 10M vg00/pool
.
.SH SEE ALSO
.
.nh
.BR lvm (8),
.BR lvm.conf (5),
.BR lvmcache (7),

View File

@@ -37,7 +37,7 @@ lvdisplay \(em display attributes of a logical volume
.RB [ \-\-noheadings ]
.RB [ \-\-nosuffix ]
.RB [ \-o | \-\-options
.RI [ + ] Field [ ,Field ...]]
.RI [ + | \- | # ] Field [ ,Field ...]]
.RB [ \-O | \-\-sort
.RI [ + | \- ] Key1 [ , [ + | \- ] Key2 ...]]
.RB [ \-P | \-\-partial ]

View File

@@ -1,29 +1,35 @@
.TH LVM 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
.
.SH NAME
.
lvm \(em LVM2 tools
.
.SH SYNOPSIS
.
.B lvm
[command | file]
.RI [ command | file ]
.
.SH DESCRIPTION
.
lvm provides the command-line tools for LVM2. A separate
manual page describes each command in detail.
.LP
.P
If \fBlvm\fP is invoked with no arguments it presents a readline prompt
(assuming it was compiled with readline support).
LVM commands may be entered interactively at this prompt with
readline facilities including history and command name and option
completion. Refer to \fBreadline\fP(3) for details.
.LP
.P
If \fBlvm\fP is invoked with argv[0] set to the name of a specific
LVM command (for example by using a hard or soft link) it acts as
that command.
.LP
.P
On invocation, \fBlvm\fP requires that only the standard file descriptors
stdin, stdout and stderr are available. If others are found, they
get closed and messages are issued warning about the leak.
This warning can be suppressed by setting the environment variable
.B LVM_SUPPRESS_FD_WARNINGS\fP.
.LP
.P
Where commands take VG or LV names as arguments, the full path name is
optional. An LV called "lvol0" in a VG called "vg0" can be specified
as "vg0/lvol0". Where a list of VGs is required but is left empty,
@@ -31,223 +37,319 @@ a list of all VGs will be substituted. Where a list of LVs is required
but a VG is given, a list of all the LVs in that VG will be substituted.
So \fBlvdisplay vg0\fP will display all the LVs in "vg0".
Tags can also be used - see \fB\-\-addtag\fP below.
.LP
.P
One advantage of using the built-in shell is that configuration
information gets cached internally between commands.
.LP
.P
A file containing a simple script with one command per line
can also be given on the command line. The script can also be
executed directly if the first line is #! followed by the absolute
path of \fBlvm\fP.
.
.SH BUILT-IN COMMANDS
The following commands are built into lvm without links normally
being created in the filesystem for them.
.
The following commands are built into lvm without links
normally being created in the filesystem for them.
.sp
.PD 0
.HP
\fBconfig\fP \(em The same as \fBlvmconfig\fP(8) below.
.HP
\fBdevtypes\fP \(em Display the recognised built-in block device types.
.HP
\fBdumpconfig\fP \(em The same as \fBlvmconfig\fP(8) below.
.HP
\fBformats\fP \(em Display recognised metadata formats.
.HP
\fBhelp\fP \(em Display the help text.
.HP
\fBlvpoll\fP \(em Internal command used by lvmpolld to complete some Logical Volume operations.
.HP
\fBpvdata\fP \(em Not implemented in LVM2.
.HP
\fBsegtypes\fP \(em Display recognised Logical Volume segment types.
.HP
\fBsystemid\fP \(em Display the system ID, if any, currently set on this host.
.HP
\fBtags\fP \(em Display any tags defined on this host.
.HP
\fBversion\fP \(em Display version information.
.TP 14
.B config
The same as \fBlvmconfig\fP(8) below.
.TP
.B devtypes
Display the recognised built-in block device types.
.TP
.B dumpconfig
The same as \fBlvmconfig\fP(8) below.
.TP
.B formats
Display recognised metadata formats.
.TP
.B help
Display the help text.
.TP
.B lvpoll
Complete lvmpolld operations (Internal command).
.TP
.B pvdata
Not implemented in LVM2.
.TP
.B segtypes
Display recognised Logical Volume segment types.
.TP
.B systemid
Display any system ID currently set on this host.
.TP
.B tags
Display any tags defined on this host.
.TP
.B version
Display version information.
.PD
.
.SH COMMANDS
.
The following commands implement the core LVM functionality.
.sp
.PD 0
.HP
\fBpvchange\fP \(em Change attributes of a Physical Volume.
.HP
\fBpvck\fP \(em Check Physical Volume metadata.
.HP
\fBpvcreate\fP \(em Initialize a disk or partition for use by LVM.
.HP
\fBpvdisplay\fP \(em Display attributes of a Physical Volume.
.HP
\fBpvmove\fP \(em Move Physical Extents.
.HP
\fBpvremove\fP \(em Remove a Physical Volume.
.HP
\fBpvresize\fP \(em Resize a disk or partition in use by LVM2.
.HP
\fBpvs\fP \(em Report information about Physical Volumes.
.HP
\fBpvscan\fP \(em Scan all disks for Physical Volumes.
.HP
\fBvgcfgbackup\fP \(em Backup Volume Group descriptor area.
.HP
\fBvgcfgrestore\fP \(em Restore Volume Group descriptor area.
.HP
\fBvgchange\fP \(em Change attributes of a Volume Group.
.HP
\fBvgck\fP \(em Check Volume Group metadata.
.HP
\fBvgconvert\fP \(em Convert Volume Group metadata format.
.HP
\fBvgcreate\fP \(em Create a Volume Group.
.HP
\fBvgdisplay\fP \(em Display attributes of Volume Groups.
.HP
\fBvgexport\fP \(em Make volume Groups unknown to the system.
.HP
\fBvgextend\fP \(em Add Physical Volumes to a Volume Group.
.HP
\fBvgimport\fP \(em Make exported Volume Groups known to the system.
.HP
\fBvgimportclone\fP \(em Import and rename duplicated Volume Group (e.g. a hardware snapshot).
.HP
\fBvgmerge\fP \(em Merge two Volume Groups.
.HP
\fBvgmknodes\fP \(em Recreate Volume Group directory and Logical Volume special files
.HP
\fBvgreduce\fP \(em Reduce a Volume Group by removing one or more
Physical Volumes.
.HP
\fBvgremove\fP \(em Remove a Volume Group.
.HP
\fBvgrename\fP \(em Rename a Volume Group.
.HP
\fBvgs\fP \(em Report information about Volume Groups.
.HP
\fBvgscan\fP \(em Scan all disks for Volume Groups and rebuild caches.
.HP
\fBvgsplit\fP \(em Split a Volume Group into two, moving any logical
.TP 14
.B pvchange
Change attributes of a Physical Volume.
.TP
.B pvck
Check Physical Volume metadata.
.TP
.B pvcreate
Initialize a disk or partition for use by LVM.
.TP
.B pvdisplay
Display attributes of a Physical Volume.
.TP
.B pvmove
Move Physical Extents.
.TP
.B pvremove
Remove a Physical Volume.
.TP
.B pvresize
Resize a disk or partition in use by LVM2.
.TP
.B pvs
Report information about Physical Volumes.
.TP
.B pvscan
Scan all disks for Physical Volumes.
.TP
.B vgcfgbackup
Backup Volume Group descriptor area.
.TP
.B vgcfgrestore
Restore Volume Group descriptor area.
.TP
.B vgchange
Change attributes of a Volume Group.
.TP
.B vgck
Check Volume Group metadata.
.TP
.B vgconvert
Convert Volume Group metadata format.
.TP
.B vgcreate
Create a Volume Group.
.TP
.B vgdisplay
Display attributes of Volume Groups.
.TP
.B vgexport
Make volume Groups unknown to the system.
.TP
.B vgextend
Add Physical Volumes to a Volume Group.
.TP
.B vgimport
Make exported Volume Groups known to the system.
.TP
.B vgimportclone
Import and rename duplicated Volume Group (e.g. a hardware snapshot).
.TP
.B vgmerge
Merge two Volume Groups.
.TP
.B vgmknodes
Recreate Volume Group directory and Logical Volume special files
.TP
.B vgreduce
Reduce a Volume Group by removing one or more Physical Volumes.
.TP
.B vgremove
Remove a Volume Group.
.TP
.B vgrename
Rename a Volume Group.
.TP
.B vgs
Report information about Volume Groups.
.TP
.B vgscan
Scan all disks for Volume Groups and rebuild caches.
.TP
.B vgsplit
Split a Volume Group into two, moving any logical
volumes from one Volume Group to another by moving entire Physical
Volumes.
.HP
\fBlvchange\fP \(em Change attributes of a Logical Volume.
.HP
\fBlvconvert\fP \(em Convert a Logical Volume from linear to mirror or snapshot.
.HP
\fBlvcreate\fP \(em Create a Logical Volume in an existing Volume Group.
.HP
\fBlvdisplay\fP \(em Display attributes of a Logical Volume.
.HP
\fBlvextend\fP \(em Extend the size of a Logical Volume.
.HP
\fBlvmchange\fP \(em Change attributes of the Logical Volume Manager.
.HP
\fBlvmconfig\fP \(em Display the configuration information after
.TP
.B lvchange
Change attributes of a Logical Volume.
.TP
.B lvconvert
Convert a Logical Volume from linear to mirror or snapshot.
.TP
.B lvcreate
Create a Logical Volume in an existing Volume Group.
.TP
.B lvdisplay
Display attributes of a Logical Volume.
.TP
.B lvextend
Extend the size of a Logical Volume.
.TP
.B lvmchange
Change attributes of the Logical Volume Manager.
.TP
.B lvmconfig
Display the configuration information after
loading \fBlvm.conf\fP(5) and any other configuration files.
.HP
\fBlvmdiskscan\fP \(em Scan for all devices visible to LVM2.
.HP
\fBlvmdump\fP \(em Create lvm2 information dumps for diagnostic purposes.
.HP
\fBlvreduce\fP \(em Reduce the size of a Logical Volume.
.HP
\fBlvremove\fP \(em Remove a Logical Volume.
.HP
\fBlvrename\fP \(em Rename a Logical Volume.
.HP
\fBlvresize\fP \(em Resize a Logical Volume.
.HP
\fBlvs\fP \(em Report information about Logical Volumes.
.HP
\fBlvscan\fP \(em Scan (all disks) for Logical Volumes.
.TP
.B lvmdiskscan
Scan for all devices visible to LVM2.
.TP
.B lvmdump
Create lvm2 information dumps for diagnostic purposes.
.TP
.B lvreduce
Reduce the size of a Logical Volume.
.TP
.B lvremove
Remove a Logical Volume.
.TP
.B lvrename
Rename a Logical Volume.
.TP
.B lvresize
Resize a Logical Volume.
.TP
.B lvs
Report information about Logical Volumes.
.TP
.B lvscan
Scan (all disks) for Logical Volumes.
.PD
.HP
The following commands are not implemented in LVM2 but might be in the future: lvmsadc, lvmsar, pvdata.
.P
The following commands are not implemented in LVM2 but might be
in the future:
.BR lvmsadc ", " lvmsar ", " pvdata .
.
.SH OPTIONS
.
The following options are available for many of the commands.
They are implemented generically and documented here rather
than repeated on individual manual pages.
.P
Additional hyphens within option names are ignored. For example,
\-\-readonly and \-\-read\-only are both accepted.
.TP
.BR \-h ", " \-? ", " \-\-help
\fB\-\-readonly\fP and \fB\-\-read\-only\fP are both accepted.
.
.HP
.BR \-h | \-? | \-\-help
.br
Display the help text.
.TP
.B \-\-version
.
.HP
.BR \-\-version
.br
Display version information.
.TP
.BR \-v ", " \-\-verbose
.
.HP
.BR \-v | \-\-verbose
.br
Set verbose level. Repeat from 1 to 3 times to increase the detail
of messages sent to stdout and stderr. Overrides config file setting.
.TP
.BR \-d ", " \-\-debug
.
.HP
.BR \-d | \-\-debug
.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).
Overrides config file setting.
.TP
.BR \-q ", " \-\-quiet
.
.HP
.BR \-q | \-\-quiet
.br
Suppress output and log messages.
Overrides \fB\-d\fP and \fB\-v\fP.
Repeat once to also suppress any prompts with answer 'no'.
.TP
.
.HP
.BR \-\-yes
.br
Don't prompt for confirmation interactively but instead always assume the
answer is 'yes'. Take great care if you use this!
.TP
.BR \-t ", " \-\-test
.
.HP
.BR \-t | \-\-test
.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.
.TP
.BR \-\-driverloaded " {" \fIy | \fIn }
.
.HP
.BR \-\-driverloaded
.RB { y | n }
.br
Whether or not the device-mapper kernel driver is loaded.
If you set this to \fIn\fP, no attempt will be made to contact the driver.
.TP
.BR \-A ", " \-\-autobackup " {" \fIy | \fIn }
If you set this to \fBn\fP, no attempt will be made to contact the driver.
.
.HP
.BR \-A | \-\-autobackup
.RB { y | n }
.br
Whether or not to metadata should be backed up automatically after a change.
You are strongly advised not to disable this!
See \fBvgcfgbackup\fP(8).
.TP
.BR \-P ", " \-\-partial
.
.HP
.BR \-P | \-\-partial
.br
When set, the tools will do their best to provide access to Volume Groups
that are only partially available (one or more Physical Volumes belonging
to the Volume Group are missing from the system). Where part of a logical
volume is missing, \fB/dev/ioerror\fP will be substituted, and you could use
volume is missing, \fI\%/dev/ioerror\fP will be substituted, and you could use
\fBdmsetup\fP(8) to set this up to return I/O errors when accessed,
or create it as a large block device of nulls. Metadata may not be
changed with this option. To insert a replacement Physical Volume
of the same or large size use \fBpvcreate \-u\fP to set the uuid to
match the original followed by \fBvgcfgrestore\fP(8).
.TP
.BR \-S ", " \-\-select " " \fISelection
For reporting commands, display only rows that match selection criteria.
.
.HP
.BR \-S | \-\-select
.IR Selection
.br
For reporting commands, display only rows that match \fISelection\fP criteria.
All rows are displayed with the additional "selected" column (\fB-o selected\fP)
showing 1 if the row matches the Selection and 0 otherwise. For non-reporting
showing 1 if the row matches the \fISelection\fP and 0 otherwise. For non-reporting
commands which process LVM entities, the selection can be used to match items
to process. See \fBSELECTION CRITERIA\fP section of this man page for more
information about the way the selection criteria are constructed.
.TP
.BR \-M ", " \-\-metadatatype " " \fIType
Specifies which type of on-disk metadata to use, such as \fIlvm1\fP
or \fIlvm2\fP, which can be abbreviated to \fI1\fP or \fI2\fP respectively.
The default (\fIlvm2\fP) can be changed by setting \fBformat\fP
in the \fBglobal\fP section of the config file.
.TP
.B \-\-ignorelockingfailure
.
.HP
.BR \-M | \-\-metadatatype
.IR Type
.br
Specifies which \fItype\fP of on-disk metadata to use, such as \fBlvm1\fP
or \fBlvm2\fP, which can be abbreviated to \fB1\fP or \fB2\fP respectively.
The default (\fBlvm2\fP) can be changed by setting \fBformat\fP
in the \fBglobal\fP section of the config file \fBlvm.conf\fP(5).
.
.HP
.BR \-\-ignorelockingfailure
.br
This lets you proceed with read-only metadata operations such as
\fBlvchange \-ay\fP and \fBvgchange \-ay\fP even if the locking module fails.
One use for this is in a system init script if the lock directory
is mounted read-only when the script runs.
.TP
.B \-\-ignoreskippedcluster
.
.HP
.BR \-\-ignoreskippedcluster
.br
Use to avoid exiting with an non-zero status code if the command is run
without clustered locking and some clustered Volume Groups have to be
skipped over.
.TP
.B \-\-readonly
.
.HP
.BR \-\-readonly
.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
@@ -255,21 +357,28 @@ machine is running.
It can also be used to peek inside the metadata of clustered Volume
Groups 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 Logical Volumes are
this option is unable to report whether or not Logical Volumes are
actually in use.
.TP
.B \-\-foreign
.
.HP
.BR \-\-foreign
.br
Cause the command to access foreign VGs, that would otherwise be skipped.
It can be used to report or display a VG that is owned by another host.
This option can cause a command to perform poorly because lvmetad caching
is not used and metadata is read from disks.
.TP
.B \-\-shared
.
.HP
.BR \-\-shared
.br
Cause the command to access shared VGs, that would otherwise be skipped
when lvmlockd is not being used. It can be used to report or display a
lockd VG without locking.
.TP
.B \-\-addtag \fITag
.
.HP
.BR \-\-addtag
.IR Tag
.br
Add the tag \fITag\fP to a PV, VG or LV.
Supply this argument multiple times to add more than one tag at once.
A tag is a word that can be used to group LVM2 objects of the same type
@@ -288,79 +397,113 @@ Only the new LVM2 metadata format supports tagging: objects using the
LVM1 metadata format cannot be tagged because the on-disk format does not
support it.
Characters allowed in tags are:
.B A-Z a-z 0-9 _ + . -
.BR A - Z
.BR a - z
.BR 0 - 9
.BR "_ + . -"
and as of version 2.02.78 the following characters are also accepted:
.B / = ! : # &
.TP
.B \-\-deltag \fITag
.BR "/ = ! : # &"
..
.HP
.BR \-\-deltag
.IR Tag
.br
Delete the tag \fITag\fP from a PV, VG or LV, if it's present.
Supply this argument multiple times to remove more than one tag at once.
.TP
.IR \fB\-\-alloc \ { anywhere | contiguous | cling | inherit | normal }
.
.HP
.BR \-\-alloc
.RB { anywhere | contiguous | cling | inherit | normal }
.br
Selects the allocation policy when a command needs to allocate
Physical Extents from the Volume Group.
Each Volume Group and Logical Volume has an allocation policy defined.
The default for a Volume Group is \fInormal\fP which applies
The default for a Volume Group is \fBnormal\fP which applies
common-sense rules such as not placing parallel stripes on the same
Physical Volume. The default for a Logical Volume is \fIinherit\fP
Physical Volume. The default for a Logical Volume is \fBinherit\fP
which applies the same policy as for the Volume Group. These policies can
be changed using \fBlvchange\fP(8) and \fBvgchange\fP(8) or overridden
on the command line of any command that performs allocation.
The \fIcontiguous\fP policy requires that new Physical Extents be placed adjacent
The \fBcontiguous\fP policy requires that new Physical Extents be placed adjacent
to existing Physical Extents.
The \fIcling\fP policy places new Physical Extents on the same Physical
The \fBcling\fP policy places new Physical Extents on the same Physical
Volume as existing Physical Extents in the same stripe of the Logical Volume.
If there are sufficient free Physical Extents to satisfy
an allocation request but \fInormal\fP doesn't use them,
\fIanywhere\fP will - even if that reduces performance by
an allocation request but \fBnormal\fP doesn't use them,
\fBanywhere\fP will - even if that reduces performance by
placing two stripes on the same Physical Volume.
.TP
.IR \fB\-\-commandprofile " " \fIProfileName
.
.HP
.BR \-\-commandprofile
.IR ProfileName
.br
Selects the command configuration profile to use when processing an LVM command.
See also \fBlvm.conf\fP(5) for more information about \fBcommand profile config\fP and
the way it fits with other LVM configuration methods. Using \fB\-\-commandprofile\fP
option overrides any command profile specified via \fBLVM_COMMAND_PROFILE\fP
environment variable.
.TP
.IR \fB\-\-metadataprofile " " \fIProfileName
.
.HP
.BR \-\-metadataprofile
.IR ProfileName
.br
Selects the metadata configuration profile to use when processing an LVM command.
When using metadata profile during Volume Group or Logical Volume creation,
the metadata profile name is saved in metadata. When such Volume Group or Logical
Volume is processed next time, the metadata profile is automatically applied
and the use of \-\-metadataprofile option is not necessary. See also
and the use of \fB\-\-metadataprofile\fP option is not necessary. See also
\fBlvm.conf\fP(5) for more information about \fBmetadata profile config\fP and the
way it fits with other LVM configuration methods.
.TP
.IR \fB\-\-profile " " \fIProfileName
.
.HP
.BR \-\-profile
.IR ProfileName
.br
A short form of \fB\-\-metadataprofile\fP for \fBvgcreate\fP, \fBlvcreate\fP,
\fBvgchange\fP and \fBlvchange\fP command and a short form of \fB\-\-commandprofile\fP
for any other command (with the exception of \fBlvmconfig\fP command where the
\-\-profile has special meaning, see \fBlvmconfig\fP(8) for more information).
.TP
.IR \fB\-\-config " " \fIConfigurationString
\fB\-\-profile\fP has special meaning, see \fBlvmconfig\fP(8) for more information).
.
.HP
.BR \-\-config
.IR ConfigurationString
.br
Uses the ConfigurationString as direct string representation of the configuration
to override the existing configuration. The ConfigurationString is of exactly
the same format as used in any LVM configuration file. See \fBlvm.conf\fP(5)
for more information about \fBdirect config override on command line\fP and the
way it fits with other LVM configuration methods.
.
.SH VALID NAMES
.
The valid characters for VG and LV names are:
.B a-z A-Z 0-9 + _ . -
.LP
.BR a - z
.BR A - Z
.BR 0 - 9
.BR "+ _ . -"
.P
VG and LV names cannot begin with a hyphen.
There are also various reserved names that are used internally by lvm that can not be used as LV or VG names.
A VG cannot be called anything that exists in /dev/ at the time of creation, nor can it be called '.' or '..'.
An LV cannot be called '.', '..', 'snapshot' or 'pvmove'. The LV name may also not contain any of the following
strings: '_cdata', '_cmeta', '_corig', '_mlog', '_mimage', '_pmspare', '_rimage', '_rlog', '_tdata' or '_tmeta'.
A directory bearing the name of each Volume Group is created under /dev when any of its Logical Volumes are activated.
Each active Logical Volume is accessible from this directory as a symbolic link leading to a device node.
Links or nodes in /dev/mapper are intended only for internal use and the precise format and escaping might change between releases and distributions.
There are also various reserved names that are used internally by lvm that can
not be used as LV or VG names. A VG cannot be called anything that exists in
\fI/dev/\fP at the time of creation, nor can it be called '.' or '..'.
An LV cannot be called '.', '..', 'snapshot' or 'pvmove'.
The LV name may also not contain any of the following strings:
'_cdata', '_cmeta', '_corig', '_mlog', '_mimage', '_pmspare', '_rimage',
'_rlog', '_tdata' or '_tmeta'.
A directory bearing the name of each Volume Group is created under
\fI/dev\fP when any of its Logical Volumes are activated.
Each active Logical Volume is accessible from this directory as a symbolic
link leading to a device node.
Links or nodes in \fI/dev/mapper\fP are intended only for internal use and
the precise format and escaping might change between releases and distributions.
Other software and scripts should use the
/dev/VolumeGroupName/LogicalVolumeName format to reduce the chance of needing
\fI/dev/VolumeGroupName/LogicalVolumeName\fP format to reduce the chance of needing
amendment when the software is updated. Should you need to process the node
names in /dev/mapper, you may use \fBdmsetup splitname\fP to separate out the
original VG, LV and internal layer names.
.
.SH ALLOCATION
.
When an operation needs to allocate Physical Extents for one or more
Logical Volumes, the tools proceed as follows:
@@ -370,7 +513,7 @@ the end of the command line, only unallocated Physical Extents within
those ranges on the specified Physical Volumes are considered.
Then they try each allocation policy in turn, starting with the strictest
policy (\fIcontiguous\fP) and ending with the allocation policy specified
policy (\fBcontiguous\fP) and ending with the allocation policy specified
using \fB\-\-alloc\fP or set as the default for the particular Logical
Volume or Volume Group concerned. For each policy, working from the
lowest-numbered Logical Extent of the empty Logical Volume space that
@@ -380,15 +523,15 @@ they move on to the next policy.
The restrictions are as follows:
\fIContiguous\fP requires that the physical location of any Logical
\fBContiguous\fP requires that the physical location of any Logical
Extent that is not the first Logical Extent of a Logical Volume is
adjacent to the physical location of the Logical Extent immediately
preceding it.
\fICling\fP requires that the Physical Volume used for any Logical
\fBCling\fP requires that the Physical Volume used for any Logical
Extent to be added to an existing Logical Volume is already in use by at
least one Logical Extent earlier in that Logical Volume. If the
configuration parameter allocation/cling_tag_list is defined, then two
configuration parameter \fBallocation/cling_tag_list\fP is defined, then two
Physical Volumes are considered to match if any of the listed tags is
present on both Physical Volumes. This allows groups of Physical
Volumes with similar properties (such as their physical location) to be
@@ -398,25 +541,25 @@ When a Logical Volume is striped or mirrored, the above restrictions are
applied independently to each stripe or mirror image (leg) that needs
space.
\fINormal\fP will not choose a Physical Extent that shares the same Physical
\fBNormal\fP will not choose a Physical Extent that shares the same Physical
Volume as a Logical Extent already allocated to a parallel Logical
Volume (i.e. a different stripe or mirror image/leg) at the same offset
Volume (i.e. a different stripe or mirror image/leg) at the same offset
within that parallel Logical Volume.
When allocating a mirror log at the same time as Logical Volumes to hold
the mirror data, Normal will first try to select different Physical
Volumes for the log and the data. If that's not possible and the
allocation/mirror_logs_require_separate_pvs configuration parameter is
set to 0, it will then allow the log to share Physical Volume(s) with
part of the data.
.B allocation/mirror_logs_require_separate_pvs
configuration parameter is set to 0, it will then allow the log
to share Physical Volume(s) with part of the data.
When allocating thin pool metadata, similar considerations to those of a
mirror log in the last paragraph apply based on the value of the
allocation/thin_pool_metadata_require_separate_pvs configuration
parameter.
.B allocation/thin_pool_metadata_require_separate_pvs
configuration parameter.
If you rely upon any layout behaviour beyond that documented here, be
aware that it might change in future versions of the code.
aware that it might change in future versions of the code.
For example, if you supply on the command line two empty Physical
Volumes that have an identical number of free Physical Extents available for
@@ -431,87 +574,123 @@ discretion over the layout.
To view the way the allocation process currently works in any specific
case, read the debug logging output, for example by adding \fB\-vvvv\fP to
a command.
.
.SH LOGICAL VOLUME TYPES
.
Some logical volume types are simple to create and can be done with a
single \fBlvcreate\fP(8) command. The linear and striped logical
volume types are an example of this. Other logical volume types may
require more than one command to create. The cache (\fBlvmcache\fP(7))
and thin provisioning (\fBlvmthin\fP(7)) types are examples of this.
.
.SH SELECTION CRITERIA
.LP
.
The selection criteria are a set of \fBstatements\fP combined by \fBlogical
and grouping operators\fP. The \fBstatement\fP consists of \fBcolumn\fP
name for which a set of valid \fBvalues\fP is defined using
\fBcomparison operators\fP. For complete list of column names (fields)
that can be used in selection, see the output of \fB<lvm reporting command> -S help\fP.
.LP
\fBComparison operators\fP (cmp_op):
.IP
\fB=~\fP \(em Matching regular expression.
.IP
\fB!~\fP \(em Not matching regular expression.
.IP
\fB=\fP \(em Equal to.
.IP
\fB!=\fP \(em Not equal to.
.IP
\fB>=\fP \(em Greater than or equal to.
.IP
\fB>\fP \(em Greater than
.IP
\fB<=\fP \(em Less than or equal to.
.IP
\fB<\fP \(em Less than.
.LP
\fBBinary logical operators\fP (cmp_log):
.IP
\fB&&\fP \(em All fields must match
.IP
\fB,\fP \(em All fields must match
.IP
\fB||\fP \(em At least one field must match
.IP
\fB#\fP \(em At least one field must match
.LP
\fBUnary logical operators\fP:
.IP
\fB!\fP \(em Logical negation
.LP
\fBGrouping operators\fP:
.IP
\fB(\fP \(em Left parenthesis
.IP
\fB)\fP \(em Right parenthesis
.IP
\fB[\fP \(em List start
.IP
\fB]\fP \(em List end
.IP
\fB{\fP \(em List subset start
.IP
\fB}\fP \(em List subset end
.LP
\fBInformal grammar specification\fP:
.IP
.BR STATEMENT " = " column " cmp_op " VALUE " | " STATEMENT " log_op " STATEMENT " | " (STATEMENT) " | " !(STATEMENT)
.IP
.P
.SS Comparison operators \fR(cmp_op)
.sp
.PD 0
.TP
.B =~
Matching regular expression.
.TP
.B !~
Not matching regular expression.
.TP
.B =
Equal to.
.TP
.B !=
Not equal to.
.TP
.B >=
Greater than or equal to.
.TP
.B >
Greater than
.TP
.B <=
Less than or equal to.
.TP
.B <
Less than.
.PD
.P
.SS Binary logical operators \fR(cmp_log)
.sp
.PD 0
.TP
.B &&
All fields must match
.TP
.B ,
All fields must match
.TP
.B ||
At least one field must match
.TP
.B #
At least one field must match
.PD
.P
.SS Unary logical operators
.TP
.B !
Logical negation
.P
.SS Grouping operators
.sp
.PD 0
.TP
.B (
Left parenthesis
.TP
.B )
Right parenthesis
.TP
.B [
List start
.TP
.B ]
List end
.TP
.B {
List subset start
.TP
.B }
List subset end
.PD
.SS Informal grammar specification
.HP
.BR STATEMENT " = " column " cmp_op " VALUE " | " \%STATEMENT " log_op " STATEMENT " | " \%(STATEMENT) " | " \%!(STATEMENT)
.br
.HP
.BR VALUE " = " [VALUE " log_op " VALUE]
.br
For list-based types: string list. Matches strictly. The log_op must always be of one type within the whole list value.
.IP
For list-based types: string list. Matches strictly.
The log_op must always be of one type within the whole list value.
.HP
.BR VALUE " = " {VALUE " log_op " VALUE}
.br
For list-based types: string list. Matches a subset. The log_op must always be of one type within the whole list value.
.IP
For list-based types: string list. Matches a subset.
The log_op must always be of one type within the whole list value.
.HP
.BR VALUE " = " value
.br
For scalar types: number (integer), size (floating point number with size unit suffix), percent (floating point number with or without % suffix), string.
For scalar types: number (integer), size (floating point number
with size unit suffix), percent (floating point number with or
without % suffix), string.
.
.SH DIAGNOSTICS
.
All tools return a status code of zero on success or non-zero on failure.
.
.SH ENVIRONMENT VARIABLES
.
.TP
.B HOME
Directory containing \fI.lvm_history\fP if the internal readline
@@ -523,7 +702,7 @@ is overriden by direct use of \fB\-\-commandprofile\fP command line option.
.TP
.B LVM_SYSTEM_DIR
Directory containing \fBlvm.conf\fP(5) and other LVM system files.
Defaults to "#DEFAULT_SYS_DIR#".
Defaults to "\fI#DEFAULT_SYS_DIR#\fP".
.TP
.B LVM_SUPPRESS_FD_WARNINGS
Suppress warnings about unexpected file descriptors passed into LVM.
@@ -554,9 +733,10 @@ separate file.
The status anticipated when the process exits. Use ">N" to match any
status greater than N. If the actual exit status matches and a log
file got produced, it is deleted.
LVM_LOG_FILE_EPOCH and LVM_EXPECTED_EXIT_STATUS together allow
automated test scripts to discard uninteresting log data.
.B LVM_LOG_FILE_EPOCH
and
.B LVM_EXPECTED_EXIT_STATUS
together allow automated test scripts to discard uninteresting log data.
.TP
.B LVM_SUPPRESS_LOCKING_FAILURE_MESSAGES
Used to suppress warning messages when the configured locking is known
@@ -568,11 +748,16 @@ Abort processing if the code detects a non-fatal internal error.
.B DM_DISABLE_UDEV
Avoid interaction with udev. LVM will manage the relevant nodes in /dev
directly.
.
.SH FILES
.
.I #DEFAULT_SYS_DIR#/lvm.conf
.br
.I $HOME/.lvm_history
.
.SH SEE ALSO
.
.nh
.BR lvm.conf (5),
.BR lvmcache (7),
.BR lvmthin (7),

View File

@@ -28,8 +28,8 @@ layered on top of encrypted devices.
\fIlvm2-activation-net.service\fP
used for activation of LVM2 volumes that is ordered after systemd's
special \fBremote-fs.target\fP to support LVM2 volumes which are layered
on attached remote devices.
special \fBremote-fs-pre.target\fP to support LVM2 volumes which are
layered on attached remote devices.
Note that all the underlying devices (Physical Volumes) need to be present
when the service is run. If the there are any devices presented in the system

View File

@@ -195,6 +195,7 @@ Users who are concerned about the possibility of failures in their fast
devices that could lead to data loss might consider making their cache
pool sub-LVs redundant.
.I Example
.nf
0. Create an origin LV we wish to cache
# lvcreate \-L 10G \-n lv1 vg /dev/slow_devs
@@ -228,14 +229,18 @@ from the cache pool back to the origin LV. This mode will increase
performance, but the loss of a device associated with the cache pool LV
can result in lost data.
The cache mode can be specified with the --cachemode option when a cache
pool LV is created.
With the \-\-cachemode option, the cache mode can be set when creating a
cache LV, or changed on an existing cache LV. The current cache mode of a
cache LV can be displayed with the cache_mode reporting option:
.B lvs \-o+cache_mode VG/CacheLV
.BR lvm.conf (5)
.B cache_pool_cachemode
.B allocation/cache_mode
.br
defines the default cache mode.
.I Example
.nf
0. Create an origin LV we wish to cache (yours may already exist)
# lvcreate \-L 10G \-n lv1 vg /dev/slow
@@ -246,50 +251,55 @@ defines the default cache mode.
2. Create a cache metadata LV
# lvcreate \-L 8M \-n cache1meta vg /dev/fast
3. Create a cache pool LV specifying cache mode "writethrough"
# lvconvert \-\-type cache\-pool \-\-poolmetadata vg/cache1meta \\
\-\-cachemode writethrough vg/cache1
3. Create a cache pool LV
# lvconvert \-\-type cache\-pool \-\-poolmetadata vg/cache1meta vg/cache1
4. Create a cache LV by combining the cache pool LV and origin LV
# lvconvert \-\-type cache \-\-cachepool vg/cache1 vg/lv1
4. Create a cache LV by combining the cache pool LV and origin LV,
and use the writethrough cache mode.
# lvconvert \-\-type cache \-\-cachepool vg/cache1 \\
\-\-cachemode writethrough vg/lv1
.fi
The cache mode can be changed on an existing LV with the command:
.B lvconvert --cachemode writethrough|writeback VG/CacheLV
.SS Cache policy & policy settings
.SS Cache policy
\&
The cache subsystem has an additional per-LV parameter, namely the cache policy
to use, and possibly the tunable parameters of the said cache policy. In the
current implementation, two policies are available, "mq" which is the default
policy and "cleaner" which is used to force the cache to write back (flush) all
cached writes to the origin LV. Moreover, the "mq" policy has a number of
tunable parameters: the defaults are chosen to be suitable for the vast
majority of systems. However, under special circumstances, changing the tunable
settings of the cache policy can improve performance.
The cache subsystem has additional per-LV parameters: the cache policy to
use, and possibly tunable parameters for the cache policy. Three policies
are currently available: "smq" is the default policy, "mq" is an older
implementation, and "cleaner" is used to force the cache to write back
(flush) all cached writes to the origin LV.
On an existing cache LV, the policy can be set (to "mq") and the cache settings
can be changed using commands like these:
The "mq" policy has a number of tunable parameters. The defaults are
chosen to be suitable for the majority of systems, but in special
circumstances, changing the settings can improve performance.
With the \-\-cachepolicy and \-\-cachesettings options, the cache policy
and settings can be set when creating a cache LV, or changed on an
existing cache LV (both options can be used together). The current cache
policy and settings of a cache LV can be displayed with the cache_policy
and cache_settings reporting options:
.B lvs \-o+cache_policy,cache_settings VG/CacheLV
.I Example
.nf
# lvchange \-\-cachepolicy mq vg/lv1
# lvchange \-\-cachesettings \(aqmigration_threshold=2048 random_threshold=4\(aq \\
vg/lv1
Change the cache policy and settings of an existing cache LV.
# lvchange \-\-cachepolicy mq \-\-cachesettings \\
\(aqmigration_threshold=2048 random_threshold=4\(aq vg/lv1
.fi
Both commands can be combined, setting both cache policy and its settings
together. Moreover, when creating a cache LV for the first time (using
lvcreate), the \-\-cachepolicy and \-\-cachesettings parameters can be used as
well. The current policy and the policy settings can be listed using the lvs
command, using 'cache_policy' and 'cache_settings' fields:
.BR lvm.conf (5)
.B allocation/cache_policy
.br
defines the default cache policy.
.BR lvm.conf (5)
.B allocation/cache_settings
.br
defines the default cache settings.
# lvs -o +cache_policy,cache_settings
.SS Spare metadata LV

View File

@@ -5,11 +5,13 @@ lvmetad \(em LVM metadata cache daemon
.SH SYNOPSIS
.B lvmetad
.RB [ \-l
.RI { all | wire | debug }]
.IR level [,level...]]
.RB [ \-p
.IR pidfile_path ]
.RB [ \-s
.IR socket_path ]
.RB [ \-t
.IR timeout_value ]
.RB [ \-f ]
.RB [ \-h ]
.RB [ \-V ]
@@ -75,15 +77,11 @@ Don't fork, but run in the foreground.
.BR \-h ", " \-?
Show help information.
.TP
.IR \fB\-l " {" all | wire | debug }
Select the type of log messages to generate.
Messages are logged by syslog.
.B \-l \fIlevels
Specify the levels of log messages to generate as a comma separated list.
Messages are logged by syslog.
Additionally, when \-f is given they are also sent to standard error.
Since release 2.02.98, there are two classes of messages: wire and debug.
Selecting 'all' supplies both and is equivalent to a comma-separated list
\-l wire,debug.
Prior to release 2.02.98, repeating \-d from 1 to 3 times, viz. \-d, \-dd, \-ddd,
increased the detail of messages.
Possible levels are: all, fatal, error, warn, info, wire, debug.
.TP
.B \-p \fIpidfile_path
Path to the pidfile. This overrides both the built-in default
@@ -97,6 +95,10 @@ Path to the socket file. This overrides both the built-in default
\fBLVM_LVMETAD_SOCKET\fP. To communicate successfully with lvmetad,
all LVM2 processes should use the same socket path.
.TP
.B \-t \fItimeout_value
The daemon may shutdown after being idle for the given time (in seconds). When the
option is omitted or the value given is zero the daemon never shutdowns on idle.
.TP
.B \-V
Display the version of lvmetad daemon.
.SH ENVIRONMENT VARIABLES

View File

@@ -84,7 +84,7 @@ version without the system_id feature.
.SS Types of VG access
A local VG is mean to be used by a single host.
A local VG is meant to be used by a single host.
.br
A shared or clustered VG is meant to be used by multiple hosts.
.br
@@ -274,7 +274,7 @@ cache with pvscan --cache will allow a host to recognize the newly
exported VG.
vgimport sets the VG system_id to the local system_id as determined by
lvm.conf system_id_sources. vgimport automatically scans storage for
lvm.conf system_id_source. vgimport automatically scans storage for
newly exported VGs.
After vgimport, the exporting host will continue to see the VG as
@@ -300,9 +300,9 @@ To move a VG from one host to another, vgexport and vgimport should be
used.
To forcibly gain ownership of a foreign VG, a host can add the foreign
system_id to its allow_system_id list, change the system_id of the foreign
VG to its own, and remove the foreign system_id from its allow_system_id
list.
system_id to its extra_system_ids list, change the system_id of the
foreign VG to its own, and remove the foreign system_id from its
extra_system_ids list.
.SS shared VGs
@@ -328,7 +328,7 @@ creation_host will be the same.
Orphan PVs are unused devices; they are not currently used in any VG.
Because of this, they are not protected by a system_id, and any host can
use them. Coodination of changes to orphan PVs is beyond the scope of
use them. Coordination of changes to orphan PVs is beyond the scope of
system_id. The same is true of any block device that is not a PV.
The effects of this are especially evident when lvm uses lvmetad caching.
@@ -337,7 +337,7 @@ using the orphan, the other hosts will continue to report the PV as an
orphan. Nothing would automatically prevent the other hosts from using
the newly allocated PV and corrupting it. If the other hosts run a
command to rescan devices, and update lvmetad, they would then recognize
the PV has been used by another host. A command that rescans devices
that the PV has been used by another host. A command that rescans devices
could be pvscan --cache, or vgs --foreign.
.SH SEE ALSO

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