1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-10-14 15:33:15 +03:00

Compare commits

...

351 Commits

Author SHA1 Message Date
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
Alasdair G Kergon
629398d0f2 pre-release 2015-09-22 16:00:10 +01:00
Peter Rajnoha
fd773dffb2 man: drop superfluous '--' in lvmconf man page for --enable/disable-halvm 2015-09-22 14:28:31 +02:00
Peter Rajnoha
001f747963 lvmconf: set locking_type=2 if external library is requested
Also, set safe use_lvmetad=0 for external locking (locking_type=2)
similarly to locking_type=3.
2015-09-22 13:33:12 +02:00
Peter Rajnoha
2081071bee wiping: warn if use_blkid_wiping=1 is set and LVM not compiled with blkid_wiping support 2015-09-22 11:11:26 +02:00
Zdenek Kabelac
47f623d64b tests: update removal test
Test is currently checking a very non-standard use case.
Make it a more resistent against being blocked in kernel.
2015-09-22 00:08:45 +02:00
Zdenek Kabelac
7e63364529 tests: check for block device
Need to detect if block device exist.
2015-09-22 00:08:44 +02:00
Zdenek Kabelac
2e5bde4a77 lvchange: update help text
Use <> for user specified options.
(meant to match 'Italic' style in man page).
2015-09-22 00:08:44 +02:00
Zdenek Kabelac
cfe869692f man: update man pages
Start to use 'italic' when the argument is not a fixed string.
Keep 'bold' when user cannot use any other string instead.
2015-09-22 00:08:44 +02:00
Zdenek Kabelac
a61f3c5316 clvmd: update help test
Use <n> for <input> value.
2015-09-22 00:08:44 +02:00
Alasdair G Kergon
ce80d73684 lvmcache: Remove verbose msg when rescanning dev. 2015-09-21 19:51:15 +01:00
Peter Rajnoha
804c25a81a WHATS_NEW: commits cb8f29d147 - a54b4bba35 2015-09-21 14:28:41 +02:00
Peter Rajnoha
a54b4bba35 report: add lv_convert_lv_uuid field 2015-09-21 14:22:23 +02:00
Peter Rajnoha
0a01c5aa36 report: add lv_move_pv_uuid field 2015-09-21 14:22:03 +02:00
Peter Rajnoha
f01b7afa19 pv: add 'mem' arg for pv_uuid_dup and pv_name_dup 2015-09-21 14:21:42 +02:00
Peter Rajnoha
ffa7b37b28 report: add lv_mirror_log_uuid field 2015-09-21 14:21:39 +02:00
Peter Rajnoha
f61a394be4 report: add lv_data_lv_uuid field 2015-09-21 14:21:21 +02:00
Peter Rajnoha
c2ea5b3dee report: add lv_metadata_lv_uuid field 2015-09-21 14:20:58 +02:00
Peter Rajnoha
199697accf report: add lv_origin_uuid field 2015-09-21 14:20:36 +02:00
Peter Rajnoha
cb8f29d147 report: add lv_pool_lv_uuid field 2015-09-21 14:20:12 +02:00
Peter Rajnoha
0e3042f488 lv: add 'mem' arg for lv_uuid_dup 2015-09-21 12:25:31 +02:00
Peter Rajnoha
f644431346 cleanup: report: reuse existing _uuid_disp fn to report pv_uuid field 2015-09-21 12:13:01 +02:00
Zdenek Kabelac
83a52c07b7 tests: check dmsetup remove --force 2015-09-18 17:45:46 +02:00
Zdenek Kabelac
7d1dd5f52d tests: use remount-ro for extfs
Avoid showing kernel warn of umounting broken fs.
2015-09-18 17:45:46 +02:00
Zdenek Kabelac
330d584617 man: use PD/HP for compressed lines
Using .PD 0  to user zero spacing together with .HP is the best way
for condensed list of commands.
2015-09-18 17:45:46 +02:00
Zdenek Kabelac
11d6f81316 man: enhance dmsetup/dmstats
Document more supported options.
Cleanup man-style when documenting options.
Use .PD 0  and .HP
2015-09-18 17:45:46 +02:00
Zdenek Kabelac
f9c8cefd06 dmsetup: improve help text
Document more options.
2015-09-18 17:45:45 +02:00
Zdenek Kabelac
791e76ff70 dmsetup: use noflush with force removal
When user specifies '--force' with remove/remove_all/wipe_table
use '--noflush --nolockfs' resume flags, so the operation
will not block when device underneath is blocked.
2015-09-18 17:45:45 +02:00
Zdenek Kabelac
e0d915a873 libdm: parse Overflow string from snapshot status
This is likely to be a new 'info' provided by kernel
snapshot target.
For now just parse this string.
2015-09-18 17:45:45 +02:00
Heinz Mauelshagen
90ad817a43 uuid: Report invalid character. 2015-09-18 14:19:32 +01:00
Peter Rajnoha
5bc8c713e2 WHATS_NEW: commit 6c0b4a2769 2015-09-17 14:36:39 +02:00
Peter Rajnoha
6c0b4a2769 libdm: file: add proper checks for directory components in dm_create_dir
Also make error messages more consistent:

Before this patch:

(/run/lock exists and is not a directory)
$ pvs
  /run/lock/lvm: mkdir failed: Not a directory
  File-based locking initialisation failed.

(/run/lock/lvm exists and is not a directory)
$ pvs
  Directory "/run/lock/lvm" not found
  File-based locking initialisation failed.

With this patch applied:

(/run/lock exists and is not a directory)
$ pvs
  Existing path /run/lock is not a directory.
  Failed to create directory /run/lock/lvm.
  File-based locking initialisation failed

(/run/lock/lvm exists and is not a directory)
$ pvs
  Existing path /run/lock/lvm is not a directory.
  Failed to create directory /run/lock/lvm.
  File-based locking initialisation failed.
2015-09-17 14:29:51 +02:00
Peter Rajnoha
afdae26c71 libdm: dev_node: use lstat instead of stat while removing and renaming nodes
When using udev, the /dev/mapper entries are symlinks - fix the code
to count with this.

This patch also fixes the dmsetup mknodes and vgmknodes to properly
repair /dev/mapper content if it sees dangling symlink in /dev/mapper.
2015-09-17 13:37:15 +02:00
Peter Rajnoha
b5022102bb libdm: report: make it possible to use blank value as selection for string list report field
$ lvs -o name,tags vg
  LV    LV Tags
  lvol0
  lvol1 mytag

Before this patch:
$ lvs -o name,tags vg -S 'tags=""'
  Failed to parse string list value for selection field lv_tags.
  Selection syntax error at 'tags=""'.
  Use 'help' for selection to get more help.

(and the same for -S 'tags={}' and -S 'tags=[]')

With this patch applied:
$ lvs -o name,tags vg -S 'tags=""'
  LV    LV Tags
  lvol0

(and the same for -S 'tags={}' and -S 'tags=[]')
2015-09-17 10:19:15 +02:00
David Teigland
b7410c95cf lvmlockd: unlock lv if command fails before lock completes
If lvmlockd acquires an lv lock for a command, but the
command exits before the reply, then the command has
not activated the lv and lvmlockd should unlock it.
This only applies when the lv was not already locked.

(There will always be a chance that the lv lock is held
while the lv is not active, i.e. if the command fails in
the small window between getting the lv lock and before
doing the activation.  In that case, rerunning the
activation command corrects the inconsistency.)

This commit helps by automatically clearing the
inconsistency (lv locked by not activated) in the most
common case when the lv lock operation is slow to
complete and the command is canceled by the user.

This commit also adds and cleans up references to the
client id in a bunch of log messages, which is useful
to follow processing on each independent lock request.
2015-09-16 15:56:54 -05:00
Peter Rajnoha
fcfca57e2e format-text: label: fix missing dev assignment for struct label in _text_pv_write
When using lvm shell, some structures which are cached in memory may be
reused. This happens for the struct label (a part of lvmcache_info
structure) when lvmetad is used in which case the PV scan is not
done that would normally overwrite these label structures in memory
and making them up-to-date.

This is all consequence of the fact that struct lvmcache_info and
struct label are not always assigned in the same part of the code.
For example, if lvmetad *is not* used, parts of the struct label are
reassigned in label_read fn while struct lvmcache_info is created
elsewhere. No part of the code reused struct label (and its "dev"
field) before calling label_read fn. That's why the real bug is
hidden when using lvm shell without lvmetad.

However, with lvmetad and lvm shell, the situation is a bit different.
The label_read fn is not called if lvmetad *is* used, hence the
struct label may have ended up not initialized properly.

There was missing assignment for the dev field in struct label
in _text_pv_write fn which caused this problem to appear in
lvm shell with lvmetad, for example:

Before this patch:

lvm> pvcreate /dev/sda
  Physical volume "/dev/sda" successfully created
lvm> pvs /dev/sda
  PV             VG     Fmt  Attr PSize   PFree
  unknown device        lvm2 ---  128.00m 128.00m

With this patch applied:

lvm> pvcreate /dev/sda
  Physical volume "/dev/sda" successfully created
lvm> pvs /dev/sda
  PV         VG   Fmt  Attr PSize   PFree
  /dev/sda        lvm2 ---  128.00m 128.00m

Also, this problem had not appeared before changes introduced
by commits e1a63905d1 through
3a6f91d713 which, among other
things, added proper label field type reporting. Before, label
reporting was the same as using struct physical_volume which
has its own dev field assigned and so this problem was not exposed.
2015-09-15 18:07:32 +02:00
Alasdair G Kergon
0ac10bb23a post-release 2015-09-15 14:09:10 +01:00
Alasdair G Kergon
a729b1aa29 pre-release 2015-09-15 13:17:50 +01:00
Alasdair G Kergon
548c09acfc man: Add all_man Makefile target.
Use 'make all_man' to generate all man pages (regardless of
configuration options) or 'make install_all_man' to install them.
2015-09-15 13:14:16 +01:00
David Teigland
2ce8ee0214 vgcreate: initialize new PVs only in first vg_write
When a command does a sequence of
vg_write + vg_commit + vg_write + vg_commit,

initialization of non-PV devices happens during the
first vg_write, and does not need to be repeated by
the second vg_write.

When creating a lockd VG, this sequence occurs because
the VG is first created, then the lockd data is created,
then the lockd data is then written to the VG metadata.
2015-09-14 13:22:22 -05:00
Zdenek Kabelac
cee9ed2244 tests: early check for snapshot-merge 2015-09-14 20:18:54 +02:00
Zdenek Kabelac
e7e15631dd tests: lvextend of full thin pool 2015-09-14 20:18:54 +02:00
Zdenek Kabelac
ffeeb5c1e7 thin: show message on error path
Add missing log_error and show proper reason for failure
when autoextend is set to 0.

Add missing log_error when checked LV is not locally active.
2015-09-14 20:18:54 +02:00
Zdenek Kabelac
c356991fa8 libdm: no validate for pool without messages
Avoid validation of free space in pool, when no messages are passed.

Patch a3c7e326c3 add new check for
pool overload - but this check should not be made if there are
no messages and transaction_id is still within 'bounds' (bigger by 1).
2015-09-14 20:18:54 +02:00
Zdenek Kabelac
e42ee69988 vgimporeclone: use correct cache dir path
Commit 00b36ef06a had a typo
and missed '{' for shell variable, thus command used slightly
different 'tmp' dir name for cache dir (with extra '}').

Such change was unnoticed until a recent fix in persistent
filter, lvm2 missed to update cache file when --config
was specified.

The result was, /tmp dir was accumulating snap.XXXXX} dirs when
running vgimportclose  script.
2015-09-14 09:31:26 +02:00
Zdenek Kabelac
226e7d7b3c tests: wait for sync before deactivation
On slower machine/disk, sync may block udev from reading and may prevent
deactivation.
2015-09-11 21:52:27 +02:00
Zdenek Kabelac
cd2e4310b3 tests: new thin tests 2015-09-11 21:52:27 +02:00
Zdenek Kabelac
fd3d795b93 makefiles: distclean missing files 2015-09-11 21:52:27 +02:00
Zdenek Kabelac
729b035edd pool: validate pool_metadata has proper suffix 2015-09-11 21:52:27 +02:00
Zdenek Kabelac
fda853b573 thin: improve swapping of identifiers
Since we may want to swap names when LVs are complex types, we cannot
avoid doing full renames on both LV stacks.
Temporarily use 'pvmove_tmeta' as unused name to prevent validation troubles.
2015-09-11 21:51:11 +02:00
Zdenek Kabelac
280a6275ce thin: lvconvert use passed PVs for _pmspare
When PVs are given on 'lvconvert' respect them when converting
volume to thin-pool and allocating i.e. _pmspare.
2015-09-11 21:48:19 +02:00
Zdenek Kabelac
95b5d24f43 configure: relocate configure.h
Commit 9403edbb93 move location of
configure.h and lvm-version.h.

Let's try even better place then /conf dir which should be left
for user configurable files.

Put these files right into include dir.
2015-09-11 21:46:35 +02:00
Zdenek Kabelac
19443035a6 configure: correct message 2015-09-11 21:46:34 +02:00
David Teigland
8b8103efef man lvmlockd: move and update text about vgremove
The requirement to stop VGs before vgremove applies
to both sanlock and dlm VGs.
2015-09-11 14:34:22 -05:00
David Teigland
6bc3d72a65 lvmlockd: prevent vgremove of dlm VG while lockspace is used
This applies the same rule/logic to dlm VGs that has always
existed for sanlock VGs.  Allowing a dlm VG to be removed
while its lockspace was still running on other hosts largely
worked, but there were difficult problems if another VG with
the same name was recreated.  Forcing the VG lockspace to
be stopped, gives both sanlock and dlm VGs the same behavior.
2015-09-11 14:12:13 -05:00
David Teigland
854a559a49 lvmlockd: remove shortcut for lockspace thread cleanup
This shortcut was added for an odd case that I do not
believe is relevant any more.  Having an alternate
path for lockspace thread cleanup is a complication
that could lead to problems.
2015-09-11 13:20:20 -05:00
David Teigland
18dfbbb150 lvmlockd: optimize dlm global lockspace creation
Set a flag indicating that the dlm global lockspace
exists to avoid going through the entire process of
trying to add it before finding it exists.
2015-09-11 13:20:01 -05:00
David Teigland
0a26c20b88 lockd: fix rescanning VG metadata
The code was expecting the wrong return value from
compare_config, which returns 0 when equal.

This is a problem for a lockd VG using multiple PVs
when the VG needs to be rescanned.
2015-09-11 13:10:48 -05:00
Zdenek Kabelac
0889cff5d5 spec: upgrade
Upgrade spec rules to be in touch with recent code.
Provide services and proper postin/preun/postun scriplets.
2015-09-10 17:28:47 +02:00
Zdenek Kabelac
9b8c876293 tests: remove only existing loops
If loop device meanwhile dissapered, skip 'losetup -d' call.
2015-09-10 17:28:47 +02:00
Zdenek Kabelac
e94ab01940 tests: fix check lv_not_exist
Use 'not' to set proper 'expected return status'
so we do not 'leak' debug logs printed for failing case.
2015-09-10 17:28:47 +02:00
Zdenek Kabelac
54c982081f tests: check cache stripe and raid behavior
Somehow raid tests landed in plain cache - separte them out
so they properly check for  have_raid.

Check we do not support strip option with cache-pool creation.
2015-09-10 17:28:47 +02:00
Zdenek Kabelac
a631fa20d0 cache: disallow stripes/size for cache pool
ATM allocation can't handle stripping and cache pool allocation.
It's not yet even clear what should be actually result.
Until resolved, disable this option (it's been coredumping
inside allocation anyway).
2015-09-10 17:28:15 +02:00
Zdenek Kabelac
5911fa1d91 cache: warn if caching causes troubles
Certain stacks of cached LVs may have unexpected consequences.
So add a warning function called when LV is cached to detect
such caces and WARN user about them - the best we could do ATM.
2015-09-10 17:27:30 +02:00
Zdenek Kabelac
e1edb5676e lib: when moving segtypes, move LV bits
When we insert layer we also move status flag-bits for certain LV types,
so internal volume_group structure remains consistent.
(Perhaps it's misuse of 'insert_layer' function and we should have
another similar function for this.)

Basically we aim to maintain the same state as after reading fresh
metadata out of volume group.

Currently we when i.e. cache  'raid' LV - this should transfer 'raidLV' flag
to  _corigin LV and cache is no longer a raid.

TODO: bits for stacked devices needs more exact rules.
2015-09-10 17:25:28 +02:00
David Teigland
3670f095c7 lvmlockd: check all variations of lvb values
The dlm will often lose the lvb content, so we need to
check quite a few possibilities for lvb values that
were not being checked before.

Refactoring was required to pass the entire lvb value
back to the core code instead of the single value.

The only functional change should be detecting new
lvb states where metadata is now invalidated where
it wasn't before.
2015-09-10 09:47:26 -05:00
David Teigland
f11d690967 lvmlockd: flag for internal actions
When an action is created by lvmlockd for itself,
there is no client to send the result to.  Add
the NO_CLIENT flag to the action to skip sending
the result to a client.
2015-09-10 09:47:26 -05:00
David Teigland
15ae237d2c lvmlockd: rename ADOPT_CLIENT_ID
to INTERNAL_CLIENT_ID since it will be
used for more than adopting locks.
2015-09-10 09:47:26 -05:00
David Teigland
36d16fed1f lockd: add start_init arg to lockd_start_vg
Add a new arg to lockd_start_vg() that indicates
it is being called for a new lockd VG, so that
lvmlockd knows the lockspace being started is new.
(Will be used by a following commit.)
2015-09-10 09:47:26 -05:00
David Teigland
30e489db5e vgchange: lock-stop only needs shared lock
lock-stop is one of the vgchange options that
doesn't change the VG so we can override the
default ex lock and use sh.
2015-09-10 09:47:26 -05:00
Peter Rajnoha
2296999cf6 dev-cache: ignore persistent cache if configuration changed
Commit f6473baffc introduced a new
cmd->initialized variable to keep info about which parts of the
cmd_context have been initialized.

A part of this patch was also a change in refresh_filters fn
which checks for cmd->initialized.filters variable and it does
the filter refresh *only* if the filter has already been initialized
before otherwise it's a NOOP (before, the refresh_filters also
initialized filters as a side effect in case it had not been
initialized before which was not quite correct).

However, the commit f6473baffc
did not handle the case in which configuration changes
either via --config argument or when configuration file changed
and its timestamp was higher than the timestamp of the persistent
cache file - the /etc/lvm/cache/.cache.

This patch fixes this issue and it causes the init_filters fn
in lvm_run_command fn to be called with proper value of
"load_persistent_cache" switch even if the configuration changes,
hence causing the persistent cache file to be ignored in this
case.
2015-09-10 16:13:39 +02:00
David Teigland
d323acdfec man lvmlockd: fix typo 2015-09-09 15:43:28 -05:00
David Teigland
81b0e9de7c man lvmlockd: mention device used for first vgcreate 2015-09-09 15:21:10 -05:00
Zdenek Kabelac
587fd6a0e4 tests: ensure dd flushed all data before exit 2015-09-08 15:41:34 +02:00
Zdenek Kabelac
6cb7f21e38 tests: better check for compiled version
Use install /lib files to check for expected version.
2015-09-08 15:41:34 +02:00
Zdenek Kabelac
8ff43c3705 makefiles: ensure no old .h are left
Ensure make clean  cleans any left-over file from their previous
location so they are not in conflict with new ones.

Also hide error message when .commands file is not present.
2015-09-08 15:41:33 +02:00
Peter Rajnoha
026db90621 WHATS_NEW: commit b77497cbd8 2015-09-08 15:37:23 +02:00
Peter Rajnoha
b77497cbd8 filters: make sure regex filter is evaluated before any filter that needs disk access
The regex filter (controlled by devices/filter lvm.conf setting) was
evaluated as the very last filter. However, this is not optimal when
it comes to restricting disk access - users define devices/filter
as well as devices/global_filter to avoid this.

The devices/global_filter is already positioned at the beginning of the
filter chain. We need to do the same for devices/filter.

Filter chains before this patch:

  A: when lvmetad is not used:
       persistent_filter -> sysfs_filter -> global_regex_filter ->
       type_filter -> usable->filter -> mpath_component_filter ->
       partition_filter -> md_component_filter -> fw_raid_filter ->
       regex_filter

  B: when lvmetad is used:

    B1: to update lvmetad:
      sysfs_filter -> global_regex_filter -> type_filter ->
      usable_filter -> mpath_component_filter -> partition_filter ->
      md_component_filter -> fw_raid_filter

    B2: to retrieve info from lvmetad:
      persistent_filter -> usable_filter -> regex_filter

From the chain list above we can see that particularly in case when
lvmetad is not used, the regex filter is the very last one that is
processed. If lvmetad is used, it doesn't matter much as there's
the global_regex_filter which is used instead when updating lvmetad
and when retrieving info from lvmetad, putting regex_filter in front
of usable_filter wouldn't change much since usabled_filter is not
reading disks directly.

This patch puts the regex filter to the front even in case lvmetad
is not used, hence reinstating the state as it was before commit
a7be3b12df (which moved the regex_filter
position in the chain). Still, the arguments for the commit
a7be3b12df still apply and they're
still satisfied since component filters (MD, mpath...) are evaluated
first just before updating lvmetad.

So with this patch, we end up with:

  A: when lvmetad is not used:
       persistent_filter -> sysfs_filter -> global_regex_filter ->
       regex_filter -> type_filter -> usable->filter ->
       mpath_component_filter -> partition_filter ->
       md_component_filter -> fw_raid_filter

  B: when lvmetad is used:

    B1: to update lvmetad:
      sysfs_filter -> global_regex_filter -> type_filter ->
      usable_filter -> mpath_component_filter -> partition_filter ->
      md_component_filter -> fw_raid_filter

    B2: to retrieve info from lvmetad:
      persistent_filter -> regex_filter -> usable_filter

This way, specifying the regex_filter in non-lvmetad case causes
the devices to be filtered based on regex first before processing
any other filters which can access disks (like md_component_filter).

This patch also streamlines the code for better readability.
2015-09-08 15:28:10 +02:00
Zdenek Kabelac
596ec5c74b tests: skip raid testing on 4.[1,2] fc24 kernels
Hopefull 4.3 will be fixed and test will be updated to let
raid test running again.

Meanwhile using md-raid may effectively kill kernel,
so leave at least other tests running.
2015-09-08 12:12:38 +02:00
Zdenek Kabelac
0ec64370b2 specs: install lvmlockctl only when built
Move install line into proper section.
2015-09-07 23:27:50 +02:00
Bryn M. Reeves
d7f45ebca5 libdm: clean up stats local variable use 2015-09-07 20:14:53 +01:00
Bryn M. Reeves
daa94eb792 libdm: fix display of nsec suffixes in histogram strings 2015-09-07 20:14:53 +01:00
Bryn M. Reeves
5f990473e4 libdm: clean up _build_histogram_arg()
Split up _build_histogram_arg() into separate functions to allocate
and fill the histogram arg string and remove nested local variable
declarations from the parent function.
2015-09-07 19:30:03 +01:00
Bryn M. Reeves
4bc7a86f3a libdm: only free the first histogram explicitly (Coverity)
Coverity flags a user-after-free in _stats_histograms_destroy():

>>>     Calling "dm_pool_free" frees pointer "mem->chunk" which has
>>>     already been freed.

This should not be possible since the histograms are destroyed in
reverse order of allocation:

 203         for (n = _nr_areas_region(region) - 1; n; n--)
 204                 if (region->counters[n].histogram)
 205                         dm_pool_free(mem, region->counters[n].histogram);

It appears that Coverity is unaware that pool->chunk is updated
during the call to dm_pool_free() and valgrind flags no errors in
this function when called with multiple allocated histograms.

Since there is no actual need to free the histograms individually
in this way simplify the code and just free the first allocated
object (which will also free all later allocated histograms in a
single call).
2015-09-07 17:53:56 +01:00
Zdenek Kabelac
ffbf12504d cleanup: assign seg_name once 2015-09-07 17:44:08 +02:00
Zdenek Kabelac
330cad1567 specs: package lvmlockctl man page 2015-09-07 17:44:08 +02:00
Zdenek Kabelac
fa4d2ec241 tests: update install rules
Enhnace 'make install' rules for test suite (used for rpm packaging).
Install lvmlockd conf files.
Compile runner with correct CXXFLAGS.
2015-09-07 17:44:08 +02:00
Zdenek Kabelac
acfc56957c makefiles: do not generate tags for everyone
Create tags file only on request (make tags).
Also clean file with 'make clean'.
2015-09-07 17:44:04 +02:00
Zdenek Kabelac
3ba431e79e makefiles: deps depends on header links
Put include/.symlinks_created as a prerequisite for dep calc.
Otherwise if these are not generated and user enters tests subdir and
runs 'make' he just gets endless loop of dep calculation.
2015-09-07 17:43:27 +02:00
Zdenek Kabelac
d62448cb45 configure: regenerate 2015-09-07 17:43:27 +02:00
Zdenek Kabelac
1999e368f1 configure: simpler version reading
Avoid calling 'cat' when 'read' could handle it.

Also drop DM_LIB_VERSION from AC_SUBST as it's not used anywhere
in .in file.
2015-09-07 17:43:27 +02:00
Zdenek Kabelac
fc4f0d3fce configure: support --disable-dependency-tracking
One-time build may enjoy little speedup of build when dependencies are not
calculated.
2015-09-07 17:43:11 +02:00
Zdenek Kabelac
9403edbb93 configure: relocate generated headers
Relocate generated configure.h and lvm-version.h outside
of compilable .c source tree.

The reason is behind - when compiling in builddir != srcdir
the generated file in lib/misc/configure.h was used for all compiled
source file except ones located in lib/misc dir - those would have used
configure.h file located in this dir - if there have existed one (i.e.
from some other build)

This problem was only visible, when srcdir == buildir was used before
trying to use  srcdri != builddir  (as configure.h appeared then in
srcdir).
2015-09-07 17:40:58 +02:00
Bryn M. Reeves
ab1b54c3e3 libdm: fix dm_stats leak in dm_stats_create()
The histogram changes adds a new error path to dm_stats_create().
Make sure that the dm_stats handle is properly destroyed if we fail
to create the histogram pool and check for failures setting the
program_id.
2015-09-07 12:08:34 +01:00
Bryn M. Reeves
0f5933ecc1 libdm: handle pool errors in dm_histogram_to_string() 2015-09-07 12:01:20 +01:00
Bryn M. Reeves
e75b4bc2df libdm: check dm_pool_begin_object() return value. 2015-09-07 11:52:54 +01:00
Bryn M. Reeves
36b09fd147 libdm: add missing error handling in _stats_parse_histogram()
Since we are growing an object in the histogram pool the return
value of dm_pool_grow_object() must be checked and error paths need
to abandon the object before returning.
2015-09-07 11:44:53 +01:00
Bryn M. Reeves
a26523330e dmsetup: fix bounds leak in _do_stats_create_regions()
If we fail to create the DM_DEVICE_TABLE dm_task destroy the bounds
object before returning.
2015-09-07 11:14:28 +01:00
Alasdair G Kergon
2a022e9e6e post-release 2015-09-05 23:58:40 +01:00
Alasdair G Kergon
fb12308416 style: Standardise some error paths. 2015-09-05 23:56:30 +01:00
Alasdair G Kergon
f5a3b05c7a pre-release 2015-09-05 23:46:22 +01:00
Bryn M. Reeves
f868624f85 WHATS_NEW_DM: fix histogram entries for 1.02.107
The histogram entries were under the wrong version (1.02.106). Fix
that and describe the library changes in more detail.
2015-09-04 19:53:10 +01:00
David Teigland
10ccbc5efa lvmlockd: don't stop lockspace for EREMOVED
Undo the part of the recent EREMOVED change which
automatically stopped the lockspace for a remotely
removed VG.  It didn't always work (would not work
when lvb content was rebuilt in the dlm).  This will
be handled better when the lvb content is controlled
more strictly.
2015-09-04 13:41:38 -05:00
David Teigland
43d6b5b375 man lvmlockd: add section about first sanlock VG
Add a section specifically about creating the first
sanlock VG.
2015-09-04 13:01:03 -05:00
David Teigland
869c0bdeb8 man lvmlockctl: add man page 2015-09-04 11:05:13 -05:00
David Teigland
c71af0895d lvmlockctl: update command descriptions and add logging
The one line descriptions will match the man page.

Add a syslog entry when enabling/disabling the global lock
to help debugging.
2015-09-04 11:05:13 -05:00
David Teigland
b00ee99a21 man lvmlockd: explain the use of lvmlockctl kill 2015-09-04 11:05:13 -05:00
Peter Rajnoha
55c13f3de4 dev-cache: fix use of uninitialized device status if reading outdated .cache record
As part of fix that came with cf700151eb,
I forgot to add the check whether the result of stat was successful or
not. This bug caused uninitialized buffer to be used for entries
from .cache file which are no longer valid.

This bug may have caused these uninitialized values to be used further,
for example (see the unreal (2567,590944) representing major:minor
pair):

$ pvs
  /dev/abc: stat failed: No such file or directory
  Path /dev/abc no longer valid for device(2567,590944)
  PV               VG   Fmt  Attr PSize   PFree
  /dev/mapper/test      lvm2 ---  104.00m 104.00m
  /dev/vda2        rhel lvm2 a--    9.51g      0
2015-09-04 18:00:29 +02:00
David Teigland
9694854082 vgchange: improve error message about changing lock type 2015-09-04 09:53:33 -05:00
Bryn M. Reeves
cdca2782d2 libdm: fix uninitialized variable warnings on older gcc
Older versions of gcc aren't able to track the assignments of
local variables as well as the latest versions leading to spurious
warnings like:

libdm-stats.c:2183: warning: "len" may be used uninitialized in this
function
libdm-stats.c:2177: warning: "minwidth" may be used uninitialized in
this function

Both of these variables are in fact assigned in all possible paths
through the function and later compilers do not produce these
warnings.

There's no reason to not initialize these variables though and
it makes the function slightly easier to follow.

Also fix one use of 'unsigned' for a nr_bins value.
2015-09-04 11:46:48 +01:00
Bryn M. Reeves
cebbb0feaf dmstats: replace histogram command with switch
Replace the histogram stats subcommand with a --histogram switch
to enable histogram related fields for both list and report output.

To avoid overloading the existing --histogram rename it to --bounds:
this is also a better description of the option.
2015-09-03 23:39:11 +01:00
David Teigland
6240a7639d lvmlockd: fixes for starting dlm global lockspace
Remove the optimization/shortcut for starting the dlm global
lockspace when it was already running.

Reenable automatically starting the dlm global lockspace
when a command attempts to use it and it's not yet started.
This had become disabled at some point.
2015-09-03 16:47:54 -05:00
David Teigland
9e8b3d4a98 lockd: check for unlock failure in all cases
This suppresses an unwanted error message.
2015-09-03 16:47:54 -05:00
David Teigland
c27015368b lvmlockd: improve log messages for adding dlm global lockspace 2015-09-03 16:47:54 -05:00
Zdenek Kabelac
5da497d0a8 tests: update thin test
Use slightly better values
2015-09-03 23:34:37 +02:00
Zdenek Kabelac
dc261f17e9 tests: use conv=fdatasync
Should be slightly better to flushed before dd exits
instead of using direct IO.
2015-09-03 23:34:37 +02:00
Zdenek Kabelac
ee8200f1c6 cleanup: use just 2 decimal digits 2015-09-03 23:34:37 +02:00
Zdenek Kabelac
0a389691dc cleanup: avoid printing -0.00
Nice trick to not print -0.00 for some percent values.
2015-09-03 23:34:37 +02:00
Zdenek Kabelac
32d6ca9196 cleanup: show error message
Add error message on error path.
2015-09-03 23:34:36 +02:00
Zdenek Kabelac
20e317cf92 lvcreate: restore missed --monitor
Fix regression from d13239b054.
This patch reorganized whole command option parsing, however
it has lost support to accept --monitor arg.
2015-09-03 23:34:36 +02:00
Zdenek Kabelac
2b9843c20b dmeventd: reorder mempool allocation
Since lvm2_init() effectively detects memory leaks
allocate mempool after this initialization
(so it's not reported as leak).
2015-09-03 23:34:36 +02:00
Zdenek Kabelac
872ea3b987 thin: do not flush when quering for thin percent
Since we may easily get blocked when checking for percentage
of thin-pool - do not flush and just show current values.
This avoids holding VG locked when pool is overfilled.
2015-09-03 23:34:36 +02:00
Zdenek Kabelac
df110bccbe thin: validate mapped size of thin volume
Never show we map more then 100% for a volume.
But show warning when there could be some consistency problems.
2015-09-03 23:34:36 +02:00
Zdenek Kabelac
a01eb9c451 thin: detect unusable thins
Try to detect thin-pool which my block lvm2 command from furher
processing (i.e. lvextend).

Check if pool is read-only or out-of-space and in this case thins
will skipped from being scanned (so user may miss some PVs located
on thin volumes).
2015-09-03 23:34:36 +02:00
Zdenek Kabelac
81a9da8f61 filters: swap device_is_usable test
Fix regression introduced with commit:
2fc126b00d

This commit has moved  pv_min_size() test in front
of device_is_usable(). However pv_min_size needs to open device,
so it may have actually get blocked.

So restore the original order and first validate
dm device to be usable for open.

It's worth to note that such check is not 'race-free',
but it usually eliminates 99.99% of problems ;).
2015-09-03 23:34:36 +02:00
Zdenek Kabelac
a3c7e326c3 libdm: relocate parsing of thin-pool status
Use single routine for parsing status.

Internally we do not need to allocate pool memory for
passed struct.
2015-09-03 23:34:36 +02:00
Zdenek Kabelac
5ce334923f configure: better parsing of cache_check version
Properly read also version string like  0.5.5-1.fc24
and read just first 3 digits split by '.'

Also remove one extra  $HAVE_REALTIME.
2015-09-03 23:34:36 +02:00
Bryn M. Reeves
49b5022993 dmstats: support --noheadings for histogram fields 2015-09-03 22:04:11 +01:00
Bryn M. Reeves
84d88cb2cf dmstats: add --notimesuffix switch
Add a switch to disable the printing of time unit suffixes in
histogram bounds descriptions.
2015-09-03 22:04:10 +01:00
Bryn M. Reeves
f09e4f7b10 libdm: allow formatting histogram strings with no whitespace
Allow dm_histogram_to_string() to format histogram strings with
no whitespace by passing a width value less than zero.
2015-09-03 22:04:10 +01:00
David Teigland
0a73a5012a vgrename: add missing trace on error path 2015-09-03 10:38:16 -05:00
David Teigland
96dc03b337 lockd: vgrename fixes
If busy locks in lvmlockd prevent vgrename, use the
correct error exit path, and print a user-friendly
error message.
2015-09-03 10:21:44 -05:00
Peter Rajnoha
d1d00fdeec dev-cache: append (major:minor) to debug messages about adding device or its alias to cache
device/dev-cache.c:350         /dev/sda: Added to device cache (8:0)
device/dev-cache.c:346         /dev/disk/by-id/lvm-pv-uuid-5nPovF-EWp4-vBwd-ylCJ-9Y0B-yzHQ-ek1li2: Aliased to /dev/sda in device cache (8:0)
...
2015-09-03 14:36:15 +02:00
Peter Rajnoha
00b610e542 filters: do not print [none:nil] as external device info's [source:handler] if "none" source is used
Print [source:handler] in filters' debug messages only if external
device info source other than "none" is used.

$ lvmconfig --type full devices/external_device_info_source
external_device_info_source="none

Before this patch (from the -vvvv log):

filters/filter-usable.c:47         /dev/mapper/test: Skipping: Too small to hold a PV [none:(nil)]
filters/filter-md.c:33         /dev/sdb: Skipping md component device [none:(nil)]
filters/filter-partitioned.c:25         /dev/vda: Skipping: Partition table signature found [none:(nil)]

With this patch applied:

filters/filter-usable.c:44         /dev/mapper/test: Skipping: Too small to hold a PV
filters/filter-md.c:35         /dev/sdb: Skipping md component device
filters/filter-partitioned.c:27         /dev/vda: Skipping: Partition table signature found
2015-09-03 14:19:48 +02:00
Peter Rajnoha
fc35b6988d libdm: pkgconfig: fix devmapper.pc to not reference nonexistent rt.pc file
librt doesn't have a pkgconfig file so use Libs.private: -lrt instead
to declare the dependency directly.

The same applies for -lm which is also used and which hasn't been
defined in the devmapper.pc file yet.
2015-09-03 09:28:42 +02:00
Bryn M. Reeves
b86bd3b074 man: fix typo in dmstats.8.in 2015-09-02 23:01:46 +01:00
374 changed files with 9552 additions and 5580 deletions

View File

@@ -131,6 +131,9 @@ rpm: dist
generate: conf.generate
$(MAKE) -C conf generate
all_man:
$(MAKE) -C man all_man
install_system_dirs:
$(INSTALL_DIR) $(DESTDIR)$(DEFAULT_SYS_DIR)
$(INSTALL_ROOT_DIR) $(DESTDIR)$(DEFAULT_ARCHIVE_DIR)
@@ -150,8 +153,8 @@ install_systemd_generators:
install_systemd_units:
$(MAKE) -C scripts install_systemd_units
install_full_man:
$(MAKE) -C man install_full_man
install_all_man:
$(MAKE) -C man install_all_man
ifeq ("@PYTHON_BINDINGS@", "yes")
install_python_bindings:
@@ -229,10 +232,9 @@ endif
ifneq ($(shell which ctags),)
.PHONY: tags
all: tags
tags:
test -z "$(shell find $(top_srcdir) -type f -name '*.[ch]' -newer tags | head -1)" || $(RM) tags
test -f tags || find $(top_srcdir) -maxdepth 4 -type f -name '*.[ch]' -exec ctags -a '{}' +
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 5 -type f -name '*.[ch]' -exec ctags -a '{}' +
DISTCLEAN_TARGETS += tags
CLEAN_TARGETS += tags
endif

View File

@@ -1 +1 @@
2.02.130(2)-git (2015-08-26)
2.02.133(2)-git (2015-10-30)

View File

@@ -1 +1 @@
1.02.107-git (2015-08-26)
1.02.110-git (2015-10-30)

View File

@@ -1,5 +1,66 @@
Version 2.02.130 -
===================================
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.
Remove verbose message when rescanning an unchanged device. (2.02.119)
Add origin_uuid, mirror_log_uuid, move_pv_uuid, convert_lv_uuid report fields.
Add pool_lv_uuid, metadata_lv_uuid, data_lv_uuid reporting fields.
Fix PV label processing failure after pvcreate in lvm shell with lvmetad.
Version 2.02.131 - 15th September 2015
======================================
Rename 'make install_full_man' to install_all_man and add all_man target.
Fix vgimportclone cache_dir path name (2.02.115).
Swapping of LV identifiers handles more complex LVs.
Use passed list of PVS when allocating space in lvconvert --thinpool.
Disallow usage of --stripe and --stripesize when creating cache pool.
Warn user when caching raid or thin pool data LV.
When layering LV, move LV flags with segments.
Ignore persistent cache if configuration changed. (2.02.127)
Fix devices/filter to be applied before disk-accessing filters. (2.02.112)
Make tags only when requested via 'make tags'.
Configure supports --disable-dependency-tracking for one-time builds.
Fix usage of configure.h when building in srcdir != builddir.
Version 2.02.130 - 5th September 2015
=====================================
Fix use of uninitialized device status if reading outdated .cache record.
Restore support for --monitor option in lvcreate (2.02.112).
Read thin-pool data and metadata percent without flush.
Detect blocked thin-pool and avoid scanning their thin volumes.
Check if dm device is usable before checking its size (2.02.116).
Extend parsing of cache_check version in configure.
Make lvpoll error messages visible in lvmpolld's stderr and in syslog.
Add 'make install_full_man' to install all man pages regardless of config.

View File

@@ -1,13 +1,62 @@
Version 1.02.107 -
===================================
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.
Improve help text for dmsetup.
Use --noflush and --nolockfs when removing device with --force.
Parse new Overflow status string for snapshot target.
Check dir path components are valid if using dm_create_dir, error out if not.
Fix /dev/mapper handling to remove dangling entries if symlinks are found.
Make it possible to use blank value as selection for string list report field.
Version 1.02.108 - 15th September 2015
======================================
Do not check for full thin pool when activating without messages (1.02.107).
Version 1.02.107 - 5th September 2015
=====================================
Parse thin-pool status with one single routine internally.
Add --histogram to select default histogram fields for list and report.
Add report fields for displaying latency histogram configuration and data.
Add dmstats --bounds to specify histogram boundaries for a new region.
Add dm_histogram_to_string() to format histogram data in string form.
Add public methods to libdm to access numerical histogram config and data.
Parse and store histogram data in dm_stats_list() and dm_stats_populate().
Add an argument to specify histogram bounds to dm_stats_create_region().
Add dm_histogram_bounds_from_{string,uint64_t}() to parse histogram bounds.
Add dm_histogram handle type to represent a latency histogram and its bounds.
Fix devmapper.pc pkgconfig file to not reference non-existent rt.pc file.
Reinstate dm_task_get_info@Base to libdevmapper exports. (1.02.106)
Version 1.02.106 - 26th August 2015
===================================
Add basic report fields for displaying latency histogram data.
Add dmstats --histogram to specify histogram boundaries for a region.
Add public methods to libdm-stats to access numerical histogram data.
Add the ability to parse histogram data into numeric form to libdm-stats.
Add 'precise' column to statistics reports.
Add --precise switch to 'dmstats create' to request nanosecond counters.
Add precise argument to dm_stats_create_region().

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

2
conf/.gitignore vendored
View File

@@ -2,3 +2,5 @@ command_profile_template.profile
example.conf
lvmlocal.conf
metadata_profile_template.profile
configure.h
lvm-version.h

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.

42
configure vendored
View File

@@ -643,6 +643,7 @@ LVMETAD_PIDFILE
DMEVENTD_PIDFILE
WRITE_INSTALL
VALGRIND_POOL
USE_TRACKING
UDEV_HAS_BUILTIN_BLKID
UDEV_RULE_EXEC_DETECTION
UDEV_SYSTEMD_BACKGROUND_JOBS
@@ -659,7 +660,7 @@ SELINUX_PC
SELINUX_LIBS
REPLICATORS
READLINE_LIBS
RT_PC
RT_LIB
RAID
PYTHON_LIBDIRS
PYTHON_INCDIRS
@@ -693,7 +694,6 @@ BLKDEACTIVATE
FSADM
ELDFLAGS
DM_LIB_PATCHLEVEL
DM_LIB_VERSION
DMEVENTD_PATH
DMEVENTD
DL_LIBS
@@ -876,6 +876,7 @@ SHELL'
ac_subst_files=''
ac_user_opts='
enable_option_checking
enable_dependency_tracking
enable_static_link
with_user
with_group
@@ -1634,6 +1635,8 @@ Optional Features:
--disable-option-checking ignore unrecognized --enable/--with options
--disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
--enable-FEATURE[=ARG] include FEATURE [ARG=yes]
--disable-dependency-tracking
speeds up one-time build.
--enable-static_link use this to link the tools to their libraries
statically (default is dynamic linking
--enable-lvm1_fallback use this to fall back and use LVM1 binaries if
@@ -2966,7 +2969,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
ac_config_headers="$ac_config_headers lib/misc/configure.h"
ac_config_headers="$ac_config_headers include/configure.h"
################################################################################
@@ -7632,6 +7635,19 @@ done
################################################################################
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable dependency tracking" >&5
$as_echo_n "checking whether to enable dependency tracking... " >&6; }
# Check whether --enable-dependency-tracking was given.
if test "${enable_dependency_tracking+set}" = set; then :
enableval=$enable_dependency_tracking; USE_TRACKING=$enableval
else
USE_TRACKING=yes
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_TRACKING" >&5
$as_echo "$USE_TRACKING" >&6; }
################################################################################
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use static linking" >&5
$as_echo_n "checking whether to use static linking... " >&6; }
@@ -8816,7 +8832,7 @@ $as_echo "$as_me: WARNING: cache_check not found in path $PATH" >&2;}
if test "$CACHE_CHECK_NEEDS_CHECK" = yes; then
$CACHE_CHECK_CMD -V 2>/dev/null >conftest.tmp
read -r CACHE_CHECK_VSN < conftest.tmp
IFS=. read -r CACHE_CHECK_VSN_MAJOR CACHE_CHECK_VSN_MINOR CACHE_CHECK_VSN_PATCH < conftest.tmp
IFS=.- read -r CACHE_CHECK_VSN_MAJOR CACHE_CHECK_VSN_MINOR CACHE_CHECK_VSN_PATCH LEFTOVER < conftest.tmp
rm -f conftest.tmp
# Require version >= 0.5.4 for --clear-needs-check-flag
@@ -12847,13 +12863,11 @@ fi
$as_echo "#define HAVE_REALTIME 1" >>confdefs.h
LIBS="-lrt $LIBS"
RT_PC="librt"
RT_LIB="-lrt"
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Disabling realtime clock" >&5
$as_echo "$as_me: WARNING: Disabling realtime clock" >&2;}
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $HAVE_REALTIME" >&5
$as_echo "$HAVE_REALTIME" >&6; }
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for struct stat has st_ctim." >&5
@@ -14028,18 +14042,18 @@ test "$interface" != ioctl && as_fn_error $? "--with-interface=ioctl required. f
$as_echo "$interface" >&6; }
################################################################################
DM_LIB_VERSION="\"`cat "$srcdir"/VERSION_DM 2>/dev/null || echo Unknown`\""
read DM_LIB_VERSION < "$srcdir"/VERSION_DM 2>/dev/null || DM_LIB_VERSION=Unknown
cat >>confdefs.h <<_ACEOF
#define DM_LIB_VERSION $DM_LIB_VERSION
#define DM_LIB_VERSION "$DM_LIB_VERSION"
_ACEOF
DM_LIB_PATCHLEVEL=`cat "$srcdir"/VERSION_DM | $AWK -F '[-. ]' '{printf "%s.%s.%s",$1,$2,$3}'`
LVM_VERSION="\"`cat "$srcdir"/VERSION 2>/dev/null || echo Unknown`\""
read VER < "$srcdir"/VERSION 2>/dev/null || VER=Unknown
VER=`cat "$srcdir"/VERSION`
LVM_VERSION=\"$VER\"
LVM_RELEASE_DATE="\"`echo $VER | $SED 's/.* (//;s/).*//'`\""
VER=`echo "$VER" | $AWK '{print $1}'`
LVM_RELEASE="\"`echo "$VER" | $AWK -F '-' '{print $2}'`\""
@@ -14198,7 +14212,7 @@ LVM_LIBAPI=`echo "$VER" | $AWK -F '[()]' '{print $2}'`
################################################################################
ac_config_files="$ac_config_files Makefile make.tmpl daemons/Makefile daemons/clvmd/Makefile daemons/cmirrord/Makefile daemons/dmeventd/Makefile daemons/dmeventd/libdevmapper-event.pc daemons/dmeventd/plugins/Makefile daemons/dmeventd/plugins/lvm2/Makefile daemons/dmeventd/plugins/raid/Makefile daemons/dmeventd/plugins/mirror/Makefile daemons/dmeventd/plugins/snapshot/Makefile daemons/dmeventd/plugins/thin/Makefile daemons/lvmetad/Makefile daemons/lvmpolld/Makefile daemons/lvmlockd/Makefile conf/Makefile conf/example.conf conf/lvmlocal.conf conf/command_profile_template.profile conf/metadata_profile_template.profile include/.symlinks include/Makefile lib/Makefile lib/format1/Makefile lib/format_pool/Makefile lib/locking/Makefile lib/mirror/Makefile lib/replicator/Makefile lib/misc/lvm-version.h lib/raid/Makefile lib/snapshot/Makefile lib/thin/Makefile lib/cache_segtype/Makefile libdaemon/Makefile libdaemon/client/Makefile libdaemon/server/Makefile libdm/Makefile libdm/libdevmapper.pc liblvm/Makefile liblvm/liblvm2app.pc man/Makefile po/Makefile python/Makefile python/setup.py scripts/blkdeactivate.sh scripts/blk_availability_init_red_hat scripts/blk_availability_systemd_red_hat.service scripts/clvmd_init_red_hat scripts/cmirrord_init_red_hat scripts/dm_event_systemd_red_hat.service scripts/dm_event_systemd_red_hat.socket scripts/lvm2_cluster_activation_red_hat.sh scripts/lvm2_cluster_activation_systemd_red_hat.service scripts/lvm2_clvmd_systemd_red_hat.service scripts/lvm2_cmirrord_systemd_red_hat.service scripts/lvm2_lvmetad_init_red_hat scripts/lvm2_lvmetad_systemd_red_hat.service scripts/lvm2_lvmetad_systemd_red_hat.socket scripts/lvm2_lvmpolld_init_red_hat scripts/lvm2_lvmpolld_systemd_red_hat.service scripts/lvm2_lvmpolld_systemd_red_hat.socket scripts/lvm2_lvmlockd_systemd_red_hat.service scripts/lvm2_lvmlocking_systemd_red_hat.service scripts/lvm2_monitoring_init_red_hat scripts/lvm2_monitoring_systemd_red_hat.service scripts/lvm2_pvscan_systemd_red_hat@.service scripts/lvm2_tmpfiles_red_hat.conf scripts/Makefile test/Makefile test/api/Makefile test/unit/Makefile tools/Makefile udev/Makefile unit-tests/datastruct/Makefile unit-tests/regex/Makefile unit-tests/mm/Makefile"
ac_config_files="$ac_config_files Makefile make.tmpl daemons/Makefile daemons/clvmd/Makefile daemons/cmirrord/Makefile daemons/dmeventd/Makefile daemons/dmeventd/libdevmapper-event.pc daemons/dmeventd/plugins/Makefile daemons/dmeventd/plugins/lvm2/Makefile daemons/dmeventd/plugins/raid/Makefile daemons/dmeventd/plugins/mirror/Makefile daemons/dmeventd/plugins/snapshot/Makefile daemons/dmeventd/plugins/thin/Makefile daemons/lvmetad/Makefile daemons/lvmpolld/Makefile daemons/lvmlockd/Makefile conf/Makefile conf/example.conf conf/lvmlocal.conf conf/command_profile_template.profile conf/metadata_profile_template.profile include/.symlinks include/Makefile lib/Makefile lib/format1/Makefile lib/format_pool/Makefile lib/locking/Makefile lib/mirror/Makefile lib/replicator/Makefile include/lvm-version.h lib/raid/Makefile lib/snapshot/Makefile lib/thin/Makefile lib/cache_segtype/Makefile libdaemon/Makefile libdaemon/client/Makefile libdaemon/server/Makefile libdm/Makefile libdm/libdevmapper.pc liblvm/Makefile liblvm/liblvm2app.pc man/Makefile po/Makefile python/Makefile python/setup.py scripts/blkdeactivate.sh scripts/blk_availability_init_red_hat scripts/blk_availability_systemd_red_hat.service scripts/clvmd_init_red_hat scripts/cmirrord_init_red_hat scripts/dm_event_systemd_red_hat.service scripts/dm_event_systemd_red_hat.socket scripts/lvm2_cluster_activation_red_hat.sh scripts/lvm2_cluster_activation_systemd_red_hat.service scripts/lvm2_clvmd_systemd_red_hat.service scripts/lvm2_cmirrord_systemd_red_hat.service scripts/lvm2_lvmetad_init_red_hat scripts/lvm2_lvmetad_systemd_red_hat.service scripts/lvm2_lvmetad_systemd_red_hat.socket scripts/lvm2_lvmpolld_init_red_hat scripts/lvm2_lvmpolld_systemd_red_hat.service scripts/lvm2_lvmpolld_systemd_red_hat.socket scripts/lvm2_lvmlockd_systemd_red_hat.service scripts/lvm2_lvmlocking_systemd_red_hat.service scripts/lvm2_monitoring_init_red_hat scripts/lvm2_monitoring_systemd_red_hat.service scripts/lvm2_pvscan_systemd_red_hat@.service scripts/lvm2_tmpfiles_red_hat.conf scripts/Makefile test/Makefile test/api/Makefile test/unit/Makefile tools/Makefile udev/Makefile unit-tests/datastruct/Makefile unit-tests/regex/Makefile unit-tests/mm/Makefile"
cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
@@ -14892,7 +14906,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
for ac_config_target in $ac_config_targets
do
case $ac_config_target in
"lib/misc/configure.h") CONFIG_HEADERS="$CONFIG_HEADERS lib/misc/configure.h" ;;
"include/configure.h") CONFIG_HEADERS="$CONFIG_HEADERS include/configure.h" ;;
"Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
"make.tmpl") CONFIG_FILES="$CONFIG_FILES make.tmpl" ;;
"daemons/Makefile") CONFIG_FILES="$CONFIG_FILES daemons/Makefile" ;;
@@ -14922,7 +14936,7 @@ do
"lib/locking/Makefile") CONFIG_FILES="$CONFIG_FILES lib/locking/Makefile" ;;
"lib/mirror/Makefile") CONFIG_FILES="$CONFIG_FILES lib/mirror/Makefile" ;;
"lib/replicator/Makefile") CONFIG_FILES="$CONFIG_FILES lib/replicator/Makefile" ;;
"lib/misc/lvm-version.h") CONFIG_FILES="$CONFIG_FILES lib/misc/lvm-version.h" ;;
"include/lvm-version.h") CONFIG_FILES="$CONFIG_FILES include/lvm-version.h" ;;
"lib/raid/Makefile") CONFIG_FILES="$CONFIG_FILES lib/raid/Makefile" ;;
"lib/snapshot/Makefile") CONFIG_FILES="$CONFIG_FILES lib/snapshot/Makefile" ;;
"lib/thin/Makefile") CONFIG_FILES="$CONFIG_FILES lib/thin/Makefile" ;;

View File

@@ -16,7 +16,7 @@ AC_PREREQ(2.61)
dnl -- Process this file with autoconf to produce a configure script.
AC_INIT
AC_CONFIG_SRCDIR([lib/device/dev-cache.h])
AC_CONFIG_HEADERS([lib/misc/configure.h])
AC_CONFIG_HEADERS([include/configure.h])
################################################################################
dnl -- Setup the directory where autoconf has auxilary files
@@ -155,6 +155,15 @@ AC_FUNC_STAT
AC_FUNC_STRTOD
AC_FUNC_VPRINTF
################################################################################
dnl -- Disable dependency tracking
AC_MSG_CHECKING(whether to enable dependency tracking)
AC_ARG_ENABLE(dependency-tracking,
AC_HELP_STRING([--disable-dependency-tracking],
[speeds up one-time build.]),
USE_TRACKING=$enableval, USE_TRACKING=yes)
AC_MSG_RESULT($USE_TRACKING)
################################################################################
dnl -- Enables statically-linked tools
AC_MSG_CHECKING(whether to use static linking)
@@ -586,7 +595,7 @@ case "$CACHE" in
if test "$CACHE_CHECK_NEEDS_CHECK" = yes; then
$CACHE_CHECK_CMD -V 2>/dev/null >conftest.tmp
read -r CACHE_CHECK_VSN < conftest.tmp
IFS=. read -r CACHE_CHECK_VSN_MAJOR CACHE_CHECK_VSN_MINOR CACHE_CHECK_VSN_PATCH < conftest.tmp
IFS=.- read -r CACHE_CHECK_VSN_MAJOR CACHE_CHECK_VSN_MINOR CACHE_CHECK_VSN_PATCH LEFTOVER < conftest.tmp
rm -f conftest.tmp
# Require version >= 0.5.4 for --clear-needs-check-flag
@@ -1581,11 +1590,10 @@ if test "$REALTIME" = yes; then
if test "$HAVE_REALTIME" = yes; then
AC_DEFINE([HAVE_REALTIME], 1, [Define to 1 to include support for realtime clock.])
LIBS="-lrt $LIBS"
RT_PC="librt"
RT_LIB="-lrt"
else
AC_MSG_WARN(Disabling realtime clock)
fi
AC_MSG_RESULT($HAVE_REALTIME)
fi
dnl Check if the system has struct stat st_ctim.
@@ -1880,14 +1888,14 @@ test "$interface" != ioctl && AC_MSG_ERROR([--with-interface=ioctl required. fs
AC_MSG_RESULT($interface)
################################################################################
DM_LIB_VERSION="\"`cat "$srcdir"/VERSION_DM 2>/dev/null || echo Unknown`\""
AC_DEFINE_UNQUOTED(DM_LIB_VERSION, $DM_LIB_VERSION, [Library version])
read DM_LIB_VERSION < "$srcdir"/VERSION_DM 2>/dev/null || DM_LIB_VERSION=Unknown
AC_DEFINE_UNQUOTED(DM_LIB_VERSION, "$DM_LIB_VERSION", [Library version])
DM_LIB_PATCHLEVEL=`cat "$srcdir"/VERSION_DM | $AWK -F '[[-. ]]' '{printf "%s.%s.%s",$1,$2,$3}'`
LVM_VERSION="\"`cat "$srcdir"/VERSION 2>/dev/null || echo Unknown`\""
read VER < "$srcdir"/VERSION 2>/dev/null || VER=Unknown
VER=`cat "$srcdir"/VERSION`
LVM_VERSION=\"$VER\"
LVM_RELEASE_DATE="\"`echo $VER | $SED 's/.* (//;s/).*//'`\""
VER=`echo "$VER" | $AWK '{print $1}'`
LVM_RELEASE="\"`echo "$VER" | $AWK -F '-' '{print $2}'`\""
@@ -1955,7 +1963,6 @@ AC_SUBST(DLM_LIBS)
AC_SUBST(DL_LIBS)
AC_SUBST(DMEVENTD)
AC_SUBST(DMEVENTD_PATH)
AC_SUBST(DM_LIB_VERSION)
AC_SUBST(DM_LIB_PATCHLEVEL)
AC_SUBST(ELDFLAGS)
AC_SUBST(FSADM)
@@ -1995,7 +2002,7 @@ AC_SUBST(PYTHON_LIBDIRS)
AC_SUBST(QUORUM_CFLAGS)
AC_SUBST(QUORUM_LIBS)
AC_SUBST(RAID)
AC_SUBST(RT_PC)
AC_SUBST(RT_LIB)
AC_SUBST(READLINE_LIBS)
AC_SUBST(REPLICATORS)
AC_SUBST(SACKPT_CFLAGS)
@@ -2024,6 +2031,7 @@ AC_SUBST(UDEV_SYNC)
AC_SUBST(UDEV_SYSTEMD_BACKGROUND_JOBS)
AC_SUBST(UDEV_RULE_EXEC_DETECTION)
AC_SUBST(UDEV_HAS_BUILTIN_BLKID)
AC_SUBST(USE_TRACKING)
AC_SUBST(VALGRIND_POOL)
AC_SUBST(WRITE_INSTALL)
AC_SUBST(DMEVENTD_PIDFILE)
@@ -2078,7 +2086,7 @@ lib/format_pool/Makefile
lib/locking/Makefile
lib/mirror/Makefile
lib/replicator/Makefile
lib/misc/lvm-version.h
include/lvm-version.h
lib/raid/Makefile
lib/snapshot/Makefile
lib/thin/Makefile

View File

@@ -154,7 +154,7 @@ static void usage(const char *prog, FILE *file)
{
fprintf(file, "Usage: %s [options]\n"
" -C Sets debug level (from -d) on all clvmd instances clusterwide\n"
" -d[n] Set debug logging (0:none, 1:stderr (implies -f option), 2:syslog)\n"
" -d[<n>] Set debug logging (0:none, 1:stderr (implies -f option), 2:syslog)\n"
" -E<uuid> Take this lock uuid as exclusively locked resource (for restart)\n"
" -f Don't fork, run in the foreground\n"
" -h Show this help information\n"

View File

@@ -1445,7 +1445,7 @@ static int disk_status_info(struct log_c *lc, struct dm_ulog_request *rq)
char *data = (char *)rq->data;
struct stat statbuf;
if(fstat(lc->disk_fd, &statbuf)) {
if (fstat(lc->disk_fd, &statbuf)) {
rq->error = -errno;
return -errno;
}
@@ -1508,7 +1508,7 @@ static int disk_status_table(struct log_c *lc, struct dm_ulog_request *rq)
char *data = (char *)rq->data;
struct stat statbuf;
if(fstat(lc->disk_fd, &statbuf)) {
if (fstat(lc->disk_fd, &statbuf)) {
rq->error = -errno;
return -errno;
}

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);
@@ -94,24 +61,26 @@ int dmeventd_lvm2_init(void)
pthread_mutex_lock(&_register_mutex);
/*
* Need some space for allocations. 1024 should be more
* than enough for what we need (device mapper name splitting)
*/
if (!_mem_pool && !(_mem_pool = dm_pool_create("mirror_dso", 1024)))
goto out;
if (!_lvm_handle) {
if (!getenv("LVM_LOG_FILE_EPOCH"))
lvm2_log_fn(_temporary_log_fn);
if (!(_lvm_handle = lvm2_init())) {
dm_pool_destroy(_mem_pool);
_mem_pool = NULL;
lvm2_log_fn(_lvm2_print_log);
if (!(_lvm_handle = lvm2_init()))
goto out;
/*
* Need some space for allocations. 1024 should be more
* than enough for what we need (device mapper name splitting)
*/
if (!_mem_pool && !(_mem_pool = dm_pool_create("mirror_dso", 1024))) {
lvm2_exit(_lvm_handle);
_lvm_handle = NULL;
goto out;
}
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++;
@@ -127,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);
@@ -154,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;
}
@@ -169,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

@@ -45,6 +45,8 @@ lvmetactl: lvmetactl.o $(top_builddir)/libdaemon/client/libdaemonclient.a \
$(top_builddir)/libdaemon/server/libdaemonserver.a
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ lvmetactl.o $(LVMLIBS)
CLEAN_TARGETS += lvmetactl.o
# TODO: No idea. No idea how to test either.
#ifneq ("$(CFLOW_CMD)", "")
#CFLOW_SOURCES = $(addprefix $(srcdir)/, $(SOURCES))

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;
@@ -578,7 +580,7 @@ static void mark_outdated_pv(lvmetad_state *s, const char *vgid, const char *pvi
!(cft_vgid = make_text_node(outdated_pvs, "vgid", dm_pool_strdup(outdated_pvs->mem, vgid),
outdated_pvs->root, NULL)))
abort();
if(!dm_hash_insert(s->vgid_to_outdated_pvs, cft_vgid->v->v.str, outdated_pvs))
if (!dm_hash_insert(s->vgid_to_outdated_pvs, cft_vgid->v->v.str, outdated_pvs))
abort();
DEBUGLOG(s, "created outdated_pvs list for VG %s", vgid);
}
@@ -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

@@ -599,14 +599,14 @@ static void print_usage(void)
printf(" Wait option for other commands.\n");
printf("--force | -f 0|1>\n");
printf(" Force option for other commands.\n");
printf("--kill | -k <vg_name>\n");
printf(" Kill access to the vg when sanlock cannot renew lease.\n");
printf("--drop | -r <vg_name>\n");
printf(" Clear locks for the vg after it has been killed and is no longer used.\n");
printf("--gl-enable <vg_name>\n");
printf(" Tell lvmlockd to enable the global lock in a sanlock vg.\n");
printf("--gl-disable <vg_name>\n");
printf(" Tell lvmlockd to disable the global lock in a sanlock vg.\n");
printf("--kill | -k <vgname>\n");
printf(" Kill access to the VG when sanlock cannot renew lease.\n");
printf("--drop | -r <vgname>\n");
printf(" Clear locks for the VG when it is unused after kill (-k).\n");
printf("--gl-enable | -E <vgname>\n");
printf(" Tell lvmlockd to enable the global lock in a sanlock VG.\n");
printf("--gl-disable | -D <vgname>\n");
printf(" Tell lvmlockd to disable the global lock in a sanlock VG.\n");
printf("--stop-lockspaces | -S\n");
printf(" Stop all lockspaces.\n");
}
@@ -731,11 +731,13 @@ int main(int argc, char **argv)
}
if (gl_enable) {
syslog(LOG_INFO, "Enabling global lock in VG %s.", arg_vg_name);
rv = do_able("enable_gl");
goto out;
}
if (gl_disable) {
syslog(LOG_INFO, "Disabling global lock in VG %s.", arg_vg_name);
rv = do_able("disable_gl");
goto out;
}

File diff suppressed because it is too large Load Diff

View File

@@ -343,7 +343,7 @@ static int to_dlm_mode(int ld_mode)
}
static int lm_adopt_dlm(struct lockspace *ls, struct resource *r, int ld_mode,
uint32_t *r_version)
struct val_blk *vb_out)
{
struct lm_dlm *lmd = (struct lm_dlm *)ls->lm_data;
struct rd_dlm *rdd = (struct rd_dlm *)r->lm_data;
@@ -352,7 +352,7 @@ static int lm_adopt_dlm(struct lockspace *ls, struct resource *r, int ld_mode,
int mode;
int rv;
*r_version = 0;
memset(vb_out, 0, sizeof(struct val_blk));
if (!r->lm_init) {
rv = lm_add_resource_dlm(ls, r, 0);
@@ -431,15 +431,13 @@ static int lm_adopt_dlm(struct lockspace *ls, struct resource *r, int ld_mode,
*/
int lm_lock_dlm(struct lockspace *ls, struct resource *r, int ld_mode,
uint32_t *r_version, int adopt)
struct val_blk *vb_out, int adopt)
{
struct lm_dlm *lmd = (struct lm_dlm *)ls->lm_data;
struct rd_dlm *rdd = (struct rd_dlm *)r->lm_data;
struct dlm_lksb *lksb;
struct val_blk vb;
uint32_t flags = 0;
uint16_t vb_version;
uint16_t vb_flags;
int mode;
int rv;
@@ -447,7 +445,7 @@ int lm_lock_dlm(struct lockspace *ls, struct resource *r, int ld_mode,
/* When adopting, we don't follow the normal method
of acquiring a NL lock then converting it to the
desired mode. */
return lm_adopt_dlm(ls, r, ld_mode, r_version);
return lm_adopt_dlm(ls, r, ld_mode, vb_out);
}
if (!r->lm_init) {
@@ -475,7 +473,7 @@ int lm_lock_dlm(struct lockspace *ls, struct resource *r, int ld_mode,
log_debug("S %s R %s lock_dlm", ls->name, r->name);
if (daemon_test) {
*r_version = 0;
memset(vb_out, 0, sizeof(struct val_blk));
return 0;
}
@@ -513,35 +511,22 @@ lockrv:
if (lksb->sb_flags & DLM_SBF_VALNOTVALID) {
log_debug("S %s R %s lock_dlm VALNOTVALID", ls->name, r->name);
memset(rdd->vb, 0, sizeof(struct val_blk));
*r_version = 0;
memset(vb_out, 0, sizeof(struct val_blk));
goto out;
}
/*
* 'vb' contains disk endian values, not host endian.
* It is copied directly to rdd->vb which is also kept
* in disk endian form.
* vb_out is returned to the caller in host endian form.
*/
memcpy(&vb, lksb->sb_lvbptr, sizeof(struct val_blk));
vb_version = le16_to_cpu(vb.version);
vb_flags = le16_to_cpu(vb.flags);
memcpy(rdd->vb, &vb, sizeof(vb));
if (vb_version && ((vb_version & 0xFF00) > (VAL_BLK_VERSION & 0xFF00))) {
log_error("S %s R %s lock_dlm ignore vb_version %x",
ls->name, r->name, vb_version);
*r_version = 0;
free(rdd->vb);
rdd->vb = NULL;
lksb->sb_lvbptr = NULL;
goto out;
}
*r_version = le32_to_cpu(vb.r_version);
memcpy(rdd->vb, &vb, sizeof(vb)); /* rdd->vb saved as le */
log_debug("S %s R %s lock_dlm get r_version %u flags %x",
ls->name, r->name, *r_version, vb_flags);
if (vb_flags & VBF_REMOVED) {
log_debug("S %s R %s lock_dlm VG has been removed",
ls->name, r->name);
return -EREMOVED;
}
vb_out->version = le16_to_cpu(vb.version);
vb_out->flags = le16_to_cpu(vb.flags);
vb_out->r_version = le32_to_cpu(vb.r_version);
}
out:
return 0;
@@ -602,12 +587,12 @@ int lm_unlock_dlm(struct lockspace *ls, struct resource *r,
struct lm_dlm *lmd = (struct lm_dlm *)ls->lm_data;
struct rd_dlm *rdd = (struct rd_dlm *)r->lm_data;
struct dlm_lksb *lksb = &rdd->lksb;
struct val_blk vb_prev;
struct val_blk vb_next;
uint32_t flags = 0;
int new_vb = 0;
int rv;
log_debug("S %s R %s unlock_dlm r_version %u flags %x",
ls->name, r->name, r_version, lmu_flags);
/*
* Do not set PERSISTENT, because we don't need an orphan
* NL lock to protect anything.
@@ -616,22 +601,45 @@ int lm_unlock_dlm(struct lockspace *ls, struct resource *r,
flags |= LKF_CONVERT;
if (rdd->vb && (r->mode == LD_LK_EX)) {
if (!rdd->vb->version) {
/* first time vb has been written */
rdd->vb->version = cpu_to_le16(VAL_BLK_VERSION);
/* vb_prev and vb_next are in disk endian form */
memcpy(&vb_prev, rdd->vb, sizeof(struct val_blk));
memcpy(&vb_next, rdd->vb, sizeof(struct val_blk));
if (!vb_prev.version) {
vb_next.version = cpu_to_le16(VAL_BLK_VERSION);
new_vb = 1;
}
if (r_version)
rdd->vb->r_version = cpu_to_le32(r_version);
if ((lmu_flags & LMUF_FREE_VG) && (r->type == LD_RT_VG))
rdd->vb->flags = cpu_to_le16(VBF_REMOVED);
if ((lmu_flags & LMUF_FREE_VG) && (r->type == LD_RT_VG)) {
vb_next.flags = cpu_to_le16(VBF_REMOVED);
new_vb = 1;
}
memcpy(lksb->sb_lvbptr, rdd->vb, sizeof(struct val_blk));
if (r_version) {
vb_next.r_version = cpu_to_le32(r_version);
new_vb = 1;
}
log_debug("S %s R %s unlock_dlm set r_version %u",
ls->name, r->name, r_version);
if (new_vb) {
memcpy(rdd->vb, &vb_next, sizeof(struct val_blk));
memcpy(lksb->sb_lvbptr, &vb_next, sizeof(struct val_blk));
log_debug("S %s R %s unlock_dlm vb old %x %x %u new %x %x %u",
ls->name, r->name,
le16_to_cpu(vb_prev.version),
le16_to_cpu(vb_prev.flags),
le32_to_cpu(vb_prev.r_version),
le16_to_cpu(vb_next.version),
le16_to_cpu(vb_next.flags),
le32_to_cpu(vb_next.r_version));
} else {
log_debug("S %s R %s unlock_dlm vb unchanged", ls->name, r->name);
}
flags |= LKF_VALBLK;
} else {
log_debug("S %s R %s unlock_dlm", ls->name, r->name);
}
if (daemon_test)
@@ -654,6 +662,62 @@ int lm_unlock_dlm(struct lockspace *ls, struct resource *r,
#define DLM_LOCKSPACES_PATH "/sys/kernel/config/dlm/cluster/spaces"
/*
* FIXME: this should be implemented differently.
* It's not nice to use an aspect of the dlm clustering
* implementation, which could change. It would be
* better to do something like use a special lock in the
* lockspace that was held PR by all nodes, and then an
* EX request on it could check if it's started (and
* possibly also notify others to stop it automatically).
* Or, possibly an enhancement to libdlm that would give
* info about lockspace members.
*
* (We could let the VG be removed while others still
* have the lockspace running, which largely works, but
* introduces problems if another VG with the same name is
* recreated while others still have the lockspace running
* for the previous VG. We'd also want a way to clean up
* the stale lockspaces on the others eventually.)
*/
int lm_hosts_dlm(struct lockspace *ls, int notify)
{
static const char closedir_err_msg[] = "lm_hosts_dlm: closedir failed";
char ls_nodes_path[PATH_MAX];
struct dirent *de;
DIR *ls_dir;
int count = 0;
memset(ls_nodes_path, 0, sizeof(ls_nodes_path));
snprintf(ls_nodes_path, PATH_MAX-1, "%s/%s/nodes",
DLM_LOCKSPACES_PATH, ls->name);
if (!(ls_dir = opendir(ls_nodes_path)))
return -ECONNREFUSED;
while ((de = readdir(ls_dir))) {
if (de->d_name[0] == '.')
continue;
count++;
}
if (closedir(ls_dir))
log_error(closedir_err_msg);
if (!count) {
log_error("lm_hosts_dlm found no nodes in %s", ls_nodes_path);
return 0;
}
/*
* Assume that a count of one node represents ourself,
* and any value over one represents other nodes.
*/
return count - 1;
}
int lm_get_lockspaces_dlm(struct list_head *ls_rejoin)
{
static const char closedir_err_msg[] = "lm_get_lockspace_dlm: closedir failed";
@@ -700,3 +764,4 @@ int lm_is_running_dlm(void)
return 0;
return 1;
}

View File

@@ -52,6 +52,7 @@ enum {
LD_OP_FIND_FREE_LOCK,
LD_OP_KILL_VG,
LD_OP_DROP_VG,
LD_OP_BUSY,
};
/* resource types */
@@ -89,7 +90,7 @@ struct client {
};
#define LD_AF_PERSISTENT 0x00000001
#define LD_AF_UNUSED 0x00000002 /* use me */
#define LD_AF_NO_CLIENT 0x00000002
#define LD_AF_UNLOCK_CANCEL 0x00000004
#define LD_AF_NEXT_VERSION 0x00000008
#define LD_AF_WAIT 0x00000010
@@ -102,6 +103,8 @@ struct client {
#define LD_AF_DUP_GL_LS 0x00002000
#define LD_AF_ADOPT 0x00010000
#define LD_AF_WARN_GL_REMOVED 0x00020000
#define LD_AF_LV_LOCK 0x00040000
#define LD_AF_LV_UNLOCK 0x00080000
/*
* Number of times to repeat a lock request after
@@ -140,12 +143,13 @@ struct resource {
int8_t mode;
unsigned int sh_count; /* number of sh locks on locks list */
uint32_t version;
uint32_t last_client_id; /* last client_id to lock or unlock resource */
unsigned int lm_init : 1; /* lm_data is initialized */
unsigned int adopt : 1; /* temp flag in remove_inactive_lvs */
unsigned int version_zero_valid : 1;
unsigned int use_vb : 1;
struct list_head locks;
struct list_head actions;
struct val_blk *vb;
char lv_args[MAX_ARGS+1];
char lm_data[0]; /* lock manager specific data */
};
@@ -313,14 +317,12 @@ static inline int list_empty(const struct list_head *head)
* or when disable_gl matches.
*/
EXTERN int dlm_gl_lockspace_running;
EXTERN int gl_type_static;
EXTERN int gl_use_dlm;
EXTERN int gl_use_sanlock;
EXTERN pthread_mutex_t gl_type_mutex;
EXTERN char gl_lsname_dlm[MAX_NAME+1];
EXTERN char gl_lsname_sanlock[MAX_NAME+1];
EXTERN int global_dlm_lockspace_exists;
EXTERN int daemon_test; /* run as much as possible without a live lock manager */
EXTERN int daemon_debug;
@@ -357,7 +359,7 @@ int lm_prepare_lockspace_dlm(struct lockspace *ls);
int lm_add_lockspace_dlm(struct lockspace *ls, int adopt);
int lm_rem_lockspace_dlm(struct lockspace *ls, int free_vg);
int lm_lock_dlm(struct lockspace *ls, struct resource *r, int ld_mode,
uint32_t *r_version, int adopt);
struct val_blk *vb_out, int adopt);
int lm_convert_dlm(struct lockspace *ls, struct resource *r,
int ld_mode, uint32_t r_version);
int lm_unlock_dlm(struct lockspace *ls, struct resource *r,
@@ -366,6 +368,7 @@ int lm_rem_resource_dlm(struct lockspace *ls, struct resource *r);
int lm_get_lockspaces_dlm(struct list_head *ls_rejoin);
int lm_data_size_dlm(void);
int lm_is_running_dlm(void);
int lm_hosts_dlm(struct lockspace *ls, int notify);
static inline int lm_support_dlm(void)
{
@@ -395,7 +398,7 @@ static inline int lm_rem_lockspace_dlm(struct lockspace *ls, int free_vg)
}
static inline int lm_lock_dlm(struct lockspace *ls, struct resource *r, int ld_mode,
uint32_t *r_version, int adopt)
struct val_blk *vb_out, int adopt)
{
return -1;
}
@@ -437,6 +440,11 @@ static inline int lm_support_dlm(void)
return 0;
}
static inline int lm_hosts_dlm(struct lockspace *ls, int notify)
{
return 0;
}
#endif /* dlm support */
#ifdef LOCKDSANLOCK_SUPPORT
@@ -449,7 +457,7 @@ int lm_prepare_lockspace_sanlock(struct lockspace *ls);
int lm_add_lockspace_sanlock(struct lockspace *ls, int adopt);
int lm_rem_lockspace_sanlock(struct lockspace *ls, int free_vg);
int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode,
uint32_t *r_version, int *retry, int adopt);
struct val_blk *vb_out, int *retry, int adopt);
int lm_convert_sanlock(struct lockspace *ls, struct resource *r,
int ld_mode, uint32_t r_version);
int lm_unlock_sanlock(struct lockspace *ls, struct resource *r,
@@ -507,7 +515,7 @@ static inline int lm_rem_lockspace_sanlock(struct lockspace *ls, int free_vg)
}
static inline int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode,
uint32_t *r_version, int *retry, int adopt)
struct val_blk *vb_out, int *retry, int adopt)
{
return -1;
}

View File

@@ -1300,7 +1300,7 @@ int lm_rem_resource_sanlock(struct lockspace *ls, struct resource *r)
}
int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode,
uint32_t *r_version, int *retry, int adopt)
struct val_blk *vb_out, int *retry, int adopt)
{
struct lm_sanlock *lms = (struct lm_sanlock *)ls->lm_data;
struct rd_sanlock *rds = (struct rd_sanlock *)r->lm_data;
@@ -1308,7 +1308,6 @@ int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode,
uint64_t lock_lv_offset;
uint32_t flags = 0;
struct val_blk vb;
uint16_t vb_version;
int added = 0;
int rv;
@@ -1384,7 +1383,7 @@ int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode,
(unsigned long long)rs->disks[0].offset);
if (daemon_test) {
*r_version = 0;
memset(vb_out, 0, sizeof(struct val_blk));
return 0;
}
@@ -1393,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) {
@@ -1463,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);
@@ -1501,26 +1529,23 @@ int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode,
rv = sanlock_get_lvb(0, rs, (char *)&vb, sizeof(vb));
if (rv < 0) {
log_error("S %s R %s lock_san get_lvb error %d", ls->name, r->name, rv);
*r_version = 0;
memset(rds->vb, 0, sizeof(struct val_blk));
memset(vb_out, 0, sizeof(struct val_blk));
goto out;
}
vb_version = le16_to_cpu(vb.version);
/*
* 'vb' contains disk endian values, not host endian.
* It is copied directly to rrs->vb which is also kept
* in disk endian form.
* vb_out is returned to the caller in host endian form.
*/
if (vb_version && ((vb_version & 0xFF00) > (VAL_BLK_VERSION & 0xFF00))) {
log_error("S %s R %s lock_san ignore vb_version %x",
ls->name, r->name, vb_version);
*r_version = 0;
free(rds->vb);
rds->vb = NULL;
goto out;
}
memcpy(rds->vb, &vb, sizeof(vb));
*r_version = le32_to_cpu(vb.r_version);
memcpy(rds->vb, &vb, sizeof(vb)); /* rds->vb saved as le */
log_debug("S %s R %s lock_san get r_version %u",
ls->name, r->name, *r_version);
vb_out->version = le16_to_cpu(vb.version);
vb_out->flags = le16_to_cpu(vb.flags);
vb_out->r_version = le32_to_cpu(vb.r_version);
}
out:
return rv;

View File

@@ -45,7 +45,6 @@
@top_srcdir@/lib/metadata/vg.h
@top_srcdir@/lib/mm/memlock.h
@top_srcdir@/lib/mm/xlate.h
@top_builddir@/lib/misc/configure.h
@top_srcdir@/lib/misc/crc.h
@top_srcdir@/lib/misc/intl.h
@top_srcdir@/lib/misc/last-path-component.h
@@ -56,7 +55,6 @@
@top_srcdir@/lib/misc/lvm-globals.h
@top_srcdir@/lib/misc/lvm-signal.h
@top_srcdir@/lib/misc/lvm-string.h
@top_builddir@/lib/misc/lvm-version.h
@top_srcdir@/lib/misc/lvm-percent.h
@top_srcdir@/lib/misc/lvm-wrappers.h
@top_srcdir@/lib/misc/sharedlib.h

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.
#
@@ -35,5 +35,5 @@ device-mapper: all
cflow: all
DISTCLEAN_TARGETS += .symlinks
DISTCLEAN_TARGETS += .symlinks configure.h lvm-version.h
CLEAN_TARGETS += $(LINKS) .include_symlinks .symlinks_created

View File

@@ -1,4 +1,4 @@
/* lib/misc/configure.h.in. Generated from configure.in by autoheader. */
/* include/configure.h.in. Generated from configure.in by autoheader. */
/* Define to 1 to use libblkid detection of signatures when wiping. */
#undef BLKID_WIPING_SUPPORT

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 \
@@ -230,4 +231,4 @@ CFLAGS += $(BLKID_CFLAGS) $(UDEV_CFLAGS) $(VALGRIND_CFLAGS)
$(SUBDIRS): $(LIB_STATIC)
DISTCLEAN_TARGETS += misc/configure.h misc/lvm-version.h
CLEAN_TARGETS += misc/configure.h misc/lvm-version.h

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;
@@ -518,6 +518,73 @@ out:
return r;
}
static int _ignore_unusable_thins(struct device *dev)
{
/* TODO make function for thin testing */
struct dm_pool *mem;
struct dm_status_thin_pool *status;
struct dm_task *dmt = NULL;
void *next = NULL;
uint64_t start, length;
char *target_type = NULL;
char *params;
int minor, major;
int r = 0;
if (!(mem = dm_pool_create("unusable_thins", 128)))
return_0;
if (!(dmt = dm_task_create(DM_DEVICE_TABLE)))
goto_out;
if (!dm_task_no_open_count(dmt))
goto_out;
if (!dm_task_set_major_minor(dmt, MAJOR(dev->dev), MINOR(dev->dev), 1))
goto_out;
if (!dm_task_run(dmt)) {
log_error("Failed to get state of mapped device.");
goto out;
}
dm_get_next_target(dmt, next, &start, &length, &target_type, &params);
if (sscanf(params, "%d:%d", &minor, &major) != 2) {
log_error("Failed to get thin-pool major:minor for thin device %d:%d.",
(int)MAJOR(dev->dev), (int)MINOR(dev->dev));
goto out;
}
dm_task_destroy(dmt);
if (!(dmt = dm_task_create(DM_DEVICE_STATUS)))
goto_out;
if (!dm_task_no_flush(dmt))
log_warn("Can't set no_flush.");
if (!dm_task_no_open_count(dmt))
goto_out;
if (!dm_task_set_major_minor(dmt, minor, major, 1))
goto_out;
if (!dm_task_run(dmt)) {
log_error("Failed to get state of mapped device.");
goto out;
}
dm_get_next_target(dmt, next, &start, &length, &target_type, &params);
if (!dm_get_status_thin_pool(mem, params, &status))
return_0;
if (status->read_only || status->out_of_data_space) {
log_warn("WARNING: %s: Thin's thin-pool needs inspection.",
dev_name(dev));
goto out;
}
r = 1;
out:
if (dmt)
dm_task_destroy(dmt);
dm_pool_destroy(mem);
return r;
}
/*
* device_is_usable
* @dev
@@ -646,6 +713,13 @@ int device_is_usable(struct device *dev, struct dev_usable_check_params check)
goto out;
}
/* TODO: extend check struct ? */
if (target_type && !strcmp(target_type, "thin") &&
!_ignore_unusable_thins(dev)) {
log_debug_activation("%s: %s device %s not usable.", dev_name(dev), target_type, name);
goto out;
}
if (target_type && strcmp(target_type, "error"))
only_error_target = 0;
} while (next);
@@ -971,6 +1045,11 @@ static int _percent_run(struct dev_manager *dm, const char *name,
wait ? DM_DEVICE_WAITEVENT : DM_DEVICE_STATUS, 0, 0, 0)))
return_0;
/* No freeze on overfilled thin-pool, read existing slightly outdated data */
if (lv && lv_is_thin_pool(lv) &&
!dm_task_no_flush(dmt))
log_warn("Can't set no_flush flag."); /* Non fatal */
if (!dm_task_run(dmt))
goto_out;
@@ -1038,7 +1117,7 @@ static int _percent_run(struct dev_manager *dm, const char *name,
goto_out;
}
log_debug_activation("LV percent: %f", dm_percent_to_float(*overall_percent));
log_debug_activation("LV percent: %.2f", dm_percent_to_float(*overall_percent));
r = 1;
out:
@@ -3198,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:
@@ -3217,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) {

32
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) &&
@@ -1871,8 +1867,8 @@ struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
* device already exists? Things don't seem to work
* if we do that for some reason.
*/
log_verbose("Found same device %s with same pvid %s",
dev_name(existing->dev), pvid_s);
log_debug_cache("Found same device %s with same pvid %s",
dev_name(existing->dev), pvid_s);
}
/*
@@ -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

96
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");
if (compare_config(vgmeta_ret->root, vgmeta->root)) {
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);
@@ -1069,7 +1070,7 @@ static struct dev_filter *_init_lvmetad_filter_chain(struct cmd_context *cmd)
nr_filt++;
}
/* regex filter. Optional. */
/* global regex filter. Optional. */
if ((cn = find_config_tree_node(cmd, devices_global_filter_CFG, NULL))) {
if (!(filters[nr_filt] = regex_filter_create(cn->v))) {
log_error("Failed to create global regex device filter");
@@ -1078,6 +1079,17 @@ static struct dev_filter *_init_lvmetad_filter_chain(struct cmd_context *cmd)
nr_filt++;
}
/* regex filter. Optional. */
if (!lvmetad_used()) {
if ((cn = find_config_tree_node(cmd, devices_filter_CFG, NULL))) {
if (!(filters[nr_filt] = regex_filter_create(cn->v))) {
log_error("Failed to create regex device filter");
goto bad;
}
nr_filt++;
}
}
/* device type filter. Required. */
if (!(filters[nr_filt] = lvm_type_filter_create(cmd->dev_types))) {
log_error("Failed to create lvm type filter");
@@ -1145,26 +1157,24 @@ bad:
* md component filter -> fw raid filter
*
* - cmd->filter - the filter chain used for lvmetad responses:
* persistent filter -> usable device filter(FILTER_MODE_POST_LVMETAD) ->
* regex filter
* persistent filter -> regex_filter -> usable device filter(FILTER_MODE_POST_LVMETAD)
*
* - cmd->full_filter - the filter chain used for all the remaining situations:
* lvmetad_filter -> filter
* cmd->lvmetad_filter -> cmd->filter
*
* If lvmetad isnot used, there's just one filter chain:
* If lvmetad is not used, there's just one filter chain:
*
* - cmd->filter == cmd->full_filter:
* persistent filter -> regex filter -> sysfs filter ->
* global regex filter -> type filter ->
* usable device filter(FILTER_MODE_NO_LVMETAD) ->
* mpath component filter -> partitioned filter ->
* md component filter -> fw raid filter
* persistent filter -> sysfs filter -> global regex filter ->
* regex_filter -> type filter -> usable device filter(FILTER_MODE_NO_LVMETAD) ->
* mpath component filter -> partitioned filter -> md component filter -> fw raid filter
*
*/
int init_filters(struct cmd_context *cmd, unsigned load_persistent_cache)
{
const char *dev_cache;
struct dev_filter *filter = NULL, *filter_components[2] = {0};
int nr_filt;
struct stat st;
const struct dm_config_node *cn;
struct timespec ts, cts;
@@ -1193,26 +1203,26 @@ int init_filters(struct cmd_context *cmd, unsigned load_persistent_cache)
*/
/* filter component 0 */
if (lvmetad_used()) {
if (!(filter_components[0] = usable_filter_create(cmd->dev_types, FILTER_MODE_POST_LVMETAD))) {
nr_filt = 0;
if ((cn = find_config_tree_array(cmd, devices_filter_CFG, NULL))) {
if (!(filter_components[nr_filt] = regex_filter_create(cn->v))) {
log_verbose("Failed to create regex device filter.");
goto bad;
}
nr_filt++;
}
if (!(filter_components[nr_filt] = usable_filter_create(cmd->dev_types, FILTER_MODE_POST_LVMETAD))) {
log_verbose("Failed to create usable device filter.");
goto bad;
}
nr_filt++;
if (!(filter = composite_filter_create(nr_filt, 0, filter_components)))
goto_bad;
} else {
filter_components[0] = cmd->lvmetad_filter;
filter = cmd->lvmetad_filter;
cmd->lvmetad_filter = NULL;
}
/* filter component 1 */
if ((cn = find_config_tree_array(cmd, devices_filter_CFG, NULL))) {
if (!(filter_components[1] = regex_filter_create(cn->v)))
goto_bad;
/* we have two filter components - create composite filter */
if (!(filter = composite_filter_create(2, 0, filter_components)))
goto_bad;
} else
/* we have only one filter component - no need to create composite filter */
filter = filter_components[0];
if (!(dev_cache = find_config_tree_str(cmd, devices_cache_CFG, NULL)))
goto_bad;
@@ -1224,9 +1234,12 @@ int init_filters(struct cmd_context *cmd, unsigned load_persistent_cache)
cmd->filter = filter;
if (lvmetad_used()) {
filter_components[0] = cmd->lvmetad_filter;
filter_components[1] = cmd->filter;
if (!(cmd->full_filter = composite_filter_create(2, 0, filter_components)))
nr_filt = 0;
filter_components[nr_filt] = cmd->lvmetad_filter;
nr_filt++;
filter_components[nr_filt] = cmd->filter;
nr_filt++;
if (!(cmd->full_filter = composite_filter_create(nr_filt, 0, filter_components)))
goto_bad;
} else
cmd->full_filter = filter;

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

View File

@@ -341,11 +341,13 @@ static int _add_alias(struct device *dev, const char *path)
if (!dm_list_empty(&dev->aliases)) {
oldpath = dm_list_item(dev->aliases.n, struct dm_str_list)->str;
prefer_old = _compare_paths(path, oldpath);
log_debug_devs("%s: Aliased to %s in device cache%s",
path, oldpath, prefer_old ? "" : " (preferred name)");
log_debug_devs("%s: Aliased to %s in device cache%s (%d:%d)",
path, oldpath, prefer_old ? "" : " (preferred name)",
(int) MAJOR(dev->dev), (int) MINOR(dev->dev));
} else
log_debug_devs("%s: Added to device cache", path);
log_debug_devs("%s: Added to device cache (%d:%d)", path,
(int) MAJOR(dev->dev), (int) MINOR(dev->dev));
if (prefer_old)
dm_list_add(&dev->aliases, &sl->list);
@@ -946,6 +948,7 @@ struct device *dev_cache_get(const char *name, struct dev_filter *f)
{
struct stat buf;
struct device *d = (struct device *) dm_hash_lookup(_cache.names, name);
int info_available = 0;
if (d && (d->flags & DEV_REGULAR))
return d;
@@ -956,7 +959,8 @@ struct device *dev_cache_get(const char *name, struct dev_filter *f)
dm_hash_remove(_cache.names, name);
log_sys_very_verbose("stat", name);
d = NULL;
}
} else
info_available = 1;
if (d && (buf.st_rdev != d->dev)) {
dm_hash_remove(_cache.names, name);
@@ -964,7 +968,7 @@ struct device *dev_cache_get(const char *name, struct dev_filter *f)
}
if (!d) {
_insert(name, &buf, 0, obtain_device_list_from_udev());
_insert(name, info_available ? &buf : NULL, 0, obtain_device_list_from_udev());
d = (struct device *) dm_hash_lookup(_cache.names, name);
if (!d) {
_full_scan(0);

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++;
@@ -734,13 +739,20 @@ int wipe_known_signatures(struct cmd_context *cmd, struct device *dev,
uint32_t types_no_prompt, int yes, force_t force,
int *wiped)
{
int blkid_wiping_enabled = find_config_tree_bool(cmd, allocation_use_blkid_wiping_CFG, NULL);
#ifdef BLKID_WIPING_SUPPORT
if (find_config_tree_bool(cmd, allocation_use_blkid_wiping_CFG, NULL))
if (blkid_wiping_enabled)
return _wipe_known_signatures_with_blkid(dev, name,
types_to_exclude,
types_no_prompt,
yes, force, wiped);
#endif
if (blkid_wiping_enabled) {
log_warn("allocation/use_blkid_wiping=1 configuration setting is set "
"while LVM is not compiled with blkid wiping support.");
log_warn("Falling back to native LVM signature detection.");
}
return _wipe_known_signatures_with_lvm(dev, name,
types_to_exclude,
types_no_prompt,

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

@@ -61,6 +61,8 @@ static int _dev_is_fwraid(struct device *dev)
return 0;
}
#define MSG_SKIPPING "%s: Skipping firmware RAID component device"
static int _ignore_fwraid(struct dev_filter *f __attribute__((unused)),
struct device *dev)
{
@@ -72,8 +74,11 @@ static int _ignore_fwraid(struct dev_filter *f __attribute__((unused)),
ret = _dev_is_fwraid(dev);
if (ret == 1) {
log_debug_devs("%s: Skipping firmware RAID component device [%s:%p]",
dev_name(dev), dev_ext_name(dev), dev->ext.handle);
if (dev->ext.src == DEV_EXT_NONE)
log_debug_devs(MSG_SKIPPING, dev_name(dev));
else
log_debug_devs(MSG_SKIPPING " [%s:%p]", dev_name(dev),
dev_ext_name(dev), dev->ext.handle);
return 0;
}

View File

@@ -18,6 +18,8 @@
#ifdef __linux__
#define MSG_SKIPPING "%s: Skipping md component device"
static int _ignore_md(struct dev_filter *f __attribute__((unused)),
struct device *dev)
{
@@ -29,8 +31,11 @@ static int _ignore_md(struct dev_filter *f __attribute__((unused)),
ret = dev_is_md(dev, NULL);
if (ret == 1) {
log_debug_devs("%s: Skipping md component device [%s:%p]",
dev_name(dev), dev_ext_name(dev), dev->ext.handle);
if (dev->ext.src == DEV_EXT_NONE)
log_debug_devs(MSG_SKIPPING, dev_name(dev));
else
log_debug_devs(MSG_SKIPPING " [%s:%p]", dev_name(dev),
dev_ext_name(dev), dev->ext.handle);
return 0;
}

View File

@@ -244,11 +244,16 @@ static int _dev_is_mpath(struct dev_filter *f, struct device *dev)
return 0;
}
#define MSG_SKIPPING "%s: Skipping mpath component device"
static int _ignore_mpath(struct dev_filter *f, struct device *dev)
{
if (_dev_is_mpath(f, dev) == 1) {
log_debug_devs("%s: Skipping mpath component device [%s:%p]",
dev_name(dev), dev_ext_name(dev), dev->ext.handle);
if (dev->ext.src == DEV_EXT_NONE)
log_debug_devs(MSG_SKIPPING, dev_name(dev));
else
log_debug_devs(MSG_SKIPPING " [%s:%p]", dev_name(dev),
dev_ext_name(dev), dev->ext.handle);
return 0;
}

View File

@@ -16,13 +16,18 @@
#include "lib.h"
#include "filter.h"
#define MSG_SKIPPING "%s: Skipping: Partition table signature found"
static int _passes_partitioned_filter(struct dev_filter *f, struct device *dev)
{
struct dev_types *dt = (struct dev_types *) f->private;
if (dev_is_partitioned(dt, dev)) {
log_debug_devs("%s: Skipping: Partition table signature found [%s:%p]",
dev_name(dev), dev_ext_name(dev), dev->ext.handle);
if (dev->ext.src == DEV_EXT_NONE)
log_debug_devs(MSG_SKIPPING, dev_name(dev));
else
log_debug_devs(MSG_SKIPPING " [%s:%p]", dev_name(dev),
dev_ext_name(dev), dev->ext.handle);
return 0;
}

View File

@@ -29,22 +29,19 @@ static int _native_check_pv_min_size(struct device *dev)
/* Check it's accessible */
if (!dev_open_readonly_quiet(dev)) {
log_debug_devs("%s: Skipping: open failed [%s:%p]",
dev_name(dev), dev_ext_name(dev), dev->ext.handle);
log_debug_devs("%s: Skipping: open failed", dev_name(dev));
return 0;
}
/* Check it's not too small */
if (!dev_get_size(dev, &size)) {
log_debug_devs("%s: Skipping: dev_get_size failed [%s:%p]",
dev_name(dev), dev_ext_name(dev), dev->ext.handle);
log_debug_devs("%s: Skipping: dev_get_size failed", dev_name(dev));
goto out;
}
if (size < pv_min_size()) {
log_debug_devs("%s: Skipping: %s [%s:%p]", dev_name(dev),
_too_small_to_hold_pv_msg,
dev_ext_name(dev), dev->ext.handle);
log_debug_devs("%s: Skipping: %s", dev_name(dev),
_too_small_to_hold_pv_msg);
goto out;
}
@@ -115,26 +112,11 @@ static int _passes_usable_filter(struct dev_filter *f, struct device *dev)
{
filter_mode_t mode = *((filter_mode_t *) f->private);
struct dev_usable_check_params ucp = {0};
int r;
/* check if the device is not too small to hold a PV */
switch (mode) {
case FILTER_MODE_NO_LVMETAD:
/* fall through */
case FILTER_MODE_PRE_LVMETAD:
if (!_check_pv_min_size(dev))
return 0;
break;
case FILTER_MODE_POST_LVMETAD:
/* nothing to do here */
break;
}
int r = 1;
/* further checks are done on dm devices only */
if (!dm_is_dm_major(MAJOR(dev->dev)))
return 1;
switch (mode) {
if (dm_is_dm_major(MAJOR(dev->dev))) {
switch (mode) {
case FILTER_MODE_NO_LVMETAD:
ucp.check_empty = 1;
ucp.check_blocked = 1;
@@ -163,10 +145,25 @@ static int _passes_usable_filter(struct dev_filter *f, struct device *dev)
ucp.check_error_target = 0;
ucp.check_reserved = 0;
break;
}
if (!(r = device_is_usable(dev, ucp)))
log_debug_devs("%s: Skipping unusable device.", dev_name(dev));
}
if (!(r = device_is_usable(dev, ucp)))
log_debug_devs("%s: Skipping unusable device", dev_name(dev));
if (r) {
/* check if the device is not too small to hold a PV */
switch (mode) {
case FILTER_MODE_NO_LVMETAD:
/* fall through */
case FILTER_MODE_PRE_LVMETAD:
r = _check_pv_min_size(dev);
break;
case FILTER_MODE_POST_LVMETAD:
/* nothing to do here */
break;
}
}
return r;
}

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;
@@ -1339,6 +1339,7 @@ static int _text_pv_write(const struct format_type *fmt, struct physical_volume
label = lvmcache_get_label(info);
label->sector = pv->label_sector;
label->dev = pv->dev;
lvmcache_update_pv(info, pv, fmt);
@@ -2145,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;
@@ -2242,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);
@@ -698,15 +698,6 @@ static int _free_vg_dlm(struct cmd_context *cmd, struct volume_group *vg)
if (!_lvmlockd_connected)
return 0;
/*
* For the dlm, free_vg means unlock the ex VG lock,
* and include an indication in the lvb that the VG
* has been removed. Then, leave the lockspace.
* If another host tries to acquire the VG lock, it
* will see that the VG has been removed by looking
* at the lvb value.
*/
reply = _lockd_send("free_vg",
"pid = %d", getpid(),
"vg_name = %s", vg->name,
@@ -730,6 +721,50 @@ static int _free_vg_dlm(struct cmd_context *cmd, struct volume_group *vg)
/* called before vg_remove on disk */
static int _busy_vg_dlm(struct cmd_context *cmd, struct volume_group *vg)
{
daemon_reply reply;
uint32_t lockd_flags = 0;
int result;
int ret;
if (!_use_lvmlockd)
return 0;
if (!_lvmlockd_connected)
return 0;
/*
* Check that other hosts do not have the VG lockspace started.
*/
reply = _lockd_send("busy_vg",
"pid = %d", getpid(),
"vg_name = %s", vg->name,
"vg_lock_type = %s", vg->lock_type,
"vg_lock_args = %s", vg->lock_args,
NULL);
if (!_lockd_result(reply, &result, &lockd_flags)) {
ret = 0;
} else {
ret = (result < 0) ? 0 : 1;
}
if (result == -EBUSY) {
log_error("Lockspace for \"%s\" not stopped on other hosts", vg->name);
goto out;
}
if (!ret)
log_error("_busy_vg_dlm lvmlockd result %d", result);
out:
daemon_reply_destroy(reply);
return ret;
}
/* called before vg_remove on disk */
static int _free_vg_sanlock(struct cmd_context *cmd, struct volume_group *vg)
{
daemon_reply reply;
@@ -844,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);
@@ -881,8 +919,10 @@ int lockd_free_vg_before(struct cmd_context *cmd, struct volume_group *vg,
switch (lock_type_num) {
case LOCK_TYPE_NONE:
case LOCK_TYPE_CLVM:
case LOCK_TYPE_DLM:
return 1;
case LOCK_TYPE_DLM:
/* returning an error will prevent vg_remove() */
return _busy_vg_dlm(cmd, vg);
case LOCK_TYPE_SANLOCK:
/* returning an error will prevent vg_remove() */
return _free_vg_sanlock(cmd, vg);
@@ -921,9 +961,13 @@ void lockd_free_vg_final(struct cmd_context *cmd, struct volume_group *vg)
* for starting the lockspace. To use the vg after starting
* the lockspace, follow the standard method which is:
* lock the vg, read/use/write the vg, unlock the vg.
*
* start_init is 1 when the VG is being started after the
* command has done lockd_init_vg(). This tells lvmlockd
* that the VG lockspace being started is new.
*/
int lockd_start_vg(struct cmd_context *cmd, struct volume_group *vg)
int lockd_start_vg(struct cmd_context *cmd, struct volume_group *vg, int start_init)
{
char uuid[64] __attribute__((aligned(8)));
daemon_reply reply;
@@ -945,8 +989,8 @@ int lockd_start_vg(struct cmd_context *cmd, struct volume_group *vg)
return 0;
}
log_debug("lockd start VG %s lock_type %s",
vg->name, vg->lock_type ? vg->lock_type : "empty");
log_debug("lockd start VG %s lock_type %s init %d",
vg->name, vg->lock_type ? vg->lock_type : "empty", start_init);
if (!id_write_format(&vg->id, uuid, sizeof(uuid)))
return_0;
@@ -973,6 +1017,7 @@ int lockd_start_vg(struct cmd_context *cmd, struct volume_group *vg)
"vg_uuid = %s", uuid[0] ? uuid : "none",
"version = %d", (int64_t)vg->seqno,
"host_id = %d", host_id,
"opts = %s", start_init ? "start_init" : "none",
NULL);
if (!_lockd_result(reply, &result, NULL)) {
@@ -1454,6 +1499,10 @@ int lockd_gl(struct cmd_context *cmd, const char *def_mode, uint32_t flags)
}
}
if (!strcmp(mode, "un"))
return 1;
/*
* ENOLS: no lockspace was found with a global lock.
* The VG with the global lock may not be visible or started yet,
@@ -1473,10 +1522,6 @@ int lockd_gl(struct cmd_context *cmd, const char *def_mode, uint32_t flags)
result == -ESTARTING ||
result == -EVGKILLED ||
result == -ELOCKIO) {
if (!strcmp(mode, "un"))
return 1;
/*
* If an ex global lock fails, then the command fails.
*/
@@ -1965,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++) {
@@ -2423,6 +2477,12 @@ int lockd_rename_vg_before(struct cmd_context *cmd, struct volume_group *vg)
}
daemon_reply_destroy(reply);
/* Other hosts have not stopped the lockspace. */
if (result == -EBUSY) {
log_error("Lockspace for \"%s\" not stopped on other hosts", vg->name);
return 0;
}
if (!ret) {
log_error("lockd_rename_vg_before lvmlockd result %d", result);
@@ -2455,7 +2515,7 @@ int lockd_rename_vg_final(struct cmd_context *cmd, struct volume_group *vg, int
* Depending on the problem that caused the rename to
* fail, it may make sense to not restart the VG here.
*/
if (!lockd_start_vg(cmd, vg))
if (!lockd_start_vg(cmd, vg, 0))
log_error("Failed to restart VG %s lockspace.", vg->name);
return 1;
}
@@ -2495,13 +2555,13 @@ int lockd_rename_vg_final(struct cmd_context *cmd, struct volume_group *vg, int
}
}
if (!lockd_start_vg(cmd, vg))
if (!lockd_start_vg(cmd, vg, 1))
log_error("Failed to start VG %s lockspace.", vg->name);
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;
@@ -2523,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

@@ -62,7 +62,7 @@ int lockd_rename_vg_final(struct cmd_context *cmd, struct volume_group *vg, int
/* start and stop the lockspace for a vg */
int lockd_start_vg(struct cmd_context *cmd, struct volume_group *vg);
int lockd_start_vg(struct cmd_context *cmd, struct volume_group *vg, int start_init);
int lockd_stop_vg(struct cmd_context *cmd, struct volume_group *vg);
int lockd_start_wait(struct cmd_context *cmd);
@@ -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);
@@ -147,7 +147,7 @@ static inline int lockd_rename_vg_final(struct cmd_context *cmd, struct volume_g
return 1;
}
static inline int lockd_start_vg(struct cmd_context *cmd, struct volume_group *vg)
static inline int lockd_start_vg(struct cmd_context *cmd, struct volume_group *vg, int start_init)
{
return 0;
}
@@ -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

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014 Red Hat, Inc. All rights reserved.
* Copyright (C) 2014-2015 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
@@ -101,6 +101,23 @@ int cache_set_mode(struct lv_segment *seg, const char *str)
return 1;
}
/*
* At least warn a user if certain cache stacks may present some problems
*/
void cache_check_for_warns(const struct lv_segment *seg)
{
struct logical_volume *origin_lv = seg_lv(seg, 0);
if (lv_is_raid(origin_lv) &&
first_seg(seg->pool_lv)->feature_flags & DM_CACHE_FEATURE_WRITEBACK)
log_warn("WARNING: Data redundancy is lost with writeback "
"caching of raid logical volume!");
if (lv_is_thin_pool_data(seg->lv))
log_warn("WARNING: Cached thin pool's data cannot be currently "
"resized and require manual uncache before resize!");
}
int update_cache_pool_params(const struct segment_type *segtype,
struct volume_group *vg, unsigned attr,
int passed_args, uint32_t pool_data_extents,
@@ -244,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"))
@@ -390,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))))
@@ -436,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)
@@ -219,21 +236,37 @@ uint32_t lv_kernel_read_ahead(const struct logical_volume *lv)
return info.read_ahead;
}
static char *_do_lv_origin_dup(struct dm_pool *mem, const struct logical_volume *lv,
int uuid)
{
struct logical_volume *origin;
if (lv_is_cow(lv))
origin = origin_from_cow(lv);
else if (lv_is_cache(lv) && first_seg(lv)->origin)
origin = first_seg(lv)->origin;
else if (lv_is_thin_volume(lv) && first_seg(lv)->origin)
origin = first_seg(lv)->origin;
else if (lv_is_thin_volume(lv) && first_seg(lv)->external_lv)
origin = first_seg(lv)->external_lv;
else
return NULL;
if (uuid)
return lv_uuid_dup(mem, origin);
else
return lv_name_dup(mem, origin);
}
char *lv_origin_dup(struct dm_pool *mem, const struct logical_volume *lv)
{
if (lv_is_cow(lv))
return lv_name_dup(mem, origin_from_cow(lv));
return _do_lv_origin_dup(mem, lv, 0);
}
if (lv_is_cache(lv) && first_seg(lv)->origin)
return lv_name_dup(mem, first_seg(lv)->origin);
if (lv_is_thin_volume(lv) && first_seg(lv)->origin)
return lv_name_dup(mem, first_seg(lv)->origin);
if (lv_is_thin_volume(lv) && first_seg(lv)->external_lv)
return lv_name_dup(mem, first_seg(lv)->external_lv);
return NULL;
char *lv_origin_uuid_dup(struct dm_pool *mem, const struct logical_volume *lv)
{
return _do_lv_origin_dup(mem, lv, 1);
}
char *lv_name_dup(struct dm_pool *mem, const struct logical_volume *lv)
@@ -292,43 +325,112 @@ char *lv_modules_dup(struct dm_pool *mem, const struct logical_volume *lv)
return tags_format_and_copy(mem, modules);
}
char *lv_mirror_log_dup(struct dm_pool *mem, const struct logical_volume *lv)
static char *_do_lv_mirror_log_dup(struct dm_pool *mem, const struct logical_volume *lv,
int uuid)
{
struct lv_segment *seg;
dm_list_iterate_items(seg, &lv->segments)
if (seg_is_mirrored(seg) && seg->log_lv)
return dm_pool_strdup(mem, seg->log_lv->name);
dm_list_iterate_items(seg, &lv->segments) {
if (seg_is_mirrored(seg) && seg->log_lv) {
if (uuid)
return lv_uuid_dup(mem, seg->log_lv);
else
return lv_name_dup(mem, seg->log_lv);
}
}
return NULL;
}
char *lv_mirror_log_dup(struct dm_pool *mem, const struct logical_volume *lv)
{
return _do_lv_mirror_log_dup(mem, lv, 0);
}
char *lv_mirror_log_uuid_dup(struct dm_pool *mem, const struct logical_volume *lv)
{
return _do_lv_mirror_log_dup(mem, lv, 1);
}
static char *_do_lv_pool_lv_dup(struct dm_pool *mem, const struct logical_volume *lv,
int uuid)
{
struct lv_segment *seg;
dm_list_iterate_items(seg, &lv->segments) {
if (seg->pool_lv &&
(seg_is_thin_volume(seg) || seg_is_cache(seg))) {
if (uuid)
return lv_uuid_dup(mem, seg->pool_lv);
else
return lv_name_dup(mem, seg->pool_lv);
}
}
return NULL;
}
char *lv_pool_lv_dup(struct dm_pool *mem, const struct logical_volume *lv)
{
struct lv_segment *seg;
return _do_lv_pool_lv_dup(mem, lv, 0);
}
dm_list_iterate_items(seg, &lv->segments)
if (seg->pool_lv &&
(seg_is_thin_volume(seg) || seg_is_cache(seg)))
return dm_pool_strdup(mem, seg->pool_lv->name);
char *lv_pool_lv_uuid_dup(struct dm_pool *mem, const struct logical_volume *lv)
{
return _do_lv_pool_lv_dup(mem, lv, 1);
}
static char *_do_lv_data_lv_dup(struct dm_pool *mem, const struct logical_volume *lv,
int uuid)
{
struct lv_segment *seg = (lv_is_thin_pool(lv) || lv_is_cache_pool(lv)) ?
first_seg(lv) : NULL;
if (seg) {
if (uuid)
return lv_uuid_dup(mem, seg_lv(seg, 0));
else
return lv_name_dup(mem, seg_lv(seg, 0));
}
return NULL;
}
char *lv_data_lv_dup(struct dm_pool *mem, const struct logical_volume *lv)
{
struct lv_segment *seg = (lv_is_thin_pool(lv) || lv_is_cache_pool(lv)) ?
first_seg(lv) : NULL;
return seg ? dm_pool_strdup(mem, seg_lv(seg, 0)->name) : NULL;
return _do_lv_data_lv_dup(mem, lv, 0);
}
char *lv_metadata_lv_dup(struct dm_pool *mem, const struct logical_volume *lv)
char *lv_data_lv_uuid_dup(struct dm_pool *mem, const struct logical_volume *lv)
{
return _do_lv_data_lv_dup(mem, lv, 1);
}
static char *_do_lv_metadata_lv_dup(struct dm_pool *mem, const struct logical_volume *lv,
int uuid)
{
struct lv_segment *seg = (lv_is_thin_pool(lv) || lv_is_cache_pool(lv)) ?
first_seg(lv) : NULL;
return seg ? dm_pool_strdup(mem, seg->metadata_lv->name) : NULL;
if (seg) {
if (uuid)
return lv_uuid_dup(mem, seg->metadata_lv);
else
return lv_name_dup(mem, seg->metadata_lv);
}
return NULL;
}
char *lv_metadata_lv_dup(struct dm_pool *mem, const struct logical_volume *lv)
{
return _do_lv_metadata_lv_dup(mem, lv, 0);
}
char *lv_metadata_lv_uuid_dup(struct dm_pool *mem, const struct logical_volume *lv)
{
return _do_lv_metadata_lv_dup(mem, lv, 1);
}
const char *lv_layer(const struct logical_volume *lv)
@@ -358,7 +460,8 @@ int lv_kernel_major(const struct logical_volume *lv)
return -1;
}
char *lv_convert_lv_dup(struct dm_pool *mem, const struct logical_volume *lv)
static char *_do_lv_convert_lv_dup(struct dm_pool *mem, const struct logical_volume *lv,
int uuid)
{
struct lv_segment *seg;
@@ -367,17 +470,32 @@ char *lv_convert_lv_dup(struct dm_pool *mem, const struct logical_volume *lv)
/* Temporary mirror is always area_num == 0 */
if (seg_type(seg, 0) == AREA_LV &&
is_temporary_mirror_layer(seg_lv(seg, 0)))
return dm_pool_strdup(mem, seg_lv(seg, 0)->name);
is_temporary_mirror_layer(seg_lv(seg, 0))) {
if (uuid)
return lv_uuid_dup(mem, seg_lv(seg, 0));
else
return lv_name_dup(mem, seg_lv(seg, 0));
}
}
return NULL;
}
char *lv_move_pv_dup(struct dm_pool *mem, const struct logical_volume *lv)
char *lv_convert_lv_dup(struct dm_pool *mem, const struct logical_volume *lv)
{
return _do_lv_convert_lv_dup(mem, lv, 0);
}
char *lv_convert_lv_uuid_dup(struct dm_pool *mem, const struct logical_volume *lv)
{
return _do_lv_convert_lv_dup(mem, lv, 1);
}
static char *_do_lv_move_pv_dup(struct dm_pool *mem, const struct logical_volume *lv,
int uuid)
{
struct logical_volume *mimage0_lv;
struct lv_segment *seg;
const struct device *dev;
struct pv_segment *pvseg;
dm_list_iterate_items(seg, &lv->segments) {
if (seg->status & PVMOVE) {
@@ -388,17 +506,30 @@ char *lv_move_pv_dup(struct dm_pool *mem, const struct logical_volume *lv)
"Bad pvmove structure");
return NULL;
}
dev = seg_dev(first_seg(mimage0_lv), 0);
pvseg = seg_pvseg(first_seg(mimage0_lv), 0);
} else /* Segment pvmove */
dev = seg_dev(seg, 0);
pvseg = seg_pvseg(seg, 0);
return dm_pool_strdup(mem, dev_name(dev));
if (uuid)
return pv_uuid_dup(mem, pvseg->pv);
else
return pv_name_dup(mem, pvseg->pv);
}
}
return NULL;
}
char *lv_move_pv_dup(struct dm_pool *mem, const struct logical_volume *lv)
{
return _do_lv_move_pv_dup(mem, lv, 0);
}
char *lv_move_pv_uuid_dup(struct dm_pool *mem, const struct logical_volume *lv)
{
return _do_lv_move_pv_dup(mem, lv, 1);
}
uint64_t lv_origin_size(const struct logical_volume *lv)
{
struct lv_segment *seg;
@@ -479,9 +610,9 @@ char *lv_dmpath_dup(struct dm_pool *mem, const struct logical_volume *lv)
return repstr;
}
char *lv_uuid_dup(const struct logical_volume *lv)
char *lv_uuid_dup(struct dm_pool *mem, const struct logical_volume *lv)
{
return id_format_and_copy(lv->vg->vgmem, &lv->lvid.id[1]);
return id_format_and_copy(mem ? mem : lv->vg->vgmem, &lv->lvid.id[1]);
}
char *lv_tags_dup(const struct logical_volume *lv)
@@ -534,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;
@@ -62,25 +62,34 @@ uint64_t lv_size(const struct logical_volume *lv);
uint64_t lv_metadata_size(const struct logical_volume *lv);
char *lv_attr_dup_with_info_and_seg_status(struct dm_pool *mem, const struct lv_with_info_and_seg_status *lvdm);
char *lv_attr_dup(struct dm_pool *mem, const struct logical_volume *lv);
char *lv_uuid_dup(const struct logical_volume *lv);
char *lv_uuid_dup(struct dm_pool *mem, const struct logical_volume *lv);
char *lv_tags_dup(const struct logical_volume *lv);
char *lv_path_dup(struct dm_pool *mem, const struct logical_volume *lv);
char *lv_dmpath_dup(struct dm_pool *mem, const struct logical_volume *lv);
uint64_t lv_origin_size(const struct logical_volume *lv);
char *lv_move_pv_dup(struct dm_pool *mem, const struct logical_volume *lv);
char *lv_move_pv_uuid_dup(struct dm_pool *mem, const struct logical_volume *lv);
char *lv_convert_lv_dup(struct dm_pool *mem, const struct logical_volume *lv);
char *lv_convert_lv_uuid_dup(struct dm_pool *mem, const struct logical_volume *lv);
int lv_kernel_major(const struct logical_volume *lv);
int lv_kernel_minor(const struct logical_volume *lv);
char *lv_mirror_log_dup(struct dm_pool *mem, const struct logical_volume *lv);
char *lv_mirror_log_uuid_dup(struct dm_pool *mem, const struct logical_volume *lv);
char *lv_data_lv_dup(struct dm_pool *mem, const struct logical_volume *lv);
char *lv_data_lv_uuid_dup(struct dm_pool *mem, const struct logical_volume *lv);
char *lv_metadata_lv_dup(struct dm_pool *mem, const struct logical_volume *lv);
char *lv_metadata_lv_uuid_dup(struct dm_pool *mem, const struct logical_volume *lv);
char *lv_pool_lv_dup(struct dm_pool *mem, const struct logical_volume *lv);
char *lv_pool_lv_uuid_dup(struct dm_pool *mem, const struct logical_volume *lv);
char *lv_modules_dup(struct dm_pool *mem, const struct logical_volume *lv);
char *lv_name_dup(struct dm_pool *mem, const struct logical_volume *lv);
char *lv_fullname_dup(struct dm_pool *mem, const struct logical_volume *lv);
struct logical_volume *lv_parent(const struct logical_volume *lv);
char *lv_parent_dup(struct dm_pool *mem, const struct logical_volume *lv);
char *lv_origin_dup(struct dm_pool *mem, const struct logical_volume *lv);
char *lv_origin_uuid_dup(struct dm_pool *mem, const struct logical_volume *lv);
uint32_t lv_kernel_read_ahead(const struct logical_volume *lv);
const char *lvseg_name(const struct lv_segment *seg);
uint64_t lvseg_start(const struct lv_segment *seg);
@@ -92,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,43 +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;
if (!strcmp(first_seg(lv)->segtype->name, SEG_TYPE_NAME_RAID1)) {
segtype = first_seg(lv)->segtype;
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(first_seg(lv)->segtype->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(first_seg(lv)->segtype->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 = first_seg(lv)->segtype->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 = first_seg(lv)->segtype->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;
}
@@ -503,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.
@@ -778,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);
}
@@ -928,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;
@@ -936,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;
}
/*
@@ -1011,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;
@@ -1035,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;
@@ -1052,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;
}
@@ -1069,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;
}
}
@@ -1103,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;
@@ -1241,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.
*/
@@ -1391,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;
@@ -1458,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 */
@@ -1496,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
*/
@@ -1581,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);
@@ -1724,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))) {
@@ -1742,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;
}
@@ -1908,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)
@@ -2954,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;
@@ -3399,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,
@@ -3492,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]) {
@@ -3606,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;
@@ -3665,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);
}
@@ -3763,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,
@@ -4390,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)
{
@@ -4399,49 +4452,65 @@ 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)
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)) {
log_error("Can't read state of locally inactive LV %s.",
display_lvname(lv));
return 0;
}
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;
@@ -4536,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);
@@ -5145,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.");
@@ -5162,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 */
@@ -6198,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;
}
@@ -6252,6 +6321,7 @@ int move_lv_segments(struct logical_volume *lv_to,
struct logical_volume *lv_from,
uint64_t set_status, uint64_t reset_status)
{
const uint64_t MOVE_BITS = (RAID | MIRROR | THIN_VOLUME);
struct lv_segment *seg;
dm_list_iterate_items(seg, &lv_to->segments)
@@ -6269,6 +6339,16 @@ int move_lv_segments(struct logical_volume *lv_to,
seg->status |= set_status;
}
/*
* Move LV status bits for selected types with their segments
* i.e. when inserting layer to cache LV, we move raid segments
* to a new place, thus 'raid' LV property now belongs to this LV.
*
* Bits should match to those which appears after read from disk.
*/
lv_to->status |= lv_from->status & MOVE_BITS;
lv_from->status &= ~MOVE_BITS;
lv_to->le_count = lv_from->le_count;
lv_to->size = lv_from->size;
@@ -6321,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;
@@ -6385,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);
@@ -6433,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 */
@@ -6483,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 */
@@ -6756,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;
}
@@ -6910,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;
@@ -6975,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.");
@@ -7038,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) &&
@@ -7091,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) &&
@@ -7160,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)) {
@@ -7207,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 */
@@ -7301,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;
@@ -7503,6 +7588,8 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
if (!cache_set_policy(first_seg(lv), lp->policy_name, lp->policy_settings))
return_NULL; /* revert? */
cache_check_for_warns(first_seg(lv));
if (!lv_update_and_reload(lv)) {
/* FIXME Do a better revert */
log_error("Aborting. Manual intervention required.");
@@ -7602,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)))
@@ -7614,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

@@ -119,12 +119,24 @@ int check_lv_segments(struct logical_volume *lv, int complete_vg)
inc_error_count;
}
if (lv_is_pool_metadata(lv) &&
(!(seg2 = first_seg(lv)) || !(seg2 = find_pool_seg(seg2)) ||
seg2->metadata_lv != lv)) {
log_error("LV %s: segment 1 pool metadata LV does not point back to same LV",
lv->name);
inc_error_count;
if (lv_is_pool_metadata(lv)) {
if (!(seg2 = first_seg(lv)) || !(seg2 = find_pool_seg(seg2)) ||
seg2->metadata_lv != lv) {
log_error("LV %s: segment 1 pool metadata LV does not point back to same LV",
lv->name);
inc_error_count;
}
if (lv_is_thin_pool_metadata(lv) &&
!strstr(lv->name, "_tmeta")) {
log_error("LV %s: thin pool metadata LV does not use _tmeta",
lv->name);
inc_error_count;
} else if (lv_is_cache_pool_metadata(lv) &&
!strstr(lv->name, "_cmeta")) {
log_error("LV %s: cache pool metadata LV does not use _cmeta",
lv->name);
inc_error_count;
}
}
}

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.
@@ -1158,6 +1156,7 @@ int cache_mode_is_set(const struct lv_segment *seg);
int cache_set_mode(struct lv_segment *cache_seg, const char *str);
int cache_set_policy(struct lv_segment *cache_seg, const char *name,
const struct dm_config_tree *settings);
void cache_check_for_warns(const struct lv_segment *seg);
int update_cache_pool_params(const struct segment_type *segtype,
struct volume_group *vg, unsigned attr,
int passed_args, uint32_t pool_data_extents,

View File

@@ -319,10 +319,11 @@ static struct pv_list *_copy_pvl(struct dm_pool *pvmem, struct pv_list *pvl_from
if (!(pvl_to->pv = dm_pool_alloc(pvmem, sizeof(*pvl_to->pv))))
goto_bad;
if(!_copy_pv(pvmem, pvl_to->pv, pvl_from->pv))
if (!_copy_pv(pvmem, pvl_to->pv, pvl_from->pv))
goto_bad;
return pvl_to;
bad:
dm_pool_free(pvmem, pvl_to);
return NULL;
@@ -3010,7 +3011,7 @@ out:
int vg_write(struct volume_group *vg)
{
struct dm_list *mdah;
struct pv_to_create *pv_to_create;
struct pv_to_create *pv_to_create, *pv_to_create_safe;
struct metadata_area *mda;
struct lv_list *lvl;
int revert = 0, wrote = 0;
@@ -3066,10 +3067,11 @@ int vg_write(struct volume_group *vg)
memlock_unlock(vg->cmd);
vg->seqno++;
dm_list_iterate_items(pv_to_create, &vg->pvs_to_create) {
dm_list_iterate_items_safe(pv_to_create, pv_to_create_safe, &vg->pvs_to_create) {
if (!_pvcreate_write(vg->cmd, pv_to_create))
return 0;
}
dm_list_del(&pv_to_create->list);
}
/* Write to each copy of the metadata area */
dm_list_iterate_items(mda, &vg->fid->metadata_areas_in_use) {
@@ -4923,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
@@ -4931,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;
@@ -4942,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)) {
@@ -4965,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. */
@@ -4974,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;
}
@@ -5055,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);
}
/*
@@ -5077,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

@@ -29,9 +29,9 @@ char *pv_fmt_dup(const struct physical_volume *pv)
return dm_pool_strdup(pv->vg->vgmem, pv->fmt->name);
}
char *pv_name_dup(const struct physical_volume *pv)
char *pv_name_dup(struct dm_pool *mem, const struct physical_volume *pv)
{
return dm_pool_strdup(pv->vg->vgmem, dev_name(pv->dev));
return dm_pool_strdup(mem ? mem : pv->vg->vgmem, dev_name(pv->dev));
}
/*
@@ -42,9 +42,9 @@ struct id pv_id(const struct physical_volume *pv)
return pv_field(pv, id);
}
char *pv_uuid_dup(const struct physical_volume *pv)
char *pv_uuid_dup(struct dm_pool *mem, const struct physical_volume *pv)
{
return id_format_and_copy(pv->vg->vgmem, &pv->id);
return id_format_and_copy(mem ? mem : pv->vg->vgmem, &pv->id);
}
char *pv_tags_dup(const struct physical_volume *pv)

View File

@@ -68,12 +68,12 @@ struct physical_volume {
};
char *pv_fmt_dup(const struct physical_volume *pv);
char *pv_name_dup(const struct physical_volume *pv);
char *pv_name_dup(struct dm_pool *mem, const struct physical_volume *pv);
struct device *pv_dev(const struct physical_volume *pv);
const char *pv_vg_name(const struct physical_volume *pv);
char *pv_attr_dup(struct dm_pool *mem, const struct physical_volume *pv);
const char *pv_dev_name(const struct physical_volume *pv);
char *pv_uuid_dup(const struct physical_volume *pv);
char *pv_uuid_dup(struct dm_pool *mem, const struct physical_volume *pv);
char *pv_tags_dup(const struct physical_volume *pv);
uint64_t pv_size(const struct physical_volume *pv);
uint64_t pv_size_field(const struct physical_volume *pv);

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

@@ -397,8 +397,10 @@ static struct logical_volume *_alloc_image_component(struct logical_volume *lv,
}
if (dm_snprintf(img_name, sizeof(img_name), "%s_%s_%%d",
(alt_base_name) ? : lv->name, type_suffix) < 0)
return_0;
(alt_base_name) ? : lv->name, type_suffix) < 0) {
log_error("Component name for raid %s is too long.", lv->name);
return 0;
}
status = LVM_READ | LVM_WRITE | LV_REBUILD | type;
if (!(tmp_lv = lv_create_empty(img_name, NULL, status, ALLOC_INHERIT, lv->vg))) {
@@ -406,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)) {
@@ -458,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,
@@ -865,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;
/*
@@ -1100,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;
@@ -1473,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;
}
@@ -1661,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;
@@ -1893,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

2
lib/misc/.gitignore vendored
View File

@@ -1,2 +0,0 @@
configure.h
lvm-version.h

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

@@ -63,6 +63,7 @@ FIELD(LVS, lv, SIZ, "LSize", size, 5, size64, lv_size, "Size of LV in current un
FIELD(LVS, lv, SIZ, "MSize", lvid, 6, lvmetadatasize, lv_metadata_size, "For thin and cache pools, the size of the LV that holds the metadata.", 0)
FIELD(LVS, lv, NUM, "#Seg", lvid, 4, lvsegcount, seg_count, "Number of segments in LV.", 0)
FIELD(LVS, lv, STR, "Origin", lvid, 6, origin, origin, "For snapshots, the origin device of this LV.", 0)
FIELD(LVS, lv, STR, "Origin UUID", lvid, 38, originuuid, origin_uuid, "For snapshots, the UUID of origin device of this LV.", 0)
FIELD(LVS, lv, SIZ, "OSize", lvid, 5, originsize, origin_size, "For snapshots, the size of the origin device of this LV.", 0)
FIELD(LVS, lv, STR_LIST, "Ancestors", lvid, 12, lvancestors, lv_ancestors, "Ancestors of this LV.", 0)
FIELD(LVS, lv, STR_LIST, "Descendants", lvid, 12, lvdescendants, lv_descendants, "Descendants of this LV.", 0)
@@ -77,11 +78,17 @@ FIELD(LVS, lv, NUM, "WBehind", lvid, 7, raidwritebehind, raid_write_behind, "For
FIELD(LVS, lv, NUM, "MinSync", lvid, 7, raidminrecoveryrate, raid_min_recovery_rate, "For RAID1, the minimum recovery I/O load in kiB/sec/disk.", 0)
FIELD(LVS, lv, NUM, "MaxSync", lvid, 7, raidmaxrecoveryrate, raid_max_recovery_rate, "For RAID1, the maximum recovery I/O load in kiB/sec/disk.", 0)
FIELD(LVS, lv, STR, "Move", lvid, 4, movepv, move_pv, "For pvmove, Source PV of temporary LV created by pvmove.", 0)
FIELD(LVS, lv, STR, "Move UUID", lvid, 38, movepvuuid, move_pv_uuid, "For pvmove, the UUID of Source PV of temporary LV created by pvmove.", 0)
FIELD(LVS, lv, STR, "Convert", lvid, 7, convertlv, convert_lv, "For lvconvert, Name of temporary LV created by lvconvert.", 0)
FIELD(LVS, lv, STR, "Convert", lvid, 38, convertlvuuid, convert_lv_uuid, "For lvconvert, UUID of temporary LV created by lvconvert.", 0)
FIELD(LVS, lv, STR, "Log", lvid, 3, loglv, mirror_log, "For mirrors, the LV holding the synchronisation log.", 0)
FIELD(LVS, lv, STR, "Log UUID", lvid, 38, loglvuuid, mirror_log_uuid, "For mirrors, the UUID of the LV holding the synchronisation log.", 0)
FIELD(LVS, lv, STR, "Data", lvid, 4, datalv, data_lv, "For thin and cache pools, the LV holding the associated data.", 0)
FIELD(LVS, lv, STR, "Data UUID", lvid, 38, datalvuuid, data_lv_uuid, "For thin and cache pools, the UUID of the LV holding the associated data.", 0)
FIELD(LVS, lv, STR, "Meta", lvid, 4, metadatalv, metadata_lv, "For thin and cache pools, the LV holding the associated metadata.", 0)
FIELD(LVS, lv, STR, "Meta UUID", lvid, 38, metadatalvuuid, metadata_lv_uuid, "For thin and cache pools, the UUID of the LV holding the associated metadata.", 0)
FIELD(LVS, lv, STR, "Pool", lvid, 4, poollv, pool_lv, "For thin volumes, the thin pool LV for this volume.", 0)
FIELD(LVS, lv, STR, "Pool UUID", lvid, 38, poollvuuid, pool_lv_uuid, "For thin volumes, the UUID of the thin pool LV for this volume.", 0)
FIELD(LVS, lv, STR_LIST, "LV Tags", tags, 7, tags, lv_tags, "Tags, if any.", 0)
FIELD(LVS, lv, STR, "LProfile", lvid, 8, lvprofile, lv_profile, "Configuration profile attached to this LV.", 0)
FIELD(LVS, lv, STR, "Lock Args", lvid, 9, lvlockargs, lv_lockargs, "Lock args of the LV used by lvmlockd.", 0)
@@ -151,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)
@@ -183,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

@@ -149,11 +149,11 @@ static dm_percent_t _metadata_percent(const struct logical_volume *lv)
/* PV */
GET_PV_STR_PROPERTY_FN(pv_fmt, pv_fmt_dup(pv))
#define _pv_fmt_set prop_not_implemented_set
GET_PV_STR_PROPERTY_FN(pv_uuid, pv_uuid_dup(pv))
GET_PV_STR_PROPERTY_FN(pv_uuid, pv_uuid_dup(pv->vg->vgmem, pv))
#define _pv_uuid_set prop_not_implemented_set
GET_PV_NUM_PROPERTY_FN(dev_size, SECTOR_SIZE * pv_dev_size(pv))
#define _dev_size_set prop_not_implemented_set
GET_PV_STR_PROPERTY_FN(pv_name, pv_name_dup(pv))
GET_PV_STR_PROPERTY_FN(pv_name, pv_name_dup(pv->vg->vgmem, pv))
#define _pv_name_set prop_not_implemented_set
GET_PV_NUM_PROPERTY_FN(pv_mda_free, SECTOR_SIZE * pv_mda_free(pv))
#define _pv_mda_free_set prop_not_implemented_set
@@ -264,7 +264,7 @@ GET_PV_NUM_PROPERTY_FN(pv_ba_size, SECTOR_SIZE * pv->ba_size)
#define _cache_write_misses_get prop_not_implemented_get
/* LV */
GET_LV_STR_PROPERTY_FN(lv_uuid, lv_uuid_dup(lv))
GET_LV_STR_PROPERTY_FN(lv_uuid, lv_uuid_dup(lv->vg->vgmem, lv))
#define _lv_uuid_set prop_not_implemented_set
GET_LV_STR_PROPERTY_FN(lv_name, lv_name_dup(lv->vg->vgmem, lv))
#define _lv_name_set prop_not_implemented_set
@@ -298,6 +298,8 @@ GET_LV_NUM_PROPERTY_FN(seg_count, dm_list_size(&lv->segments))
#define _seg_count_set prop_not_implemented_set
GET_LV_STR_PROPERTY_FN(origin, lv_origin_dup(lv->vg->vgmem, lv))
#define _origin_set prop_not_implemented_set
GET_LV_STR_PROPERTY_FN(origin_uuid, lv_origin_uuid_dup(lv->vg->vgmem, lv))
#define _origin_uuid_set prop_not_implemented_set
GET_LV_NUM_PROPERTY_FN(origin_size, (SECTOR_SIZE * lv_origin_size(lv)))
#define _origin_size_set prop_not_implemented_set
#define _lv_ancestors_set prop_not_implemented_set
@@ -322,20 +324,32 @@ GET_LV_STR_PROPERTY_FN(raid_sync_action, _raidsyncaction(lv))
#define _raid_sync_action_set prop_not_implemented_set
GET_LV_STR_PROPERTY_FN(move_pv, lv_move_pv_dup(lv->vg->vgmem, lv))
#define _move_pv_set prop_not_implemented_set
GET_LV_STR_PROPERTY_FN(move_pv_uuid, lv_move_pv_uuid_dup(lv->vg->vgmem, lv))
#define _move_pv_uuid_set prop_not_implemented_set
GET_LV_STR_PROPERTY_FN(convert_lv, lv_convert_lv_dup(lv->vg->vgmem, lv))
#define _convert_lv_set prop_not_implemented_set
GET_LV_STR_PROPERTY_FN(convert_lv_uuid, lv_convert_lv_uuid_dup(lv->vg->vgmem, lv))
#define _convert_lv_uuid_set prop_not_implemented_set
GET_LV_STR_PROPERTY_FN(lv_tags, lv_tags_dup(lv))
#define _lv_tags_set prop_not_implemented_set
GET_LV_STR_PROPERTY_FN(mirror_log, lv_mirror_log_dup(lv->vg->vgmem, lv))
#define _mirror_log_set prop_not_implemented_set
GET_LV_STR_PROPERTY_FN(mirror_log_uuid, lv_mirror_log_uuid_dup(lv->vg->vgmem, lv))
#define _mirror_log_uuid_set prop_not_implemented_set
GET_LV_STR_PROPERTY_FN(lv_modules, lv_modules_dup(lv->vg->vgmem, lv))
#define _lv_modules_set prop_not_implemented_set
GET_LV_STR_PROPERTY_FN(data_lv, lv_data_lv_dup(lv->vg->vgmem, lv))
#define _data_lv_set prop_not_implemented_set
GET_LV_STR_PROPERTY_FN(data_lv_uuid, lv_data_lv_uuid_dup(lv->vg->vgmem, lv))
#define _data_lv_uuid_set prop_not_implemented_set
GET_LV_STR_PROPERTY_FN(metadata_lv, lv_metadata_lv_dup(lv->vg->vgmem, lv))
#define _metadata_lv_set prop_not_implemented_set
GET_LV_STR_PROPERTY_FN(metadata_lv_uuid, lv_metadata_lv_uuid_dup(lv->vg->vgmem, lv))
#define _metadata_lv_uuid_set prop_not_implemented_set
GET_LV_STR_PROPERTY_FN(pool_lv, lv_pool_lv_dup(lv->vg->vgmem, lv))
#define _pool_lv_set prop_not_implemented_set
GET_LV_STR_PROPERTY_FN(pool_lv_uuid, lv_pool_lv_uuid_dup(lv->vg->vgmem, lv))
#define _pool_lv_uuid_set prop_not_implemented_set
GET_LV_NUM_PROPERTY_FN(data_percent, _data_percent(lv))
#define _data_percent_set prop_not_implemented_set
GET_LV_NUM_PROPERTY_FN(metadata_percent, _metadata_percent(lv))
@@ -406,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))
@@ -449,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

@@ -1271,6 +1271,18 @@ static int _chars_disp(struct dm_report *rh, struct dm_pool *mem __attribute__((
return dm_report_field_string(rh, field, (const char * const *) &data);
}
static int _uuid_disp(struct dm_report *rh __attribute__((unused)), struct dm_pool *mem,
struct dm_report_field *field,
const void *data, void *private __attribute__((unused)))
{
char *repstr;
if (!(repstr = id_format_and_copy(mem, data)))
return_0;
return _field_set_value(field, repstr, NULL);
}
static int _dev_name_disp(struct dm_report *rh, struct dm_pool *mem __attribute__((unused)),
struct dm_report_field *field,
const void *data, void *private __attribute__((unused)))
@@ -1292,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)))
@@ -1304,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)
@@ -1543,17 +1579,37 @@ static int _segtype_disp(struct dm_report *rh __attribute__((unused)),
return _field_set_value(field, name, NULL);
}
static int _do_loglv_disp(struct dm_report *rh, struct dm_pool *mem __attribute__((unused)),
struct dm_report_field *field,
const void *data, void *private __attribute__((unused)),
int uuid)
{
const struct logical_volume *lv = (const struct logical_volume *) data;
const char *repstr = NULL;
if (uuid)
repstr = lv_mirror_log_uuid_dup(mem, lv);
else
repstr = lv_mirror_log_dup(mem, lv);
if (repstr)
return dm_report_field_string(rh, field, &repstr);
return _field_set_value(field, "", NULL);
}
static int _loglv_disp(struct dm_report *rh, struct dm_pool *mem __attribute__((unused)),
struct dm_report_field *field,
const void *data, void *private __attribute__((unused)))
{
const struct logical_volume *lv = (const struct logical_volume *) data;
const char *name;
return _do_loglv_disp(rh, mem, field, data, private, 0);
}
if ((name = lv_mirror_log_dup(mem, lv)))
return dm_report_field_string(rh, field, &name);
return _field_set_value(field, "", NULL);
static int _loglvuuid_disp(struct dm_report *rh, struct dm_pool *mem __attribute__((unused)),
struct dm_report_field *field,
const void *data, void *private __attribute__((unused)))
{
return _do_loglv_disp(rh, mem, field, data, private, 1);
}
static int _lvname_disp(struct dm_report *rh, struct dm_pool *mem,
@@ -1612,15 +1668,52 @@ static int _lvparent_disp(struct dm_report *rh, struct dm_pool *mem,
return _field_set_value(field, repstr, NULL);
}
static int _datalv_disp(struct dm_report *rh, struct dm_pool *mem __attribute__((unused)),
struct dm_report_field *field,
const void *data, void *private __attribute__((unused)))
static int _do_datalv_disp(struct dm_report *rh, struct dm_pool *mem __attribute__((unused)),
struct dm_report_field *field,
const void *data, void *private __attribute__((unused)),
int uuid)
{
const struct logical_volume *lv = (const struct logical_volume *) data;
const struct lv_segment *seg = (lv_is_pool(lv)) ? first_seg(lv) : NULL;
if (seg)
return _lvname_disp(rh, mem, field, seg_lv(seg, 0), private);
if (seg) {
if (uuid)
return _uuid_disp(rh, mem, field, &seg_lv(seg, 0)->lvid.id[1], private);
else
return _lvname_disp(rh, mem, field, seg_lv(seg, 0), private);
}
return _field_set_value(field, "", NULL);
}
static int _datalv_disp(struct dm_report *rh, struct dm_pool *mem __attribute__((unused)),
struct dm_report_field *field,
const void *data, void *private __attribute__((unused)))
{
return _do_datalv_disp(rh, mem, field, data, private, 0);
}
static int _datalvuuid_disp(struct dm_report *rh, struct dm_pool *mem __attribute__((unused)),
struct dm_report_field *field,
const void *data, void *private __attribute__((unused)))
{
return _do_datalv_disp(rh, mem, field, data, private, 1);
}
static int _do_metadatalv_disp(struct dm_report *rh, struct dm_pool *mem __attribute__((unused)),
struct dm_report_field *field,
const void *data, void *private __attribute__((unused)),
int uuid)
{
const struct logical_volume *lv = (const struct logical_volume *) data;
const struct lv_segment *seg = (lv_is_pool(lv)) ? first_seg(lv) : NULL;
if (seg) {
if (uuid)
return _uuid_disp(rh, mem, field, &seg->metadata_lv->lvid.id[1], private);
else
return _lvname_disp(rh, mem, field, seg->metadata_lv, private);
}
return _field_set_value(field, "", NULL);
}
@@ -1629,11 +1722,31 @@ static int _metadatalv_disp(struct dm_report *rh, struct dm_pool *mem __attribut
struct dm_report_field *field,
const void *data, void *private __attribute__((unused)))
{
const struct logical_volume *lv = (const struct logical_volume *) data;
const struct lv_segment *seg = (lv_is_pool(lv)) ? first_seg(lv) : NULL;
return _do_metadatalv_disp(rh, mem, field, data, private, 0);
}
if (seg)
return _lvname_disp(rh, mem, field, seg->metadata_lv, private);
static int _metadatalvuuid_disp(struct dm_report *rh, struct dm_pool *mem __attribute__((unused)),
struct dm_report_field *field,
const void *data, void *private __attribute__((unused)))
{
return _do_metadatalv_disp(rh, mem, field, data, private, 1);
}
static int _do_poollv_disp(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field,
const void *data, void *private,
int uuid)
{
const struct logical_volume *lv = (const struct logical_volume *) data;
struct lv_segment *seg = (lv_is_thin_volume(lv) || lv_is_cache(lv)) ?
first_seg(lv) : NULL;
if (seg) {
if (uuid)
return _uuid_disp(rh, mem, field, &seg->pool_lv->lvid.id[1], private);
else
return _lvname_disp(rh, mem, field, seg->pool_lv, private);
}
return _field_set_value(field, "", NULL);
}
@@ -1642,14 +1755,14 @@ static int _poollv_disp(struct dm_report *rh, struct dm_pool *mem __attribute__(
struct dm_report_field *field,
const void *data, void *private __attribute__((unused)))
{
const struct logical_volume *lv = (const struct logical_volume *) data;
struct lv_segment *seg = (lv_is_thin_volume(lv) || lv_is_cache(lv)) ?
first_seg(lv) : NULL;
return _do_poollv_disp(rh, mem, field, data, private, 0);
}
if (seg)
return _lvname_disp(rh, mem, field, seg->pool_lv, private);
return _field_set_value(field, "", NULL);
static int _poollvuuid_disp(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field,
const void *data, void *private __attribute__((unused)))
{
return _do_poollv_disp(rh, mem, field, data, private, 1);
}
static int _lvpath_disp(struct dm_report *rh, struct dm_pool *mem,
@@ -1678,26 +1791,44 @@ static int _lvdmpath_disp(struct dm_report *rh, struct dm_pool *mem,
return _field_set_value(field, repstr, NULL);
}
static int _do_origin_disp(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field,
const void *data, void *private,
int uuid)
{
const struct logical_volume *lv = (const struct logical_volume *) data;
const struct lv_segment *seg = first_seg(lv);
struct logical_volume *origin;
if (lv_is_cow(lv))
origin = origin_from_cow(lv);
else if (lv_is_cache(lv) && !lv_is_pending_delete(lv))
origin = seg_lv(seg, 0);
else if (lv_is_thin_volume(lv) && first_seg(lv)->origin)
origin = first_seg(lv)->origin;
else if (lv_is_thin_volume(lv) && first_seg(lv)->external_lv)
origin = first_seg(lv)->external_lv;
else
return _field_set_value(field, "", NULL);
if (uuid)
return _uuid_disp(rh, mem, field, &origin->lvid.id[1], private);
else
return _lvname_disp(rh, mem, field, origin, private);
}
static int _origin_disp(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field,
const void *data, void *private)
{
const struct logical_volume *lv = (const struct logical_volume *) data;
const struct lv_segment *seg = first_seg(lv);
return _do_origin_disp(rh, mem, field, data, private, 0);
}
if (lv_is_cow(lv))
return _lvname_disp(rh, mem, field, origin_from_cow(lv), private);
if (lv_is_cache(lv) && !lv_is_pending_delete(lv))
return _lvname_disp(rh, mem, field, seg_lv(seg, 0), private);
if (lv_is_thin_volume(lv) && first_seg(lv)->origin)
return _lvname_disp(rh, mem, field, first_seg(lv)->origin, private);
if (lv_is_thin_volume(lv) && first_seg(lv)->external_lv)
return _lvname_disp(rh, mem, field, first_seg(lv)->external_lv, private);
return _field_set_value(field, "", NULL);
static int _originuuid_disp(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field,
const void *data, void *private)
{
return _do_origin_disp(rh, mem, field, data, private, 1);
}
static int _find_ancestors(struct _str_list_append_baton *ancestors,
@@ -1800,15 +1931,54 @@ static int _lvdescendants_disp(struct dm_report *rh, struct dm_pool *mem,
return _field_set_string_list(rh, field, descendants.result, private, 0);
}
static int _do_movepv_disp(struct dm_report *rh, struct dm_pool *mem __attribute__((unused)),
struct dm_report_field *field,
const void *data, void *private __attribute__((unused)),
int uuid)
{
const struct logical_volume *lv = (const struct logical_volume *) data;
const char *repstr;
if (uuid)
repstr = lv_move_pv_uuid_dup(mem, lv);
else
repstr = lv_move_pv_dup(mem, lv);
if (repstr)
return dm_report_field_string(rh, field, &repstr);
return _field_set_value(field, "", NULL);
}
static int _movepv_disp(struct dm_report *rh, struct dm_pool *mem __attribute__((unused)),
struct dm_report_field *field,
const void *data, void *private __attribute__((unused)))
{
const struct logical_volume *lv = (const struct logical_volume *) data;
const char *name;
return _do_movepv_disp(rh, mem, field, data, private, 0);
}
if ((name = lv_move_pv_dup(mem, lv)))
return dm_report_field_string(rh, field, &name);
static int _movepvuuid_disp(struct dm_report *rh, struct dm_pool *mem __attribute__((unused)),
struct dm_report_field *field,
const void *data, void *private __attribute__((unused)))
{
return _do_movepv_disp(rh, mem, field, data, private, 1);
}
static int _do_convertlv_disp(struct dm_report *rh, struct dm_pool *mem __attribute__((unused)),
struct dm_report_field *field,
const void *data, void *private __attribute__((unused)),
int uuid)
{
const struct logical_volume *lv = (const struct logical_volume *) data;
const char *repstr;
if (uuid)
repstr = lv_convert_lv_uuid_dup(mem, lv);
else
repstr = lv_convert_lv_dup(mem, lv);
if (repstr)
return dm_report_field_string(rh, field, &repstr);
return _field_set_value(field, "", NULL);
}
@@ -1817,13 +1987,14 @@ static int _convertlv_disp(struct dm_report *rh, struct dm_pool *mem __attribute
struct dm_report_field *field,
const void *data, void *private __attribute__((unused)))
{
const struct logical_volume *lv = (const struct logical_volume *) data;
const char *name;
return _do_convertlv_disp(rh, mem, field, data, private, 0);
}
if ((name = lv_convert_lv_dup(mem, lv)))
return dm_report_field_string(rh, field, &name);
return _field_set_value(field, "", NULL);
static int _convertlvuuid_disp(struct dm_report *rh, struct dm_pool *mem __attribute__((unused)),
struct dm_report_field *field,
const void *data, void *private __attribute__((unused)))
{
return _do_convertlv_disp(rh, mem, field, data, private, 1);
}
static int _size32_disp(struct dm_report *rh __attribute__((unused)), struct dm_pool *mem,
@@ -2187,30 +2358,16 @@ static int _vglockargs_disp(struct dm_report *rh, struct dm_pool *mem,
return _string_disp(rh, mem, field, &repstr, private);
}
static int _uuid_disp(struct dm_report *rh __attribute__((unused)), struct dm_pool *mem,
struct dm_report_field *field,
const void *data, void *private __attribute__((unused)))
{
char *repstr;
if (!(repstr = id_format_and_copy(mem, data)))
return_0;
return _field_set_value(field, repstr, NULL);
}
static int _pvuuid_disp(struct dm_report *rh __attribute__((unused)), struct dm_pool *mem,
struct dm_report_field *field,
const void *data, void *private __attribute__((unused)))
{
const struct label *label = (const struct label *) data;
const char *repstr = "";
if (label->dev &&
!(repstr = id_format_and_copy(mem, (const struct id *) label->dev->pvid)))
return_0;
if (!label->dev)
return _field_set_value(field, "", NULL);
return _field_set_value(field, repstr, NULL);
return _uuid_disp(rh, mem, field, label->dev->pvid, private);
}
static int _pvmdas_disp(struct dm_report *rh, struct dm_pool *mem,
@@ -2281,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)
@@ -3228,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;
@@ -620,6 +625,15 @@ static int _thin_target_percent(void **target_state __attribute__((unused)),
/* Pool allocates whole chunk so round-up to nearest one */
csize = first_seg(seg->pool_lv)->chunk_size;
csize = ((seg->lv->size + csize - 1) / csize) * csize;
if (s->mapped_sectors > csize) {
log_warn("WARNING: LV %s maps %s while the size is only %s.",
display_lvname(seg->lv),
display_size(cmd, s->mapped_sectors),
display_size(cmd, csize));
/* Don't show nonsense numbers like i.e. 1000% full */
s->mapped_sectors = csize;
}
*percent = dm_make_percent(s->mapped_sectors, csize);
*total_denominator += csize;
} else {

View File

@@ -140,7 +140,7 @@ int id_valid(struct id *id)
for (i = 0; i < ID_LEN; i++)
if (!_inverse_c[id->uuid[i]]) {
log_error("UUID contains invalid character");
log_error("UUID contains invalid character '%c'", id->uuid[i]);
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

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