1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-09-26 01:44:19 +03:00

Compare commits

...

539 Commits

Author SHA1 Message Date
Alasdair Kergon
b9f5a18a76 Add regex functions to library. 2007-04-27 18:40:23 +00:00
Alasdair Kergon
d3f157f08a configure.h isn't a system header 2007-04-27 18:01:45 +00:00
Alasdair Kergon
2294fdb496 Change some #include lines to search only standard system directories. 2007-04-27 17:46:16 +00:00
Alasdair Kergon
d7ba0e01a5 Avoid trailing separator in reports when there are hidden sort fields. 2007-04-27 15:22:27 +00:00
Alasdair Kergon
b6172b53fd Fix segfault in 'dmsetup status' without --showkeys against crypt target. [nec] 2007-04-27 15:12:26 +00:00
Alasdair Kergon
477ec611d5 Deal with some more compiler warnings. Hope this doesn't break anything... 2007-04-27 14:52:41 +00:00
Alasdair Kergon
b6194edd67 add preferred_names to man page. 2007-04-26 17:14:57 +00:00
Alasdair Kergon
dcdbbb3ecb Add devices/preferred_names config regex list for displayed device names.
Free a temporary dir string in fcntl_lock_file() after use.
Fix a dm_pool_destroy() in matcher_create().
Introduce goto_bad macro.
2007-04-26 16:44:59 +00:00
Dave Wysochanski
7ef99ee4e6 Fix warnings on x86_64 involving ptrdiff_t:
config/config.c:493: warning: format '%d' expects type 'int', but argument 5 has type 'long int'

Modified original patch from Jim Meyering <jim@meyering.net>
2007-04-26 16:40:46 +00:00
Dave Wysochanski
1ac1418286 Update pvck to include text metadata area and record detection.
--
2007-04-25 21:10:55 +00:00
Dave Wysochanski
8fc854f38e Add support functions for analysis of config sections,
and hence, on-disk LVM2 metadata.

--
2007-04-25 20:38:39 +00:00
Dave Wysochanski
1c2360b335 Update pvck to read labels on disk, with flexible --labelsector
parameter.

--
2007-04-25 20:03:16 +00:00
Dave Wysochanski
dd4477406b Add count_chars and count_chars_len functions, two
generic string utility functions.

--
2007-04-25 18:24:19 +00:00
Bryn M. Reeves
9d67bbb104 Make lvm_dump.sh capture a listing of /sys/block entries. 2007-04-25 14:49:27 +00:00
Patrick Caulfield
d6c8e1df61 Fix thread race in clvmd. 2007-04-24 15:13:13 +00:00
Petr Rockai
5ec7c8fece Fix the regression introduced by dmeventd leak fixes. 2007-04-24 13:29:02 +00:00
Dave Wysochanski
86b21eaf83 Add 'scan_sector' parameter to label_read and _find_labeller to add
flexibility in searching for disk labels.
2007-04-23 18:21:01 +00:00
Petr Rockai
228486a971 Fix some memory leaks in dmeventd. 2007-04-23 15:06:03 +00:00
Patrick Caulfield
88c0caab26 Make clvmd cope with quorum devices in RHEL5
bz#237386
2007-04-23 14:55:28 +00:00
Bryn M. Reeves
5cd4679419 re-commit lvm_dump.sh change 2007-04-19 23:06:05 +00:00
Bryn M. Reeves
eeed5e0d19 Make lvm_dump.sh list /dev recursively to aid identifying devices. 2007-04-19 22:56:16 +00:00
Alasdair Kergon
369ab1e0b2 Introduce _add_field() and _is_same_field() to libdm-report.c. 2007-04-19 20:24:00 +00:00
Milan Broz
2e21519a10 Fix libdevmapper-event memory leaks 2007-04-19 19:10:19 +00:00
Dave Wysochanski
ecc001ed08 Add dev_read_circular, read 2 regions on same device. 2007-04-19 02:10:42 +00:00
Dave Wysochanski
cd96852696 Add stub for pvck, a command to check physical volume consistency. 2007-03-30 21:00:26 +00:00
Patrick Caulfield
b9f7f30158 Add some extra error checking & robustness.
Thanks to the Crosswalk engineering team:
    Leonard Maiorani
    Henry Harris
    Scott Cannata
2007-03-29 13:59:33 +00:00
Alasdair Kergon
ca5e423331 Update lists of attribute characters in man pages.
Change cling alloc policy attribute character from 'C' to l'.
2007-03-27 13:35:33 +00:00
Milan Broz
fa9407089c Fix creation and conversion of mirrors with tags. 2007-03-26 16:10:10 +00:00
Milan Broz
66f28e193a Fix vgsplit for lvm1 format (set and validate VG name in PVs metadata).
Split metadata areas in vgsplit properly.
2007-03-23 12:43:17 +00:00
Alasdair Kergon
0d93f89f5c post-release 2007-03-19 21:16:49 +00:00
Alasdair Kergon
154e9a2c47 pre-release 2007-03-19 21:12:54 +00:00
Milan Broz
84574a1257 Fix processing of exit status in init scripts 2007-03-16 17:15:36 +00:00
Alasdair Kergon
bf83527b64 Remove unnecessary memset() return value checks. [Jim Meyering] 2007-03-16 14:36:14 +00:00
Milan Broz
12c53622a0 Fix vgremove to require at least one vg argument. 2007-03-15 14:00:30 +00:00
Alasdair Kergon
d8f54cf891 Try to fix reading in of lvm1 striped LVs.
There are two fixes other than improving variable names and updating code
layout etc.
The loop counter is incremented by area_len instead of area_len * stripes;
the 3rd _check_stripe parameter is no longer multiplied by number of stripes.
2007-03-15 13:38:28 +00:00
Patrick Caulfield
625a671189 Flag nolocking as a clustered locking module as we need to be able
to look at clustered LVs at clvmd startup
2007-03-13 14:59:21 +00:00
Alasdair Kergon
6ebdad3102 Add a few missing pieces of vgname command line validation. 2007-03-09 21:25:33 +00:00
Alasdair Kergon
9a8f21aa03 Support the /dev/mapper prefix on most command lines. 2007-03-09 20:47:41 +00:00
Alasdair Kergon
291dd8edc2 post-release 2007-03-08 21:37:48 +00:00
Alasdair Kergon
de4c1daf29 pre-release 2007-03-08 21:28:13 +00:00
Alasdair Kergon
0b55d7d0d8 Fix vgrename active LV check to ignore differing vgids. 2007-03-08 21:08:25 +00:00
Alasdair Kergon
5d86fd8fdb Remove no-longer-used uuid_out parameter from activation info functions. 2007-03-08 19:58:04 +00:00
Alasdair Kergon
1b76eb1f59 Fix two more segfaults if an empty config file section encountered. 2007-03-08 19:22:52 +00:00
Alasdair Kergon
b05678d8bf Move .cache file into a new /etc/lvm/cache directory by default.
Add devices/cache_dir & devices/cache_file_prefix, deprecating devices/cache.
Create directory in fcntl_lock_file() if required.
2007-02-28 18:27:13 +00:00
Alasdair Kergon
781f4971c6 Exclude readline support from lvm.static 2007-02-14 16:51:48 +00:00
Alasdair Kergon
d02ac7b99a Fix a leak in a reporting error path. 2007-02-14 15:18:31 +00:00
Alasdair Kergon
b1b6c97f7c Fix a few leaks in reporting error paths. 2007-02-14 15:12:16 +00:00
Alasdair Kergon
baee28ab5c post-release 2007-02-13 16:16:15 +00:00
Alasdair Kergon
83edf68ff9 pre-release 2007-02-13 16:12:24 +00:00
Alasdair Kergon
c7588f91dd Correct -b and -P on a couple of man pages.
Add global/units to example.conf.
2007-02-13 16:04:01 +00:00
Alasdair Kergon
30b432adc5 Fix loading of segment_libraries. [gentoo] 2007-02-08 17:31:02 +00:00
Alasdair Kergon
7c9733eb5d If a PV reappears after it was removed from its VG, make it an orphan. 2007-02-07 13:29:52 +00:00
Alasdair Kergon
a223c3fea3 Improve dmeventd messaging protocol: drain pipe and tag messages. 2007-02-02 17:08:51 +00:00
Alasdair Kergon
d5250f4901 Fix some &->&& vgreduce cmdline validation. [Andre Noll] 2007-01-31 16:26:23 +00:00
Alasdair Kergon
25f29f4712 post-release 2007-01-30 21:37:18 +00:00
Alasdair Kergon
382af5563d pre-release 2007-01-30 18:08:17 +00:00
Alasdair Kergon
8cf3d165d3 Add warning to lvm2_monitoring_init_rhel4 if attempting to stop monitoring. 2007-01-30 18:02:15 +00:00
Alasdair Kergon
0fd6ce546f Fix vgsplit to handle mirrors.
Reorder fields in reporting field definitions.
2007-01-29 23:01:18 +00:00
Alasdair Kergon
b881c372bc post-release 2007-01-29 20:25:19 +00:00
Alasdair Kergon
94c5e7deb0 pre-release 2007-01-29 19:57:24 +00:00
Alasdair Kergon
c344766f3c Add recent reporting options to dmsetup man page.
Revise some report fields names.
2007-01-29 19:35:24 +00:00
Alasdair Kergon
67895de0bc help on help 2007-01-29 18:45:08 +00:00
Alasdair Kergon
ff00cb6990 help unused attr 2007-01-29 18:43:27 +00:00
Alasdair Kergon
2cc75c11ed add help -c for field list 2007-01-29 18:37:57 +00:00
Alasdair Kergon
cd79e58eda Add dmsetup 'help' command and update usage text. 2007-01-29 18:18:41 +00:00
Alasdair Kergon
6fa801f3d8 reorder report field definitions 2007-01-29 17:45:32 +00:00
Alasdair Kergon
684eecba1d Use fixed-size fields in report interface. 2007-01-29 17:23:54 +00:00
Alasdair Kergon
da9cf7e5de fix pvsegs report too 2007-01-27 02:32:31 +00:00
Alasdair Kergon
f57e7445fd Fix vgs to treat args as VGs even when PV fields are displayed. 2007-01-27 02:09:06 +00:00
Alasdair Kergon
fba1388719 Fix md signature check to handle both endiannesses. 2007-01-26 17:15:16 +00:00
Alasdair Kergon
80ed029c17 post-release 2007-01-25 23:40:33 +00:00
Alasdair Kergon
34a74e81e3 pre-release 2007-01-25 23:36:59 +00:00
Alasdair Kergon
cb120ddb15 dmeventd mirror sets ignore_suspended_devices and avoids scanning mirrors. 2007-01-25 23:32:29 +00:00
Alasdair Kergon
f9ee4395b0 also ignore mirrors 2007-01-25 23:03:48 +00:00
Alasdair Kergon
71f06d51ed Add devices/ignore_suspended_devices to ignore suspended dm devices. 2007-01-25 21:22:30 +00:00
Alasdair Kergon
217f70952f don't remove libdm-common.h any more 2007-01-25 15:45:10 +00:00
Alasdair Kergon
f813d41a76 Add some missing close() and fclose() return code checks.
Fix exit statuses of reporting tools (2.02.19).
2007-01-25 14:37:48 +00:00
Alasdair Kergon
d851289d8a Add some missing close() and fclose() return value checks. 2007-01-25 14:16:20 +00:00
Alasdair Kergon
b115b8a2ea Add init script for dmeventd monitoring. 2007-01-24 23:44:43 +00:00
Alasdair Kergon
d0f7067471 lvm.static no longer interacts with dmeventd unless explicitly asked to. 2007-01-24 23:43:27 +00:00
Alasdair Kergon
be5b4c38a7 fix earlier checkin 2007-01-24 22:06:11 +00:00
Alasdair Kergon
d6d597e3dd Migrate dmsetup column-based output over to new libdevmapper report framework. 2007-01-24 18:09:07 +00:00
Alasdair Kergon
84e348fade Add field definitions to report help text.
Remove unnecessary cmd arg from target_*monitor_events().
2007-01-24 16:51:24 +00:00
Alasdair Kergon
910054657e Adjust report field help description layout. 2007-01-24 16:41:33 +00:00
Alasdair Kergon
8357a11249 fix earlier checkin 2007-01-23 23:58:55 +00:00
Alasdair Kergon
9b021ba057 Add descriptions to reporting field definitions. 2007-01-23 19:18:52 +00:00
Alasdair Kergon
317e588efd Add private variable to dmeventd shared library interface. 2007-01-23 17:40:40 +00:00
Alasdair Kergon
b1d32a03c7 add a dso-private variable to dmeventd interface
more inline docn
2007-01-23 17:38:39 +00:00
Alasdair Kergon
ee6e6529ee Long-lived processes write out persistent dev cache in refresh_toolcontext(). 2007-01-23 16:03:54 +00:00
Alasdair Kergon
9d944d6cf9 Fix refresh_toolcontext() always to wipe persistent device filter cache.
Add is_long_lived to toolcontext.
2007-01-23 15:58:06 +00:00
Alasdair Kergon
13635d281a Add --clustered to man pages. 2007-01-23 13:08:34 +00:00
Alasdair Kergon
2493c46970 Streamline dm_report_field_* interface. 2007-01-22 15:07:21 +00:00
Alasdair Kergon
63e4217271 Add dm_event_handler_[gs]et_timeout functions.
Streamline dm_report_field_* interface.
2007-01-22 15:03:57 +00:00
Alasdair Kergon
f4bd12e8e9 register->monitor etc. 2007-01-19 22:21:45 +00:00
Alasdair Kergon
df15f46900 var dev_name->device_name (lvm2 has dev_name()) 2007-01-19 20:42:09 +00:00
Alasdair Kergon
fb3a732361 fix exit status; always print message on child failure 2007-01-19 18:08:36 +00:00
Alasdair Kergon
2d74110feb Add cmdline debug & version options to dmeventd.
Fix oom_adj handling.
2007-01-19 17:22:17 +00:00
Alasdair Kergon
19d102082d Add DM_LIB_VERSION definition to configure.h. 2007-01-19 15:53:01 +00:00
Alasdair Kergon
d2af2c9487 Update reporting man pages. 2007-01-18 22:33:24 +00:00
Alasdair Kergon
82980149fa Suppress 'Unrecognised field' error if report field is 'help'. 2007-01-18 22:15:04 +00:00
Alasdair Kergon
a19bb7b909 fix last checkin 2007-01-18 21:59:02 +00:00
Alasdair Kergon
9d98c3278d No longer necessary to specify alignment for report fields. 2007-01-18 17:48:29 +00:00
Alasdair Kergon
26376ac1c9 Some internal renaming.
Add --separator and --sort to dmsetup (unused as yet).
Make alignment flag optional when specifying report fields.
2007-01-18 17:47:58 +00:00
Alasdair Kergon
8459f99341 post-release 2007-01-17 17:56:15 +00:00
Alasdair Kergon
e5bdb0e0b5 pre-release 2007-01-17 17:51:51 +00:00
Alasdair Kergon
1106b7775a Fix a segfault if an empty config file section encountered. 2007-01-17 16:22:59 +00:00
Alasdair Kergon
ae2852156d merge _target_*register_events
introduce _create_dm_event_handler()
2007-01-17 15:00:57 +00:00
Alasdair Kergon
44c6c36c43 stat oom_adj and stay silent if it doesn't exist
dm_event_handler now keeps private copies of strings
2007-01-17 14:45:10 +00:00
Alasdair Kergon
a81926503d use updated dm_event_get_registered_device interface 2007-01-16 23:05:13 +00:00
Alasdair Kergon
af13ccddda more fixes 2007-01-16 23:03:13 +00:00
Alasdair Kergon
392e1bc2e8 more little fixes 2007-01-16 21:13:07 +00:00
Alasdair Kergon
9268d92c70 clean up global mutex usage and fix a race in thread finalisation code
properly clean up thread status when thread terminates from within
2007-01-16 20:27:07 +00:00
Alasdair Kergon
bb3366c07d dmeventd oom_adj + reduce thread stack size 2007-01-16 20:13:04 +00:00
Alasdair Kergon
d24d563ebc Move basic reporting functions into libdevmapper. 2007-01-16 18:06:12 +00:00
Alasdair Kergon
954bd9257b Add basic reporting functions to libdevmapper. 2007-01-16 18:04:15 +00:00
Alasdair Kergon
5d51a56c02 reduce some if/else complexity 2007-01-15 22:37:40 +00:00
Alasdair Kergon
f48648552e Fix a malloc error path in dmsetup message. 2007-01-15 22:05:50 +00:00
Alasdair Kergon
edb9c3cc9f Fix partition table processing after sparc changes (introduced in 2.02.16).
Fix cmdline PE range processing segfault (introduced in 2.02.13).
2007-01-15 21:55:11 +00:00
Alasdair Kergon
01dc83b936 fix recent checkins 2007-01-15 19:47:49 +00:00
Alasdair Kergon
3a8dff3a62 fail registration if timeout thread cannot be started 2007-01-15 19:19:31 +00:00
Alasdair Kergon
13b234ccba use DMEVENTD_PATH 2007-01-15 19:11:58 +00:00
Alasdair Kergon
e451e93664 static naming 2007-01-15 18:58:40 +00:00
Alasdair Kergon
b4f9531475 Some libdevmapper-event interface changes. 2007-01-15 18:22:02 +00:00
Alasdair Kergon
3184ff75c4 More libdevmapper-event interface changes and fixes.
Rename dm_saprintf() to dm_asprintf().
2007-01-15 18:21:01 +00:00
Alasdair Kergon
43243f4d30 Report error if NULL pointer supplied to dm_strdup_aux(). 2007-01-15 14:39:12 +00:00
Alasdair Kergon
c975a100b1 Report dmeventd mirror monitoring status. 2007-01-12 20:38:30 +00:00
Alasdair Kergon
02bf389425 Reinstate dm_event_get_registered_device 2007-01-12 20:22:11 +00:00
Alasdair Kergon
bcb9a3dd04 post-release 2007-01-11 23:19:08 +00:00
Alasdair Kergon
cce3baa275 pre-release 2007-01-11 22:49:43 +00:00
Alasdair Kergon
2b48fad426 updated dmeventd interface 2007-01-11 22:24:32 +00:00
Alasdair Kergon
d554b2bc94 Lots of dmeventd-related changes. 2007-01-11 21:54:53 +00:00
Alasdair Kergon
f66943de43 fail if status args are missing 2007-01-11 20:11:19 +00:00
Alasdair Kergon
9d1e9bc2fb Remove dmeventd mirror status line word limit 2007-01-11 19:52:06 +00:00
Alasdair Kergon
2d6a014920 Use CFLAGS when linking so mixed sparc builds can supply -m64 2007-01-11 17:12:27 +00:00
Alasdair Kergon
c1952bf257 Use CFLAGS when linking so mixed sparc builds can supply -m64. 2007-01-11 16:23:22 +00:00
Alasdair Kergon
a10227eb03 Prevent permission changes on active mirrors. 2007-01-10 19:56:39 +00:00
Milan Broz
475ae29b85 Print warning instead of error message if cannot zero volume
Update lvconvert man page (snapshot option)
2007-01-10 14:13:46 +00:00
Alasdair Kergon
0b9cfc278b dumpconfig accepts a list of configuration variables to display.
Change dumpconfig to use --file to redirect output to a file.
2007-01-09 23:22:31 +00:00
Alasdair Kergon
b57b6b4fba Avoid vgreduce error when mirror code removes the log LV. 2007-01-09 23:14:35 +00:00
Alasdair Kergon
7d948f7bc5 Remove 3 redundant AC_MSG_RESULTs from configure.in. 2007-01-09 22:07:20 +00:00
Alasdair Kergon
459023d171 Free memory in _raw_read_mda_header() error paths.
Fix ambiguous vgsplit error message for split LV.
Fix lvextend man page typo.
2007-01-09 21:12:41 +00:00
Alasdair Kergon
fd6570720a Add configure --with-dmdir to compile against a device-mapper source tree.
Use no flush suspending for mirrors.
2007-01-09 20:31:08 +00:00
Alasdair Kergon
7831665417 Add dm_tree_use_no_flush_suspend(). 2007-01-09 19:44:07 +00:00
Alasdair Kergon
7c9920d982 fix last checkin 2007-01-08 15:35:08 +00:00
Alasdair Kergon
cbdccf0a9c Lots of dmevent changes.
Export dm_basename().
Cope with a trailing space when comparing tables prior to possible reload.
2007-01-08 15:18:52 +00:00
Alasdair Kergon
64fa83ec3f Add dmeventd_mirror register_mutex, tidy initialisation & add memlock. 2007-01-08 14:24:20 +00:00
Milan Broz
faff865cfd Fix create mirror with name longer than 22 chars. 2007-01-05 15:53:40 +00:00
Alasdair Kergon
742ab55a9a Fix some activate.c prototypes when compiled without devmapper. 2006-12-20 16:19:01 +00:00
Alasdair Kergon
66e623fb2a Fix dmeventd mirror to cope if monitored device disappears. 2006-12-20 14:35:02 +00:00
Alasdair Kergon
4ab17ee965 post-release 2006-12-14 22:21:32 +00:00
Alasdair Kergon
7f48ca5132 pre-release 2006-12-14 20:05:08 +00:00
Alasdair Kergon
da983848b4 Add missing pvremove error message when device doesn't exist. 2006-12-13 18:40:23 +00:00
Alasdair Kergon
bc03f7bad3 When lvconvert allocates a mirror log, respect parallel area constraints.
Use loop to iterate through the now-ordered policy list in _allocate().
Check for failure to allocate just the mirror log.
Introduce calc_area_multiple().
Support mirror log allocation when there is only one PV: area_count now 0.

(See lvm-devel list archives for further details.)
2006-12-13 03:39:58 +00:00
Alasdair Kergon
a1c8bd3846 Fix detection of smallest area in _alloc_parallel_area() for cling policy. 2006-12-12 19:30:10 +00:00
Patrick Caulfield
404bc284e0 Add manpage reference for clvmd -T that got missed out when I
checked the code in (sorry).
2006-12-11 14:06:25 +00:00
Patrick Caulfield
9dee30ff0e Fix gulm operation of clvmd. including a hang when attempting to
exclusively lock an LV that is already locked no another node.
2006-12-11 14:00:26 +00:00
Patrick Caulfield
f91aadbea8 Fix hang in clvmd if a pre-command failed. The pre/post thread was getting
out of sync in this instance and would not quit.
2006-12-11 13:48:41 +00:00
Alasdair Kergon
aa15a10c91 post-release 2006-12-01 23:29:54 +00:00
Alasdair Kergon
5b03e36351 pre release 2006-12-01 23:15:59 +00:00
Alasdair Kergon
b9ba9ffad2 clvmd ia64 alignment fixes etc. (pjc) 2006-12-01 23:10:26 +00:00
Alasdair Kergon
642be5d16c Fix VG clustered read locks to use PR not CR.
VG metadata reads were not being locked out during metadata updates.
2006-12-01 22:48:47 +00:00
Alasdair Kergon
ee68d715bf Adjust some alignments for ia64 and sparc.
(Some of the changes are probably unnecessary.)
2006-11-30 23:11:42 +00:00
Alasdair Kergon
224084f056 Fix mirror segment removal to use temporary error segment. 2006-11-30 17:52:47 +00:00
Patrick Caulfield
1cd8c849b8 Always compile debug logging into clvmd as it's too useful to
restrict to just developers.
-d will switch it on and run the daemon in the foreground
2006-11-30 13:19:42 +00:00
Patrick Caulfield
169f68bfcd Add timeout to RHEL4 clvmd init script.
With the previous clvmd checkin this should address bz#187812
2006-11-30 10:16:48 +00:00
Patrick Caulfield
d2b7cfa2d1 Add -T (startup timeout) switch to clvmd 2006-11-30 09:44:07 +00:00
Alasdair Kergon
a40c7dff5d post-release 2006-11-28 22:51:01 +00:00
Alasdair Kergon
e8e00630d3 pre-release 2006-11-28 22:49:58 +00:00
Alasdair Kergon
e33720c854 Update dmsetup man page (setgeometry & message) 2006-11-23 20:34:16 +00:00
Alasdair Kergon
bd8a4e0d17 mention new env vars on man page 2006-11-23 17:44:15 +00:00
Alasdair Kergon
586a2aef76 Improve lvm_dump.sh robustness. 2006-11-23 17:23:14 +00:00
Alasdair Kergon
ce1d8f6754 Update lvm2create_initrd to support gentoo. 2006-11-21 22:41:56 +00:00
Alasdair Kergon
7b0f401065 . 2006-11-21 17:46:11 +00:00
Alasdair Kergon
8387016eef Fix clvmd_init_rhel4 line truncation (2.02.14). 2006-11-21 17:44:46 +00:00
Alasdair Kergon
4e1342b641 fix _find_config_node: null parameter is permitted 2006-11-21 15:13:36 +00:00
Alasdair Kergon
e45a184d90 post-release 2006-11-20 23:30:45 +00:00
Alasdair Kergon
979e1012d2 Install lvmdump by default. 2006-11-20 20:03:26 +00:00
Alasdair Kergon
fe10a50e23 pre-release 2006-11-20 19:33:03 +00:00
Alasdair Kergon
8ab6d72519 Fix check for snapshot module when activating snapshot. 2006-11-20 16:45:45 +00:00
Alasdair Kergon
3aada6dd1d Fix pvremove error path for case when PV is in use. 2006-11-17 02:45:51 +00:00
Alasdair Kergon
0933036366 Warn if certain duplicate config file entries are seen.
(not thoroughly tested)
2006-11-16 17:36:00 +00:00
Alasdair Kergon
05f5abdc06 Enhance lvm_dump.sh for sysreport integration and add man page. 2006-11-16 16:44:48 +00:00
Alasdair Kergon
fb875e0709 Fix --autobackup argument which could never disable backups. 2006-11-14 15:28:50 +00:00
Alasdair Kergon
9acdc2f6bf Fix a label_verify error path. 2006-11-14 15:03:07 +00:00
Alasdair Kergon
028ce4bff6 post-release 2006-11-10 21:27:51 +00:00
Alasdair Kergon
3f245ad6db pre-release 2006-11-10 21:22:34 +00:00
Alasdair Kergon
23115f4116 fix cast 2006-11-10 20:15:10 +00:00
Alasdair Kergon
cf5f48e6cc Fix adjusted_mirror_region_size() for 64-bit size. 2006-11-10 19:35:03 +00:00
Alasdair Kergon
997fa756ad Add some missing bounds checks on 32 bit extent counters.
Add Petabyte and Exabyte support.
Fix lvcreate error message when 0 extents requested.
2006-11-10 18:24:11 +00:00
Patrick Caulfield
e23f75b1cc Add note to lvremove man page: volumes must be inactive on
all cluster nodes before being removed.
2006-11-06 14:11:40 +00:00
Alasdair Kergon
6531e88761 Protect .cache manipulations with fcntl locking.
Change .cache timestamp comparisons to use ctime.
2006-11-04 03:34:10 +00:00
Alasdair Kergon
e76a9c2618 fix shift 2006-11-03 21:23:06 +00:00
Alasdair Kergon
45be8a836b fix last check-in: lv->size is in sectors 2006-11-03 21:07:15 +00:00
Alasdair Kergon
954b6032e7 Fix mirror log LV writing to set all bits in whole LV. 2006-11-02 23:33:20 +00:00
Alasdair Kergon
bd95416f27 Fix clustered VG detection and default runlevels in clvmd_init_rhel4. 2006-11-01 18:25:26 +00:00
Alasdair Kergon
df2577ace2 Fix high-level free space check for partial allocations. 2006-10-30 16:10:55 +00:00
Alasdair Kergon
720e6558c9 post-release 2006-10-27 15:37:02 +00:00
Alasdair Kergon
c239f15d8a pre-release 2006-10-27 15:21:07 +00:00
Alasdair Kergon
dfa1f80a57 dd couple of missing files to tools/Makefile CLEAN_TARGETS. 2006-10-26 20:37:13 +00:00
Alasdair Kergon
15dfb93b17 When adding snapshot leave cow LV mapped device active after zeroing. 2006-10-26 18:22:10 +00:00
Alasdair Kergon
0ec8488c2b . 2006-10-24 19:07:32 +00:00
Jonathan Earl Brassow
94b2e29cb1 - likely cut and paste error. Fix wrong function name in debug
output.
2006-10-24 18:49:31 +00:00
Alasdair Kergon
fefa8e9b4d Add dev_flush() to set_lv() 2006-10-24 18:25:30 +00:00
Alasdair Kergon
32c4c44812 resync alphabetical order 2006-10-24 17:19:48 +00:00
Alasdair Kergon
05195e2b1d try forcesync -> resync 2006-10-24 17:18:25 +00:00
Alasdair Kergon
4c2ff675b8 reword --resync desc a bit 2006-10-24 17:09:40 +00:00
Alasdair Kergon
e5692a4721 fix forcesync local active detection 2006-10-24 15:30:33 +00:00
Alasdair Kergon
312e6a0d31 Add lvchange --forcesync. 2006-10-23 23:03:55 +00:00
Alasdair Kergon
5bb8efa41f Perform high-level free space check before each allocation attempt. 2006-10-23 15:54:51 +00:00
Patrick Caulfield
949a835f4a Don't allow a node to remove an LV that's exclusively active on anther node. 2006-10-23 11:46:16 +00:00
Alasdair Kergon
85e6042941 Cope if same PV is included more than once in cmdline PE range list. 2006-10-21 23:18:43 +00:00
Alasdair Kergon
3cd2f28975 getline debug free 2006-10-19 16:50:05 +00:00
Alasdair Kergon
2179a72c3a Suppress encryption key in 'dmsetup table' output unless --showkeys supplied. 2006-10-19 15:34:50 +00:00
Alasdair Kergon
a5f282f156 Set PV size to current device size if it is found to be zero. 2006-10-19 12:53:47 +00:00
Alasdair Kergon
40e8631f63 Add segment parameter to target_present functions. 2006-10-18 18:01:53 +00:00
Alasdair Kergon
9ded05bb97 post-release 2006-10-16 17:18:08 +00:00
Alasdair Kergon
ec8efa35a1 revert 2006-10-16 16:47:56 +00:00
Alasdair Kergon
f72bf20482 pre-release 2006-10-16 16:44:28 +00:00
Alasdair Kergon
ebde2002e8 Fix pvdisplay to use vg_read() for non-orphans 2006-10-16 16:29:40 +00:00
Alasdair Kergon
352a66f46f Fall back to internal locking if external locking lib is missing or fails. 2006-10-14 16:37:54 +00:00
Alasdair Kergon
d84c5391f7 Retain activation state after changing LV minor number with --force. 2006-10-13 21:33:31 +00:00
Alasdair Kergon
f4c582472b post-release.
Note that I've dropped the 2.4 kernel files from the release tarballs now.
2006-10-13 19:01:30 +00:00
Alasdair Kergon
1485586f7e pre-release 2006-10-13 18:43:53 +00:00
Alasdair Kergon
d5c9024335 Avoid deptree attempting to suspend a device that's already suspended. 2006-10-13 14:03:35 +00:00
Alasdair Kergon
860cf80703 Propagate clustered flag in vgsplit and require resizeable flag. 2006-10-13 13:22:44 +00:00
Alasdair Kergon
897ff3161f post-release 2006-10-12 18:20:45 +00:00
Alasdair Kergon
b356b2e501 fix realtime msg alignment 2006-10-12 18:17:09 +00:00
Alasdair Kergon
1d2733c893 pre-release 2006-10-12 18:13:33 +00:00
Alasdair Kergon
32d9126094 . 2006-10-12 17:42:40 +00:00
Alasdair Kergon
db43314e50 missing mesg 2006-10-12 17:41:21 +00:00
Alasdair Kergon
68d2baeb65 pre-release 2006-10-12 17:37:42 +00:00
Alasdair Kergon
1fd5f562d3 noflush code fixes: missing debug log; non-standard variable name 2006-10-12 17:29:05 +00:00
Alasdair Kergon
48e02f2086 remove unused variable 2006-10-12 17:18:40 +00:00
Alasdair Kergon
eab7b2b581 fix dmsetup usage display (missing \n and --noflush wrong place) 2006-10-12 17:09:09 +00:00
Alasdair Kergon
45abade7fc Add suspend noflush support.
Add basic dmsetup loop support.
2006-10-12 15:42:25 +00:00
Alasdair Kergon
5372fc4b43 Test message to lvm-devel list. 2006-10-10 17:20:40 +00:00
Patrick Caulfield
4e2f240c98 Add clvmd call to return the cluster name. 2006-10-09 14:11:57 +00:00
Alasdair Kergon
bb3605518d add cling allocation policy 2006-10-08 12:01:13 +00:00
Alasdair Kergon
3ef6d37f27 . 2006-10-07 23:42:03 +00:00
Alasdair Kergon
88e9f2f7f4 check_contiguous to use for_each_pv 2006-10-07 23:40:36 +00:00
Alasdair Kergon
704a447df9 More work towards pv->size always holding the same value in internal metadata.
Store it in external text metadata as dev_size, and estimate it if not
present when metadata is read back in.
2006-10-07 23:17:17 +00:00
Alasdair Kergon
a5fcb26a33 rely on pv_setup functions to fix up pe_count 2006-10-07 23:06:18 +00:00
Alasdair Kergon
2491a61481 Accept regionsize with lvconvert. 2006-10-07 23:04:36 +00:00
Alasdair Kergon
91831d51ed more refactoring 2006-10-07 16:00:28 +00:00
Alasdair Kergon
174f0c19f7 Extend _for_each_pv() to allow termination without error. 2006-10-07 12:41:06 +00:00
Alasdair Kergon
de6fadfb4f abstract _is_contiguous() 2006-10-07 11:34:53 +00:00
Alasdair Kergon
f946db3e00 move _for_each_pv() 2006-10-07 11:23:22 +00:00
Alasdair Kergon
8d05e5bc31 Remove duplicated pv arg from _check_contiguous(). 2006-10-07 11:00:09 +00:00
Alasdair Kergon
cfb46820e4 Accept regionsize with lvconvert 2006-10-07 10:47:05 +00:00
Alasdair Kergon
081f1cbcc2 Correct regionsize default on lvcreate man page (MB). 2006-10-07 10:43:40 +00:00
Alasdair Kergon
7bc6da326f Add report columns with underscore before field names ending 'size'. 2006-10-07 10:42:27 +00:00
Patrick Caulfield
cd95a0df7b Use strncpy rather than strcpy 2006-10-06 10:06:37 +00:00
Patrick Caulfield
82fa497c16 Fix clvmd bug that could cause it to die when a node with a long name crashed. 2006-10-06 10:06:10 +00:00
Alasdair Kergon
44fd345206 Fix format_text mda_setup pv->size and pv_setup pe_count calculations.
(This area of the code needs a lot more work.)
2006-10-05 22:02:52 +00:00
Alasdair Kergon
088e1c9db4 Fix _for_each_pv() for mirror with core log. 2006-10-05 21:24:48 +00:00
Alasdair Kergon
d4f16e666e Add lvm_dump.sh script to create a tarball of debugging info from a system. 2006-10-05 18:42:33 +00:00
Patrick Caulfield
8233cfd371 Vastly improve the errors returned to the user from clvmd.
It now captures the error messages that are generated and returns them
in the reply packet rather than just telling the user to check syslog.
2006-10-05 13:55:50 +00:00
Alasdair Kergon
ff05e2e30d Remove unused #defines from filter-md.c. 2006-10-04 16:03:17 +00:00
Patrick Caulfield
a8ea7dd3fb Make clvmd restart init script wait until clvmd has died before starting it. 2006-10-04 08:42:14 +00:00
Patrick Caulfield
96f70a5303 Update man page for clvmd -R 2006-10-04 08:28:17 +00:00
Patrick Caulfield
f1604c3e69 Add -R switch to clvmd.
This option will instruct all the clvmd daemons in the cluster to reload their device cache
2006-10-04 08:22:16 +00:00
Alasdair Kergon
c42c8c5192 Test. Future commit messages should now also go to the dm-devel list
(450 subscribers) for discussion as well as the read-only dm-cvs list
(just 15 subscribers).
2006-10-03 21:51:28 +00:00
Alasdair Kergon
5facb53a41 exclude targets that are always built-in 2006-10-03 18:02:06 +00:00
Alasdair Kergon
d039ce89af Add LV column to reports listing kernel modules needed for activation. 2006-10-03 17:55:20 +00:00
Alasdair Kergon
bc7605103f Show available fields if report given invalid field. (e.g. lvs -o list) 2006-10-02 16:46:27 +00:00
Alasdair Kergon
d305d655d4 Fix compiler warnings in percent arg. [pjc] 2006-10-02 16:15:03 +00:00
Alasdair Kergon
4ef1220b16 Add timestamp functions with --disable-realtime configure option. [AJ] 2006-09-30 20:02:02 +00:00
Alasdair Kergon
a4fef143cd Add %VG, %LV and %FREE suffices to lvcreate/lvresize --extents arg.
e.g. lvcreate -l 100%FREE to create an LV using all available space.
     lvextend -l 50%LV to increase an LV by 50% of its existing size.
     lvcreate -l 20%VG to create an LV using 20% of the total VG size.
2006-09-26 09:35:43 +00:00
Alasdair Kergon
74ecb724a9 Fix two potential NULL pointer derefs in error cases in vg_read(). 2006-09-21 20:25:54 +00:00
Alasdair Kergon
af235897ab Separate --enable-cluster from locking lib options in lvmconf.sh. 2006-09-20 17:36:47 +00:00
Alasdair Kergon
5ec4e458b5 Supply missing comma. [via Debian] 2006-09-19 20:20:40 +00:00
Alasdair Kergon
2dae63ce21 post-release 2006-09-19 19:36:59 +00:00
Alasdair Kergon
be748fe33b pre-release 2006-09-19 19:15:10 +00:00
Alasdair Kergon
7408340b6a Fix lvconvert mirror change case detection logic.
Fix mirror log detachment so it correctly becomes a standalone LV.
2006-09-19 19:13:41 +00:00
Alasdair Kergon
29eb92446e post-release 2006-09-19 17:50:58 +00:00
Alasdair Kergon
ae6918742e pre-release 2006-09-19 17:43:03 +00:00
Alasdair Kergon
863484bb65 Reorder mm bounds_check code to reduce window for a dmeventd race. (dm_free_aux) 2006-09-19 17:30:04 +00:00
Alasdair Kergon
1cd7ebce4c Extend _check_contiguous() to detect single-area LVs.
Include mirror log (untested) in _for_each_pv() processing.
Use MIRROR_LOG_SIZE constant.
Remove struct seg_pvs from _for_each_pv() for generalisation.
Avoid adding duplicates to list of parallel PVs to avoid.
2006-09-11 21:14:56 +00:00
Alasdair Kergon
eef8c7862e Fix several incorrect comparisons in parallel area avoidance code.
Fix segment lengths when flattening existing parallel areas.
Log existing parallel areas prior to allocation.
Fix mirror log creation when activation disabled.
2006-09-11 14:24:58 +00:00
Alasdair Kergon
b52375d446 fix vgreduce clustered check 2006-09-07 23:23:45 +00:00
Alasdair Kergon
6e2babc2ce When using local file locking, skip clustered VGs.
Add fallback_to_clustered_locking and fallback_to_local_locking parameters.
2006-09-02 01:18:17 +00:00
Alasdair Kergon
08e253bed1 lvm.static uses built-in cluster locking instead of external locking.
Don't attempt to load shared libraries if built statically.
2006-08-31 22:21:00 +00:00
Alasdair Kergon
c6661477a2 Change default locking_lib to liblvm2clusterlock.so. 2006-08-31 20:56:33 +00:00
Alasdair Kergon
415cfd99a0 Add skip_dev_dir() to process command line VGs. 2006-08-25 23:02:33 +00:00
Patrick Caulfield
8c2e37381a Stop clvmd complaining about nodes that have left the cluster 2006-08-24 12:45:05 +00:00
Alasdair Kergon
45df79feba stub.h shouldn't be here 2006-08-22 15:56:06 +00:00
Patrick Caulfield
5824f992b7 Add needed new parameter to create_toolcontext(). 2006-08-22 09:49:20 +00:00
Alasdair Kergon
b0b60fafd5 Move lvm_snprintf into libdevmapper. 2006-08-21 12:54:53 +00:00
Alasdair Kergon
8d98b02ba2 Add dm_snprintf 2006-08-21 12:52:39 +00:00
Alasdair Kergon
a93fe79bc4 Add dm_split_words() and dm_split_lvm_name() to libdevmapper. 2006-08-21 12:07:03 +00:00
Alasdair Kergon
4aebd7be37 fix lvm.conf (5) refs 2006-08-18 22:35:59 +00:00
Alasdair Kergon
3170a5db32 mirror man page tweaks 2006-08-18 22:27:01 +00:00
Alasdair Kergon
3605b9eef6 Add mirroring into man pages 2006-08-18 21:49:19 +00:00
Alasdair Kergon
a945f1fde2 reorder bounds check code 2006-08-18 21:38:58 +00:00
Alasdair Kergon
461a997b5b Prevent mirror renames. 2006-08-18 21:19:54 +00:00
Alasdair Kergon
a80afd7b4e Move CMDLIB code into separate file and record whether static build. 2006-08-18 21:17:18 +00:00
Alasdair Kergon
aad2b51d85 post 2006-08-17 20:04:38 +00:00
Alasdair Kergon
36a9a81ff1 wrappers files 2006-08-17 19:56:28 +00:00
Alasdair Kergon
42c88546ae pre-release 2006-08-17 19:55:50 +00:00
Alasdair Kergon
0f0e86ef9b Fix PE_ALIGN for pagesize over 32KB. 2006-08-17 19:53:36 +00:00
Alasdair Kergon
98efd9a857 wrap PE_ALIGN 2006-08-17 19:30:59 +00:00
Alasdair Kergon
a0c27d95b7 Separate out LVM1_PE_ALIGN. 2006-08-17 19:15:27 +00:00
Alasdair Kergon
984651d99d Add lvm_getpagesize wrapper. 2006-08-17 18:23:44 +00:00
Alasdair Kergon
c6f7370b30 Add --maxphysicalvolumes to vgchange. 2006-08-16 14:41:42 +00:00
Alasdair Kergon
3e4b8e8985 post-release 2006-08-15 19:13:06 +00:00
Alasdair Kergon
73f08b98d2 pre-release 2006-08-15 19:06:09 +00:00
Alasdair Kergon
8607a74206 post-release 2006-08-15 17:43:10 +00:00
Alasdair Kergon
8339f3ceb3 pre-release 2006-08-15 17:38:38 +00:00
Alasdair Kergon
c0c9f3cc19 fix getopt_long error check 2006-08-10 20:53:21 +00:00
Alasdair Kergon
81f4813c29 Add --table argument to dmsetup for a one-line table.
Abort if errors are found during cmdline option processing.
2006-08-10 14:11:03 +00:00
Alasdair Kergon
94f57745b9 Add checks for duplicate LV name, lvid and PV id before writing metadata.
Report all sanity check failures, not just the first.
2006-08-09 19:33:25 +00:00
Alasdair Kergon
54fb2ebbe0 Add lockfs indicator to debug output. 2006-08-08 21:22:31 +00:00
Alasdair Kergon
02d122b65b Fix missing lockfs on first snapshot creation. 2006-08-08 21:20:00 +00:00
Alasdair Kergon
df0a5561a1 Add --trustcache option to reporting commands in preparation for supporting
event-driven model.  Without changes to the way the cache gets updated, the
option is currently unreliable without a global lock to prevent any lvm2
commands from running concurrently.
2006-08-01 14:56:33 +00:00
Alasdair Kergon
f7c55da7d0 Fix locking for mimage removal. 2006-07-20 20:37:10 +00:00
Alasdair Kergon
b385f701ce Fix clvmd_init_rhel4 'status' exit code. 2006-07-19 18:55:58 +00:00
Alasdair Kergon
05dd42f443 post-release 2006-07-17 14:39:54 +00:00
Alasdair Kergon
36d816d5cb pre-release 2006-07-17 14:32:00 +00:00
Alasdair Kergon
92a6746e70 Fix activation logic in lvchange --persistent. 2006-07-10 19:39:14 +00:00
Alasdair Kergon
1728848a39 Don't ignore persistent minor numbers when activating. 2006-07-10 19:17:40 +00:00
Alasdair Kergon
f9eb4e7487 test 2006-07-05 21:07:35 +00:00
Alasdair Kergon
d0b9f33aeb test 2006-07-05 21:03:15 +00:00
Alasdair Kergon
718583b241 Append full patch to checkin emails. 2006-07-05 21:01:06 +00:00
Alasdair Kergon
6737127e9a Avoid duplicate dmeventd subdir with 'make distclean'. 2006-07-05 17:29:12 +00:00
Alasdair Kergon
19a7b4479b add dlerror to another error path 2006-07-05 17:26:36 +00:00
Alasdair Kergon
c340647502 Differentiate between the two 'log device failed' cases in vgreduce. 2006-07-04 19:52:47 +00:00
Alasdair Kergon
0f987d2982 Use RTLD_GLOBAL when loading shared libraries. 2006-07-04 19:40:27 +00:00
Alasdair Kergon
52bcaed169 Add some forgotten memlock checks to _vg_read to protect against full scans. 2006-07-04 19:36:49 +00:00
Alasdair Kergon
177bd565ac Add mutex to dmeventd_mirror to avoid concurrent execution. 2006-07-04 18:57:27 +00:00
Alasdair Kergon
c801c32fc5 If VG is already consistent with --removemissing, return success not failure. 2006-07-04 18:51:59 +00:00
Alasdair Kergon
d090cf3058 force remove fixes 2006-06-18 11:51:46 +00:00
Alasdair Kergon
1e4b82cc94 Add --force to dmsetup remove* to load error target. [Untested.]
Update dmsetup man page.
2006-06-18 11:35:04 +00:00
Alasdair Kergon
3426f31184 dmsetup remove_all also performs mknodes. 2006-06-17 16:12:41 +00:00
Alasdair Kergon
b4fb7af1df Don't suppress identical table reloads if permission changes. 2006-06-14 22:00:03 +00:00
Alasdair Kergon
b36647598b Fix return code if VG specified on command line is not found. 2006-06-14 20:27:15 +00:00
Alasdair Kergon
fd6b94f20e Fix PV tools to include orphaned PVs in default output again. 2006-06-14 20:11:22 +00:00
Alasdair Kergon
296dc0ed8a test checkin 2006-06-12 17:34:20 +00:00
Alasdair Kergon
4f869e14d6 test checkin 2006-06-12 17:32:43 +00:00
Alasdair Kergon
5704270e9d test checkin 2006-06-12 17:30:29 +00:00
Alasdair Kergon
505b381e85 checkin test 2006-06-12 17:18:31 +00:00
Patrick Caulfield
da6cb15393 Fix "Unaligned access" when using clvm
bz#194626
2006-06-12 09:46:35 +00:00
Alasdair Kergon
16843f6cc8 Fix an extra dev_close in a label_read error path. 2006-06-08 22:15:49 +00:00
Alasdair Kergon
64f3ad1fd4 change two files in different directories 2006-06-06 17:44:11 +00:00
Alasdair Kergon
ff4c4f99b3 test 2006-06-06 17:42:20 +00:00
Alasdair Kergon
f5d2e09569 test one change 2006-06-06 17:41:30 +00:00
Alasdair Kergon
f2bdbe0d4d Fix target_register_events args. 2006-05-25 13:32:26 +00:00
Alasdair Kergon
c51a13caa6 Prevent snapshots of mirrors. 2006-05-24 13:58:14 +00:00
Alasdair Kergon
7840c78a23 Add DISTCLEAN_TARGETS to make template for configure.h.
More fixes to error paths.
2006-05-16 20:53:13 +00:00
Alasdair Kergon
c706f3246b fix error path 2006-05-16 20:42:01 +00:00
Alasdair Kergon
608eedf88d Fix lvcreate corelog validation.
Add --config for overriding most config file settings from cmdline.
  Quote arguments when printing command line.
  Remove linefeed from 'initialising logging' message.
  Add 'Completed' debug message.
  Don't attempt library exit after reloading config files.
  Always compile with libdevmapper, even if device-mapper is disabled.
2006-05-16 16:48:31 +00:00
Alasdair Kergon
a564ca82be Fix corelog segment line.
Suppress some compiler warnings.
2006-05-16 16:20:29 +00:00
Patrick Caulfield
c868b1fee2 Add needed include. 2006-05-15 12:32:08 +00:00
Alasdair Kergon
22374f718f fix compile 2006-05-15 11:56:15 +00:00
Alasdair Kergon
abe3cfcf41 post-release 2006-05-12 20:32:39 +00:00
Alasdair Kergon
59db4b50cd fix dev->device 2006-05-12 19:47:40 +00:00
Alasdair Kergon
bdae38765d not reqd 2006-05-12 19:44:42 +00:00
Alasdair Kergon
66d3ceeb61 pre-release 2006-05-12 19:41:43 +00:00
Alasdair Kergon
445dd17db3 Add --monitor to vgcreate and lvcreate to control dmeventd registration.
Propagate --monitor around cluster.
Filter LCK_NONBLOCK in clvmd lock_vg.
2006-05-12 19:16:48 +00:00
Alasdair Kergon
cff78a2577 fix compile 2006-05-12 13:33:22 +00:00
Alasdair Kergon
6a09e64195 Pre-release. 2006-05-11 20:24:07 +00:00
Alasdair Kergon
22eabe5eab M for unsynced mirror 2006-05-11 20:17:17 +00:00
Alasdair Kergon
b69ba36c2d Add --nosync to lvcreate with LV flag NOTSYNCED. 2006-05-11 20:03:40 +00:00
Alasdair Kergon
5240aad22b Use mirror's uuid for a core log. 2006-05-11 19:47:53 +00:00
Alasdair Kergon
2897eb3cb3 Add mirror log fault-handling policy. 2006-05-11 19:45:53 +00:00
Alasdair Kergon
d3f2f00c25 Add DM_CORELOG flag to dm_tree_node_add_mirror_target(). 2006-05-11 19:10:55 +00:00
Alasdair Kergon
bacfb913a0 Avoid a dmeventd compiler warning. 2006-05-11 19:08:02 +00:00
Alasdair Kergon
c99d0236a0 Propagate nosync flag around cluster. 2006-05-11 19:05:21 +00:00
Alasdair Kergon
aac2b655f7 Allow vgreduce to handle mirror log failures. 2006-05-11 19:01:11 +00:00
Alasdair Kergon
126c41e73a Check in-sync status before changing disk log. 2006-05-11 18:56:55 +00:00
Alasdair Kergon
359ee54f0d Add --corelog to lvcreate and lvconvert. 2006-05-11 18:54:04 +00:00
Alasdair Kergon
28ab560907 Create a log header for replacement in-sync mirror log.
Use set_lv() and dev_set() to wipe sections of devices.
Add mirror_in_sync() flag to avoid unnecessary resync on activation.
2006-05-11 18:39:24 +00:00
Alasdair Kergon
ead252fee4 Add mirror_library description to example.conf.
More compile-time cleanup.
2006-05-11 17:58:58 +00:00
Alasdair Kergon
abf67914c4 post-release 2006-05-10 20:46:28 +00:00
Alasdair Kergon
127884e9dd pre-release 2006-05-10 20:14:15 +00:00
Alasdair Kergon
654f5049eb Move DEFS into configure.h.
Remove dmsetup line buffer limitation.
2006-05-10 19:38:25 +00:00
Alasdair Kergon
979ca34259 fix last commit 2006-05-10 17:51:02 +00:00
Alasdair Kergon
4dd1086805 more coverity fixes 2006-05-10 17:49:25 +00:00
Alasdair Kergon
3503d4b72c Fix uuid_from_num() buffer overrun. 2006-05-10 16:42:03 +00:00
Alasdair Kergon
b8d32a0d33 coverity fixes 2006-05-10 16:23:41 +00:00
Alasdair Kergon
45dca55fc8 Make SIZE_SHORT the default for display_size().
Fix some memory leaks in error paths found by coverity.
Use C99 struct initialisers.
Move DEFS into configure.h.
Clean-ups to remove miscellaneous compiler warnings.
2006-05-09 21:23:51 +00:00
Alasdair Kergon
445d8ecd9f sign fix 2006-05-04 09:33:42 +00:00
Alasdair Kergon
c980add503 fix stripesize const 2006-05-02 07:14:43 +00:00
Alasdair Kergon
133842392a Improve stripe size validation.
Increase maximum stripe size limit to physical extent size for lvm2 metadata.
2006-04-29 22:08:43 +00:00
Alasdair Kergon
8baf2ef155 missing { 2006-04-28 21:07:19 +00:00
Alasdair Kergon
20b71340bc validate region size against page size 2006-04-28 17:25:54 +00:00
Alasdair Kergon
61d8baf8b1 Fix activation code to check for pre-existing mirror logs. 2006-04-28 17:01:07 +00:00
Alasdair Kergon
56a9645aa5 Tighten region size validation. 2006-04-28 15:01:39 +00:00
Alasdair Kergon
85877000a6 tweak .so loading messages; extra device_exists() sanity check 2006-04-28 14:08:04 +00:00
Alasdair Kergon
2f7d2477b6 _register_dev_for_events to return error on failure 2006-04-28 14:06:06 +00:00
Alasdair Kergon
21ea3f05f4 Ignore empty strings in config files. 2006-04-28 13:30:59 +00:00
Alasdair Kergon
79d3492e90 Require non-zero regionsize and document parameter on lvcreate man page. 2006-04-28 13:11:05 +00:00
Alasdair Kergon
5972777abe remove redundant list_init 2006-04-27 17:58:48 +00:00
Alasdair Kergon
8e373ff868 Invalidate cache if composition of VG changed externally. 2006-04-21 19:12:41 +00:00
Alasdair Kergon
a4db92da3a terminate vgid in debug mesg 2006-04-21 15:37:08 +00:00
Alasdair Kergon
9b777eb281 pre-release 2006-04-21 15:27:38 +00:00
Alasdair Kergon
bd3c652184 Fix vgid string termination in recent cache code. 2006-04-21 14:44:33 +00:00
Alasdair Kergon
800f747570 Increase dmsetup line buffer to 4k. 2006-04-19 20:43:30 +00:00
Alasdair Kergon
2b8423437e post-release 2006-04-19 20:15:11 +00:00
Alasdair Kergon
8b4b6945f8 remove inlines 2006-04-19 18:12:33 +00:00
Alasdair Kergon
e5ecfec5c4 pre-release 2006-04-19 18:06:56 +00:00
Alasdair Kergon
f95dbff71f fix makefile 2006-04-19 17:32:05 +00:00
Alasdair Kergon
098f6830a6 fix makefile 2006-04-19 17:24:00 +00:00
Alasdair Kergon
d1ecebdb52 post-release 2006-04-19 17:21:39 +00:00
Alasdair Kergon
590b654251 fix makefile 2006-04-19 17:15:08 +00:00
Alasdair Kergon
3bf190c8ab update version 2006-04-19 16:41:03 +00:00
Alasdair Kergon
dcca7638e0 make pkgconfig installation step optional, and clean up generated files 2006-04-19 16:38:56 +00:00
Alasdair Kergon
70e45ad37b Check for libsepol.
Add some cflow & scope support.
Separate out DEFS from CFLAGS.
Remove inlines and use unique function names.
2006-04-19 15:33:07 +00:00
Alasdair Kergon
db88210289 configure/makefile tidying + pkg-config support. 2006-04-19 15:23:10 +00:00
Alasdair Kergon
d2e0d96cc3 post-release 2006-04-14 21:39:32 +00:00
Alasdair Kergon
3feba82ccc pre-release 2006-04-14 21:11:38 +00:00
Alasdair Kergon
db924da231 vgrename accepts vgid and exported VG. 2006-04-13 21:08:29 +00:00
Alasdair Kergon
fc55ae7e6d Add --partial to pvs. 2006-04-13 17:51:40 +00:00
Alasdair Kergon
86e757a6ad When choosing between identically-named VGs, also consider creation_host. 2006-04-13 17:32:24 +00:00
Alasdair Kergon
4790715cd3 Fix vgexport/vgimport to set/reset PV exported flag so pv_attr is correct.
Add vgid to struct physical_volume and pass with vg_name to some functions.
2006-04-12 21:23:04 +00:00
Alasdair Kergon
e7e9c60042 If two or more VGs are found with the same name, use one that is not exported. 2006-04-12 17:54:11 +00:00
Alasdair Kergon
1c3bc52cc4 tidy 2006-04-11 19:09:55 +00:00
Alasdair Kergon
5227dff0e1 When scanning, also record whether or not VG is exported. 2006-04-11 17:42:15 +00:00
Alasdair Kergon
33f0b5b7c2 Use lvmcache_update_vgname_and_id throughout. 2006-04-11 16:00:26 +00:00
Alasdair Kergon
0a02968303 Whenever vgname is captured, also capture vgid. 2006-04-11 13:55:59 +00:00
Alasdair Kergon
f7bf658c07 Capture vgid in more places. 2006-04-10 22:09:00 +00:00
Alasdair Kergon
8d16a0abad lv_is_visible() 2006-04-07 17:41:56 +00:00
Alasdair Kergon
c974b97ca3 missing vg_name initialisation 2006-04-07 14:14:31 +00:00
Alasdair Kergon
b8025bfebd Update extent size information in vgchange and vgcreate man pages 2006-04-06 21:15:14 +00:00
Alasdair Kergon
30323b253f Bring dmsetup man page up-to-date. 2006-04-06 16:20:40 +00:00
Alasdair Kergon
535c3ede96 more snapshot code tidying 2006-04-06 14:06:27 +00:00
Alasdair Kergon
89fed8ca33 Introduce origin_from_cow() 2006-04-06 13:39:16 +00:00
Alasdair Kergon
f43c77aaed pvremove without -f now fails if there's no PV label. 2006-04-05 22:24:16 +00:00
Alasdair Kergon
96c676b371 Support lvconvert -s. 2006-04-05 20:43:23 +00:00
Alasdair Kergon
113047e1a2 Suppress locking library load failure message if --ignorelockingfailure. 2006-04-03 18:43:55 +00:00
Alasdair Kergon
abed57cb53 Use name-based device refs if kernel doesn't support device number refs.
Fix memory leak (struct dm_ioctl) when struct dm_task is reused.
2006-04-03 15:56:02 +00:00
Alasdair Kergon
c01a800a6b If _create_and_load_v4 fails part way through, revert the creation. 2006-03-30 15:15:47 +00:00
Patrick Caulfield
d648832a2d allow new cman to shutdown on request. 2006-03-21 10:31:08 +00:00
Patrick Caulfield
f06833fbd2 Make sure it compiles if gulm is NOT selected AND using an old libcman.h 2006-03-15 08:36:11 +00:00
Patrick Caulfield
c561addc94 Get clvmd to use libcman rather than cman ioctl calls. This makes
it forward-compatible with the new userland CMAN in cluster head.

To build it you will need the libcman header & library installed.
2006-03-14 14:18:34 +00:00
Alasdair Kergon
702f5f1f4c Remove an incorrect unlock_vg() from process_each_lv(). 2006-03-10 15:41:04 +00:00
Alasdair Kergon
1273f179e8 Propagate partial mode around cluster. 2006-03-09 22:34:13 +00:00
Alasdair Kergon
5d02f60bde dmeventd thread/fifo fixes. 2006-03-09 21:33:59 +00:00
Alasdair Kergon
4cf7a108e8 Fix archive file expiration. 2006-03-07 15:43:05 +00:00
Alasdair Kergon
42635c3938 Add file & line to dm_strdup_aux(). 2006-02-23 19:11:51 +00:00
Alasdair Kergon
ed43dc842b A setgeometry implementation. [untested] 2006-02-20 23:55:58 +00:00
Alasdair Kergon
49d4db6cd2 post-release 2006-02-08 23:24:02 +00:00
Alasdair Kergon
ea80ab2cae post-release
fix dmeventd build
2006-02-08 23:23:19 +00:00
Alasdair Kergon
382e808b8d fix mirror log parm count 2006-02-08 14:14:13 +00:00
Alasdair Kergon
846befa7e0 release 2006-02-07 16:33:48 +00:00
Alasdair Kergon
74dd29f843 add clustered log uuid 2006-02-06 20:18:10 +00:00
Alasdair Kergon
b0473bffcb remove a dmeventd_mirror syslog message 2006-02-06 19:34:45 +00:00
Alasdair Kergon
24dd9ab1a7 Change prefix for clustered log from "clustered " to "clustered_" 2006-02-06 19:32:18 +00:00
Alasdair Kergon
49d3037e87 fix tabs 2006-02-03 21:34:11 +00:00
Alasdair Kergon
37ad2bd4e8 tweak clvmd makefile 2006-02-03 21:31:00 +00:00
Alasdair Kergon
7d7b332b02 Temporary device_exists() fixes. 2006-02-03 19:44:59 +00:00
Alasdair Kergon
ac033b8612 Use supplied full dso name. 2006-02-03 19:41:34 +00:00
Alasdair Kergon
a7b98dfe25 suspend using existing LV metadata; vgreduce then needs partial flag 2006-02-03 19:36:20 +00:00
Alasdair Kergon
7fb7c86c46 fix libdevmapper-event-mirror liblvm2cmd link search path 2006-02-03 14:48:38 +00:00
Alasdair Kergon
ed036598a9 Add exported functions to set uid, gid and mode. [Bastian Blank] 2006-02-03 14:23:22 +00:00
Alasdair Kergon
160bb70cdf Add %.so: %.a make template rule. 2006-02-02 19:16:47 +00:00
Alasdair Kergon
c2e61f3c21 autoconf LIB_SUFFIX 2006-02-02 18:39:23 +00:00
Alasdair Kergon
18218467f3 remove unnecessary 0 in format string 2006-02-02 17:23:04 +00:00
Alasdair Kergon
17e298ad2a Only do lockfs filesystem sync when suspending snapshots.
Switchover library building to use LIB_SUFFIX.
2006-01-31 14:52:30 +00:00
Alasdair Kergon
d031a374f9 Rename _log to dm_log and export.
Fix misc compile-time warnings.
2006-01-31 14:50:38 +00:00
Alasdair Kergon
55f69c98cb Add dm_tree_skip_lockfs. 2006-01-30 23:36:04 +00:00
Alasdair Kergon
71f2e4306d Tidy some comments/messages. 2006-01-27 20:52:21 +00:00
Alasdair Kergon
f8af23a025 Fix renamed dso. 2006-01-27 20:51:36 +00:00
Alasdair Kergon
4ef55a6cd3 dmeventd thread termination fix 2006-01-27 20:50:01 +00:00
Alasdair Kergon
312f866723 some init_client cleanup 2006-01-27 20:49:13 +00:00
Alasdair Kergon
0ebe1f6dec More dmeventd mirror cleanups. 2006-01-27 20:48:19 +00:00
Alasdair Kergon
2ad92e0e6e Remove avoidable dmeventd mirror forking. 2006-01-27 20:47:20 +00:00
Alasdair Kergon
ac8823cdcf Fix libdevmapper event daemon_running status. 2006-01-27 20:46:06 +00:00
Alasdair Kergon
77565f7ee4 Replace deprecated signal functions. 2006-01-27 20:45:17 +00:00
Alasdair Kergon
d656d90fa8 Use split_dm_name in dmeventd mirror code. 2006-01-27 20:43:52 +00:00
Alasdair Kergon
175b3b0834 When suspending, dmeventd deregistration needs to use existing details
not precommitted ones.
2006-01-27 20:39:37 +00:00
Alasdair Kergon
7477e6b714 Fix dmeventd sharedlib path & start tidying registration code. 2006-01-27 20:13:12 +00:00
Alasdair Kergon
cd6568db69 fix dmevent registration return codes 2006-01-27 20:01:45 +00:00
Alasdair Kergon
6aff325fb2 Add config file setting: dmeventd/mirror_library 2006-01-27 19:05:05 +00:00
Alasdair Kergon
0d603cfe9c Rename register_dev; fix missing initialisation; reduce number of ifdefs. 2006-01-27 18:38:14 +00:00
Alasdair Kergon
34a1f14a17 Fix dm_strdup debug definition. 2006-01-11 15:40:54 +00:00
Alasdair Kergon
efe1c8a070 Fix dm_strdup debug definition. 2006-01-10 22:19:41 +00:00
Alasdair Kergon
1575844344 Fix hash function to avoid using a negative array offset. 2006-01-09 20:35:24 +00:00
Alasdair Kergon
221ac1c208 vgreduce remove mirror images
adjust block_on_error version no detection for RHEL4U3
2006-01-04 18:09:52 +00:00
Alasdair Kergon
57442db759 Don't inline _find in hash.c and tidy signed/unsigned etc. 2006-01-04 16:07:27 +00:00
Alasdair Kergon
5fdb3e7cd6 Fix libdevmapper.h #endif 2006-01-04 16:05:44 +00:00
Alasdair Kergon
96f259726c Fix dmsetup version driver version 2006-01-03 20:53:57 +00:00
Alasdair Kergon
4936efba5e Always print warning if activation is disabled. 2005-12-22 16:13:38 +00:00
Alasdair Kergon
d5a3559a2f Add --mirrorsonly arg to vgreduce. (Doesn't handle mirrors yet.) 2005-12-21 21:21:45 +00:00
Alasdair Kergon
114a1c7f52 some fixes 2005-12-21 20:24:22 +00:00
Alasdair Kergon
ce5265c203 fix libdevmapper-event include 2005-12-21 19:45:16 +00:00
Alasdair Kergon
1a575d926f vgreduce replaces active LVs with error segment before removing them. 2005-12-21 18:51:50 +00:00
Alasdair Kergon
85c818a39e read/write loop fixes 2005-12-19 22:56:47 +00:00
Alasdair Kergon
4ffa2defe4 fixme 2005-12-19 22:36:04 +00:00
Alasdair Kergon
8825157fbb Change dm_tree_node_add_mirror_target_log parm order 2005-12-19 21:03:17 +00:00
Alasdair Kergon
966d608dc5 Set block_on_error parameter if available.
Add target_version.
2005-12-19 21:01:39 +00:00
Alasdair Kergon
b808c89471 Add details to format1 'Invalid LV in extent map' error message. 2005-12-19 16:28:35 +00:00
Alasdair Kergon
75d4e6490f ability to pass log flags to libdevmapper 2005-12-13 15:57:32 +00:00
Alasdair Kergon
a82775f544 Add sync, nosync and block_on_error mirror log parameters.
Add hweight32.
2005-12-13 15:49:27 +00:00
Alasdair Kergon
6a22ad0171 comments 2005-12-13 13:34:31 +00:00
Alasdair Kergon
c854e88186 comment 2005-12-13 13:32:19 +00:00
Alasdair Kergon
d02203060c Fix lvscan snapshot full display.
dmeventd fixes
2005-12-08 17:49:34 +00:00
Alasdair Kergon
cf703b0433 Fix dmeventd build. 2005-12-05 11:16:48 +00:00
Alasdair Kergon
c0197a72d3 fix exports 2005-12-02 21:00:33 +00:00
Alasdair Kergon
e5a543e283 More dmeventd support. 2005-12-02 20:35:07 +00:00
Alasdair Kergon
b8b029b7d3 Add mirror dmeventd library 2005-12-02 19:52:06 +00:00
Alasdair Kergon
370f368b1a post-release 2005-12-02 17:24:06 +00:00
Alasdair Kergon
8288b45b4f 1.02.02 2005-12-02 15:44:18 +00:00
Alasdair Kergon
fe529faf8e dmeventd 2005-12-02 15:41:14 +00:00
Alasdair Kergon
ab931b177d dmeventd updates 2005-12-02 15:39:16 +00:00
Alasdair Kergon
9aa3465513 Export dm_task_update_nodes.
Use names instead of numbers in messages when ioctls fail.
2005-12-01 23:11:41 +00:00
Alasdair Kergon
6c70fc1a6c Add some FIXMEs to libdm-event. 2005-11-30 18:35:03 +00:00
Alasdair Kergon
1ccc39962a more lvconvert mirror code 2005-11-29 18:20:23 +00:00
Alasdair Kergon
99c941fc85 Allow signed mirrors arguments.
Move create_mirror_log() into toollib.
2005-11-28 21:00:37 +00:00
Alasdair Kergon
19729fdcc2 Determine parallel PVs to avoid with ALLOC_NORMAL allocation. (untested) 2005-11-28 20:01:00 +00:00
Alasdair Kergon
02e17998ce alloc avoids parallel pvs when supplied 2005-11-24 21:23:55 +00:00
Alasdair Kergon
459e00c67a preparation for parallel_areas changes to allocation code 2005-11-24 20:58:44 +00:00
Alasdair Kergon
292f665650 Fix lv_empty. 2005-11-24 18:46:51 +00:00
Alasdair Kergon
93bbb79569 _find_parallel_space -> _find_segment_space 2005-11-24 18:00:47 +00:00
Alasdair Kergon
273e724f2b post_release 2005-11-23 18:45:30 +00:00
Alasdair Kergon
5d2615c56f post-release 2005-11-23 18:44:59 +00:00
Alasdair Kergon
bfaaf21330 2.02.01 2005-11-23 18:42:45 +00:00
Alasdair Kergon
dcb8415b7a 1.02.01 2005-11-23 18:36:33 +00:00
Alasdair Kergon
699e1c75ce Fix lvdisplay cmdline to accept snapshots. 2005-11-23 16:16:39 +00:00
Alasdair Kergon
465b6e613e Fix open RO->RW promotions. 2005-11-23 16:07:40 +00:00
Alasdair Kergon
05fa105855 Resume snapshot-origins last. 2005-11-22 20:00:35 +00:00
Alasdair Kergon
d7a0cdebe5 Remove a resolved FIXME. 2005-11-22 19:37:14 +00:00
Alasdair Kergon
b049ab31eb Suppress unnecessary resumes. 2005-11-22 19:31:20 +00:00
Alasdair Kergon
6db4dcff7a Drop leading zeros from dm_format_dev.
Suppress attempt to reload identical table.
2005-11-22 18:43:12 +00:00
Alasdair Kergon
3eeaef00ec Additional LVM- prefix matching for transitional period. 2005-11-12 22:46:48 +00:00
Alasdair Kergon
8bf4c38a00 lvcreate vg_revert 2005-11-12 22:42:08 +00:00
Alasdair Kergon
3a32b09ad1 A missing vg_revert in an error path. 2005-11-12 22:00:50 +00:00
Alasdair Kergon
6315982752 more debug fixes 2005-11-11 16:16:37 +00:00
Alasdair Kergon
374a171e82 Fix selinux compile. 2005-11-10 18:31:17 +00:00
Alasdair Kergon
fc5d801f91 fix debug linking 2005-11-10 16:33:04 +00:00
Alasdair Kergon
5146641848 post-release 2005-11-10 16:06:29 +00:00
Alasdair Kergon
cdd0ac42cf pre-release 2005-11-10 15:27:19 +00:00
Alasdair Kergon
e5895500a2 remove a debugging line 2005-11-10 15:17:54 +00:00
Alasdair Kergon
9cb4dde3fa Extend allocation areas to avoid overflow with contiguous with other PVs.
Another pvmove fix.
2005-11-10 14:45:39 +00:00
Patrick Caulfield
3c2a4370a5 Make it compile with debug enabled. 2005-11-10 08:49:29 +00:00
Alasdair Kergon
e7a360dd6f revert - alternative pvmove fix, disabling preloading completely for now 2005-11-09 23:57:40 +00:00
Alasdair Kergon
c814c2fd35 workaround for pvmove with new activation code 2005-11-09 23:56:36 +00:00
Alasdair Kergon
fefa7fe262 more mirror fixing 2005-11-09 18:13:10 +00:00
Alasdair Kergon
26f01a29d1 some fixes for mirrors 2005-11-09 17:32:31 +00:00
Alasdair Kergon
169d4090ab fix last checkin 2005-11-09 15:41:42 +00:00
260 changed files with 18927 additions and 5997 deletions

View File

@@ -16,7 +16,7 @@ srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
SUBDIRS = doc include man
SUBDIRS = doc include man scripts
ifeq ("@INTL@", "yes")
SUBDIRS += po
@@ -24,8 +24,13 @@ endif
SUBDIRS += lib tools daemons
ifeq ("@DMEVENTD@", "yes")
SUBDIRS += dmeventd
endif
ifeq ($(MAKECMDGOALS),distclean)
SUBDIRS += daemons/clvmd \
dmeventd \
lib/format1 \
lib/format_pool \
lib/locking \
@@ -33,6 +38,7 @@ ifeq ($(MAKECMDGOALS),distclean)
lib/snapshot \
po \
test/mm test/device test/format1 test/regex test/filters
DISTCLEAN_TARGETS += lib/misc/configure.h
endif
include make.tmpl
@@ -40,13 +46,25 @@ include make.tmpl
daemons: lib
lib: include
tools: lib
po: tools daemons
dmeventd: tools
po: tools daemons dmeventd
ifeq ("@INTL@", "yes")
lib.pofile: include.pofile
tools.pofile: lib.pofile
daemons.pofile: lib.pofile
po.pofile: tools.pofile daemons.pofile
dmeventd.pofile: tools.pofile
po.pofile: tools.pofile daemons.pofile dmeventd.pofile
pofile: po.pofile
endif
ifneq ("@CFLOW_CMD@", "")
tools.cflow: lib.cflow
cflow: tools.cflow
endif
ifneq ("@CSCOPE_CMD@", "")
cscope.out: tools
@CSCOPE_CMD@ -b -R
all: cscope.out
endif

View File

@@ -1 +1 @@
2.02.00-cvs (2005-10-16)
2.02.25-cvs (2007-03-19)

374
WHATS_NEW
View File

@@ -1,5 +1,377 @@
Version 2.02.00 -
Version 2.02.25 -
=================================
Change some #include lines to search only standard system directories.
Add devices/preferred_names config regex list for displayed device names.
Free a temporary dir string in fcntl_lock_file() after use.
Fix a dm_pool_destroy() in matcher_create().
Introduce goto_bad macro.
Fix warnings on x86_64 involving ptrdiff_t in log_error messages.
Update pvck to include text metadata area and record detection.
Add support functions for token counting in config file extracts.
Update pvck to read labels on disk, with --labelsector parameter.
Add count_chars and count_chars_len functions.
Add /sys/block listings to lvm_dump.sh.
Make lvm_dump.sh list /dev recursively.
Fix thread race in clvmd.
Add scan_sector param to label_read and _find_labeller.
Make clvmd cope with quorum devices.
Add extra internal error checking to clvmd.
Add dev_read_circular.
Add pvck command stub.
Update lists of attribute characters in man pages.
Change cling alloc policy attribute character from 'C' to l'.
Fix creation and conversion of mirrors with tags.
Fix vgsplit for lvm1 format (set and validate VG name in PVs metadata).
Split metadata areas in vgsplit properly.
Version 2.02.24 - 19th March 2007
=================================
Fix processing of exit status in init scripts
Fix vgremove to require at least one vg argument.
Fix reading of striped LVs in LVM1 format.
Flag nolocking as clustered so clvmd startup sees clustered LVs. (2.02.10)
Add a few missing pieces of vgname command line validation.
Support the /dev/mapper prefix on most command lines.
Version 2.02.23 - 8th March 2007
================================
Fix vgrename active LV check to ignore differing vgids.
Remove no-longer-used uuid_out parameter from activation info functions.
Fix two more segfaults if an empty config file section encountered.
Move .cache file into a new /etc/lvm/cache directory by default.
Add devices/cache_dir & devices/cache_file_prefix, deprecating devices/cache.
Create directory in fcntl_lock_file() if required.
Exclude readline support from lvm.static.
Fix a leak in a reporting error path (2.02.19).
Version 2.02.22 - 13th February 2007
====================================
Correct -b and -P on a couple of man pages.
Add global/units to example.conf.
Fix loading of segment_libraries.
If a PV reappears after it was removed from its VG, make it an orphan.
Don't update metadata automatically if VGIDs don't match.
Fix some vgreduce --removemissing command line validation.
Version 2.02.21 - 30th January 2007
===================================
Add warning to lvm2_monitoring_init_rhel4 if attempting to stop monitoring.
Fix vgsplit to handle mirrors.
Reorder fields in reporting field definitions.
Fix vgs to treat args as VGs even when PV fields are displayed.
Fix md signature check to handle both endiannesses.
Version 2.02.20 - 25th January 2007
===================================
dmeventd mirror sets ignore_suspended_devices and avoids scanning mirrors.
Add devices/ignore_suspended_devices to ignore suspended dm devices.
Add some missing close() and fclose() return code checks.
Fix exit statuses of reporting tools (2.02.19).
Add init script for dmeventd monitoring.
lvm.static no longer interacts with dmeventd unless explicitly asked to.
Add field definitions to report help text.
Remove unnecessary cmd arg from target_*monitor_events().
Add private variable to dmeventd shared library interface.
Long-lived processes write out persistent dev cache in refresh_toolcontext().
Fix refresh_toolcontext() always to wipe persistent device filter cache.
Add is_long_lived to toolcontext.
Add --clustered to man pages.
Streamline dm_report_field_* interface.
Change remaining dmeventd terminology 'register' to 'monitor'.
Update reporting man pages.
No longer necessary to specify alignment type for report fields.
Version 2.02.19 - 17th January 2007
===================================
Fix a segfault if an empty config file section encountered.
Move basic reporting functions into libdevmapper.
Fix partition table processing after sparc changes (2.02.16).
Fix cmdline PE range processing segfault (2.02.13).
Some libdevmapper-event interface changes.
Report dmeventd mirror monitoring status.
Fix dmeventd mirror status line processing.
Version 2.02.18 - 11th January 2007
===================================
Revised libdevmapper-event interface for dmeventd.
Remove dmeventd mirror status line word limit.
Use CFLAGS when linking so mixed sparc builds can supply -m64.
Prevent permission changes on active mirrors.
Print warning instead of error message if lvconvert cannot zero volume.
Add snapshot options to lvconvert man page.
dumpconfig accepts a list of configuration variables to display.
Change dumpconfig to use --file to redirect output to a file.
Avoid vgreduce error when mirror code removes the log LV.
Remove 3 redundant AC_MSG_RESULTs from configure.in.
Free memory in _raw_read_mda_header() error paths.
Fix ambiguous vgsplit error message for split LV.
Fix lvextend man page typo.
Add configure --with-dmdir to compile against a device-mapper source tree.
Use no flush suspending for mirrors.
Add dmeventd_mirror register_mutex, tidy initialisation & add memlock.
Fix create mirror with name longer than 22 chars.
Fix some activate.c prototypes when compiled without devmapper.
Fix dmeventd mirror to cope if monitored device disappears.
Version 2.02.17 - 14th December 2006
====================================
Add missing pvremove error message when device doesn't exist.
When lvconvert allocates a mirror log, respect parallel area constraints.
Use loop to iterate through the now-ordered policy list in _allocate().
Check for failure to allocate just the mirror log.
Introduce calc_area_multiple().
Support mirror log allocation when there is only one PV: area_count now 0.
Fix detection of smallest area in _alloc_parallel_area() for cling policy.
Add manpage entry for clvmd -T
Fix gulm operation of clvmd, including a hang when doing lvchange -aey
Fix hang in clvmd if a pre-command failed.
Version 2.02.16 - 1st December 2006
===================================
Fix VG clustered read locks to use PR not CR.
Adjust some alignments for ia64/sparc.
Fix mirror segment removal to use temporary error segment.
Always compile debug logging into clvmd.
Add startup timeout to RHEL4 clvmd startup script.
Add -T (startup timeout) switch to clvmd.
Improve lvm_dump.sh robustness.
Update lvm2create_initrd to support gentoo.
Version 2.02.15 - 21st November 2006
====================================
Fix clvmd_init_rhel4 line truncation (2.02.14).
Install lvmdump by default.
Fix check for snapshot module when activating snapshot.
Fix pvremove error path for case when PV is in use.
Warn if certain duplicate config file entries are seen.
Enhance lvm_dump.sh for sysreport integration and add man page.
Fix --autobackup argument which could never disable backups.
Fix a label_verify error path.
Version 2.02.14 - 10th November 2006
====================================
Fix adjusted_mirror_region_size() to handle 64-bit size.
Add some missing bounds checks on 32-bit extent counters.
Add Petabyte and Exabyte support.
Fix lvcreate error message when 0 extents requested.
lvremove man page: volumes must be cluster inactive before being removed.
Protect .cache manipulations with fcntl locking.
Change .cache timestamp comparisons to use ctime.
Fix mirror log LV writing to set all bits in whole LV.
Fix clustered VG detection and default runlevels in clvmd_init_rhel4.
Fix high-level free space check for partial allocations.
Version 2.02.13 - 27th October 2006
===================================
Add couple of missing files to tools/Makefile CLEAN_TARGETS.
When adding snapshot leave cow LV mapped device active after zeroing.
Fix a clvmd debug message.
Add dev_flush() to set_lv().
Add lvchange --resync.
Perform high-level free space check before each allocation attempt.
Don't allow a node to remove an LV that's exclusively active on anther node.
Cope if same PV is included more than once in cmdline PE range list.
Set PV size to current device size if it is found to be zero.
Add segment parameter to target_present functions.
Version 2.02.12 - 16th October 2006
===================================
Fix pvdisplay to use vg_read() for non-orphans.
Fall back to internal locking if external locking lib is missing or fails.
Retain activation state after changing LV minor number with --force.
Propagate clustered flag in vgsplit and require resizeable flag.
Version 2.02.11 - 12th October 2006
===================================
Add clvmd function to return the cluster name. not used by LVM yet.
Add cling allocation policy.
Change _check_contiguous() to use _for_each_pv().
Extend _for_each_pv() to allow termination without error.
Abstract _is_contiguous().
Remove duplicated pv arg from _check_contiguous().
Accept regionsize with lvconvert.
Add report columns with underscore before field names ending 'size'.
Correct regionsize default on lvcreate man page (MB).
Fix clvmd bug that could cause it to die when a node with a long name crashed.
Add device size to text metadata.
Fix format_text mda_setup pv->size and pv_setup pe_count calculations.
Fix _for_each_pv() for mirror with core log.
Add lvm_dump.sh script to create a tarball of debugging info from a system.
Capture error messages in clvmd and pass them back to the user.
Remove unused #defines from filter-md.c.
Make clvmd restart init script wait until clvmd has died before starting it.
Add -R to clvmd which tells running clvmds to reload their device cache.
Add LV column to reports listing kernel modules needed for activation.
Show available fields if report given invalid field. (e.g. lvs -o list)
Add timestamp functions with --disable-realtime configure option.
Add %VG, %LV and %FREE suffices to lvcreate/lvresize --extents arg.
Fix two potential NULL pointer derefs in error cases in vg_read().
Separate --enable-cluster from locking lib options in lvmconf.sh.
Add a missing comma in lvcreate man page.
Version 2.02.10 - 19th September 2006
=====================================
Fix lvconvert mirror change case detection logic.
Fix mirror log detachment so it correctly becomes a standalone LV.
Extend _check_contiguous() to detect single-area LVs.
Include mirror log (untested) in _for_each_pv() processing.
Use MIRROR_LOG_SIZE constant.
Remove struct seg_pvs from _for_each_pv() to generalise.
Avoid adding duplicates to list of parallel PVs to avoid.
Fix several incorrect comparisons in parallel area avoidance code.
Fix segment lengths when flattening existing parallel areas.
Log existing parallel areas prior to allocation.
Fix mirror log creation when activation disabled.
Don't attempt automatic recovery without proper locking.
When using local file locking, skip clustered VGs.
Add fallback_to_clustered_locking and fallback_to_local_locking parameters.
lvm.static uses built-in cluster locking instead of external locking.
Don't attempt to load shared libraries if built statically.
Change default locking_lib to liblvm2clusterlock.so.
Add skip_dev_dir() to process command line VGs.
Stop clvmd complaining about nodes that have left the cluster.
Move lvm_snprintf(), split_words() and split_dm_name() into libdevmapper.
Add lvconvert man page.
Add mirror options to man pages.
Prevent mirror renames.
Move CMDLIB code into separate file and record whether static build.
Version 2.02.09 - 17th August 2006
==================================
Fix PE_ALIGN for pagesize over 32KB.
Separate out LVM1_PE_ALIGN and pe_align().
Add lvm_getpagesize wrapper.
Add --maxphysicalvolumes to vgchange.
Version 2.02.08 - 15th August 2006
==================================
Add checks for duplicate LV name, lvid and PV id before writing metadata.
Report all sanity check failures, not just the first.
Fix missing lockfs on first snapshot creation.
Add unreliable --trustcache option to reporting commands.
Fix locking for mimage removal.
Fix clvmd_init_rhel4 'status' exit code.
Version 2.02.07 - 17th July 2006
================================
Fix activation logic in lvchange --persistent.
Don't ignore persistent minor numbers when activating.
Use RTLD_GLOBAL when loading shared libraries.
Add some forgotten memlock checks to _vg_read to protect against full scans.
Add mutex to dmeventd_mirror to avoid concurrent execution.
Fix vgreduce --removemissing to return success if VG is already consistent.
Fix return code if VG specified on command line is not found.
Fix PV tools to include orphaned PVs in default output again.
Fixed unaligned access when using clvm.
Fix an extra dev_close in a label_read error path.
Append patches to commit emails.
Fix target_register_events args.
Prevent snapshots of mirrors.
Add DISTCLEAN_TARGETS to make template for configure.h.
More fixes to error paths.
Fix lvcreate corelog validation.
Add --config for overriding most config file settings from cmdline.
Quote arguments when printing command line.
Remove linefeed from 'initialising logging' message.
Add 'Completed' debug message.
Don't attempt library exit after reloading config files.
Always compile with libdevmapper, even if device-mapper is disabled.
Version 2.02.06 - 12th May 2006
===============================
Propagate --monitor around cluster.
Add --monitor to vgcreate and lvcreate to control dmeventd registration.
Filter LCK_NONBLOCK in clvmd lock_vg.
Add --nosync to lvcreate with LV flag NOTSYNCED.
Use mirror's uuid for a core log.
Add mirror log fault-handling policy.
Improve mirror warning messages and tidy dmeventd syslog output.
Propagate nosync flag around cluster.
Allow vgreduce to handle mirror log failures.
Add --corelog to lvcreate and lvconvert.
Create a log header for replacement in-sync mirror log.
Use set_lv() and dev_set() to wipe sections of devices.
Add mirror_in_sync() flag to avoid unnecessary resync on activation.
Add mirror_library description to example.conf.
Fix uuid_from_num() buffer overrun.
Make SIZE_SHORT the default for display_size().
Fix some memory leaks in error paths found by coverity.
Use C99 struct initialisers.
Move DEFS into configure.h.
Clean-ups to remove miscellaneous compiler warnings.
Improve stripe size validation.
Increase maximum stripe size limit to physical extent size for lvm2 metadata.
Fix activation code to check for pre-existing mirror logs.
Tighten region size validation.
Ignore empty strings in config files.
Require non-zero regionsize and document parameter on lvcreate man page.
Invalidate cache if composition of VG changed externally.
Version 2.02.05 - 21st April 2006
=================================
Fix vgid string termination in recent cache code.
Version 2.02.04 - 19th April 2006
=================================
Check for libsepol.
Add some cflow & scope support.
Separate out DEFS from CFLAGS.
Remove inlines and use unique function names.
Version 2.02.03 - 14th April 2006
=================================
vgrename accepts vgid and exported VG.
Add --partial to pvs.
When choosing between identically-named VGs, also consider creation_host.
Provide total log suppression with 2.
Fix vgexport/vgimport to set/reset PV exported flag so pv_attr is correct.
Add vgid to struct physical_volume and pass with vg_name to some functions.
If two or more VGs are found with the same name, use one that is not exported.
Whenever vgname is captured, also capture vgid and whether exported.
Remove an incorrect unlock_vg() from process_each_lv().
Update extent size information in vgchange and vgcreate man pages.
Introduce origin_from_cow() and lv_is_visible().
pvremove without -f now fails if there's no PV label.
Support lvconvert -s.
Suppress locking library load failure message if --ignorelockingfailure.
Propagate partial mode around cluster.
Fix archive file expiration.
Fix dmeventd build.
clvmd now uses libcman rather than cman ioctls.
clvmd will allow new cman to shutdown on request.
Version 2.02.02 - 7th February 2006
===================================
Add %.so: %.a make template rule.
Switchover library building to use LIB_SUFFIX.
Only do lockfs filesystem sync when suspending snapshots.
Always print warning if activation is disabled.
vgreduce removes mirror images.
Add --mirrorsonly to vgreduce.
vgreduce replaces active LVs with error segment before removing them.
Set block_on_error parameter if available.
Add target_version.
Add details to format1 'Invalid LV in extent map' error message.
Fix lvscan snapshot full display.
Bring lvdisplay man page example into line.
Add mirror dmeventd library.
Add some activation logic to remove_mirror_images().
lvconvert can remove specified PVs from a mirror.
lvconvert turns an existing LV into a mirror.
Allow signed mirrors arguments.
Move create_mirror_log() into toollib.
Determine parallel PVs to avoid with ALLOC_NORMAL allocation.
Fix lv_empty.
Version 2.02.01 - 23rd November 2005
====================================
Fix lvdisplay cmdline to accept snapshots.
Fix open RO->RW promotion.
Fix missing vg_revert in lvcreate error path.
Version 2.02.00 - 10th November 2005
====================================
Extend allocation areas to avoid overflow with contiguous with other PVs.
Stop lvcreate attempting to wipe zero or error segments.
Added new lvs table attributes.
Separated out activation preload.

View File

@@ -1,4 +1,152 @@
Version 1.02.00 -
Version 1.02.19 -
====================================
Add regex functions to library.
Avoid trailing separator in reports when there are hidden sort fields.
Fix segfault in 'dmsetup status' without --showkeys against crypt target.
Deal with some more compiler warnings.
Introduce _add_field() and _is_same_field() to libdm-report.c.
Fix some libdevmapper-event and dmeventd memory leaks.
Remove unnecessary memset() return value checks.
Fix a few leaks in reporting error paths. [1.02.15+]
Version 1.02.18 - 13th February 2007
====================================
Improve dmeventd messaging protocol: drain pipe and tag messages.
Version 1.02.17 - 29th January 2007
===================================
Add recent reporting options to dmsetup man page.
Revise some report fields names.
Add dmsetup 'help' command and update usage text.
Use fixed-size fields in report interface and reorder.
Version 1.02.16 - 25th January 2007
===================================
Add some missing close() and fclose() return value checks.
Migrate dmsetup column-based output over to new libdevmapper report framework.
Add descriptions to reporting field definitions.
Add a dso-private variable to dmeventd dso interface.
Add dm_event_handler_[gs]et_timeout functions.
Streamline dm_report_field_* interface.
Add cmdline debug & version options to dmeventd.
Add DM_LIB_VERSION definition to configure.h.
Suppress 'Unrecognised field' error if report field is 'help'.
Add --separator and --sort to dmsetup (unused).
Make alignment flag optional when specifying report fields.
Version 1.02.15 - 17th January 2007
===================================
Add basic reporting functions to libdevmapper.
Fix a malloc error path in dmsetup message.
More libdevmapper-event interface changes and fixes.
Rename dm_saprintf() to dm_asprintf().
Report error if NULL pointer is supplied to dm_strdup_aux().
Reinstate dm_event_get_registered_device.
Version 1.02.14 - 11th January 2007
===================================
Add dm_saprintf().
Use CFLAGS when linking so mixed sparc builds can supply -m64.
Add dm_tree_use_no_flush_suspend().
Lots of dmevent changes including revised interface.
Export dm_basename().
Cope with a trailing space when comparing tables prior to possible reload.
Fix dmeventd to cope if monitored device disappears.
Version 1.02.13 - 28 Nov 2006
=============================
Update dmsetup man page (setgeometry & message).
Fix dmsetup free after getline with debug.
Suppress encryption key in 'dmsetup table' output unless --showkeys supplied.
Version 1.02.12 - 13 Oct 2006
=============================
Avoid deptree attempting to suspend a device that's already suspended.
Version 1.02.11 - 12 Oct 2006
==============================
Add suspend noflush support.
Add basic dmsetup loop support.
Switch dmsetup to use dm_malloc and dm_free.
Version 1.02.10 - 19 Sep 2006
=============================
Add dm_snprintf(), dm_split_words() and dm_split_lvm_name() to libdevmapper.
Reorder mm bounds_check code to reduce window for a dmeventd race.
Version 1.02.09 - 15 Aug 2006
=============================
Add --table argument to dmsetup for a one-line table.
Abort if errors are found during cmdline option processing.
Add lockfs indicator to debug output.
Version 1.02.08 - 17 July 2006
==============================
Append full patch to check in emails.
Avoid duplicate dmeventd subdir with 'make distclean'.
Update dmsetup man page.
Add --force to dmsetup remove* to load error target.
dmsetup remove_all also performs mknodes.
Don't suppress identical table reloads if permission changes.
Fix corelog segment line.
Suppress some compiler warnings.
Version 1.02.07 - 11 May 2006
=============================
Add DM_CORELOG flag to dm_tree_node_add_mirror_target().
Avoid a dmeventd compiler warning.
Version 1.02.06 - 10 May 2006
=============================
Move DEFS into configure.h.
Fix leaks in error paths found by coverity.
Remove dmsetup line buffer limitation.
Version 1.02.05 - 19 Apr 2006
=============================
Separate install_include target in makefiles.
Separate out DEFS from CFLAGS.
Support pkg-config.
Check for libsepol.
Version 1.02.04 - 14 Apr 2006
=============================
Bring dmsetup man page up-to-date.
Use name-based device refs if kernel doesn't support device number refs.
Fix memory leak (struct dm_ioctl) when struct dm_task is reused.
If _create_and_load_v4 fails part way through, revert the creation.
dmeventd thread/fifo fixes.
Add file & line to dm_strdup_aux().
Add setgeometry.
Version 1.02.03 - 7 Feb 2006
============================
Add exported functions to set uid, gid and mode.
Rename _log to dm_log and export.
Add dm_tree_skip_lockfs.
Fix dm_strdup debug definition.
Fix hash function to avoid using a negative array offset.
Don't inline _find in hash.c and tidy signed/unsigned etc.
Fix libdevmapper.h #endif.
Fix dmsetup version driver version.
Add sync, nosync and block_on_error mirror log parameters.
Add hweight32.
Fix dmeventd build.
Version 1.02.02 - 2 Dec 2005
============================
dmeventd added.
Export dm_task_update_nodes.
Use names instead of numbers in messages when ioctls fail.
Version 1.02.01 - 23 Nov 2005
=============================
Resume snapshot-origins last.
Drop leading zeros from dm_format_dev.
Suppress attempt to reload identical table.
Additional LVM- prefix matching for transitional period.
Version 1.02.00 - 10 Nov 2005
=============================
Added activation functions to library.
Added return macros.

682
configure vendored
View File

@@ -310,7 +310,7 @@ ac_includes_default="\
#endif"
ac_default_prefix=/usr
ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os AWK CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA LN_S SET_MAKE RANLIB ac_ct_RANLIB CPP EGREP ALLOCA LIBOBJS POW_LIB MSGFMT MODPROBE_CMD JOBS STATIC_LINK LVM1 POOL SNAPSHOTS MIRRORS OWNER GROUP COPTIMISE_FLAG CLDFLAGS CLDWHOLEARCHIVE CLDNOWHOLEARCHIVE LDDEPS SOFLAG LVM_VERSION LVM1_FALLBACK DEBUG DEVMAPPER HAVE_LIBDL HAVE_SELINUX CMDLIB LOCALEDIR CONFDIR STATICDIR INTL_PACKAGE INTL CLVMD CLUSTER FSADM LTLIBOBJS'
ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os AWK CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA LN_S SET_MAKE RANLIB ac_ct_RANLIB CFLOW_CMD CSCOPE_CMD CPP EGREP ALLOCA LIBOBJS POW_LIB MSGFMT MODPROBE_CMD JOBS STATIC_LINK LVM1 POOL SNAPSHOTS MIRRORS OWNER GROUP COPTIMISE_FLAG CLDFLAGS CLDWHOLEARCHIVE CLDNOWHOLEARCHIVE LDDEPS LIB_SUFFIX LVM_VERSION LVM1_FALLBACK DEBUG DEVMAPPER HAVE_LIBDL HAVE_SELINUX HAVE_REALTIME CMDLIB LOCALEDIR CONFDIR STATICDIR DMDIR INTL_PACKAGE INTL CLVMD CLUSTER FSADM DMEVENTD LTLIBOBJS'
ac_subst_files=''
# Initialize some variables set by options.
@@ -853,11 +853,13 @@ Optional Features:
statically. Default is dynamic linking
--enable-readline Enable readline support
--disable-selinux Disable selinux support
--disable-realtime Disable realtime clock support
--enable-debug Enable debugging
--disable-devmapper Disable device-mapper interaction
--disable-o_direct Disable O_DIRECT
--enable-cmdlib Build shared command library
--enable-fsadm Enable fsadm
--enable-dmeventd Enable the device-mapper event daemon
--enable-nls Enable Native Language Support
Optional Packages:
@@ -881,6 +883,7 @@ Optional Packages:
--with-localedir=DIR Translation files in DIR PREFIX/share/locale
--with-confdir=DIR Configuration files in DIR /etc
--with-staticdir=DIR Static binary in DIR EXEC_PREFIX/sbin
--with-dmdir=DIR Build against device-mapper source tree in DIR
Some influential environment variables:
CC C compiler command
@@ -1330,6 +1333,10 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
################################################################################
ac_config_headers="$ac_config_headers lib/misc/configure.h"
################################################################################
ac_aux_dir=
for ac_dir in autoconf $srcdir/autoconf; do
@@ -1450,10 +1457,11 @@ case "$host_os" in
CLDNOWHOLEARCHIVE="-Wl,-no-whole-archive"
LDDEPS="$LDDEPS .export.sym"
LDFLAGS="$LDFLAGS -Wl,--export-dynamic"
SOFLAG="-shared"
LIB_SUFFIX="so"
DEVMAPPER=yes
ODIRECT=yes
SELINUX=yes
REALTIME=yes
CLUSTER=internal
FSADM=no ;;
darwin*)
@@ -1464,10 +1472,11 @@ case "$host_os" in
CLDNOWHOLEARCHIVE=
LDDEPS="$LDDEPS"
LDFLAGS="$LDFLAGS"
SOFLAG="-dynamiclib"
LIB_SUFFIX="dylib"
DEVMAPPER=yes
ODIRECT=no
SELINUX=no
REALTIME=no
CLUSTER=none
FSADM=no ;;
esac
@@ -2642,6 +2651,84 @@ else
RANLIB="$ac_cv_prog_RANLIB"
fi
# Extract the first word of "cflow", so it can be a program name with args.
set dummy cflow; ac_word=$2
echo "$as_me:$LINENO: checking for $ac_word" >&5
echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
if test "${ac_cv_path_CFLOW_CMD+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
case $CFLOW_CMD in
[\\/]* | ?:[\\/]*)
ac_cv_path_CFLOW_CMD="$CFLOW_CMD" # Let the user override the test with a path.
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_path_CFLOW_CMD="$as_dir/$ac_word$ac_exec_ext"
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
;;
esac
fi
CFLOW_CMD=$ac_cv_path_CFLOW_CMD
if test -n "$CFLOW_CMD"; then
echo "$as_me:$LINENO: result: $CFLOW_CMD" >&5
echo "${ECHO_T}$CFLOW_CMD" >&6
else
echo "$as_me:$LINENO: result: no" >&5
echo "${ECHO_T}no" >&6
fi
# Extract the first word of "cscope", so it can be a program name with args.
set dummy cscope; ac_word=$2
echo "$as_me:$LINENO: checking for $ac_word" >&5
echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
if test "${ac_cv_path_CSCOPE_CMD+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
case $CSCOPE_CMD in
[\\/]* | ?:[\\/]*)
ac_cv_path_CSCOPE_CMD="$CSCOPE_CMD" # Let the user override the test with a path.
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_path_CSCOPE_CMD="$as_dir/$ac_word$ac_exec_ext"
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
;;
esac
fi
CSCOPE_CMD=$ac_cv_path_CSCOPE_CMD
if test -n "$CSCOPE_CMD"; then
echo "$as_me:$LINENO: result: $CSCOPE_CMD" >&5
echo "${ECHO_T}$CSCOPE_CMD" >&6
else
echo "$as_me:$LINENO: result: no" >&5
echo "${ECHO_T}no" >&6
fi
################################################################################
@@ -7148,7 +7235,11 @@ echo "$as_me:$LINENO: result: $LVM1_FALLBACK" >&5
echo "${ECHO_T}$LVM1_FALLBACK" >&6
if test x$LVM1_FALLBACK = xyes; then
CFLAGS="$CFLAGS -DLVM1_FALLBACK"
cat >>confdefs.h <<\_ACEOF
#define LVM1_FALLBACK 1
_ACEOF
fi
################################################################################
@@ -7174,7 +7265,11 @@ echo "$as_me: error: --with-lvm1 parameter invalid
fi;
if test x$LVM1 = xinternal; then
CFLAGS="$CFLAGS -DLVM1_INTERNAL"
cat >>confdefs.h <<\_ACEOF
#define LVM1_INTERNAL 1
_ACEOF
fi
################################################################################
@@ -7200,7 +7295,11 @@ echo "$as_me: error: --with-pool parameter invalid
fi;
if test x$POOL = xinternal; then
CFLAGS="$CFLAGS -DPOOL_INTERNAL"
cat >>confdefs.h <<\_ACEOF
#define POOL_INTERNAL 1
_ACEOF
fi
################################################################################
@@ -7224,7 +7323,11 @@ echo "$as_me: error: --with-cluster parameter invalid
fi;
if test x$CLUSTER = xinternal; then
CFLAGS="$CFLAGS -DCLUSTER_LOCKING_INTERNAL"
cat >>confdefs.h <<\_ACEOF
#define CLUSTER_LOCKING_INTERNAL 1
_ACEOF
fi
################################################################################
@@ -7250,7 +7353,11 @@ echo "$as_me: error: --with-snapshots parameter invalid
fi;
if test x$SNAPSHOTS = xinternal; then
CFLAGS="$CFLAGS -DSNAPSHOT_INTERNAL"
cat >>confdefs.h <<\_ACEOF
#define SNAPSHOT_INTERNAL 1
_ACEOF
fi
################################################################################
@@ -7276,7 +7383,11 @@ echo "$as_me: error: --with-mirrors parameter invalid
fi;
if test x$MIRRORS = xinternal; then
CFLAGS="$CFLAGS -DMIRRORED_INTERNAL"
cat >>confdefs.h <<\_ACEOF
#define MIRRORED_INTERNAL 1
_ACEOF
fi
################################################################################
@@ -7306,7 +7417,11 @@ echo "$as_me:$LINENO: result: $READLINE" >&5
echo "${ECHO_T}$READLINE" >&6
if test x$READLINE = xyes; then
CFLAGS="$CFLAGS -DREADLINE_SUPPORT"
cat >>confdefs.h <<\_ACEOF
#define READLINE_SUPPORT 1
_ACEOF
fi
################################################################################
@@ -7320,6 +7435,17 @@ fi;
echo "$as_me:$LINENO: result: $SELINUX" >&5
echo "${ECHO_T}$SELINUX" >&6
################################################################################
echo "$as_me:$LINENO: checking whether to enable realtime support" >&5
echo $ECHO_N "checking whether to enable realtime support... $ECHO_C" >&6
# Check whether --enable-realtime or --disable-realtime was given.
if test "${enable_realtime+set}" = set; then
enableval="$enable_realtime"
REALTIME=$enableval
fi;
echo "$as_me:$LINENO: result: $REALTIME" >&5
echo "${ECHO_T}$REALTIME" >&6
################################################################################
echo "$as_me:$LINENO: checking whether to build cluster LVM daemon" >&5
echo $ECHO_N "checking whether to build cluster LVM daemon... $ECHO_C" >&6
@@ -7356,6 +7482,8 @@ echo "${ECHO_T}$DEBUG" >&6
if test x$DEBUG = xyes; then
COPTIMISE_FLAG=
else
CSCOPE_CMD=
fi
################################################################################
@@ -7382,7 +7510,11 @@ echo "$as_me:$LINENO: result: $DEVMAPPER" >&5
echo "${ECHO_T}$DEVMAPPER" >&6
if test x$DEVMAPPER = xyes; then
CFLAGS="$CFLAGS -DDEVMAPPER_SUPPORT"
cat >>confdefs.h <<\_ACEOF
#define DEVMAPPER_SUPPORT 1
_ACEOF
fi
################################################################################
@@ -7397,7 +7529,11 @@ echo "$as_me:$LINENO: result: $ODIRECT" >&5
echo "${ECHO_T}$ODIRECT" >&6
if test x$ODIRECT = xyes; then
CFLAGS="$CFLAGS -DO_DIRECT_SUPPORT"
cat >>confdefs.h <<\_ACEOF
#define O_DIRECT_SUPPORT 1
_ACEOF
fi
################################################################################
@@ -7413,10 +7549,6 @@ fi;
echo "$as_me:$LINENO: result: $CMDLIB" >&5
echo "${ECHO_T}$CMDLIB" >&6
if test x$CMDLIB = xyes; then
CFLAGS="$CFLAGS -DCMDLIB"
fi
################################################################################
echo "$as_me:$LINENO: checking whether to build fsadm" >&5
echo $ECHO_N "checking whether to build fsadm... $ECHO_C" >&6
@@ -7428,6 +7560,32 @@ fi;
echo "$as_me:$LINENO: result: $FSADM" >&5
echo "${ECHO_T}$FSADM" >&6
################################################################################
echo "$as_me:$LINENO: checking whether to use dmeventd" >&5
echo $ECHO_N "checking whether to use dmeventd... $ECHO_C" >&6
# Check whether --enable-dmeventd or --disable-dmeventd was given.
if test "${enable_dmeventd+set}" = set; then
enableval="$enable_dmeventd"
DMEVENTD=$enableval
fi;
echo "$as_me:$LINENO: result: $DMEVENTD" >&5
echo "${ECHO_T}$DMEVENTD" >&6
if test x$DMEVENTD = xyes && test x$MIRRORS != xinternal; then
{ { echo "$as_me:$LINENO: error: --enable-dmeventd currently requires --with-mirrors=internal
" >&5
echo "$as_me: error: --enable-dmeventd currently requires --with-mirrors=internal
" >&2;}
{ (exit 1); exit 1; }; }
fi
if test x$DMEVENTD = xyes; then
cat >>confdefs.h <<\_ACEOF
#define DMEVENTD 1
_ACEOF
fi
################################################################################
if [ "x$exec_prefix" = xNONE -a "x$prefix" = xNONE ];
then exec_prefix="";
@@ -8087,7 +8245,11 @@ fi
if [ "x$HAVE_LIBDL" = xyes ]; then
CFLAGS="$CFLAGS -DHAVE_LIBDL"
cat >>confdefs.h <<\_ACEOF
#define HAVE_LIBDL 1
_ACEOF
LIBS="-ldl $LIBS"
else
HAVE_LIBDL=no
@@ -8106,8 +8268,81 @@ fi
################################################################################
if test x$SELINUX = xyes; then
echo "$as_me:$LINENO: checking for is_selinux_enabled function" >&5
echo $ECHO_N "checking for is_selinux_enabled function... $ECHO_C" >&6
echo "$as_me:$LINENO: checking for sepol_check_context in -lsepol" >&5
echo $ECHO_N "checking for sepol_check_context in -lsepol... $ECHO_C" >&6
if test "${ac_cv_lib_sepol_sepol_check_context+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lsepol $LIBS"
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
/* Override any gcc2 internal prototype to avoid an error. */
#ifdef __cplusplus
extern "C"
#endif
/* We use char because int might match the return type of a gcc2
builtin and then its argument prototype would still apply. */
char sepol_check_context ();
int
main ()
{
sepol_check_context ();
;
return 0;
}
_ACEOF
rm -f conftest.$ac_objext conftest$ac_exeext
if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
(eval $ac_link) 2>conftest.er1
ac_status=$?
grep -v '^ *+' conftest.er1 >conftest.err
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -z "$ac_c_werror_flag"
|| test ! -s conftest.err'
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; } &&
{ ac_try='test -s conftest$ac_exeext'
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
ac_cv_lib_sepol_sepol_check_context=yes
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_cv_lib_sepol_sepol_check_context=no
fi
rm -f conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
echo "$as_me:$LINENO: result: $ac_cv_lib_sepol_sepol_check_context" >&5
echo "${ECHO_T}$ac_cv_lib_sepol_sepol_check_context" >&6
if test $ac_cv_lib_sepol_sepol_check_context = yes; then
HAVE_SEPOL=yes
else
HAVE_SEPOL=no
fi
if test x$HAVE_SEPOL = xyes; then
LIBS="-lsepol $LIBS"
fi
echo "$as_me:$LINENO: checking for is_selinux_enabled in -lselinux" >&5
echo $ECHO_N "checking for is_selinux_enabled in -lselinux... $ECHO_C" >&6
if test "${ac_cv_lib_selinux_is_selinux_enabled+set}" = set; then
@@ -8178,11 +8413,13 @@ else
HAVE_SELINUX=no
fi
echo "$as_me:$LINENO: result: $HAVE_SELINUX" >&5
echo "${ECHO_T}$HAVE_SELINUX" >&6
if test x$HAVE_SELINUX = xyes; then
CFLAGS="$CFLAGS -DHAVE_SELINUX"
cat >>confdefs.h <<\_ACEOF
#define HAVE_SELINUX 1
_ACEOF
LIBS="-lselinux $LIBS"
else
{ echo "$as_me:$LINENO: WARNING: Disabling selinux" >&5
@@ -8190,6 +8427,92 @@ echo "$as_me: WARNING: Disabling selinux" >&2;}
fi
fi
################################################################################
if test x$REALTIME = xyes; then
echo "$as_me:$LINENO: checking for clock_gettime in -lrt" >&5
echo $ECHO_N "checking for clock_gettime in -lrt... $ECHO_C" >&6
if test "${ac_cv_lib_rt_clock_gettime+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lrt $LIBS"
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
/* Override any gcc2 internal prototype to avoid an error. */
#ifdef __cplusplus
extern "C"
#endif
/* We use char because int might match the return type of a gcc2
builtin and then its argument prototype would still apply. */
char clock_gettime ();
int
main ()
{
clock_gettime ();
;
return 0;
}
_ACEOF
rm -f conftest.$ac_objext conftest$ac_exeext
if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
(eval $ac_link) 2>conftest.er1
ac_status=$?
grep -v '^ *+' conftest.er1 >conftest.err
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -z "$ac_c_werror_flag"
|| test ! -s conftest.err'
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; } &&
{ ac_try='test -s conftest$ac_exeext'
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
ac_cv_lib_rt_clock_gettime=yes
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_cv_lib_rt_clock_gettime=no
fi
rm -f conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
echo "$as_me:$LINENO: result: $ac_cv_lib_rt_clock_gettime" >&5
echo "${ECHO_T}$ac_cv_lib_rt_clock_gettime" >&6
if test $ac_cv_lib_rt_clock_gettime = yes; then
HAVE_REALTIME=yes
else
HAVE_REALTIME=no
fi
if test x$HAVE_REALTIME = xyes; then
cat >>confdefs.h <<\_ACEOF
#define HAVE_REALTIME 1
_ACEOF
LIBS="-lrt $LIBS"
else
{ echo "$as_me:$LINENO: WARNING: Disabling realtime clock" >&5
echo "$as_me: WARNING: Disabling realtime clock" >&2;}
fi
fi
################################################################################
for ac_header in getopt.h
@@ -8336,7 +8659,11 @@ if test `eval echo '${'$as_ac_Header'}'` = yes; then
cat >>confdefs.h <<_ACEOF
#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
_ACEOF
CFLAGS="$CFLAGS -DHAVE_GETOPTLONG"
cat >>confdefs.h <<\_ACEOF
#define HAVE_GETOPTLONG 1
_ACEOF
fi
done
@@ -8526,9 +8853,12 @@ fi
echo "$as_me:$LINENO: result: $ac_cv_func_rl_completion_matches" >&5
echo "${ECHO_T}$ac_cv_func_rl_completion_matches" >&6
if test $ac_cv_func_rl_completion_matches = yes; then
CFLAGS="$CFLAGS -DHAVE_RL_COMPLETION_MATCHES"
fi
cat >>confdefs.h <<\_ACEOF
#define HAVE_RL_COMPLETION_MATCHES 1
_ACEOF
fi
fi
@@ -8623,6 +8953,15 @@ else
STATICDIR='${exec_prefix}/sbin'
fi;
# Check whether --with-dmdir or --without-dmdir was given.
if test "${with_dmdir+set}" = set; then
withval="$with_dmdir"
DMDIR="$withval"
else
DMDIR=
fi;
################################################################################
if test x$READLINE = xyes; then
@@ -10454,7 +10793,6 @@ done
fi
if test x$DEVMAPPER = xyes; then
for ac_header in libdevmapper.h
do
@@ -10609,7 +10947,6 @@ fi
done
fi
if test x$HAVE_SELINUX = xyes; then
@@ -10810,7 +11147,11 @@ fi
if test x$MODPROBE_CMD != x; then
CFLAGS="$CFLAGS -DMODPROBE_CMD=\\\"$MODPROBE_CMD\\\""
cat >>confdefs.h <<_ACEOF
#define MODPROBE_CMD "$MODPROBE_CMD"
_ACEOF
fi
################################################################################
@@ -10849,6 +11190,11 @@ fi
@@ -10856,7 +11202,7 @@ fi
################################################################################
ac_config_files="$ac_config_files Makefile make.tmpl daemons/Makefile daemons/clvmd/Makefile doc/Makefile include/Makefile lib/Makefile lib/format1/Makefile lib/format_pool/Makefile lib/locking/Makefile lib/mirror/Makefile lib/snapshot/Makefile man/Makefile po/Makefile tools/Makefile tools/version.h tools/fsadm/Makefile test/mm/Makefile test/device/Makefile test/format1/Makefile test/regex/Makefile test/filters/Makefile"
ac_config_files="$ac_config_files Makefile make.tmpl daemons/Makefile daemons/clvmd/Makefile dmeventd/Makefile dmeventd/mirror/Makefile doc/Makefile include/Makefile lib/Makefile lib/format1/Makefile lib/format_pool/Makefile lib/locking/Makefile lib/mirror/Makefile lib/snapshot/Makefile man/Makefile po/Makefile scripts/Makefile tools/Makefile tools/version.h tools/fsadm/Makefile test/mm/Makefile test/device/Makefile test/format1/Makefile test/regex/Makefile test/filters/Makefile"
cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
# tests run on this system so they can be shared between configure
@@ -10931,38 +11277,7 @@ s/^[^=]*=[ ]*$//;
}'
fi
# Transform confdefs.h into DEFS.
# Protect against shell expansion while executing Makefile rules.
# Protect against Makefile macro expansion.
#
# If the first sed substitution is executed (which looks for macros that
# take arguments), then we branch to the quote section. Otherwise,
# look for a macro that doesn't take arguments.
cat >confdef2opt.sed <<\_ACEOF
t clear
: clear
s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\),-D\1=\2,g
t quote
s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\),-D\1=\2,g
t quote
d
: quote
s,[ `~#$^&*(){}\\|;'"<>?],\\&,g
s,\[,\\&,g
s,\],\\&,g
s,\$,$$,g
p
_ACEOF
# We use echo to avoid assuming a particular line-breaking character.
# The extra dot is to prevent the shell from consuming trailing
# line-breaks from the sub-command output. A line-break within
# single-quotes doesn't work because, if this script is created in a
# platform that uses two characters for line-breaks (e.g., DOS), tr
# would break.
ac_LF_and_DOT=`echo; echo .`
DEFS=`sed -n -f confdef2opt.sed confdefs.h | tr "$ac_LF_and_DOT" ' .'`
rm -f confdef2opt.sed
DEFS=-DHAVE_CONFIG_H
ac_libobjs=
ac_ltlibobjs=
@@ -11296,10 +11611,15 @@ Usage: $0 [OPTIONS] [FILE]...
--recheck update $as_me by reconfiguring in the same conditions
--file=FILE[:TEMPLATE]
instantiate the configuration file FILE
--header=FILE[:TEMPLATE]
instantiate the configuration header FILE
Configuration files:
$config_files
Configuration headers:
$config_headers
Report bugs to <bug-autoconf@gnu.org>."
_ACEOF
@@ -11412,6 +11732,8 @@ do
"make.tmpl" ) CONFIG_FILES="$CONFIG_FILES make.tmpl" ;;
"daemons/Makefile" ) CONFIG_FILES="$CONFIG_FILES daemons/Makefile" ;;
"daemons/clvmd/Makefile" ) CONFIG_FILES="$CONFIG_FILES daemons/clvmd/Makefile" ;;
"dmeventd/Makefile" ) CONFIG_FILES="$CONFIG_FILES dmeventd/Makefile" ;;
"dmeventd/mirror/Makefile" ) CONFIG_FILES="$CONFIG_FILES dmeventd/mirror/Makefile" ;;
"doc/Makefile" ) CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;;
"include/Makefile" ) CONFIG_FILES="$CONFIG_FILES include/Makefile" ;;
"lib/Makefile" ) CONFIG_FILES="$CONFIG_FILES lib/Makefile" ;;
@@ -11422,6 +11744,7 @@ do
"lib/snapshot/Makefile" ) CONFIG_FILES="$CONFIG_FILES lib/snapshot/Makefile" ;;
"man/Makefile" ) CONFIG_FILES="$CONFIG_FILES man/Makefile" ;;
"po/Makefile" ) CONFIG_FILES="$CONFIG_FILES po/Makefile" ;;
"scripts/Makefile" ) CONFIG_FILES="$CONFIG_FILES scripts/Makefile" ;;
"tools/Makefile" ) CONFIG_FILES="$CONFIG_FILES tools/Makefile" ;;
"tools/version.h" ) CONFIG_FILES="$CONFIG_FILES tools/version.h" ;;
"tools/fsadm/Makefile" ) CONFIG_FILES="$CONFIG_FILES tools/fsadm/Makefile" ;;
@@ -11430,6 +11753,7 @@ do
"test/format1/Makefile" ) CONFIG_FILES="$CONFIG_FILES test/format1/Makefile" ;;
"test/regex/Makefile" ) CONFIG_FILES="$CONFIG_FILES test/regex/Makefile" ;;
"test/filters/Makefile" ) CONFIG_FILES="$CONFIG_FILES test/filters/Makefile" ;;
"lib/misc/configure.h" ) CONFIG_HEADERS="$CONFIG_HEADERS lib/misc/configure.h" ;;
*) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
{ (exit 1); exit 1; }; };;
@@ -11442,6 +11766,7 @@ done
# bizarre bug on SunOS 4.1.3.
if $ac_need_defaults; then
test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
fi
# Have a temporary directory for convenience. Make it in the build tree
@@ -11540,6 +11865,8 @@ s,@LN_S@,$LN_S,;t t
s,@SET_MAKE@,$SET_MAKE,;t t
s,@RANLIB@,$RANLIB,;t t
s,@ac_ct_RANLIB@,$ac_ct_RANLIB,;t t
s,@CFLOW_CMD@,$CFLOW_CMD,;t t
s,@CSCOPE_CMD@,$CSCOPE_CMD,;t t
s,@CPP@,$CPP,;t t
s,@EGREP@,$EGREP,;t t
s,@ALLOCA@,$ALLOCA,;t t
@@ -11560,22 +11887,25 @@ s,@CLDFLAGS@,$CLDFLAGS,;t t
s,@CLDWHOLEARCHIVE@,$CLDWHOLEARCHIVE,;t t
s,@CLDNOWHOLEARCHIVE@,$CLDNOWHOLEARCHIVE,;t t
s,@LDDEPS@,$LDDEPS,;t t
s,@SOFLAG@,$SOFLAG,;t t
s,@LIB_SUFFIX@,$LIB_SUFFIX,;t t
s,@LVM_VERSION@,$LVM_VERSION,;t t
s,@LVM1_FALLBACK@,$LVM1_FALLBACK,;t t
s,@DEBUG@,$DEBUG,;t t
s,@DEVMAPPER@,$DEVMAPPER,;t t
s,@HAVE_LIBDL@,$HAVE_LIBDL,;t t
s,@HAVE_SELINUX@,$HAVE_SELINUX,;t t
s,@HAVE_REALTIME@,$HAVE_REALTIME,;t t
s,@CMDLIB@,$CMDLIB,;t t
s,@LOCALEDIR@,$LOCALEDIR,;t t
s,@CONFDIR@,$CONFDIR,;t t
s,@STATICDIR@,$STATICDIR,;t t
s,@DMDIR@,$DMDIR,;t t
s,@INTL_PACKAGE@,$INTL_PACKAGE,;t t
s,@INTL@,$INTL,;t t
s,@CLVMD@,$CLVMD,;t t
s,@CLUSTER@,$CLUSTER,;t t
s,@FSADM@,$FSADM,;t t
s,@DMEVENTD@,$DMEVENTD,;t t
s,@LTLIBOBJS@,$LTLIBOBJS,;t t
CEOF
@@ -11815,6 +12145,229 @@ s,@INSTALL@,$ac_INSTALL,;t t
done
_ACEOF
cat >>$CONFIG_STATUS <<\_ACEOF
#
# CONFIG_HEADER section.
#
# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
# NAME is the cpp macro being defined and VALUE is the value it is being given.
#
# ac_d sets the value in "#define NAME VALUE" lines.
ac_dA='s,^\([ ]*\)#\([ ]*define[ ][ ]*\)'
ac_dB='[ ].*$,\1#\2'
ac_dC=' '
ac_dD=',;t'
# ac_u turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
ac_uA='s,^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)'
ac_uB='$,\1#\2define\3'
ac_uC=' '
ac_uD=',;t'
for ac_file in : $CONFIG_HEADERS; do test "x$ac_file" = x: && continue
# Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
case $ac_file in
- | *:- | *:-:* ) # input from stdin
cat >$tmp/stdin
ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
*:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
* ) ac_file_in=$ac_file.in ;;
esac
test x"$ac_file" != x- && { echo "$as_me:$LINENO: creating $ac_file" >&5
echo "$as_me: creating $ac_file" >&6;}
# First look for the input files in the build tree, otherwise in the
# src tree.
ac_file_inputs=`IFS=:
for f in $ac_file_in; do
case $f in
-) echo $tmp/stdin ;;
[\\/$]*)
# Absolute (can't be DOS-style, as IFS=:)
test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
echo "$as_me: error: cannot find input file: $f" >&2;}
{ (exit 1); exit 1; }; }
# Do quote $f, to prevent DOS paths from being IFS'd.
echo "$f";;
*) # Relative
if test -f "$f"; then
# Build tree
echo "$f"
elif test -f "$srcdir/$f"; then
# Source tree
echo "$srcdir/$f"
else
# /dev/null tree
{ { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
echo "$as_me: error: cannot find input file: $f" >&2;}
{ (exit 1); exit 1; }; }
fi;;
esac
done` || { (exit 1); exit 1; }
# Remove the trailing spaces.
sed 's/[ ]*$//' $ac_file_inputs >$tmp/in
_ACEOF
# Transform confdefs.h into two sed scripts, `conftest.defines' and
# `conftest.undefs', that substitutes the proper values into
# config.h.in to produce config.h. The first handles `#define'
# templates, and the second `#undef' templates.
# And first: Protect against being on the right side of a sed subst in
# config.status. Protect against being in an unquoted here document
# in config.status.
rm -f conftest.defines conftest.undefs
# Using a here document instead of a string reduces the quoting nightmare.
# Putting comments in sed scripts is not portable.
#
# `end' is used to avoid that the second main sed command (meant for
# 0-ary CPP macros) applies to n-ary macro definitions.
# See the Autoconf documentation for `clear'.
cat >confdef2sed.sed <<\_ACEOF
s/[\\&,]/\\&/g
s,[\\$`],\\&,g
t clear
: clear
s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*\)\(([^)]*)\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1\2${ac_dC}\3${ac_dD},gp
t end
s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp
: end
_ACEOF
# If some macros were called several times there might be several times
# the same #defines, which is useless. Nevertheless, we may not want to
# sort them, since we want the *last* AC-DEFINE to be honored.
uniq confdefs.h | sed -n -f confdef2sed.sed >conftest.defines
sed 's/ac_d/ac_u/g' conftest.defines >conftest.undefs
rm -f confdef2sed.sed
# This sed command replaces #undef with comments. This is necessary, for
# example, in the case of _POSIX_SOURCE, which is predefined and required
# on some systems where configure will not decide to define it.
cat >>conftest.undefs <<\_ACEOF
s,^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */,
_ACEOF
# Break up conftest.defines because some shells have a limit on the size
# of here documents, and old seds have small limits too (100 cmds).
echo ' # Handle all the #define templates only if necessary.' >>$CONFIG_STATUS
echo ' if grep "^[ ]*#[ ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS
echo ' # If there are no defines, we may have an empty if/fi' >>$CONFIG_STATUS
echo ' :' >>$CONFIG_STATUS
rm -f conftest.tail
while grep . conftest.defines >/dev/null
do
# Write a limited-size here document to $tmp/defines.sed.
echo ' cat >$tmp/defines.sed <<CEOF' >>$CONFIG_STATUS
# Speed up: don't consider the non `#define' lines.
echo '/^[ ]*#[ ]*define/!b' >>$CONFIG_STATUS
# Work around the forget-to-reset-the-flag bug.
echo 't clr' >>$CONFIG_STATUS
echo ': clr' >>$CONFIG_STATUS
sed ${ac_max_here_lines}q conftest.defines >>$CONFIG_STATUS
echo 'CEOF
sed -f $tmp/defines.sed $tmp/in >$tmp/out
rm -f $tmp/in
mv $tmp/out $tmp/in
' >>$CONFIG_STATUS
sed 1,${ac_max_here_lines}d conftest.defines >conftest.tail
rm -f conftest.defines
mv conftest.tail conftest.defines
done
rm -f conftest.defines
echo ' fi # grep' >>$CONFIG_STATUS
echo >>$CONFIG_STATUS
# Break up conftest.undefs because some shells have a limit on the size
# of here documents, and old seds have small limits too (100 cmds).
echo ' # Handle all the #undef templates' >>$CONFIG_STATUS
rm -f conftest.tail
while grep . conftest.undefs >/dev/null
do
# Write a limited-size here document to $tmp/undefs.sed.
echo ' cat >$tmp/undefs.sed <<CEOF' >>$CONFIG_STATUS
# Speed up: don't consider the non `#undef'
echo '/^[ ]*#[ ]*undef/!b' >>$CONFIG_STATUS
# Work around the forget-to-reset-the-flag bug.
echo 't clr' >>$CONFIG_STATUS
echo ': clr' >>$CONFIG_STATUS
sed ${ac_max_here_lines}q conftest.undefs >>$CONFIG_STATUS
echo 'CEOF
sed -f $tmp/undefs.sed $tmp/in >$tmp/out
rm -f $tmp/in
mv $tmp/out $tmp/in
' >>$CONFIG_STATUS
sed 1,${ac_max_here_lines}d conftest.undefs >conftest.tail
rm -f conftest.undefs
mv conftest.tail conftest.undefs
done
rm -f conftest.undefs
cat >>$CONFIG_STATUS <<\_ACEOF
# Let's still pretend it is `configure' which instantiates (i.e., don't
# use $as_me), people would be surprised to read:
# /* config.h. Generated by config.status. */
if test x"$ac_file" = x-; then
echo "/* Generated by configure. */" >$tmp/config.h
else
echo "/* $ac_file. Generated by configure. */" >$tmp/config.h
fi
cat $tmp/in >>$tmp/config.h
rm -f $tmp/in
if test x"$ac_file" != x-; then
if diff $ac_file $tmp/config.h >/dev/null 2>&1; then
{ echo "$as_me:$LINENO: $ac_file is unchanged" >&5
echo "$as_me: $ac_file is unchanged" >&6;}
else
ac_dir=`(dirname "$ac_file") 2>/dev/null ||
$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$ac_file" : 'X\(//\)[^/]' \| \
X"$ac_file" : 'X\(//\)$' \| \
X"$ac_file" : 'X\(/\)' \| \
. : '\(.\)' 2>/dev/null ||
echo X"$ac_file" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
/^X\(\/\/\)[^/].*/{ s//\1/; q; }
/^X\(\/\/\)$/{ s//\1/; q; }
/^X\(\/\).*/{ s//\1/; q; }
s/.*/./; q'`
{ if $as_mkdir_p; then
mkdir -p "$ac_dir"
else
as_dir="$ac_dir"
as_dirs=
while test ! -d "$as_dir"; do
as_dirs="$as_dir $as_dirs"
as_dir=`(dirname "$as_dir") 2>/dev/null ||
$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$as_dir" : 'X\(//\)[^/]' \| \
X"$as_dir" : 'X\(//\)$' \| \
X"$as_dir" : 'X\(/\)' \| \
. : '\(.\)' 2>/dev/null ||
echo X"$as_dir" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
/^X\(\/\/\)[^/].*/{ s//\1/; q; }
/^X\(\/\/\)$/{ s//\1/; q; }
/^X\(\/\).*/{ s//\1/; q; }
s/.*/./; q'`
done
test ! -n "$as_dirs" || mkdir $as_dirs
fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
{ (exit 1); exit 1; }; }; }
rm -f $ac_file
mv $tmp/config.h $ac_file
fi
else
cat $tmp/config.h
rm -f $tmp/config.h
fi
done
_ACEOF
cat >>$CONFIG_STATUS <<\_ACEOF
@@ -11855,3 +12408,8 @@ if test x$FSADM == xyes; then
{ echo "$as_me:$LINENO: WARNING: fsadm support is untested" >&5
echo "$as_me: WARNING: fsadm support is untested" >&2;}
fi
if test x$DMEVENTD == xyes; then
{ echo "$as_me:$LINENO: WARNING: dmeventd support is untested" >&5
echo "$as_me: WARNING: dmeventd support is untested" >&2;}
fi

View File

@@ -18,6 +18,9 @@ AC_PREREQ(2.53)
dnl -- Process this file with autoconf to produce a configure script.
AC_INIT(lib/device/dev-cache.h)
################################################################################
AC_CONFIG_HEADERS(lib/misc/configure.h)
################################################################################
dnl -- Setup the directory where autoconf has auxilary files
AC_CONFIG_AUX_DIR(autoconf)
@@ -35,10 +38,11 @@ case "$host_os" in
CLDNOWHOLEARCHIVE="-Wl,-no-whole-archive"
LDDEPS="$LDDEPS .export.sym"
LDFLAGS="$LDFLAGS -Wl,--export-dynamic"
SOFLAG="-shared"
LIB_SUFFIX="so"
DEVMAPPER=yes
ODIRECT=yes
SELINUX=yes
REALTIME=yes
CLUSTER=internal
FSADM=no ;;
darwin*)
@@ -49,10 +53,11 @@ case "$host_os" in
CLDNOWHOLEARCHIVE=
LDDEPS="$LDDEPS"
LDFLAGS="$LDFLAGS"
SOFLAG="-dynamiclib"
LIB_SUFFIX="dylib"
DEVMAPPER=yes
ODIRECT=no
SELINUX=no
REALTIME=no
CLUSTER=none
FSADM=no ;;
esac
@@ -65,6 +70,8 @@ AC_PROG_INSTALL
AC_PROG_LN_S
AC_PROG_MAKE_SET
AC_PROG_RANLIB
AC_PATH_PROG(CFLOW_CMD, cflow)
AC_PATH_PROG(CSCOPE_CMD, cscope)
################################################################################
dnl -- Checks for header files.
@@ -150,7 +157,7 @@ AC_ARG_ENABLE(lvm1_fallback, [ --enable-lvm1_fallback Use this to fall back an
AC_MSG_RESULT($LVM1_FALLBACK)
if test x$LVM1_FALLBACK = xyes; then
CFLAGS="$CFLAGS -DLVM1_FALLBACK"
AC_DEFINE([LVM1_FALLBACK], 1, [Define to 1 if 'lvm' should fall back to using LVM1 binaries if device-mapper is missing from the kernel])
fi
################################################################################
@@ -170,7 +177,7 @@ if [[ "x$LVM1" != xnone -a "x$LVM1" != xinternal -a "x$LVM1" != xshared ]];
fi;
if test x$LVM1 = xinternal; then
CFLAGS="$CFLAGS -DLVM1_INTERNAL"
AC_DEFINE([LVM1_INTERNAL], 1, [Define to 1 to include built-in support for LVM1 metadata.])
fi
################################################################################
@@ -190,7 +197,7 @@ if [[ "x$POOL" != xnone -a "x$POOL" != xinternal -a "x$POOL" != xshared ]];
fi;
if test x$POOL = xinternal; then
CFLAGS="$CFLAGS -DPOOL_INTERNAL"
AC_DEFINE([POOL_INTERNAL], 1, [Define to 1 to include built-in support for GFS pool metadata.])
fi
################################################################################
@@ -209,7 +216,7 @@ if [[ "x$CLUSTER" != xnone -a "x$CLUSTER" != xinternal -a "x$CLUSTER" != xshared
fi;
if test x$CLUSTER = xinternal; then
CFLAGS="$CFLAGS -DCLUSTER_LOCKING_INTERNAL"
AC_DEFINE([CLUSTER_LOCKING_INTERNAL], 1, [Define to 1 to include built-in support for clustered LVM locking.])
fi
################################################################################
@@ -229,7 +236,7 @@ if [[ "x$SNAPSHOTS" != xnone -a "x$SNAPSHOTS" != xinternal -a "x$SNAPSHOTS" != x
fi;
if test x$SNAPSHOTS = xinternal; then
CFLAGS="$CFLAGS -DSNAPSHOT_INTERNAL"
AC_DEFINE([SNAPSHOT_INTERNAL], 1, [Define to 1 to include built-in support for snapshots.])
fi
################################################################################
@@ -249,7 +256,7 @@ if [[ "x$MIRRORS" != xnone -a "x$MIRRORS" != xinternal -a "x$MIRRORS" != xshared
fi;
if test x$MIRRORS = xinternal; then
CFLAGS="$CFLAGS -DMIRRORED_INTERNAL"
AC_DEFINE([MIRRORED_INTERNAL], 1, [Define to 1 to include built-in support for mirrors.])
fi
################################################################################
@@ -267,7 +274,7 @@ READLINE=$enableval, READLINE=no)
AC_MSG_RESULT($READLINE)
if test x$READLINE = xyes; then
CFLAGS="$CFLAGS -DREADLINE_SUPPORT"
AC_DEFINE([READLINE_SUPPORT], 1, [Define to 1 to include the LVM readline shell.])
fi
################################################################################
@@ -277,6 +284,13 @@ AC_ARG_ENABLE(selinux, [ --disable-selinux Disable selinux support],
SELINUX=$enableval)
AC_MSG_RESULT($SELINUX)
################################################################################
dnl -- Disable realtime clock support
AC_MSG_CHECKING(whether to enable realtime support)
AC_ARG_ENABLE(realtime, [ --disable-realtime Disable realtime clock support],
REALTIME=$enableval)
AC_MSG_RESULT($REALTIME)
################################################################################
dnl -- Build cluster LVM daemon
AC_MSG_CHECKING(whether to build cluster LVM daemon)
@@ -305,6 +319,8 @@ AC_MSG_RESULT($DEBUG)
dnl -- Normally turn off optimisation for debug builds
if test x$DEBUG = xyes; then
COPTIMISE_FLAG=
else
CSCOPE_CMD=
fi
################################################################################
@@ -323,7 +339,7 @@ DEVMAPPER=$enableval)
AC_MSG_RESULT($DEVMAPPER)
if test x$DEVMAPPER = xyes; then
CFLAGS="$CFLAGS -DDEVMAPPER_SUPPORT"
AC_DEFINE([DEVMAPPER_SUPPORT], 1, [Define to 1 to enable device-mapper interaction.])
fi
################################################################################
@@ -334,7 +350,7 @@ ODIRECT=$enableval)
AC_MSG_RESULT($ODIRECT)
if test x$ODIRECT = xyes; then
CFLAGS="$CFLAGS -DO_DIRECT_SUPPORT"
AC_DEFINE([O_DIRECT_SUPPORT], 1, [Define to 1 to enable O_DIRECT support.])
fi
################################################################################
@@ -344,10 +360,6 @@ AC_ARG_ENABLE(cmdlib, [ --enable-cmdlib Build shared command library],
CMDLIB=$enableval, CMDLIB=no)
AC_MSG_RESULT($CMDLIB)
if test x$CMDLIB = xyes; then
CFLAGS="$CFLAGS -DCMDLIB"
fi
################################################################################
dnl -- Enable fsadm
AC_MSG_CHECKING(whether to build fsadm)
@@ -355,6 +367,23 @@ AC_ARG_ENABLE(fsadm, [ --enable-fsadm Enable fsadm],
FSADM=$enableval)
AC_MSG_RESULT($FSADM)
################################################################################
dnl -- enable dmeventd handling
AC_MSG_CHECKING(whether to use dmeventd)
AC_ARG_ENABLE(dmeventd, [ --enable-dmeventd Enable the device-mapper event daemon],
DMEVENTD=$enableval)
AC_MSG_RESULT($DMEVENTD)
dnl -- dmeventd currently requires internal mirror support
if test x$DMEVENTD = xyes && test x$MIRRORS != xinternal; then
AC_MSG_ERROR(
--enable-dmeventd currently requires --with-mirrors=internal
)
fi
if test x$DMEVENTD = xyes; then
AC_DEFINE([DMEVENTD], 1, [Define to 1 to enable the device-mapper event daemon.])
fi
################################################################################
dnl -- Mess with default exec_prefix
if [[ "x$exec_prefix" = xNONE -a "x$prefix" = xNONE ]];
@@ -390,7 +419,7 @@ dnl -- Check for dlopen
AC_CHECK_LIB(dl, dlopen, HAVE_LIBDL=yes, HAVE_LIBDL=no)
if [[ "x$HAVE_LIBDL" = xyes ]]; then
CFLAGS="$CFLAGS -DHAVE_LIBDL"
AC_DEFINE([HAVE_LIBDL], 1, [Define to 1 if dynamic libraries are available.])
LIBS="-ldl $LIBS"
else
HAVE_LIBDL=no
@@ -407,23 +436,40 @@ Features cannot be 'shared' when building statically
fi
################################################################################
dnl -- Check for is_selinux_enabled
dnl -- Check for selinux
if test x$SELINUX = xyes; then
AC_MSG_CHECKING(for is_selinux_enabled function)
AC_CHECK_LIB(sepol, sepol_check_context, HAVE_SEPOL=yes, HAVE_SEPOL=no)
if test x$HAVE_SEPOL = xyes; then
LIBS="-lsepol $LIBS"
fi
AC_CHECK_LIB(selinux, is_selinux_enabled, HAVE_SELINUX=yes, HAVE_SELINUX=no)
AC_MSG_RESULT($HAVE_SELINUX)
if test x$HAVE_SELINUX = xyes; then
CFLAGS="$CFLAGS -DHAVE_SELINUX"
AC_DEFINE([HAVE_SELINUX], 1, [Define to 1 to include support for selinux.])
LIBS="-lselinux $LIBS"
else
AC_MSG_WARN(Disabling selinux)
fi
fi
################################################################################
dnl -- Check for realtime clock support
if test x$REALTIME = xyes; then
AC_CHECK_LIB(rt, clock_gettime, HAVE_REALTIME=yes, HAVE_REALTIME=no)
if test x$HAVE_REALTIME = xyes; then
AC_DEFINE([HAVE_REALTIME], 1, [Define to 1 to include support for realtime clock.])
LIBS="-lrt $LIBS"
else
AC_MSG_WARN(Disabling realtime clock)
fi
fi
################################################################################
dnl -- Check for getopt
AC_CHECK_HEADERS(getopt.h, CFLAGS="$CFLAGS -DHAVE_GETOPTLONG")
AC_CHECK_HEADERS(getopt.h, AC_DEFINE([HAVE_GETOPTLONG], 1, [Define to 1 to if getopt_long is available.]))
################################################################################
dnl -- Check for readline (Shamelessly copied from parted 1.4.17)
@@ -438,8 +484,7 @@ Note: if you are using precompiled packages you will also need the development
package as well (which may be called readline-devel or something similar).
)
)
AC_CHECK_FUNC(rl_completion_matches, CFLAGS="$CFLAGS -DHAVE_RL_COMPLETION_MATCHES")
AC_CHECK_FUNC(rl_completion_matches, AC_DEFINE([HAVE_RL_COMPLETION_MATCHES], 1, [Define to 1 if rl_completion_matches() is available.]))
fi
################################################################################
@@ -475,6 +520,11 @@ AC_ARG_WITH(staticdir,
[ STATICDIR="$withval" ],
[ STATICDIR='${exec_prefix}/sbin' ])
AC_ARG_WITH(dmdir,
[ --with-dmdir=DIR Build against device-mapper source tree in DIR],
[ DMDIR="$withval" ],
[ DMDIR= ])
################################################################################
dnl -- Ensure additional headers required
if test x$READLINE = xyes; then
@@ -507,9 +557,7 @@ if test x$INTL = xyes; then
AC_CHECK_HEADERS(libintl.h,,AC_MSG_ERROR(bailing out))
fi
if test x$DEVMAPPER = xyes; then
AC_CHECK_HEADERS(libdevmapper.h,,AC_MSG_ERROR(bailing out))
fi
AC_CHECK_HEADERS(libdevmapper.h,,AC_MSG_ERROR(bailing out))
if test x$HAVE_SELINUX = xyes; then
AC_CHECK_HEADERS(selinux/selinux.h,,AC_MSG_ERROR(bailing out))
@@ -519,7 +567,7 @@ fi
AC_PATH_PROG(MODPROBE_CMD, modprobe)
if test x$MODPROBE_CMD != x; then
CFLAGS="$CFLAGS -DMODPROBE_CMD=\\\"$MODPROBE_CMD\\\""
AC_DEFINE_UNQUOTED([MODPROBE_CMD], ["$MODPROBE_CMD"], [The path to 'modprobe', if available.])
fi
################################################################################
@@ -545,7 +593,7 @@ AC_SUBST(CLDWHOLEARCHIVE)
AC_SUBST(CLDNOWHOLEARCHIVE)
AC_SUBST(LDDEPS)
AC_SUBST(LDFLAGS)
AC_SUBST(SOFLAG)
AC_SUBST(LIB_SUFFIX)
AC_SUBST(LIBS)
AC_SUBST(LVM_VERSION)
AC_SUBST(LVM1_FALLBACK)
@@ -553,16 +601,21 @@ AC_SUBST(DEBUG)
AC_SUBST(DEVMAPPER)
AC_SUBST(HAVE_LIBDL)
AC_SUBST(HAVE_SELINUX)
AC_SUBST(HAVE_REALTIME)
AC_SUBST(CMDLIB)
AC_SUBST(MSGFMT)
AC_SUBST(LOCALEDIR)
AC_SUBST(CONFDIR)
AC_SUBST(STATICDIR)
AC_SUBST(DMDIR)
AC_SUBST(INTL_PACKAGE)
AC_SUBST(INTL)
AC_SUBST(CLVMD)
AC_SUBST(CLUSTER)
AC_SUBST(FSADM)
AC_SUBST(DMEVENTD)
AC_SUBST(CFLOW_CMD)
AC_SUBST(CSCOPE_CMD)
################################################################################
dnl -- First and last lines should not contain files to generate in order to
@@ -572,6 +625,8 @@ Makefile \
make.tmpl \
daemons/Makefile \
daemons/clvmd/Makefile \
dmeventd/Makefile \
dmeventd/mirror/Makefile \
doc/Makefile \
include/Makefile \
lib/Makefile \
@@ -582,6 +637,7 @@ lib/mirror/Makefile \
lib/snapshot/Makefile \
man/Makefile \
po/Makefile \
scripts/Makefile \
tools/Makefile \
tools/version.h \
tools/fsadm/Makefile \
@@ -599,3 +655,7 @@ fi
if test x$FSADM == xyes; then
AC_MSG_WARN(fsadm support is untested)
fi
if test x$DMEVENTD == xyes; then
AC_MSG_WARN(dmeventd support is untested)
fi

View File

@@ -19,6 +19,7 @@ SOURCES = \
clvmd-command.c \
clvmd.c \
lvm-functions.c \
refresh_clvmd.c \
system-lv.c
ifeq ("@CLVMD@", "gulm")
@@ -35,34 +36,43 @@ ifeq ("@CLVMD@", "all")
endif
ifeq ("@DEBUG@", "yes")
CFLAGS += -DDEBUG
DEFS += -DDEBUG
endif
ifeq ("$(GULM)", "yes")
SOURCES += clvmd-gulm.c tcp-comms.c
LMLIBS += -lccs -lgulm
CFLAGS += -DUSE_GULM
DEFS += -DUSE_GULM
endif
ifeq ("$(CMAN)", "yes")
SOURCES += clvmd-cman.c
LMLIBS += -ldlm
CFLAGS += -DUSE_CMAN
LMLIBS += -ldlm -lcman
DEFS += -DUSE_CMAN
endif
TARGETS = \
clvmd
include $(top_srcdir)/make.tmpl
LVMLIBS = -llvm -lpthread
CFLAGS += -D_REENTRANT -fno-strict-aliasing
LIBS += -ldevmapper -llvm -lpthread
ifeq ("@DMEVENTD@", "yes")
LVMLIBS += -ldevmapper-event
endif
LVMLIBS += -ldevmapper
DEFS += -D_REENTRANT
CFLAGS += -fno-strict-aliasing
include $(top_srcdir)/make.tmpl
INSTALL_TARGETS = \
install_clvmd
clvmd: $(OBJECTS) $(top_srcdir)/lib/liblvm.a
$(CC) -o clvmd $(OBJECTS) $(LDFLAGS) $(LVMLIBS) $(LMLIBS) $(LIBS)
$(CC) -o clvmd $(OBJECTS) $(CFLAGS) $(LDFLAGS) \
$(LVMLIBS) $(LMLIBS) $(LIBS)
.PHONY: install_clvmd

View File

@@ -63,4 +63,8 @@ static const char CLVMD_SOCKNAME[] = "\0clvmd";
#define CLVMD_CMD_LOCK_LV 50
#define CLVMD_CMD_LOCK_VG 51
/* Misc functions */
#define CLVMD_CMD_REFRESH 40
#define CLVMD_CMD_GET_CLUSTERNAME 41
#endif

View File

@@ -36,29 +36,33 @@
#include <fcntl.h>
#include <getopt.h>
#include <errno.h>
#include <libdlm.h>
#include "clvmd-comms.h"
#include "clvm.h"
#include "libdlm.h"
#include "log.h"
#include "clvmd.h"
#include "lvm-functions.h"
#define LOCKSPACE_NAME "clvmd"
static int cluster_sock;
static int num_nodes;
static struct cl_cluster_node *nodes = NULL;
static struct cman_node *nodes = NULL;
static struct cman_node this_node;
static int count_nodes; /* size of allocated nodes array */
static int max_updown_nodes = 50; /* Current size of the allocated array */
/* Node up/down status, indexed by nodeid */
static int *node_updown = NULL;
static dlm_lshandle_t *lockspace;
static cman_handle_t c_handle;
static void count_clvmds_running(void);
static void get_members(void);
static int nodeid_from_csid(char *csid);
static int name_from_nodeid(int nodeid, char *name);
static void event_callback(cman_handle_t handle, void *private, int reason, int arg);
static void data_callback(cman_handle_t handle, void *private,
char *buf, int len, uint8_t port, int nodeid);
struct lock_wait {
pthread_cond_t cond;
@@ -68,30 +72,23 @@ struct lock_wait {
static int _init_cluster(void)
{
struct sockaddr_cl saddr;
int port = CLUSTER_PORT_CLVMD;
/* Open the cluster communication socket */
cluster_sock = socket(AF_CLUSTER, SOCK_DGRAM, CLPROTO_CLIENT);
if (cluster_sock == -1) {
/* Don't print an error here because we could be just probing for CMAN */
c_handle = cman_init(NULL);
if (!c_handle) {
syslog(LOG_ERR, "Can't open cluster manager socket: %m");
return -1;
}
/* Set Close-on-exec */
fcntl(cluster_sock, F_SETFD, 1);
/* Bind to our port number on the cluster.
Writes to this will block if the cluster loses quorum */
saddr.scl_family = AF_CLUSTER;
saddr.scl_port = port;
if (bind
(cluster_sock, (struct sockaddr *) &saddr,
sizeof(struct sockaddr_cl))) {
if (cman_start_recv_data(c_handle, data_callback, CLUSTER_PORT_CLVMD)) {
syslog(LOG_ERR, "Can't bind cluster socket: %m");
return -1;
}
if (cman_start_notification(c_handle, event_callback)) {
syslog(LOG_ERR, "Can't start cluster event listening");
return -1;
}
/* Get the cluster members list */
get_members();
count_clvmds_running();
@@ -114,152 +111,121 @@ static void _cluster_init_completed(void)
static int _get_main_cluster_fd()
{
return cluster_sock;
return cman_get_fd(c_handle);
}
static int _get_num_nodes()
{
return num_nodes;
int i;
int nnodes = 0;
/* return number of ACTIVE nodes */
for (i=0; i<num_nodes; i++) {
if (nodes[i].cn_member && nodes[i].cn_nodeid)
nnodes++;
}
return nnodes;
}
/* send_message with the fd check removed */
static int _cluster_send_message(void *buf, int msglen, char *csid, const char *errtext)
{
struct iovec iov[2];
struct msghdr msg;
struct sockaddr_cl saddr;
int len = 0;
int nodeid = 0;
msg.msg_control = NULL;
msg.msg_controllen = 0;
msg.msg_iovlen = 1;
msg.msg_iov = iov;
msg.msg_flags = 0;
iov[0].iov_len = msglen;
iov[0].iov_base = buf;
if (csid)
memcpy(&nodeid, csid, CMAN_MAX_CSID_LEN);
saddr.scl_family = AF_CLUSTER;
saddr.scl_port = CLUSTER_PORT_CLVMD;
if (csid) {
msg.msg_name = &saddr;
msg.msg_namelen = sizeof(saddr);
memcpy(&saddr.scl_nodeid, csid, CMAN_MAX_CSID_LEN);
} else { /* Cluster broadcast */
msg.msg_name = NULL;
msg.msg_namelen = 0;
if (cman_send_data(c_handle, buf, msglen, 0, CLUSTER_PORT_CLVMD, nodeid) <= 0)
{
log_error(errtext);
}
do {
len = sendmsg(cluster_sock, &msg, 0);
if (len < 0 && errno != EAGAIN)
log_error(errtext);
} while (len == -1 && errno == EAGAIN);
return len;
return msglen;
}
static void _get_our_csid(char *csid)
{
int i;
memset(csid, 0, CMAN_MAX_CSID_LEN);
for (i = 0; i < num_nodes; i++) {
if (nodes[i].us)
memcpy(csid, &nodes[i].node_id, CMAN_MAX_CSID_LEN);
if (this_node.cn_nodeid == 0) {
cman_get_node(c_handle, 0, &this_node);
}
memcpy(csid, &this_node.cn_nodeid, CMAN_MAX_CSID_LEN);
}
/* Call a callback routine for each node that known (down mean not running a clvmd) */
/* Call a callback routine for each node is that known (down means not running a clvmd) */
static int _cluster_do_node_callback(struct local_client *client,
void (*callback) (struct local_client *, char *,
int))
void (*callback) (struct local_client *, char *,
int))
{
int i;
int somedown = 0;
for (i = 0; i < _get_num_nodes(); i++) {
callback(client, (char *)&nodes[i].node_id, node_updown[nodes[i].node_id]);
if (!node_updown[nodes[i].node_id])
somedown = -1;
if (nodes[i].cn_member && nodes[i].cn_nodeid) {
callback(client, (char *)&nodes[i].cn_nodeid, node_updown[nodes[i].cn_nodeid]);
if (!node_updown[nodes[i].cn_nodeid])
somedown = -1;
}
}
return somedown;
}
/* Process OOB message from the cluster socket,
this currently just means that a node has stopped listening on our port */
static void process_oob_msg(char *buf, int len, int nodeid)
/* Process OOB messages from the cluster socket */
static void event_callback(cman_handle_t handle, void *private, int reason, int arg)
{
char namebuf[256];
switch (buf[0]) {
case CLUSTER_OOB_MSG_PORTCLOSED:
name_from_nodeid(nodeid, namebuf);
log_notice("clvmd on node %s has died\n", namebuf);
DEBUGLOG("Got OOB message, removing node %s\n", namebuf);
char namebuf[MAX_CLUSTER_MEMBER_NAME_LEN];
node_updown[nodeid] = 0;
switch (reason) {
case CMAN_REASON_PORTCLOSED:
name_from_nodeid(arg, namebuf);
log_notice("clvmd on node %s has died\n", namebuf);
DEBUGLOG("Got port closed message, removing node %s\n", namebuf);
node_updown[arg] = 0;
break;
case CLUSTER_OOB_MSG_STATECHANGE:
DEBUGLOG("Got OOB message, Cluster state change\n");
case CMAN_REASON_STATECHANGE:
DEBUGLOG("Got state change message, re-reading members list\n");
get_members();
break;
#if defined(LIBCMAN_VERSION) && LIBCMAN_VERSION >= 2
case CMAN_REASON_PORTOPENED:
/* Ignore this, wait for startup message from clvmd itself */
break;
case CMAN_REASON_TRY_SHUTDOWN:
DEBUGLOG("Got try shutdown, sending OK\n");
cman_replyto_shutdown(c_handle, 1);
break;
#endif
default:
/* ERROR */
DEBUGLOG("Got unknown OOB message: %d\n", buf[0]);
DEBUGLOG("Got unknown event callback message: %d\n", reason);
break;
}
}
static int _cluster_fd_callback(struct local_client *client, char *buf, int len, char *csid,
struct local_client **new_client)
static struct local_client *cman_client;
static int _cluster_fd_callback(struct local_client *fd, char *buf, int len, char *csid,
struct local_client **new_client)
{
struct iovec iov[2];
struct msghdr msg;
struct sockaddr_cl saddr;
/* Save this for data_callback */
cman_client = fd;
/* We never return a new client */
*new_client = NULL;
msg.msg_control = NULL;
msg.msg_controllen = 0;
msg.msg_iovlen = 1;
msg.msg_iov = iov;
msg.msg_name = &saddr;
msg.msg_flags = 0;
msg.msg_namelen = sizeof(saddr);
iov[0].iov_len = len;
iov[0].iov_base = buf;
return cman_dispatch(c_handle, 0);
}
len = recvmsg(cluster_sock, &msg, MSG_OOB | O_NONBLOCK);
if (len < 0 && errno == EAGAIN)
return len;
DEBUGLOG("Read on cluster socket, len = %d\n", len);
/* A real error */
if (len < 0) {
log_error("read error on cluster socket: %m");
return 0;
}
/* EOF - we have left the cluster */
if (len == 0)
return 0;
/* Is it OOB? probably a node gone down */
if (msg.msg_flags & MSG_OOB) {
process_oob_msg(iov[0].iov_base, len, saddr.scl_nodeid);
/* Tell the upper layer to ignore this message */
len = -1;
errno = EAGAIN;
}
else {
memcpy(csid, &saddr.scl_nodeid, sizeof(saddr.scl_nodeid));
/* Send it back to clvmd */
process_message(client, buf, len, csid);
}
return len;
static void data_callback(cman_handle_t handle, void *private,
char *buf, int len, uint8_t port, int nodeid)
{
/* Ignore looped back messages */
if (nodeid == this_node.cn_nodeid)
return;
process_message(cman_client, buf, len, (char *)&nodeid);
}
static void _add_up_node(char *csid)
@@ -278,7 +244,7 @@ static void _add_up_node(char *csid)
max_updown_nodes);
} else {
log_error
("Realloc failed. Node status for clvmd will be wrong. quitting\n");
("Realloc failed. Node status for clvmd will be wrong. quitting\n");
exit(999);
}
}
@@ -290,19 +256,15 @@ static void _cluster_closedown()
{
unlock_all();
dlm_release_lockspace(LOCKSPACE_NAME, lockspace, 1);
close(cluster_sock);
cman_finish(c_handle);
}
static int is_listening(int nodeid)
{
struct cl_listen_request rq;
int status;
rq.port = CLUSTER_PORT_CLVMD;
rq.nodeid = nodeid;
do {
status = ioctl(cluster_sock, SIOCCLUSTER_ISLISTENING, &rq);
status = cman_is_listening(c_handle, nodeid, CLUSTER_PORT_CLVMD);
if (status < 0 && errno == EBUSY) { /* Don't busywait */
sleep(1);
errno = EBUSY; /* In case sleep trashes it */
@@ -320,67 +282,61 @@ static void count_clvmds_running(void)
int i;
for (i = 0; i < num_nodes; i++) {
node_updown[nodes[i].node_id] = is_listening(nodes[i].node_id);
node_updown[nodes[i].cn_nodeid] = is_listening(nodes[i].cn_nodeid);
}
}
/* Get a list of active cluster members */
static void get_members()
{
struct cl_cluster_nodelist nodelist;
int retnodes;
int status;
num_nodes = ioctl(cluster_sock, SIOCCLUSTER_GETMEMBERS, 0);
num_nodes = cman_get_node_count(c_handle);
if (num_nodes == -1) {
log_error("Unable to get node count");
} else {
/* Not enough room for new nodes list ? */
if (num_nodes > count_nodes && nodes) {
free(nodes);
nodes = NULL;
}
return;
}
if (nodes == NULL) {
count_nodes = num_nodes + 10; /* Overallocate a little */
nodes = malloc(count_nodes * sizeof(struct cl_cluster_node));
if (!nodes) {
log_error("Unable to allocate nodes array\n");
exit(5);
}
}
nodelist.max_members = count_nodes;
nodelist.nodes = nodes;
/* Not enough room for new nodes list ? */
if (num_nodes > count_nodes && nodes) {
free(nodes);
nodes = NULL;
}
num_nodes = ioctl(cluster_sock, SIOCCLUSTER_GETMEMBERS, &nodelist);
if (num_nodes <= 0) {
log_error("Unable to get node details");
exit(6);
}
/* Sanity check struct */
if (nodes[0].size != sizeof(struct cl_cluster_node)) {
log_error
("sizeof(cl_cluster_node) does not match size returned from the kernel: aborting\n");
exit(10);
}
if (node_updown == NULL) {
node_updown =
(int *) malloc(sizeof(int) *
max(num_nodes, max_updown_nodes));
memset(node_updown, 0,
sizeof(int) * max(num_nodes, max_updown_nodes));
if (nodes == NULL) {
count_nodes = num_nodes + 10; /* Overallocate a little */
nodes = malloc(count_nodes * sizeof(struct cman_node));
if (!nodes) {
log_error("Unable to allocate nodes array\n");
exit(5);
}
}
status = cman_get_nodes(c_handle, count_nodes, &retnodes, nodes);
if (status < 0) {
log_error("Unable to get node details");
exit(6);
}
if (node_updown == NULL) {
node_updown =
(int *) malloc(sizeof(int) *
max(num_nodes, max_updown_nodes));
memset(node_updown, 0,
sizeof(int) * max(num_nodes, max_updown_nodes));
}
}
/* Convert a node name to a CSID */
static int _csid_from_name(char *csid, char *name)
{
int i;
for (i = 0; i < num_nodes; i++) {
if (strcmp(name, nodes[i].name) == 0) {
memcpy(csid, &nodes[i].node_id, CMAN_MAX_CSID_LEN);
if (strcmp(name, nodes[i].cn_name) == 0) {
memcpy(csid, &nodes[i].cn_nodeid, CMAN_MAX_CSID_LEN);
return 0;
}
}
@@ -393,8 +349,8 @@ static int _name_from_csid(char *csid, char *name)
int i;
for (i = 0; i < num_nodes; i++) {
if (memcmp(csid, &nodes[i].node_id, CMAN_MAX_CSID_LEN) == 0) {
strcpy(name, nodes[i].name);
if (memcmp(csid, &nodes[i].cn_nodeid, CMAN_MAX_CSID_LEN) == 0) {
strcpy(name, nodes[i].cn_name);
return 0;
}
}
@@ -409,8 +365,8 @@ static int name_from_nodeid(int nodeid, char *name)
int i;
for (i = 0; i < num_nodes; i++) {
if (nodeid == nodes[i].node_id) {
strcpy(name, nodes[i].name);
if (nodeid == nodes[i].cn_nodeid) {
strcpy(name, nodes[i].cn_name);
return 0;
}
}
@@ -431,7 +387,7 @@ static int nodeid_from_csid(char *csid)
static int _is_quorate()
{
return ioctl(cluster_sock, SIOCCLUSTER_ISQUORATE, 0);
return cman_is_quorate(c_handle);
}
static void sync_ast_routine(void *arg)
@@ -514,6 +470,18 @@ static int _sync_unlock(const char *resource /* UNUSED */, int lockid)
}
static int _get_cluster_name(char *buf, int buflen)
{
cman_cluster_t cluster_info;
int status;
status = cman_get_cluster(c_handle, &cluster_info);
if (!status) {
strncpy(buf, cluster_info.ci_name, buflen);
}
return status;
}
static struct cluster_ops _cluster_cman_ops = {
.cluster_init_completed = _cluster_init_completed,
.cluster_send_message = _cluster_send_message,
@@ -527,6 +495,7 @@ static struct cluster_ops _cluster_cman_ops = {
.get_our_csid = _get_our_csid,
.add_up_node = _add_up_node,
.cluster_closedown = _cluster_closedown,
.get_cluster_name = _get_cluster_name,
.sync_lock = _sync_lock,
.sync_unlock = _sync_unlock,
};

View File

@@ -64,8 +64,9 @@
#include <stddef.h>
#include <unistd.h>
#include <errno.h>
#include <libdevmapper.h>
#include <libdlm.h>
#include "libdevmapper.h"
#include "list.h"
#include "locking.h"
#include "log.h"
@@ -73,7 +74,8 @@
#include "clvmd-comms.h"
#include "clvm.h"
#include "clvmd.h"
#include "libdlm.h"
extern struct cluster_ops *clops;
/* This is where all the real work happens:
NOTE: client will be NULL when this is executed on a remote node */
@@ -117,11 +119,21 @@ int do_command(struct local_client *client, struct clvm_header *msg, int msglen,
if (status == EIO) {
*retlen =
1 + snprintf(*buf, buflen,
"Internal lvm error, check syslog");
get_last_lvm_error());
return EIO;
}
break;
case CLVMD_CMD_REFRESH:
do_refresh_cache();
break;
case CLVMD_CMD_GET_CLUSTERNAME:
status = clops->get_cluster_name(*buf, buflen);
if (!status)
*retlen = strlen(*buf);
break;
default:
/* Won't get here because command is validated in pre_command */
break;
@@ -179,12 +191,16 @@ static int lock_vg(struct local_client *client)
dm_hash_remove(lock_hash, lockname);
}
else {
status = sync_lock(lockname, (int)lock_cmd, (int)lock_flags, &lkid);
/* Read locks need to be PR; other modes get passed through */
if ((lock_cmd & LCK_TYPE_MASK) == LCK_READ) {
lock_cmd &= ~LCK_TYPE_MASK;
lock_cmd |= LCK_PREAD;
}
status = sync_lock(lockname, (int)lock_cmd, (lock_flags & LCK_NONBLOCK) ? LKF_NOQUEUE : 0, &lkid);
if (status)
status = errno;
else
dm_hash_insert(lock_hash, lockname, (void *)lkid);
dm_hash_insert(lock_hash, lockname, (void *)(long)lkid);
}
return status;
@@ -208,7 +224,7 @@ int do_pre_command(struct local_client *client)
switch (header->cmd) {
case CLVMD_CMD_TEST:
status = sync_lock("CLVMD_TEST", LKM_EXMODE, 0, &lockid);
client->bits.localsock.private = (void *) lockid;
client->bits.localsock.private = (void *)(long)lockid;
break;
case CLVMD_CMD_LOCK_VG:
@@ -222,6 +238,10 @@ int do_pre_command(struct local_client *client)
status = pre_lock_lv(lock_cmd, lock_flags, lockname);
break;
case CLVMD_CMD_REFRESH:
case CLVMD_CMD_GET_CLUSTERNAME:
break;
default:
log_error("Unknown command %d received\n", header->cmd);
status = EINVAL;

View File

@@ -43,6 +43,8 @@ struct cluster_ops {
void (*reread_config) (void);
void (*cluster_closedown) (void);
int (*get_cluster_name)(char *buf, int buflen);
int (*sync_lock) (const char *resource, int mode, int flags, int *lockid);
int (*sync_unlock) (const char *resource, int lockid);
@@ -56,15 +58,19 @@ struct cluster_ops *init_gulm_cluster(void);
#endif
#ifdef USE_CMAN
# include "cnxman-socket.h"
# include <netinet/in.h>
# include "libcman.h"
# define CMAN_MAX_CSID_LEN 4
# ifndef MAX_CSID_LEN
# define MAX_CSID_LEN CMAN_MAX_CSID_LEN
# endif
# undef MAX_CLUSTER_MEMBER_NAME_LEN
# define MAX_CLUSTER_MEMBER_NAME_LEN CMAN_MAX_CLUSTER_MEMBER_NAME_LEN
# define MAX_CLUSTER_MEMBER_NAME_LEN CMAN_MAX_NODENAME_LEN
# define CMAN_MAX_CLUSTER_MESSAGE 1500
# define CLUSTER_PORT_CLVMD 11
struct cluster_ops *init_cman_cluster(void);
#endif
#endif

View File

@@ -40,9 +40,10 @@
#include <utmpx.h>
#include <syslog.h>
#include <assert.h>
#include <libdevmapper.h>
#include <ccs.h>
#include <libgulm.h>
#include "libdevmapper.h"
#include "ccs.h"
#include "list.h"
#include "locking.h"
#include "log.h"
@@ -51,7 +52,6 @@
#include "lvm-functions.h"
#include "clvmd.h"
#include "clvmd-gulm.h"
#include "libgulm.h"
/* Hash list of nodes in the cluster */
static struct dm_hash_table *node_hash;
@@ -346,8 +346,8 @@ static void set_node_state(struct node_info *ninfo, char *csid, uint8_t nodestat
*/
tcp_remove_client(csid);
DEBUGLOG("set_node_state, '%s' state = %d (oldstate=%d), num_nodes=%d\n",
ninfo->name, ninfo->state, oldstate, num_nodes);
DEBUGLOG("set_node_state, '%s' state = %d num_nodes=%d\n",
ninfo->name, ninfo->state, num_nodes);
}
static struct node_info *add_or_set_node(char *name, struct in6_addr *ip, uint8_t state)
@@ -730,7 +730,7 @@ static int _lock_resource(char *resource, int mode, int flags, int *lockid)
pthread_mutex_lock(&lwait.mutex);
/* This needs to be converted from DLM/LVM2 value for GULM */
if (flags == LCK_NONBLOCK) flags = lg_lock_flag_Try;
if (flags & LKF_NOQUEUE) flags = lg_lock_flag_Try;
dm_hash_insert(lock_hash, resource, &lwait);
DEBUGLOG("lock_resource '%s', flags=%d, mode=%d\n", resource, flags, mode);
@@ -828,6 +828,7 @@ static int _sync_lock(const char *resource, int mode, int flags, int *lockid)
}
break;
case LCK_PREAD:
case LCK_READ:
status = _lock_resource(lock1, lg_lock_state_Shared, flags, lockid);
if (status)
@@ -864,6 +865,7 @@ static int _sync_unlock(const char *resource, int lockid)
/* The held lock mode is in the lock id */
assert(lockid == LCK_EXCL ||
lockid == LCK_READ ||
lockid == LCK_PREAD ||
lockid == LCK_WRITE);
status = _unlock_resource(lock1, lockid);
@@ -973,6 +975,12 @@ static int _cluster_send_message(void *buf, int msglen, char *csid, const char *
return gulm_cluster_send_message(buf, msglen, csid, errtext);
}
static int _get_cluster_name(char *buf, int buflen)
{
strncpy(buf, cluster_name, buflen);
return 0;
}
static struct cluster_ops _cluster_gulm_ops = {
.cluster_init_completed = NULL,
.cluster_send_message = _cluster_send_message,
@@ -987,6 +995,7 @@ static struct cluster_ops _cluster_gulm_ops = {
.add_up_node = gulm_add_up_node,
.reread_config = _reread_config,
.cluster_closedown = _cluster_closedown,
.get_cluster_name = _get_cluster_name,
.sync_lock = _sync_lock,
.sync_unlock = _sync_unlock,
};

View File

@@ -1,5 +1,6 @@
/* DLM constant that clvmd uses as a generic NONBLOCK lock flag */
#define LKF_NOQUEUE 1
extern int get_next_node_csid(void **context, char *csid);
extern void add_down_node(char *csid);

View File

@@ -30,19 +30,21 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdarg.h>
#include <signal.h>
#include <unistd.h>
#include <fcntl.h>
#include <getopt.h>
#include <syslog.h>
#include <errno.h>
#include <libdlm.h>
#include "clvmd-comms.h"
#include "lvm-functions.h"
#include "clvm.h"
#include "version.h"
#include "clvmd.h"
#include "libdlm.h"
#include "refresh_clvmd.h"
#include "system-lv.h"
#include "list.h"
#include "log.h"
@@ -54,6 +56,8 @@
#define FALSE 0
#endif
#define MAX_RETRIES 4
/* The maximum size of a message that will fit into a packet. Anything bigger
than this is sent via the system LV */
#define MAX_INLINE_MESSAGE (max_cluster_message-sizeof(struct clvm_header))
@@ -66,7 +70,7 @@ static struct local_client local_client_head;
static unsigned short global_xid = 0; /* Last transaction ID issued */
static struct cluster_ops *clops = NULL;
struct cluster_ops *clops = NULL;
static char our_csid[MAX_CSID_LEN];
static unsigned max_csid_len;
@@ -84,6 +88,7 @@ struct lvm_thread_cmd {
int msglen;
unsigned short xid;
};
static int debug = 0;
static pthread_t lvm_thread;
static pthread_mutex_t lvm_thread_mutex;
static pthread_cond_t lvm_thread_cond;
@@ -98,6 +103,7 @@ static int child_pipe[2];
#define DFAIL_LOCAL_SOCK 2
#define DFAIL_CLUSTER_IF 3
#define DFAIL_MALLOC 4
#define DFAIL_TIMEOUT 5
#define SUCCESS 0
/* Prototypes for code further down */
@@ -121,7 +127,7 @@ static int process_reply(struct clvm_header *msg, int msglen, char *csid);
static int open_local_sock(void);
static struct local_client *find_client(int clientid);
static void main_loop(int local_sock, int cmd_timeout);
static void be_daemon(void);
static void be_daemon(int start_timeout);
static int check_all_clvmds_running(struct local_client *client);
static int local_rendezvous_callback(struct local_client *thisfd, char *buf,
int len, char *csid,
@@ -143,7 +149,9 @@ static void usage(char *prog, FILE *file)
fprintf(file, " -V Show version of clvmd\n");
fprintf(file, " -h Show this help information\n");
fprintf(file, " -d Don't fork, run in the foreground\n");
fprintf(file, " -R Tell all running clvmds in the cluster to reload their device cache\n");
fprintf(file, " -t<secs> Command timeout (default 60 seconds)\n");
fprintf(file, " -T<secs> Startup timeout (default none)\n");
fprintf(file, "\n");
}
@@ -159,21 +167,36 @@ static void child_init_signal(int status)
}
void debuglog(const char *fmt, ...)
{
time_t P;
va_list ap;
if (!debug)
return;
va_start(ap,fmt);
time(&P);
fprintf(stderr, "CLVMD[%x]: %.15s ", (int)pthread_self(), ctime(&P)+4 );
vfprintf(stderr, fmt, ap);
va_end(ap);
}
int main(int argc, char *argv[])
{
int local_sock;
struct local_client *newfd;
struct utsname nodeinfo;
signed char opt;
int debug = 0;
int cmd_timeout = DEFAULT_CMD_TIMEOUT;
int start_timeout = 0;
sigset_t ss;
int using_gulm = 0;
/* Deal with command-line arguments */
opterr = 0;
optind = 0;
while ((opt = getopt(argc, argv, "?vVhdt:")) != EOF) {
while ((opt = getopt(argc, argv, "?vVhdt:RT:")) != EOF) {
switch (opt) {
case 'h':
usage(argv[0], stdout);
@@ -183,6 +206,9 @@ int main(int argc, char *argv[])
usage(argv[0], stderr);
exit(0);
case 'R':
return refresh_clvmd();
case 'd':
debug++;
break;
@@ -195,6 +221,14 @@ int main(int argc, char *argv[])
exit(1);
}
break;
case 'T':
start_timeout = atoi(optarg);
if (start_timeout <= 0) {
fprintf(stderr, "startup timeout is invalid\n");
usage(argv[0], stderr);
exit(1);
}
break;
case 'V':
printf("Cluster LVM daemon version: %s\n", LVM_VERSION);
@@ -209,7 +243,7 @@ int main(int argc, char *argv[])
/* Fork into the background (unless requested not to) */
if (!debug) {
be_daemon();
be_daemon(start_timeout);
}
DEBUGLOG("CLVMD started\n");
@@ -247,7 +281,7 @@ int main(int argc, char *argv[])
if ((clops = init_cman_cluster())) {
max_csid_len = CMAN_MAX_CSID_LEN;
max_cluster_message = CMAN_MAX_CLUSTER_MESSAGE;
max_cluster_member_name_len = CMAN_MAX_CLUSTER_MEMBER_NAME_LEN;
max_cluster_member_name_len = CMAN_MAX_NODENAME_LEN;
syslog(LOG_NOTICE, "Cluster LVM daemon started - connected to CMAN");
}
#endif
@@ -293,7 +327,8 @@ int main(int argc, char *argv[])
/* This needs to be started after cluster initialisation
as it may need to take out locks */
DEBUGLOG("starting LVM thread\n");
pthread_create(&lvm_thread, NULL, lvm_thread_fn, (void *)using_gulm);
pthread_create(&lvm_thread, NULL, lvm_thread_fn,
(void *)(long)using_gulm);
/* Tell the rest of the cluster our version number */
/* CMAN can do this immediately, gulm needs to wait until
@@ -342,6 +377,9 @@ static int local_rendezvous_callback(struct local_client *thisfd, char *buf,
socklen_t sl = sizeof(socka);
int client_fd = accept(thisfd->fd, (struct sockaddr *) &socka, &sl);
if (client_fd == -1 && errno == EINTR)
return 1;
if (client_fd >= 0) {
newfd = malloc(sizeof(struct local_client));
if (!newfd) {
@@ -379,17 +417,20 @@ static int local_pipe_callback(struct local_client *thisfd, char *buf,
int status = -1; /* in error by default */
len = read(thisfd->fd, buffer, sizeof(int));
DEBUGLOG("read on PIPE %d: %d bytes: status: %d\n",
thisfd->fd, len, *(int *) buffer);
if (len == -1 && errno == EINTR)
return 1;
if (len == sizeof(int)) {
status = *(int *) buffer;
memcpy(&status, buffer, sizeof(int));
}
DEBUGLOG("read on PIPE %d: %d bytes: status: %d\n",
thisfd->fd, len, status);
/* EOF on pipe or an error, close it */
if (len <= 0) {
int jstat;
void *ret = &status;
close(thisfd->fd);
/* Clear out the cross-link */
@@ -399,9 +440,7 @@ static int local_pipe_callback(struct local_client *thisfd, char *buf,
/* Reap child thread */
if (thisfd->bits.pipe.threadid) {
jstat =
pthread_join(thisfd->bits.pipe.threadid,
(void **) &status);
jstat = pthread_join(thisfd->bits.pipe.threadid, &ret);
thisfd->bits.pipe.threadid = 0;
if (thisfd->bits.pipe.client != NULL)
thisfd->bits.pipe.client->bits.localsock.
@@ -509,6 +548,7 @@ static void main_loop(int local_sock, int cmd_timeout)
int quorate = clops->is_quorate();
/* Wait on the cluster FD and all local sockets/pipes */
local_client_head.fd = clops->get_main_cluster_fd();
FD_ZERO(&in);
for (thisfd = &local_client_head; thisfd != NULL;
thisfd = thisfd->next) {
@@ -641,16 +681,66 @@ static void main_loop(int local_sock, int cmd_timeout)
close(local_sock);
}
static __attribute__ ((noreturn)) void wait_for_child(int c_pipe, int timeout)
{
int child_status;
int sstat;
fd_set fds;
struct timeval tv = {timeout, 0};
FD_ZERO(&fds);
FD_SET(c_pipe, &fds);
sstat = select(c_pipe+1, &fds, NULL, NULL, timeout? &tv: NULL);
if (sstat == 0) {
fprintf(stderr, "clvmd startup timed out\n");
exit(DFAIL_TIMEOUT);
}
if (sstat == 1) {
if (read(c_pipe, &child_status, sizeof(child_status)) !=
sizeof(child_status)) {
fprintf(stderr, "clvmd failed in initialisation\n");
exit(DFAIL_INIT);
}
else {
switch (child_status) {
case SUCCESS:
break;
case DFAIL_INIT:
fprintf(stderr, "clvmd failed in initialisation\n");
break;
case DFAIL_LOCAL_SOCK:
fprintf(stderr, "clvmd could not create local socket\n");
fprintf(stderr, "Another clvmd is probably already running\n");
break;
case DFAIL_CLUSTER_IF:
fprintf(stderr, "clvmd could not connect to cluster manager\n");
fprintf(stderr, "Consult syslog for more information\n");
break;
case DFAIL_MALLOC:
fprintf(stderr, "clvmd failed, not enough memory\n");
break;
default:
fprintf(stderr, "clvmd failed, error was %d\n", child_status);
break;
}
exit(child_status);
}
}
fprintf(stderr, "clvmd startup, select failed: %s\n", strerror(errno));
exit(DFAIL_INIT);
}
/*
* Fork into the background and detach from our parent process.
* In the interests of user-friendliness we wait for the daemon
* to complete initialisation before returning its status
* the the user.
*/
static void be_daemon()
static void be_daemon(int timeout)
{
pid_t pid;
int child_status;
int devnull = open("/dev/null", O_RDWR);
if (devnull == -1) {
perror("Can't open /dev/null");
@@ -670,36 +760,7 @@ static void be_daemon()
default: /* Parent */
close(child_pipe[1]);
if (read(child_pipe[0], &child_status, sizeof(child_status)) !=
sizeof(child_status)) {
fprintf(stderr, "clvmd failed in initialisation\n");
exit(DFAIL_INIT);
}
else {
switch (child_status) {
case SUCCESS:
break;
case DFAIL_INIT:
fprintf(stderr, "clvmd failed in initialisation\n");
break;
case DFAIL_LOCAL_SOCK:
fprintf(stderr, "clvmd could not create local socket\n");
fprintf(stderr, "Another clvmd is probably already running\n");
break;
case DFAIL_CLUSTER_IF:
fprintf(stderr, "clvmd could not connect to cluster manager\n");
fprintf(stderr, "Consult syslog for more information\n");
break;
case DFAIL_MALLOC:
fprintf(stderr, "clvmd failed, not enough memory\n");
break;
default:
fprintf(stderr, "clvmd failed, error was %d\n", child_status);
break;
}
exit(child_status);
}
wait_for_child(child_pipe[0], timeout);
}
/* Detach ourself from the calling environment */
@@ -732,6 +793,8 @@ static int read_from_local_sock(struct local_client *thisfd)
char buffer[PIPE_BUF];
len = read(thisfd->fd, buffer, sizeof(buffer));
if (len == -1 && errno == EINTR)
return 1;
DEBUGLOG("Read on local socket %d, len = %d\n", thisfd->fd, len);
@@ -847,8 +910,12 @@ static int read_from_local_sock(struct local_client *thisfd)
len - strlen(inheader->node) - sizeof(struct clvm_header);
missing_len = inheader->arglen - argslen;
if (missing_len < 0)
missing_len = 0;
/* Save the message */
thisfd->bits.localsock.cmd = malloc(len + missing_len);
if (!thisfd->bits.localsock.cmd) {
struct clvm_header reply;
reply.cmd = CLVMD_CMD_REPLY;
@@ -873,9 +940,8 @@ static int read_from_local_sock(struct local_client *thisfd)
DEBUGLOG
("got %d bytes, need another %d (total %d)\n",
argslen, missing_len, inheader->arglen);
len =
read(thisfd->fd, argptr + argslen,
missing_len);
len = read(thisfd->fd, argptr + argslen,
missing_len);
if (len >= 0) {
missing_len -= len;
argslen += len;
@@ -1085,8 +1151,8 @@ static int distribute_command(struct local_client *thisfd)
}
/* Process a command from a remote node and return the result */
void process_remote_command(struct clvm_header *msg, int msglen, int fd,
char *csid)
static void process_remote_command(struct clvm_header *msg, int msglen, int fd,
char *csid)
{
char *replyargs;
char nodename[max_cluster_member_name_len];
@@ -1110,11 +1176,12 @@ void process_remote_command(struct clvm_header *msg, int msglen, int fd,
(struct clvm_header *) malloc(msg->arglen +
sizeof(struct clvm_header));
if (newmsg) {
if (system_lv_read_data
(nodename, (char *) newmsg,
(size_t *) &msglen) == 0) {
ssize_t len;
if (system_lv_read_data(nodename, (char *) newmsg,
&len) == 0) {
msg = newmsg;
msg_malloced = 1;
msglen = len;
} else {
struct clvm_header head;
DEBUGLOG("System LV read failed\n");
@@ -1160,8 +1227,11 @@ void process_remote_command(struct clvm_header *msg, int msglen, int fd,
/* Version check is internal - don't bother exposing it in
clvmd-command.c */
if (msg->cmd == CLVMD_CMD_VERSION) {
int *version_nums = (int *) msg->args;
int version_nums[3];
char node[256];
memcpy(version_nums, msg->args, sizeof(version_nums));
clops->name_from_csid(csid, node);
DEBUGLOG("Remote node %s is version %d.%d.%d\n",
node,
@@ -1333,10 +1403,11 @@ static void add_reply_to_list(struct local_client *client, int status,
}
/* This is the thread that runs the PRE and post commands for a particular connection */
static void *pre_and_post_thread(void *arg)
static __attribute__ ((noreturn)) void *pre_and_post_thread(void *arg)
{
struct local_client *client = (struct local_client *) arg;
int status;
int write_status;
sigset_t ss;
int pipe_fd = client->bits.localsock.pipe;
@@ -1366,8 +1437,21 @@ static void *pre_and_post_thread(void *arg)
client->bits.localsock.all_success = 0;
DEBUGLOG("Writing status %d down pipe %d\n", status, pipe_fd);
/* Tell the parent process we have finished this bit */
write(pipe_fd, &status, sizeof(int));
do {
write_status = write(pipe_fd, &status, sizeof(int));
if (write_status == sizeof(int))
break;
if (write_status < 0 &&
(errno == EINTR || errno == EAGAIN))
continue;
log_error("Error sending to pipe: %m\n");
break;
} while(1);
if (status)
continue; /* Wait for another PRE command */
/* We may need to wait for the condition variable before running the post command */
pthread_mutex_lock(&client->bits.localsock.mutex);
@@ -1386,7 +1470,16 @@ static void *pre_and_post_thread(void *arg)
status = 0;
do_post_command(client);
write(pipe_fd, &status, sizeof(int));
do {
write_status = write(pipe_fd, &status, sizeof(int));
if (write_status == sizeof(int))
break;
if (write_status < 0 &&
(errno == EINTR || errno == EAGAIN))
continue;
log_error("Error sending to pipe: %m\n");
break;
} while(1);
DEBUGLOG("Waiting for next pre command\n");
@@ -1401,7 +1494,6 @@ static void *pre_and_post_thread(void *arg)
}
DEBUGLOG("Subthread finished\n");
pthread_exit((void *) 0);
return 0;
}
/* Process a command on the local node and store the result */
@@ -1510,7 +1602,7 @@ static void send_local_reply(struct local_client *client, int status, int fd)
if (thisreply->status)
clientreply->flags |= CLVMD_FLAG_NODEERRS;
*(int *) ptr = thisreply->status;
memcpy(ptr, &thisreply->status, sizeof(int));
ptr += sizeof(int);
if (thisreply->replymsg) {
@@ -1566,19 +1658,22 @@ static void send_version_message()
{
char message[sizeof(struct clvm_header) + sizeof(int) * 3];
struct clvm_header *msg = (struct clvm_header *) message;
int *version_nums = (int *) msg->args;
int version_nums[3];
msg->cmd = CLVMD_CMD_VERSION;
msg->status = 0;
msg->flags = 0;
msg->clientid = 0;
msg->arglen = sizeof(int) * 3;
msg->arglen = sizeof(version_nums);
version_nums[0] = htonl(CLVMD_MAJOR_VERSION);
version_nums[1] = htonl(CLVMD_MINOR_VERSION);
version_nums[2] = htonl(CLVMD_PATCH_VERSION);
memcpy(&msg->args, version_nums, sizeof(version_nums));
hton_clvm(msg);
clops->cluster_send_message(message, sizeof(message), NULL,
"Error Sending version number");
}
@@ -1588,6 +1683,11 @@ static int send_message(void *buf, int msglen, char *csid, int fd,
const char *errtext)
{
int len;
int saved_errno = 0;
struct timespec delay;
struct timespec remtime;
int retry_cnt = 0;
/* Send remote messages down the cluster socket */
if (csid == NULL || !ISLOCAL_CSID(csid)) {
@@ -1598,14 +1698,38 @@ static int send_message(void *buf, int msglen, char *csid, int fd,
/* Make sure it all goes */
do {
if (retry_cnt > MAX_RETRIES)
{
errno = saved_errno;
log_error(errtext);
errno = saved_errno;
break;
}
len = write(fd, buf + ptr, msglen - ptr);
if (len <= 0) {
if (errno == EINTR)
continue;
if (errno == EAGAIN ||
errno == EIO ||
errno == ENOSPC) {
saved_errno = errno;
retry_cnt++;
delay.tv_sec = 0;
delay.tv_nsec = 100000;
remtime.tv_sec = 0;
remtime.tv_nsec = 0;
(void) nanosleep (&delay, &remtime);
continue;
}
log_error(errtext);
break;
}
ptr += len;
} while (len < msglen);
} while (ptr < msglen);
}
return len;
}
@@ -1635,11 +1759,11 @@ static int process_work_item(struct lvm_thread_cmd *cmd)
/*
* Routine that runs in the "LVM thread".
*/
static void *lvm_thread_fn(void *arg)
static __attribute__ ((noreturn)) void *lvm_thread_fn(void *arg)
{
struct list *cmdl, *tmp;
sigset_t ss;
int using_gulm = (int)arg;
int using_gulm = (int)(long)arg;
/* Don't let anyone else to do work until we are started */
pthread_mutex_lock(&lvm_start_mutex);

View File

@@ -95,11 +95,7 @@ struct local_client {
} bits;
};
#ifdef DEBUG
#define DEBUGLOG(fmt, args...) {time_t P; time(&P); fprintf(stderr, "CLVMD[%x]: %.15s ", (int)pthread_self(), ctime(&P)+4 ); fprintf(stderr, fmt, ## args);}
#else
#define DEBUGLOG(fmt, args...)
#endif
#define DEBUGLOG(fmt, args...) debuglog(fmt, ## args);
#ifndef max
#define max(a,b) ((a)>(b)?(a):(b))
@@ -117,6 +113,7 @@ extern int add_client(struct local_client *new_client);
extern void clvmd_cluster_init_completed(void);
extern void process_message(struct local_client *client, char *buf, int len, char *csid);
extern void debuglog(const char *fmt, ... );
int sync_lock(const char *resource, int mode, int flags, int *lockid);
int sync_unlock(const char *resource, int lockid);

View File

@@ -30,11 +30,11 @@
#include <errno.h>
#include <syslog.h>
#include <assert.h>
#include <libdevmapper.h>
#include <libdlm.h>
#include "libdevmapper.h"
#include "list.h"
#include "lvm-types.h"
#include "libdlm.h"
#include "clvm.h"
#include "clvmd-comms.h"
#include "clvmd.h"
@@ -45,16 +45,24 @@
#include "log.h"
#include "activate.h"
#include "locking.h"
#include "defaults.h"
static struct cmd_context *cmd = NULL;
static struct dm_hash_table *lv_hash = NULL;
static pthread_mutex_t lv_hash_lock;
static pthread_mutex_t lvm_lock;
static char last_error[1024];
struct lv_info {
int lock_id;
int lock_mode;
};
char *get_last_lvm_error()
{
return last_error;
}
/* Return the mode a lock is currently held at (or -1 if not held) */
static int get_current_lock(char *resource)
{
@@ -200,8 +208,17 @@ static int do_activate_lv(char *resource, unsigned char lock_flags, int mode)
/* Try to get the lock if it's a clustered volume group */
if (lock_flags & LCK_CLUSTER_VG) {
status = hold_lock(resource, mode, LKF_NOQUEUE);
if (status)
if (status) {
/* Return an LVM-sensible error for this.
* Forcing EIO makes the upper level return this text
* rather than the strerror text for EAGAIN.
*/
if (errno == EAGAIN) {
sprintf(last_error, "Volume is busy on another node");
errno = EIO;
}
return errno;
}
}
/* If it's suspended then resume it */
@@ -227,7 +244,7 @@ static int do_resume_lv(char *resource)
/* Is it open ? */
oldmode = get_current_lock(resource);
if (oldmode == -1) {
DEBUGLOG("do_deactivate_lock, lock not already held\n");
DEBUGLOG("do_resume_lv, lock not already held\n");
return 0; /* We don't need to do anything */
}
@@ -295,14 +312,25 @@ int do_lock_lv(unsigned char command, unsigned char lock_flags, char *resource)
DEBUGLOG("do_lock_lv: resource '%s', cmd = 0x%x, flags = %x\n",
resource, command, lock_flags);
pthread_mutex_lock(&lvm_lock);
if (!cmd->config_valid || config_files_changed(cmd)) {
/* Reinitialise various settings inc. logging, filters */
if (!refresh_toolcontext(cmd)) {
log_error("Updated config file invalid. Aborting.");
pthread_mutex_unlock(&lvm_lock);
return EINVAL;
}
}
if (lock_flags & LCK_PARTIAL_MODE)
init_partial(1);
if (lock_flags & LCK_MIRROR_NOSYNC_MODE)
init_mirror_in_sync(1);
if (!(lock_flags & LCK_DMEVENTD_MONITOR_MODE))
init_dmeventd_monitor(0);
switch (command) {
case LCK_LV_EXCLUSIVE:
status = do_activate_lv(resource, lock_flags, LKM_EXMODE);
@@ -331,8 +359,18 @@ int do_lock_lv(unsigned char command, unsigned char lock_flags, char *resource)
break;
}
if (lock_flags & LCK_PARTIAL_MODE)
init_partial(0);
if (lock_flags & LCK_MIRROR_NOSYNC_MODE)
init_mirror_in_sync(0);
if (!(lock_flags & LCK_DMEVENTD_MONITOR_MODE))
init_dmeventd_monitor(DEFAULT_DMEVENTD_MONITOR);
/* clean the pool for another command */
dm_pool_empty(cmd->mem);
pthread_mutex_unlock(&lvm_lock);
DEBUGLOG("Command return is %d\n", status);
return status;
@@ -359,6 +397,8 @@ int pre_lock_lv(unsigned char command, unsigned char lock_flags, char *resource)
int post_lock_lv(unsigned char command, unsigned char lock_flags,
char *resource)
{
int status;
/* Opposite of above, done on resume after a metadata update */
if (command == LCK_LV_RESUME) {
int oldmode;
@@ -372,7 +412,10 @@ int post_lock_lv(unsigned char command, unsigned char lock_flags,
if (oldmode == LKM_PWMODE) {
struct lvinfo lvi;
if (!lv_info_by_lvid(cmd, resource, &lvi, 0))
pthread_mutex_lock(&lvm_lock);
status = lv_info_by_lvid(cmd, resource, &lvi, 0);
pthread_mutex_unlock(&lvm_lock);
if (!status)
return EIO;
if (lvi.exists) {
@@ -397,6 +440,13 @@ int do_check_lvm1(char *vgname)
return status == 1 ? 0 : EBUSY;
}
int do_refresh_cache()
{
DEBUGLOG("Refreshing context\n");
log_notice("Refreshing context");
return refresh_toolcontext(cmd)==1?0:-1;
}
/* Only called at gulm startup. Drop any leftover VG or P_orphan locks
that might be hanging around if we died for any reason
@@ -432,7 +482,8 @@ static void drop_vg_locks()
sync_unlock(vg, LCK_EXCL);
}
fclose(vgs);
if (fclose(vgs))
DEBUGLOG("vgs fclose failed: %s\n", strerror(errno));
}
/*
@@ -482,16 +533,31 @@ static void *get_initial_state()
}
}
}
fclose(lvs);
if (fclose(lvs))
DEBUGLOG("lvs fclose failed: %s\n", strerror(errno));
return NULL;
}
static void lvm2_log_fn(int level, const char *file, int line,
const char *message)
{
/*
* Ignore non-error messages, but store the latest one for returning
* to the user.
*/
if (level != _LOG_ERR && level != _LOG_FATAL)
return;
strncpy(last_error, message, sizeof(last_error));
last_error[sizeof(last_error)-1] = '\0';
}
/* This checks some basic cluster-LVM configuration stuff */
static void check_config()
{
int locking_type;
locking_type = find_config_int(cmd->cft->root, "global/locking_type", 1);
locking_type = find_config_tree_int(cmd, "global/locking_type", 1);
if (locking_type == 3) /* compiled-in cluster support */
return;
@@ -499,7 +565,7 @@ static void check_config()
if (locking_type == 2) { /* External library, check name */
const char *libname;
libname = find_config_str(cmd->cft->root, "global/locking_library",
libname = find_config_tree_str(cmd, "global/locking_library",
"");
if (strstr(libname, "liblvm2clusterlock.so"))
return;
@@ -515,12 +581,13 @@ void init_lvhash()
/* Create hash table for keeping LV locks & status */
lv_hash = dm_hash_create(100);
pthread_mutex_init(&lv_hash_lock, NULL);
pthread_mutex_init(&lvm_lock, NULL);
}
/* Called to initialise the LVM context of the daemon */
int init_lvm(int using_gulm)
{
if (!(cmd = create_toolcontext(NULL))) {
if (!(cmd = create_toolcontext(NULL, 0, 1))) {
log_error("Failed to allocate command context");
return 0;
}
@@ -538,5 +605,8 @@ int init_lvm(int using_gulm)
get_initial_state();
/* Trap log messages so we can pass them back to the user */
init_log_fn(lvm2_log_fn);
return 1;
}

View File

@@ -25,11 +25,13 @@ extern int do_lock_lv(unsigned char lock_cmd, unsigned char lock_flags,
extern int post_lock_lv(unsigned char lock_cmd, unsigned char lock_flags,
char *resource);
extern int do_check_lvm1(char *vgname);
extern int do_refresh_cache(void);
extern int init_lvm(int using_gulm);
extern void init_lvhash(void);
extern int hold_unlock(char *resource);
extern int hold_lock(char *resource, int mode, int flags);
extern void unlock_all(void);
extern char *get_last_lvm_error(void);
#endif

View File

@@ -0,0 +1,320 @@
/*
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004-2006 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 General Public License v.2.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* Tell all clvmds in a cluster to refresh their toolcontext
*
*/
#include <stddef.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <errno.h>
#include <unistd.h>
#include <libdevmapper.h>
#include <stdint.h>
#include <stdio.h>
#include "clvm.h"
#include "refresh_clvmd.h"
typedef struct lvm_response {
char node[255];
char *response;
int status;
int len;
} lvm_response_t;
/*
* This gets stuck at the start of memory we allocate so we
* can sanity-check it at deallocation time
*/
#define LVM_SIGNATURE 0x434C564D
static int _clvmd_sock = -1;
/* Open connection to the Cluster Manager daemon */
static int _open_local_sock(void)
{
int local_socket;
struct sockaddr_un sockaddr;
/* Open local socket */
if ((local_socket = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
fprintf(stderr, "Local socket creation failed: %s", strerror(errno));
return -1;
}
memset(&sockaddr, 0, sizeof(sockaddr));
memcpy(sockaddr.sun_path, CLVMD_SOCKNAME, sizeof(CLVMD_SOCKNAME));
sockaddr.sun_family = AF_UNIX;
if (connect(local_socket,(struct sockaddr *) &sockaddr,
sizeof(sockaddr))) {
int saved_errno = errno;
fprintf(stderr, "connect() failed on local socket: %s\n",
strerror(errno));
if (close(local_socket))
return -1;
errno = saved_errno;
return -1;
}
return local_socket;
}
/* Send a request and return the status */
static int _send_request(char *inbuf, int inlen, char **retbuf)
{
char outbuf[PIPE_BUF];
struct clvm_header *outheader = (struct clvm_header *) outbuf;
int len;
int off;
int buflen;
int err;
/* Send it to CLVMD */
rewrite:
if ( (err = write(_clvmd_sock, inbuf, inlen)) != inlen) {
if (err == -1 && errno == EINTR)
goto rewrite;
fprintf(stderr, "Error writing data to clvmd: %s", strerror(errno));
return 0;
}
/* Get the response */
reread:
if ((len = read(_clvmd_sock, outbuf, sizeof(struct clvm_header))) < 0) {
if (errno == EINTR)
goto reread;
fprintf(stderr, "Error reading data from clvmd: %s", strerror(errno));
return 0;
}
if (len == 0) {
fprintf(stderr, "EOF reading CLVMD");
errno = ENOTCONN;
return 0;
}
/* Allocate buffer */
buflen = len + outheader->arglen;
*retbuf = dm_malloc(buflen);
if (!*retbuf) {
errno = ENOMEM;
return 0;
}
/* Copy the header */
memcpy(*retbuf, outbuf, len);
outheader = (struct clvm_header *) *retbuf;
/* Read the returned values */
off = 1; /* we've already read the first byte */
while (off <= outheader->arglen && len > 0) {
len = read(_clvmd_sock, outheader->args + off,
buflen - off - offsetof(struct clvm_header, args));
if (len > 0)
off += len;
}
/* Was it an error ? */
if (outheader->status != 0) {
errno = outheader->status;
/* Only return an error here if there are no node-specific
errors present in the message that might have more detail */
if (!(outheader->flags & CLVMD_FLAG_NODEERRS)) {
fprintf(stderr, "cluster request failed: %s\n", strerror(errno));
return 0;
}
}
return 1;
}
/* Build the structure header and parse-out wildcard node names */
static void _build_header(struct clvm_header *head, int cmd, const char *node,
int len)
{
head->cmd = cmd;
head->status = 0;
head->flags = 0;
head->clientid = 0;
head->arglen = len;
if (node) {
/*
* Allow a couple of special node names:
* "*" for all nodes,
* "." for the local node only
*/
if (strcmp(node, "*") == 0) {
head->node[0] = '\0';
} else if (strcmp(node, ".") == 0) {
head->node[0] = '\0';
head->flags = CLVMD_FLAG_LOCAL;
} else
strcpy(head->node, node);
} else
head->node[0] = '\0';
}
/*
* Send a message to a(or all) node(s) in the cluster and wait for replies
*/
static int _cluster_request(char cmd, const char *node, void *data, int len,
lvm_response_t ** response, int *num)
{
char outbuf[sizeof(struct clvm_header) + len + strlen(node) + 1];
char *inptr;
char *retbuf = NULL;
int status;
int i;
int num_responses = 0;
struct clvm_header *head = (struct clvm_header *) outbuf;
lvm_response_t *rarray;
*num = 0;
if (_clvmd_sock == -1)
_clvmd_sock = _open_local_sock();
if (_clvmd_sock == -1)
return 0;
_build_header(head, cmd, node, len);
memcpy(head->node + strlen(head->node) + 1, data, len);
status = _send_request(outbuf, sizeof(struct clvm_header) +
strlen(head->node) + len, &retbuf);
if (!status)
goto out;
/* Count the number of responses we got */
head = (struct clvm_header *) retbuf;
inptr = head->args;
while (inptr[0]) {
num_responses++;
inptr += strlen(inptr) + 1;
inptr += sizeof(int);
inptr += strlen(inptr) + 1;
}
/*
* Allocate response array.
* With an extra pair of INTs on the front to sanity
* check the pointer when we are given it back to free
*/
*response = dm_malloc(sizeof(lvm_response_t) * num_responses +
sizeof(int) * 2);
if (!*response) {
errno = ENOMEM;
status = 0;
goto out;
}
rarray = *response;
/* Unpack the response into an lvm_response_t array */
inptr = head->args;
i = 0;
while (inptr[0]) {
strcpy(rarray[i].node, inptr);
inptr += strlen(inptr) + 1;
memcpy(&rarray[i].status, inptr, sizeof(int));
inptr += sizeof(int);
rarray[i].response = dm_malloc(strlen(inptr) + 1);
if (rarray[i].response == NULL) {
/* Free up everything else and return error */
int j;
for (j = 0; j < i; j++)
dm_free(rarray[i].response);
free(*response);
errno = ENOMEM;
status = -1;
goto out;
}
strcpy(rarray[i].response, inptr);
rarray[i].len = strlen(inptr);
inptr += strlen(inptr) + 1;
i++;
}
*num = num_responses;
*response = rarray;
out:
if (retbuf)
dm_free(retbuf);
return status;
}
/* Free reply array */
static int _cluster_free_request(lvm_response_t * response, int num)
{
int i;
for (i = 0; i < num; i++) {
dm_free(response[i].response);
}
dm_free(response);
return 1;
}
int refresh_clvmd()
{
int num_responses;
char args[1]; // No args really.
lvm_response_t *response;
int saved_errno;
int status;
int i;
status = _cluster_request(CLVMD_CMD_REFRESH, "*", args, 0, &response, &num_responses);
/* If any nodes were down then display them and return an error */
for (i = 0; i < num_responses; i++) {
if (response[i].status == EHOSTDOWN) {
fprintf(stderr, "clvmd not running on node %s",
response[i].node);
status = 0;
errno = response[i].status;
} else if (response[i].status) {
fprintf(stderr, "Error resetting node %s: %s",
response[i].node,
response[i].response[0] ?
response[i].response :
strerror(response[i].status));
status = 0;
errno = response[i].status;
}
}
saved_errno = errno;
_cluster_free_request(response, num_responses);
errno = saved_errno;
return status;
}

View File

@@ -0,0 +1,2 @@
int refresh_clvmd(void);

View File

@@ -36,8 +36,11 @@
#include <dirent.h>
#include <errno.h>
#include <mntent.h>
#include <libdlm.h>
#ifdef HAVE_CCS
#include <ccs.h>
#endif
#include "libdlm.h"
#include "log.h"
#include "list.h"
#include "locking.h"
@@ -45,9 +48,6 @@
#include "clvm.h"
#include "clvmd-comms.h"
#include "clvmd.h"
#ifdef HAVE_CCS
#include "ccs.h"
#endif
#define SYSTEM_LV_FILESYSTEM "ext2"
#define SYSTEM_LV_MOUNTPOINT "/tmp/.clvmd-XXXXXX"

View File

@@ -34,8 +34,8 @@
#include <syslog.h>
#include <netdb.h>
#include <assert.h>
#include <libdevmapper.h>
#include "libdevmapper.h"
#include "clvm.h"
#include "clvmd-comms.h"
#include "clvmd.h"
@@ -57,7 +57,7 @@ int init_comms(unsigned short port)
struct sockaddr_in6 addr;
sock_hash = dm_hash_create(100);
tcp_port = port ? port : DEFAULT_TCP_PORT;
tcp_port = port ? : DEFAULT_TCP_PORT;
listen_fd = socket(AF_INET6, SOCK_STREAM, 0);

View File

@@ -1,3 +1,19 @@
process_event
register_device
unregister_device
dm_event_handler_create
dm_event_handler_destroy
dm_event_handler_set_dso
dm_event_handler_set_dev_name
dm_event_handler_set_uuid
dm_event_handler_set_major
dm_event_handler_set_minor
dm_event_handler_set_event_mask
dm_event_handler_get_dso
dm_event_handler_get_devname
dm_event_handler_get_uuid
dm_event_handler_get_major
dm_event_handler_get_minor
dm_event_handler_get_event_mask
dm_event_register_handler
dm_event_unregister_handler
dm_event_get_registered_device
dm_event_handler_set_timeout
dm_event_handler_get_timeout

View File

@@ -1,14 +1,13 @@
#
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
# Copyright (C) 2004 Red Hat, Inc. All rights reserved.
# Copyright (C) 2005 Red Hat, Inc. All rights reserved.
#
# This file is part of the device-mapper userspace tools.
#
# This copyrighted material is made available to anyone wishing to use,
# modify, copy, or redistribute it subject to the terms and conditions
# of the GNU General Public License v.2.
# of the GNU Lesser General Public License v.2.1.
#
# You should have received a copy of the GNU General Public License
# 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
@@ -16,36 +15,69 @@ srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
TARGETS = dmevent dmeventd
INSTALL_TYPE = install_dynamic
SOURCES = libdevmapper-event.c
SOURCES = noop.c
CLEAN_TARGETS = dmevent.o dmeventd.o
LIB_STATIC = libdevmapper-event.a
ifeq ("@LIB_SUFFIX@","dylib")
LIB_SHARED = libdmeventdnoop.dylib
LIB_SHARED = libdevmapper-event.dylib
else
LIB_SHARED = libdmeventdnoop.so
LIB_SHARED = libdevmapper-event.so
endif
LDFLAGS += -ldl -ldevmapper -lmultilog
TARGETS = dmeventd
CLEAN_TARGETS = dmeventd.o
include ../make.tmpl
libdmeventdnoop.so: noop.o
LDFLAGS += -ldl -ldevmapper -lpthread
CLDFLAGS += -ldl -ldevmapper -lpthread
dmevent: dmevent.o $(interfacedir)/libdevmapper.$(LIB_SUFFIX) $(top_srcdir)/lib/event/libdmevent.$(LIB_SUFFIX)
$(CC) -o $@ dmevent.o $(LDFLAGS) \
-L$(interfacedir) -L$(DESTDIR)/lib -L$(top_srcdir)/lib/event -L$(top_srcdir)/multilog $(LIBS)
dmeventd: $(LIB_SHARED) dmeventd.o
$(CC) -o $@ dmeventd.o $(CFLAGS) $(LDFLAGS) \
-L. -ldevmapper-event $(LIBS) -rdynamic
dmeventd: dmeventd.o $(interfacedir)/libdevmapper.$(LIB_SUFFIX) $(top_srcdir)/lib/event/libdmevent.$(LIB_SUFFIX)
$(CC) -o $@ dmeventd.o $(LDFLAGS) \
-L$(interfacedir) -L$(DESTDIR)/lib -L$(top_srcdir)/lib/event -L$(top_srcdir)/multilog -lpthread -ldmevent $(LIBS)
.PHONY: install_dynamic install_static install_include \
install_pkgconfig install_dmeventd
install: $(INSTALL_TYPE)
INSTALL_TYPE = install_dynamic
.PHONY: install_dynamic
ifeq ("@STATIC_LINK@", "yes")
INSTALL_TYPE += install_static
endif
install_dynamic: dmeventd
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) dmeventd $(sbindir)/dmeventd
ifeq ("@PKGCONFIG@", "yes")
INSTALL_TYPE += install_pkgconfig
endif
install: $(INSTALL_TYPE) install_include install_dmeventd
install_include:
$(INSTALL) -D $(OWNER) $(GROUP) -m 444 libdevmapper-event.h \
$(includedir)/libdevmapper-event.h
install_dynamic: libdevmapper-event.$(LIB_SUFFIX)
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
$(libdir)/libdevmapper-event.$(LIB_SUFFIX).$(LIB_VERSION)
$(LN_S) -f libdevmapper-event.$(LIB_SUFFIX).$(LIB_VERSION) \
$(libdir)/libdevmapper-event.$(LIB_SUFFIX)
install_dmeventd: dmeventd
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< $(sbindir)/$<
install_pkgconfig:
$(INSTALL) -D $(OWNER) $(GROUP) -m 444 libdevmapper-event.pc \
$(usrlibdir)/pkgconfig/devmapper-event.pc
install_static: libdevmapper-event.a
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
$(libdir)/libdevmapper-event.a.$(LIB_VERSION)
$(LN_S) -f libdevmapper-event.a.$(LIB_VERSION) $(libdir)/libdevmapper-event.a
.PHONY: distclean_lib distclean
distclean_lib:
$(RM) libdevmapper-event.pc
distclean: distclean_lib

View File

@@ -1,240 +0,0 @@
/*
* Copyright (C) 2005 Red Hat, Inc. All rights reserved.
*
* This file is part of the device-mapper userspace tools.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "libdevmapper.h"
#include "libdm-event.h"
#include "libmultilog.h"
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dlfcn.h>
static enum event_type events = ALL_ERRORS; /* All until we can distinguish. */
static char default_dso_name[] = "noop"; /* default DSO is noop */
static int default_reg = 1; /* default action is register */
static uint32_t timeout;
struct event_ops {
int (*dm_register_for_event)(char *dso_name, char *device,
enum event_type event_types);
int (*dm_unregister_for_event)(char *dso_name, char *device,
enum event_type event_types);
int (*dm_get_registered_device)(char **dso_name, char **device,
enum event_type *event_types, int next);
int (*dm_set_event_timeout)(char *device, uint32_t time);
int (*dm_get_event_timeout)(char *device, uint32_t *time);
};
/* Display help. */
static void print_usage(char *name)
{
char *cmd = strrchr(name, '/');
cmd = cmd ? cmd + 1 : name;
printf("Usage::\n"
"%s [options] <device>\n"
"\n"
"Options:\n"
" -d <dso> Specify the DSO to use.\n"
" -h Print this usage.\n"
" -l List registered devices.\n"
" -r Register for event (default).\n"
" -t <timeout> (un)register for timeout event.\n"
" -u Unregister for event.\n"
"\n", cmd);
}
/* Parse command line arguments. */
static int parse_argv(int argc, char **argv, char **dso_name_arg,
char **device_arg, int *reg, int *list)
{
int c;
const char *options = "d:hlrt:u";
while ((c = getopt(argc, argv, options)) != -1) {
switch (c) {
case 'd':
*dso_name_arg = optarg;
break;
case 'h':
print_usage(argv[0]);
exit(EXIT_SUCCESS);
case 'l':
*list = 1;
break;
case 'r':
*reg = 1;
break;
case 't':
events = TIMEOUT;
if (sscanf(optarg, "%"SCNu32, &timeout) != 1){
fprintf(stderr, "invalid timeout '%s'\n",
optarg);
timeout = 0;
}
break;
case 'u':
*reg = 0;
break;
default:
fprintf(stderr, "Unknown option '%c'.\n"
"Try '-h' for help.\n", c);
return 0;
}
}
if (optind >= argc) {
if (!*list) {
fprintf(stderr, "You need to specify a device.\n");
return 0;
}
} else
*device_arg = argv[optind];
return 1;
}
static int lookup_symbol(void *dl, void **symbol, const char *name)
{
if ((*symbol = dlsym(dl, name)))
return 1;
fprintf(stderr, "error looking up %s symbol: %s\n", name, dlerror());
return 0;
}
static int lookup_symbols(void *dl, struct event_ops *e)
{
return lookup_symbol(dl, (void *) &e->dm_register_for_event,
"dm_register_for_event") &&
lookup_symbol(dl, (void *) &e->dm_unregister_for_event,
"dm_unregister_for_event") &&
lookup_symbol(dl, (void *) &e->dm_get_registered_device,
"dm_get_registered_device") &&
lookup_symbol(dl, (void *) &e->dm_set_event_timeout,
"dm_set_event_timeout") &&
lookup_symbol(dl, (void *) &e->dm_get_event_timeout,
"dm_get_event_timeout");
}
int main(int argc, char **argv)
{
void *dl;
struct event_ops e;
int list = 0, next = 0, ret, reg = default_reg;
char *device, *device_arg = NULL, *dso_name, *dso_name_arg = NULL;
if (!parse_argv(argc, argv, &dso_name_arg, &device_arg, &reg, &list))
exit(EXIT_FAILURE);
if (device_arg) {
if (!(device = strdup(device_arg)))
exit(EXIT_FAILURE);
} else
device = NULL;
if (dso_name_arg) {
if (!(dso_name = strdup(dso_name_arg)))
exit(EXIT_FAILURE);
} else {
if (!(dso_name = strdup(default_dso_name)))
exit(EXIT_FAILURE);
}
/* FIXME: use -v/-q options to set this */
multilog_add_type(standard, NULL);
multilog_init_verbose(standard, _LOG_DEBUG);
if (!(dl = dlopen("libdmevent.so", RTLD_NOW))){
fprintf(stderr, "Cannot dlopen libdmevent.so: %s\n", dlerror());
goto out;
}
if (!(lookup_symbols(dl, &e)))
goto out;
if (list) {
while (1) {
if ((ret= e.dm_get_registered_device(&dso_name,
&device,
&events, next)))
break;
printf("%s %s 0x%x", dso_name, device, events);
if (events & TIMEOUT){
if ((ret = e.dm_get_event_timeout(device,
&timeout))) {
ret = EXIT_FAILURE;
goto out;
}
printf(" %"PRIu32"\n", timeout);
} else
printf("\n");
if (device_arg)
break;
next = 1;
}
ret = (ret && device_arg) ? EXIT_FAILURE : EXIT_SUCCESS;
goto out;
}
if ((ret = reg ? e.dm_register_for_event(dso_name, device, events) :
e.dm_unregister_for_event(dso_name, device, events))) {
fprintf(stderr, "Failed to %sregister %s: %s\n",
reg ? "": "un", device, strerror(-ret));
ret = EXIT_FAILURE;
} else {
if (reg && (events & TIMEOUT) &&
((ret = e.dm_set_event_timeout(device, timeout)))){
fprintf(stderr, "Failed to set timeout for %s: %s\n",
device, strerror(-ret));
ret = EXIT_FAILURE;
} else {
printf("%s %sregistered successfully.\n",
device, reg ? "" : "un");
ret = EXIT_SUCCESS;
}
}
out:
multilog_del_type(standard);
if (device)
free(device);
if (dso_name)
free(dso_name);
exit(ret);
}
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
* adjust the settings for this buffer only. This must remain at the end
* of the file.
* ---------------------------------------------------------------------------
* Local variables:
* c-file-style: "linux"
* End:
*/

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,52 @@
#ifndef __DMEVENTD_DOT_H__
#define __DMEVENTD_DOT_H__
/* FIXME This stuff must be configurable. */
#define DM_EVENT_DAEMON "/sbin/dmeventd"
#define DM_EVENT_LOCKFILE "/var/lock/dmeventd"
#define DM_EVENT_FIFO_CLIENT "/var/run/dmeventd-client"
#define DM_EVENT_FIFO_SERVER "/var/run/dmeventd-server"
#define DM_EVENT_PIDFILE "/var/run/dmeventd.pid"
#define DM_EVENT_DEFAULT_TIMEOUT 10
/* Commands for the daemon passed in the message below. */
enum dm_event_command {
DM_EVENT_CMD_ACTIVE = 1,
DM_EVENT_CMD_REGISTER_FOR_EVENT,
DM_EVENT_CMD_UNREGISTER_FOR_EVENT,
DM_EVENT_CMD_GET_REGISTERED_DEVICE,
DM_EVENT_CMD_GET_NEXT_REGISTERED_DEVICE,
DM_EVENT_CMD_SET_TIMEOUT,
DM_EVENT_CMD_GET_TIMEOUT,
DM_EVENT_CMD_HELLO,
};
/* Message passed between client and daemon. */
struct dm_event_daemon_message {
uint32_t cmd;
uint32_t size;
char *data;
};
/* FIXME Is this meant to be exported? I can't see where the
interface uses it. */
/* Fifos for client/daemon communication. */
struct dm_event_fifos {
int client;
int server;
const char *client_path;
const char *server_path;
};
/* EXIT_SUCCESS 0 -- stdlib.h */
/* EXIT_FAILURE 1 -- stdlib.h */
#define EXIT_LOCKFILE_INUSE 2
#define EXIT_DESC_CLOSE_FAILURE 3
#define EXIT_DESC_OPEN_FAILURE 4
#define EXIT_OPEN_PID_FAILURE 5
#define EXIT_FIFO_FAILURE 6
#define EXIT_CHDIR_FAILURE 7
#endif /* __DMEVENTD_DOT_H__ */

View File

@@ -0,0 +1,808 @@
/*
* Copyright (C) 2005 Red Hat, Inc. All rights reserved.
*
* This file is part of the device-mapper userspace tools.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "lib.h"
#include "libdevmapper-event.h"
//#include "libmultilog.h"
#include "dmeventd.h"
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/wait.h>
#include <arpa/inet.h> /* for htonl, ntohl */
static int _sequence_nr = 0;
struct dm_event_handler {
char *dso;
char *dev_name;
char *uuid;
int major;
int minor;
uint32_t timeout;
enum dm_event_mask mask;
};
static void _dm_event_handler_clear_dev_info(struct dm_event_handler *dmevh)
{
if (dmevh->dev_name)
dm_free(dmevh->dev_name);
if (dmevh->uuid)
dm_free(dmevh->uuid);
dmevh->dev_name = dmevh->uuid = NULL;
dmevh->major = dmevh->minor = 0;
}
struct dm_event_handler *dm_event_handler_create(void)
{
struct dm_event_handler *dmevh = NULL;
if (!(dmevh = dm_malloc(sizeof(*dmevh))))
return NULL;
dmevh->dso = dmevh->dev_name = dmevh->uuid = NULL;
dmevh->major = dmevh->minor = 0;
dmevh->mask = 0;
dmevh->timeout = 0;
return dmevh;
}
void dm_event_handler_destroy(struct dm_event_handler *dmevh)
{
_dm_event_handler_clear_dev_info(dmevh);
if (dmevh->dso)
dm_free(dmevh->dso);
dm_free(dmevh);
}
int dm_event_handler_set_dso(struct dm_event_handler *dmevh, const char *path)
{
if (!path) /* noop */
return 0;
if (dmevh->dso)
dm_free(dmevh->dso);
dmevh->dso = dm_strdup(path);
if (!dmevh->dso)
return -ENOMEM;
return 0;
}
int dm_event_handler_set_dev_name(struct dm_event_handler *dmevh, const char *dev_name)
{
if (!dev_name)
return 0;
_dm_event_handler_clear_dev_info(dmevh);
dmevh->dev_name = dm_strdup(dev_name);
if (!dmevh->dev_name)
return -ENOMEM;
return 0;
}
int dm_event_handler_set_uuid(struct dm_event_handler *dmevh, const char *uuid)
{
if (!uuid)
return 0;
_dm_event_handler_clear_dev_info(dmevh);
dmevh->uuid = dm_strdup(uuid);
if (!dmevh->dev_name)
return -ENOMEM;
return 0;
}
void dm_event_handler_set_major(struct dm_event_handler *dmevh, int major)
{
int minor = dmevh->minor;
_dm_event_handler_clear_dev_info(dmevh);
dmevh->major = major;
dmevh->minor = minor;
}
void dm_event_handler_set_minor(struct dm_event_handler *dmevh, int minor)
{
int major = dmevh->major;
_dm_event_handler_clear_dev_info(dmevh);
dmevh->major = major;
dmevh->minor = minor;
}
void dm_event_handler_set_event_mask(struct dm_event_handler *dmevh,
enum dm_event_mask evmask)
{
dmevh->mask = evmask;
}
void dm_event_handler_set_timeout(struct dm_event_handler *dmevh, int timeout)
{
dmevh->timeout = timeout;
}
const char *dm_event_handler_get_dso(const struct dm_event_handler *dmevh)
{
return dmevh->dso;
}
const char *dm_event_handler_get_dev_name(const struct dm_event_handler *dmevh)
{
return dmevh->dev_name;
}
const char *dm_event_handler_get_uuid(const struct dm_event_handler *dmevh)
{
return dmevh->uuid;
}
int dm_event_handler_get_major(const struct dm_event_handler *dmevh)
{
return dmevh->major;
}
int dm_event_handler_get_minor(const struct dm_event_handler *dmevh)
{
return dmevh->minor;
}
int dm_event_handler_get_timeout(const struct dm_event_handler *dmevh)
{
return dmevh->timeout;
}
enum dm_event_mask dm_event_handler_get_event_mask(const struct dm_event_handler *dmevh)
{
return dmevh->mask;
}
static int _check_message_id(struct dm_event_daemon_message *msg)
{
int pid, seq_nr;
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(),
_sequence_nr, msg->data);
return 0;
}
return 1;
}
/*
* daemon_read
* @fifos
* @msg
*
* Read message from daemon.
*
* Returns: 0 on failure, 1 on success
*/
static int _daemon_read(struct dm_event_fifos *fifos,
struct dm_event_daemon_message *msg)
{
unsigned bytes = 0;
int ret, i;
fd_set fds;
struct timeval tval = { 0, 0 };
size_t size = 2 * sizeof(uint32_t); /* status + size */
char *buf = alloca(size);
int header = 1;
while (bytes < size) {
for (i = 0, ret = 0; (i < 20) && (ret < 1); i++) {
/* Watch daemon read FIFO for input. */
FD_ZERO(&fds);
FD_SET(fifos->server, &fds);
tval.tv_sec = 1;
ret = select(fifos->server + 1, &fds, NULL, NULL,
&tval);
if (ret < 0 && errno != EINTR) {
log_error("Unable to read from event server");
return 0;
}
}
if (ret < 1) {
log_error("Unable to read from event server.");
return 0;
}
ret = read(fifos->server, buf + bytes, size);
if (ret < 0) {
if ((errno == EINTR) || (errno == EAGAIN))
continue;
else {
log_error("Unable to read from event server.");
return 0;
}
}
bytes += ret;
if (bytes == 2 * sizeof(uint32_t) && header) {
msg->cmd = ntohl(*((uint32_t *)buf));
msg->size = ntohl(*((uint32_t *)buf + 1));
buf = msg->data = dm_malloc(msg->size);
size = msg->size;
bytes = 0;
header = 0;
}
}
if (bytes != size) {
if (msg->data)
dm_free(msg->data);
msg->data = NULL;
}
return bytes == size;
}
/* Write message to daemon. */
static int _daemon_write(struct dm_event_fifos *fifos,
struct dm_event_daemon_message *msg)
{
unsigned bytes = 0;
int ret = 0;
fd_set fds;
size_t size = 2 * sizeof(uint32_t) + msg->size;
char *buf = alloca(size);
char drainbuf[128];
struct timeval tval = { 0, 0 };
*((uint32_t *)buf) = htonl(msg->cmd);
*((uint32_t *)buf + 1) = htonl(msg->size);
memcpy(buf + 2 * sizeof(uint32_t), msg->data, msg->size);
/* drain the answer fifo */
while (1) {
FD_ZERO(&fds);
FD_SET(fifos->server, &fds);
tval.tv_usec = 100;
ret = select(fifos->server + 1, &fds, NULL, NULL, &tval);
if ((ret < 0) && (errno != EINTR)) {
log_error("Unable to talk to event daemon");
return 0;
}
if (ret == 0)
break;
read(fifos->server, drainbuf, 127);
}
while (bytes < size) {
do {
/* Watch daemon write FIFO to be ready for output. */
FD_ZERO(&fds);
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");
return 0;
}
} while (ret < 1);
ret = write(fifos->client, ((char *) buf) + bytes,
size - bytes);
if (ret < 0) {
if ((errno == EINTR) || (errno == EAGAIN))
continue;
else {
log_error("Unable to talk to event daemon");
return 0;
}
}
bytes += ret;
}
return bytes == size;
}
static int _daemon_talk(struct dm_event_fifos *fifos,
struct dm_event_daemon_message *msg, int cmd,
const char *dso_name, const char *dev_name,
enum dm_event_mask evmask, uint32_t timeout)
{
const char *dso = dso_name ? dso_name : "";
const char *dev = dev_name ? dev_name : "";
const char *fmt = "%d:%d %s %s %u %" PRIu32;
int msg_size;
memset(msg, 0, sizeof(*msg));
/*
* Set command and pack the arguments
* into ASCII message string.
*/
msg->cmd = cmd;
if (cmd == DM_EVENT_CMD_HELLO)
fmt = "%d:%d HELLO";
if ((msg_size = dm_asprintf(&(msg->data), fmt, getpid(), _sequence_nr,
dso, dev, evmask, timeout)) < 0) {
log_error("_daemon_talk: message allocation failed");
return -ENOMEM;
}
msg->size = msg_size;
/*
* Write command and message to and
* read status return code from daemon.
*/
if (!_daemon_write(fifos, msg)) {
stack;
dm_free(msg->data);
msg->data = 0;
return -EIO;
}
do {
if (msg->data)
dm_free(msg->data);
msg->data = 0;
if (!_daemon_read(fifos, msg)) {
stack;
return -EIO;
}
} while (!_check_message_id(msg));
_sequence_nr++;
return (int32_t) msg->cmd;
}
/*
* start_daemon
*
* This function forks off a process (dmeventd) that will handle
* the events. I am currently test opening one of the fifos to
* ensure that the daemon is running and listening... I thought
* this would be less expensive than fork/exec'ing every time.
* Perhaps there is an even quicker/better way (no, checking the
* lock file is _not_ a better way).
*
* Returns: 1 on success, 0 otherwise
*/
static int _start_daemon(struct dm_event_fifos *fifos)
{
int pid, ret = 0;
int status;
struct stat statbuf;
if (stat(fifos->client_path, &statbuf))
goto start_server;
if (!S_ISFIFO(statbuf.st_mode)) {
log_error("%s is not a fifo.", fifos->client_path);
return 0;
}
/* Anyone listening? If not, errno will be ENXIO */
fifos->client = open(fifos->client_path, O_WRONLY | O_NONBLOCK);
if (fifos->client >= 0) {
/* server is running and listening */
close(fifos->client);
return 1;
} else if (errno != ENXIO) {
/* problem */
log_error("%s: Can't open client fifo %s: %s",
__func__, fifos->client_path, strerror(errno));
stack;
return 0;
}
start_server:
/* server is not running */
pid = fork();
if (pid < 0)
log_error("Unable to fork.");
else if (!pid) {
execvp(DMEVENTD_PATH, NULL);
exit(EXIT_FAILURE);
} else {
if (waitpid(pid, &status, 0) < 0)
log_error("Unable to start dmeventd: %s",
strerror(errno));
else if (WEXITSTATUS(status))
log_error("Unable to start dmeventd.");
else
ret = 1;
}
return ret;
}
/* Initialize client. */
static int _init_client(struct dm_event_fifos *fifos)
{
/* FIXME? Is fifo the most suitable method? Why not share
comms/daemon code with something else e.g. multipath? */
/* init fifos */
memset(fifos, 0, sizeof(*fifos));
fifos->client_path = DM_EVENT_FIFO_CLIENT;
fifos->server_path = DM_EVENT_FIFO_SERVER;
if (!_start_daemon(fifos)) {
stack;
return 0;
}
/* Open the fifo used to read from the daemon. */
if ((fifos->server = open(fifos->server_path, O_RDWR)) < 0) {
log_error("%s: open server fifo %s",
__func__, fifos->server_path);
stack;
return 0;
}
/* Lock out anyone else trying to do communication with the daemon. */
if (flock(fifos->server, LOCK_EX) < 0) {
log_error("%s: flock %s", __func__, fifos->server_path);
close(fifos->server);
return 0;
}
/* if ((fifos->client = open(fifos->client_path, O_WRONLY | O_NONBLOCK)) < 0) {*/
if ((fifos->client = open(fifos->client_path, O_RDWR | O_NONBLOCK)) < 0) {
log_error("%s: Can't open client fifo %s: %s",
__func__, fifos->client_path, strerror(errno));
close(fifos->server);
stack;
return 0;
}
return 1;
}
static void _dtr_client(struct dm_event_fifos *fifos)
{
if (flock(fifos->server, LOCK_UN))
log_error("flock unlock %s", fifos->server_path);
close(fifos->client);
close(fifos->server);
}
/* Get uuid of a device */
static struct dm_task *_get_device_info(const struct dm_event_handler *dmevh)
{
struct dm_task *dmt;
struct dm_info info;
if (!(dmt = dm_task_create(DM_DEVICE_INFO))) {
log_error("_get_device_info: dm_task creation for info failed");
return NULL;
}
if (dmevh->uuid)
dm_task_set_uuid(dmt, dmevh->uuid);
else if (dmevh->dev_name)
dm_task_set_name(dmt, dmevh->dev_name);
else if (dmevh->major && dmevh->minor) {
dm_task_set_major(dmt, dmevh->major);
dm_task_set_minor(dmt, dmevh->minor);
}
/* FIXME Add name or uuid or devno to messages */
if (!dm_task_run(dmt)) {
log_error("_get_device_info: dm_task_run() failed");
goto failed;
}
if (!dm_task_get_info(dmt, &info)) {
log_error("_get_device_info: failed to get info for device");
goto failed;
}
if (!info.exists) {
log_error("_get_device_info: device not found");
goto failed;
}
return dmt;
failed:
dm_task_destroy(dmt);
return NULL;
}
/* Handle the event (de)registration call and return negative error codes. */
static int _do_event(int cmd, struct dm_event_daemon_message *msg,
const char *dso_name, const char *dev_name,
enum dm_event_mask evmask, uint32_t timeout)
{
int ret;
struct dm_event_fifos fifos;
if (!_init_client(&fifos)) {
stack;
return -ESRCH;
}
ret = _daemon_talk(&fifos, msg, DM_EVENT_CMD_HELLO, 0, 0, 0, 0);
if (msg->data)
dm_free(msg->data);
msg->data = 0;
if (!ret)
ret = _daemon_talk(&fifos, msg, cmd, dso_name, dev_name, evmask, timeout);
/* what is the opposite of init? */
_dtr_client(&fifos);
return ret;
}
/* External library interface. */
int dm_event_register_handler(const struct dm_event_handler *dmevh)
{
int ret = 1, err;
const char *uuid;
struct dm_task *dmt;
struct dm_event_daemon_message msg = { 0, 0, NULL };
if (!(dmt = _get_device_info(dmevh))) {
stack;
return 0;
}
uuid = dm_task_get_uuid(dmt);
if ((err = _do_event(DM_EVENT_CMD_REGISTER_FOR_EVENT, &msg,
dmevh->dso, uuid, dmevh->mask, dmevh->timeout)) < 0) {
log_error("%s: event registration failed: %s",
dm_task_get_name(dmt),
msg.data ? msg.data : strerror(-err));
ret = 0;
}
if (msg.data)
dm_free(msg.data);
dm_task_destroy(dmt);
return ret;
}
int dm_event_unregister_handler(const struct dm_event_handler *dmevh)
{
int ret = 1, err;
const char *uuid;
struct dm_task *dmt;
struct dm_event_daemon_message msg = { 0, 0, NULL };
if (!(dmt = _get_device_info(dmevh))) {
stack;
return 0;
}
uuid = dm_task_get_uuid(dmt);
if ((err = _do_event(DM_EVENT_CMD_UNREGISTER_FOR_EVENT, &msg,
dmevh->dso, uuid, dmevh->mask, dmevh->timeout)) < 0) {
log_error("%s: event deregistration failed: %s",
dm_task_get_name(dmt),
msg.data ? msg.data : strerror(-err));
ret = 0;
}
if (msg.data)
dm_free(msg.data);
dm_task_destroy(dmt);
return ret;
}
/* Fetch a string off src and duplicate it into *dest. */
/* FIXME: move to separate module to share with the daemon. */
static char *_fetch_string(char **src, const int delimiter)
{
char *p, *ret;
if ((p = strchr(*src, delimiter)))
*p = 0;
if ((ret = dm_strdup(*src)))
*src += strlen(ret) + 1;
if (p)
*p = delimiter;
return ret;
}
/* Parse a device message from the daemon. */
static int _parse_message(struct dm_event_daemon_message *msg, char **dso_name,
char **uuid, enum dm_event_mask *evmask)
{
char *id = NULL;
char *p = msg->data;
if ((id = _fetch_string(&p, ' ')) &&
(*dso_name = _fetch_string(&p, ' ')) &&
(*uuid = _fetch_string(&p, ' '))) {
*evmask = atoi(p);
dm_free(id);
return 0;
}
if (id)
dm_free(id);
return -ENOMEM;
}
/*
* dm_event_get_registered_device
* @dso_name
* @device_path
* @mask
* @next
*
* Returns: 0 if handler found, error (-ENOMEM, -ENOENT) otherwise
*/
int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next)
{
int ret = 0;
const char *uuid = NULL;
char *reply_dso = NULL, *reply_uuid = NULL;
enum dm_event_mask reply_mask = 0;
struct dm_task *dmt = NULL;
struct dm_event_daemon_message msg = { 0, 0, NULL };
if (!(dmt = _get_device_info(dmevh))) {
stack;
return 0;
}
uuid = dm_task_get_uuid(dmt);
if (!(ret = _do_event(next ? DM_EVENT_CMD_GET_NEXT_REGISTERED_DEVICE :
DM_EVENT_CMD_GET_REGISTERED_DEVICE,
&msg, dmevh->dso, uuid, dmevh->mask, 0))) {
/* FIXME this will probably horribly break if we get
ill-formatted reply */
ret = _parse_message(&msg, &reply_dso, &reply_uuid, &reply_mask);
} else {
ret = -ENOENT;
goto fail;
}
dm_task_destroy(dmt);
if (msg.data) {
dm_free(msg.data);
msg.data = NULL;
}
_dm_event_handler_clear_dev_info(dmevh);
dmevh->uuid = dm_strdup(reply_uuid);
if (!dmevh->uuid) {
ret = -ENOMEM;
goto fail;
}
if (!(dmt = _get_device_info(dmevh))) {
ret = -ENXIO; /* dmeventd probably gave us bogus uuid back */
goto fail;
}
dm_event_handler_set_dso(dmevh, reply_dso);
dm_event_handler_set_event_mask(dmevh, reply_mask);
if (reply_dso)
dm_free(reply_dso);
if (reply_uuid)
dm_free(reply_uuid);
dmevh->dev_name = dm_strdup(dm_task_get_name(dmt));
if (!dmevh->dev_name) {
ret = -ENOMEM;
goto fail;
}
struct dm_info info;
if (!dm_task_get_info(dmt, &info)) {
ret = -1;
goto fail;
}
dmevh->major = info.major;
dmevh->minor = info.minor;
dm_task_destroy(dmt);
return ret;
fail:
if (msg.data)
dm_free(msg.data);
if (reply_dso)
dm_free(reply_dso);
if (reply_uuid)
dm_free(reply_uuid);
_dm_event_handler_clear_dev_info(dmevh);
dm_task_destroy(dmt);
return ret;
}
#if 0 /* left out for now */
static char *_skip_string(char *src, const int delimiter)
{
src = srtchr(src, delimiter);
if (src && *(src + 1))
return src + 1;
return NULL;
}
int dm_event_set_timeout(const char *device_path, uint32_t timeout)
{
struct dm_event_daemon_message msg = { 0, 0, NULL };
if (!device_exists(device_path))
return -ENODEV;
return _do_event(DM_EVENT_CMD_SET_TIMEOUT, &msg,
NULL, device_path, 0, timeout);
}
int dm_event_get_timeout(const char *device_path, uint32_t *timeout)
{
int ret;
struct dm_event_daemon_message msg = { 0, 0, NULL };
if (!device_exists(device_path))
return -ENODEV;
if (!(ret = _do_event(DM_EVENT_CMD_GET_TIMEOUT, &msg, NULL, device_path,
0, 0))) {
char *p = _skip_string(msg.data, ' ');
if (!p) {
log_error("malformed reply from dmeventd '%s'\n",
msg.data);
return -EIO;
}
*timeout = atoi(p);
}
if (msg.data)
dm_free(msg.data);
return ret;
}
#endif

View File

@@ -0,0 +1,106 @@
/*
* Copyright (C) 2005 Red Hat, Inc. All rights reserved.
*
* This file is part of the device-mapper userspace tools.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* Note that this file is released only as part of a technology preview
* and its contents may change in future updates in ways that do not
* preserve compatibility.
*/
#ifndef LIB_DMEVENT_H
#define LIB_DMEVENT_H
#include <stdint.h>
/*
* Event library interface.
*/
enum dm_event_mask {
DM_EVENT_SETTINGS_MASK = 0x0000FF,
DM_EVENT_SINGLE = 0x000001, /* Report multiple errors just once. */
DM_EVENT_MULTI = 0x000002, /* Report all of them. */
DM_EVENT_ERROR_MASK = 0x00FF00,
DM_EVENT_SECTOR_ERROR = 0x000100, /* Failure on a particular sector. */
DM_EVENT_DEVICE_ERROR = 0x000200, /* Device failure. */
DM_EVENT_PATH_ERROR = 0x000400, /* Failure on an io path. */
DM_EVENT_ADAPTOR_ERROR = 0x000800, /* Failure of a host adaptor. */
DM_EVENT_STATUS_MASK = 0xFF0000,
DM_EVENT_SYNC_STATUS = 0x010000, /* Mirror synchronization completed/failed. */
DM_EVENT_TIMEOUT = 0x020000, /* Timeout has occured */
DM_EVENT_REGISTRATION_PENDING = 0x1000000, /* Monitor thread is setting-up/shutting-down */
};
#define DM_EVENT_ALL_ERRORS DM_EVENT_ERROR_MASK
struct dm_event_handler;
struct dm_event_handler *dm_event_handler_create(void);
void dm_event_handler_destroy(struct dm_event_handler *dmevh);
/*
* Path of shared library to handle events.
*
* All of dso, device_name and uuid strings are duplicated, you do not
* need to keep the pointers valid after the call succeeds. Thes may
* return -ENOMEM though.
*/
int dm_event_handler_set_dso(struct dm_event_handler *dmevh, const char *path);
/*
* Identify the device to monitor by exactly one of device_name, uuid or
* device number. String arguments are duplicated, see above.
*/
int dm_event_handler_set_dev_name(struct dm_event_handler *dmevh, const char *device_name);
int dm_event_handler_set_uuid(struct dm_event_handler *dmevh, const char *uuid);
void dm_event_handler_set_major(struct dm_event_handler *dmevh, int major);
void dm_event_handler_set_minor(struct dm_event_handler *dmevh, int minor);
void dm_event_handler_set_timeout(struct dm_event_handler *dmevh, int timeout);
/*
* Specify mask for events to monitor.
*/
void dm_event_handler_set_event_mask(struct dm_event_handler *dmevh,
enum dm_event_mask evmask);
const char *dm_event_handler_get_dso(const struct dm_event_handler *dmevh);
const char *dm_event_handler_get_dev_name(const struct dm_event_handler *dmevh);
const char *dm_event_handler_get_uuid(const struct dm_event_handler *dmevh);
int dm_event_handler_get_major(const struct dm_event_handler *dmevh);
int dm_event_handler_get_minor(const struct dm_event_handler *dmevh);
int dm_event_handler_get_timeout(const struct dm_event_handler *dmevh);
enum dm_event_mask dm_event_handler_get_event_mask(const struct dm_event_handler *dmevh);
/* FIXME Review interface (what about this next thing?) */
int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next);
/*
* Initiate monitoring using dmeventd.
*/
int dm_event_register_handler(const struct dm_event_handler *dmevh);
int dm_event_unregister_handler(const struct dm_event_handler *dmevh);
/* Prototypes for DSO interface, see dmeventd.c, struct dso_data for
detailed descriptions. */
void process_event(struct dm_task *dmt, enum dm_event_mask evmask, void **user);
int register_device(const char *device_name, const char *uuid, int major, int minor, void **user);
int unregister_device(const char *device_name, const char *uuid, int major,
int minor, void **user);
#endif

View File

@@ -0,0 +1,12 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: devmapper-event
Description: device-mapper event library
Version: @DM_LIB_VERSION@
Requires: devmapper
Cflags: -I${includedir}
Libs: -L${libdir} -ldevmapper-event
Libs.private: -lpthread -ldl

View File

@@ -1,12 +0,0 @@
#!/bin/sh
#
# Create test devices for dmeventd
#
trap "rm -f /tmp/tmp.$$" 0 1 2 3 15
echo "0 1024 zero" > /tmp/tmp.$$
dmsetup create test /tmp/tmp.$$
dmsetup create test1 /tmp/tmp.$$
kill -15 $$

View File

@@ -1,39 +0,0 @@
/*
* Copyright (C) 2005 Red Hat, Inc. All rights reserved.
*
* This file is part of the device-mapper userspace tools.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "libdm-event.h"
#include "libmultilog.h"
void process_event(char *device, enum event_type event)
{
log_err("[%s] %s(%d) - Device: %s, Event %d\n",
__FILE__, __func__, __LINE__, device, event);
}
int register_device(char *device)
{
log_err("[%s] %s(%d) - Device: %s\n",
__FILE__, __func__, __LINE__, device);
return 1;
}
int unregister_device(char *device)
{
log_err("[%s] %s(%d) - Device: %s\n",
__FILE__, __func__, __LINE__, device);
return 1;
}

View File

@@ -0,0 +1,22 @@
#
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
# Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
#
# This file is part of the 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 General Public License v.2.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
SUBDIRS += mirror
include $(top_srcdir)/make.tmpl

View File

@@ -0,0 +1,3 @@
process_event
register_device
unregister_device

View File

@@ -0,0 +1,36 @@
#
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
# Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
#
# This file is part of the 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 General Public License v.2.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
INCLUDES += -I${top_srcdir}/tools
CLDFLAGS += -L${top_srcdir}/tools -ldevmapper -llvm2cmd
SOURCES = dmeventd_mirror.c
ifeq ("@LIB_SUFFIX@","dylib")
LIB_SHARED = libdevmapper-event-lvm2mirror.dylib
else
LIB_SHARED = libdevmapper-event-lvm2mirror.so
endif
include $(top_srcdir)/make.tmpl
install: libdevmapper-event-lvm2mirror.$(LIB_SUFFIX)
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
$(libdir)/$<.$(LIB_VERSION)
$(LN_S) -f $<.$(LIB_VERSION) $(libdir)/$<

View File

@@ -0,0 +1,281 @@
/*
* Copyright (C) 2005 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 "lvm2cmd.h"
#include <libdevmapper.h>
#include <libdevmapper-event.h>
#include <errno.h>
#include <signal.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <syslog.h> /* FIXME Replace syslog with multilog */
/* FIXME Missing openlog? */
#define ME_IGNORE 0
#define ME_INSYNC 1
#define ME_FAILURE 2
/*
* register_device() is called first and performs initialisation.
* Only one device may be registered or unregistered at a time.
*/
static pthread_mutex_t _register_mutex = PTHREAD_MUTEX_INITIALIZER;
/*
* Number of active registrations.
*/
static int _register_count = 0;
static struct dm_pool *_mem_pool = NULL;
static void *_lvm_handle = NULL;
/*
* Currently only one event can be processed at a time.
*/
static pthread_mutex_t _event_mutex = PTHREAD_MUTEX_INITIALIZER;
static int _get_mirror_event(char *params)
{
int i, r = ME_INSYNC;
char **args = NULL;
char *dev_status_str;
char *log_status_str;
char *sync_str;
char *p = NULL;
int log_argc, num_devs;
/*
* dm core parms: 0 409600 mirror
* Mirror core parms: 2 253:4 253:5 400/400
* New-style failure params: 1 AA
* New-style log params: 3 cluster 253:3 A
* or 3 disk 253:3 A
* or 1 core
*/
/* number of devices */
if (!dm_split_words(params, 1, 0, &p))
goto out_parse;
if (!(num_devs = atoi(p)))
goto out_parse;
p += strlen(p) + 1;
/* devices names + "400/400" + "1 AA" + 1 or 3 log parms + NULL */
args = dm_malloc((num_devs + 7) * sizeof(char *));
if (!args || dm_split_words(p, num_devs + 7, 0, args) < num_devs + 5)
goto out_parse;
dev_status_str = args[2 + num_devs];
log_argc = atoi(args[3 + num_devs]);
log_status_str = args[3 + num_devs + log_argc];
sync_str = args[num_devs];
/* Check for bad mirror devices */
for (i = 0; i < num_devs; i++)
if (dev_status_str[i] == 'D') {
syslog(LOG_ERR, "Mirror device, %s, has failed.\n", args[i]);
r = ME_FAILURE;
}
/* Check for bad disk log device */
if (log_argc > 1 && log_status_str[0] == 'D') {
syslog(LOG_ERR, "Log device, %s, has failed.\n",
args[2 + num_devs + log_argc]);
r = ME_FAILURE;
}
if (r == ME_FAILURE)
goto out;
p = strstr(sync_str, "/");
if (p) {
p[0] = '\0';
if (strcmp(sync_str, p+1))
r = ME_IGNORE;
p[0] = '/';
} else
goto out_parse;
out:
if (args)
dm_free(args);
return r;
out_parse:
if (args)
dm_free(args);
syslog(LOG_ERR, "Unable to parse mirror status string.");
return ME_IGNORE;
}
static void _temporary_log_fn(int level, const char *file,
int line, const char *format)
{
if (!strncmp(format, "WARNING: ", 9) && (level < 5))
syslog(LOG_CRIT, "%s", format);
else
syslog(LOG_DEBUG, "%s", format);
}
static int _remove_failed_devices(const char *device)
{
int r;
#define CMD_SIZE 256 /* FIXME Use system restriction */
char cmd_str[CMD_SIZE];
char *vg = NULL, *lv = NULL, *layer = NULL;
if (strlen(device) > 200) /* FIXME Use real restriction */
return -ENAMETOOLONG; /* FIXME These return code distinctions are not used so remove them! */
if (!dm_split_lvm_name(_mem_pool, device, &vg, &lv, &layer)) {
syslog(LOG_ERR, "Unable to determine VG name from %s",
device);
return -ENOMEM; /* FIXME Replace with generic error return - reason for failure has already got logged */
}
/* FIXME Is any sanity-checking required on %s? */
if (CMD_SIZE <= snprintf(cmd_str, CMD_SIZE, "vgreduce --config devices{ignore_suspended_devices=1} --removemissing %s", vg)) {
/* this error should be caught above, but doesn't hurt to check again */
syslog(LOG_ERR, "Unable to form LVM command: Device name too long");
dm_pool_empty(_mem_pool); /* FIXME: not safe with multiple threads */
return -ENAMETOOLONG; /* FIXME Replace with generic error return - reason for failure has already got logged */
}
r = lvm2_run(_lvm_handle, cmd_str);
dm_pool_empty(_mem_pool); /* FIXME: not safe with multiple threads */
return (r == 1) ? 0 : -1;
}
void process_event(struct dm_task *dmt, enum dm_event_mask event,
void **unused __attribute((unused)))
{
void *next = NULL;
uint64_t start, length;
char *target_type = NULL;
char *params;
const char *device = dm_task_get_name(dmt);
if (pthread_mutex_trylock(&_event_mutex)) {
syslog(LOG_NOTICE, "Another thread is handling an event. Waiting...");
pthread_mutex_lock(&_event_mutex);
}
do {
next = dm_get_next_target(dmt, next, &start, &length,
&target_type, &params);
if (!target_type) {
syslog(LOG_INFO, "%s mapping lost.\n", device);
continue;
}
if (strcmp(target_type, "mirror")) {
syslog(LOG_INFO, "%s has unmirrored portion.\n", device);
continue;
}
switch(_get_mirror_event(params)) {
case ME_INSYNC:
/* FIXME: all we really know is that this
_part_ of the device is in sync
Also, this is not an error
*/
syslog(LOG_NOTICE, "%s is now in-sync\n", device);
break;
case ME_FAILURE:
syslog(LOG_ERR, "Device failure in %s\n", device);
if (_remove_failed_devices(device))
/* FIXME Why are all the error return codes unused? Get rid of them? */
syslog(LOG_ERR, "Failed to remove faulty devices in %s\n",
device);
/* Should check before warning user that device is now linear
else
syslog(LOG_NOTICE, "%s is now a linear device.\n",
device);
*/
break;
case ME_IGNORE:
break;
default:
/* FIXME Provide value then! */
syslog(LOG_INFO, "Unknown event received.\n");
}
} while (next);
pthread_mutex_unlock(&_event_mutex);
}
int register_device(const char *device, const char *uuid, int major, int minor,
void **unused __attribute((unused)))
{
int r = 0;
pthread_mutex_lock(&_register_mutex);
syslog(LOG_INFO, "Monitoring mirror device %s for events\n", device);
/*
* 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) {
lvm2_log_fn(_temporary_log_fn);
if (!(_lvm_handle = lvm2_init())) {
dm_pool_destroy(_mem_pool);
_mem_pool = NULL;
goto out;
}
lvm2_log_level(_lvm_handle, LVM2_LOG_SUPPRESS);
/* FIXME Temporary: move to dmeventd core */
lvm2_run(_lvm_handle, "_memlock_inc");
}
_register_count++;
r = 1;
out:
pthread_mutex_unlock(&_register_mutex);
return r;
}
int unregister_device(const char *device, const char *uuid, int major, int minor,
void **unused __attribute((unused)))
{
pthread_mutex_lock(&_register_mutex);
syslog(LOG_INFO, "No longer monitoring mirror device %s for events\n",
device);
if (!--_register_count) {
dm_pool_destroy(_mem_pool);
_mem_pool = NULL;
lvm2_run(_lvm_handle, "_memlock_dec");
lvm2_exit(_lvm_handle);
_lvm_handle = NULL;
}
pthread_mutex_unlock(&_register_mutex);
return 1;
}

22
dmeventd/Makefile.in Normal file
View File

@@ -0,0 +1,22 @@
#
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
# Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
#
# This file is part of the 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 General Public License v.2.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
SUBDIRS += mirror
include $(top_srcdir)/make.tmpl

View File

@@ -0,0 +1,3 @@
process_event
register_device
unregister_device

View File

@@ -0,0 +1,36 @@
#
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
# Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
#
# This file is part of the 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 General Public License v.2.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
INCLUDES += -I${top_srcdir}/tools
CLDFLAGS += -L${top_srcdir}/tools -ldevmapper -llvm2cmd
SOURCES = dmeventd_mirror.c
ifeq ("@LIB_SUFFIX@","dylib")
LIB_SHARED = libdevmapper-event-lvm2mirror.dylib
else
LIB_SHARED = libdevmapper-event-lvm2mirror.so
endif
include $(top_srcdir)/make.tmpl
install: libdevmapper-event-lvm2mirror.$(LIB_SUFFIX)
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
$(libdir)/$<.$(LIB_VERSION)
$(LN_S) -f $<.$(LIB_VERSION) $(libdir)/$<

View File

@@ -0,0 +1,281 @@
/*
* Copyright (C) 2005 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 "lvm2cmd.h"
#include <libdevmapper.h>
#include <libdevmapper-event.h>
#include <errno.h>
#include <signal.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <syslog.h> /* FIXME Replace syslog with multilog */
/* FIXME Missing openlog? */
#define ME_IGNORE 0
#define ME_INSYNC 1
#define ME_FAILURE 2
/*
* register_device() is called first and performs initialisation.
* Only one device may be registered or unregistered at a time.
*/
static pthread_mutex_t _register_mutex = PTHREAD_MUTEX_INITIALIZER;
/*
* Number of active registrations.
*/
static int _register_count = 0;
static struct dm_pool *_mem_pool = NULL;
static void *_lvm_handle = NULL;
/*
* Currently only one event can be processed at a time.
*/
static pthread_mutex_t _event_mutex = PTHREAD_MUTEX_INITIALIZER;
static int _get_mirror_event(char *params)
{
int i, r = ME_INSYNC;
char **args = NULL;
char *dev_status_str;
char *log_status_str;
char *sync_str;
char *p = NULL;
int log_argc, num_devs;
/*
* dm core parms: 0 409600 mirror
* Mirror core parms: 2 253:4 253:5 400/400
* New-style failure params: 1 AA
* New-style log params: 3 cluster 253:3 A
* or 3 disk 253:3 A
* or 1 core
*/
/* number of devices */
if (!dm_split_words(params, 1, 0, &p))
goto out_parse;
if (!(num_devs = atoi(p)))
goto out_parse;
p += strlen(p) + 1;
/* devices names + "400/400" + "1 AA" + 1 or 3 log parms + NULL */
args = dm_malloc((num_devs + 7) * sizeof(char *));
if (!args || dm_split_words(p, num_devs + 7, 0, args) < num_devs + 5)
goto out_parse;
dev_status_str = args[2 + num_devs];
log_argc = atoi(args[3 + num_devs]);
log_status_str = args[3 + num_devs + log_argc];
sync_str = args[num_devs];
/* Check for bad mirror devices */
for (i = 0; i < num_devs; i++)
if (dev_status_str[i] == 'D') {
syslog(LOG_ERR, "Mirror device, %s, has failed.\n", args[i]);
r = ME_FAILURE;
}
/* Check for bad disk log device */
if (log_argc > 1 && log_status_str[0] == 'D') {
syslog(LOG_ERR, "Log device, %s, has failed.\n",
args[2 + num_devs + log_argc]);
r = ME_FAILURE;
}
if (r == ME_FAILURE)
goto out;
p = strstr(sync_str, "/");
if (p) {
p[0] = '\0';
if (strcmp(sync_str, p+1))
r = ME_IGNORE;
p[0] = '/';
} else
goto out_parse;
out:
if (args)
dm_free(args);
return r;
out_parse:
if (args)
dm_free(args);
syslog(LOG_ERR, "Unable to parse mirror status string.");
return ME_IGNORE;
}
static void _temporary_log_fn(int level, const char *file,
int line, const char *format)
{
if (!strncmp(format, "WARNING: ", 9) && (level < 5))
syslog(LOG_CRIT, "%s", format);
else
syslog(LOG_DEBUG, "%s", format);
}
static int _remove_failed_devices(const char *device)
{
int r;
#define CMD_SIZE 256 /* FIXME Use system restriction */
char cmd_str[CMD_SIZE];
char *vg = NULL, *lv = NULL, *layer = NULL;
if (strlen(device) > 200) /* FIXME Use real restriction */
return -ENAMETOOLONG; /* FIXME These return code distinctions are not used so remove them! */
if (!dm_split_lvm_name(_mem_pool, device, &vg, &lv, &layer)) {
syslog(LOG_ERR, "Unable to determine VG name from %s",
device);
return -ENOMEM; /* FIXME Replace with generic error return - reason for failure has already got logged */
}
/* FIXME Is any sanity-checking required on %s? */
if (CMD_SIZE <= snprintf(cmd_str, CMD_SIZE, "vgreduce --config devices{ignore_suspended_devices=1} --removemissing %s", vg)) {
/* this error should be caught above, but doesn't hurt to check again */
syslog(LOG_ERR, "Unable to form LVM command: Device name too long");
dm_pool_empty(_mem_pool); /* FIXME: not safe with multiple threads */
return -ENAMETOOLONG; /* FIXME Replace with generic error return - reason for failure has already got logged */
}
r = lvm2_run(_lvm_handle, cmd_str);
dm_pool_empty(_mem_pool); /* FIXME: not safe with multiple threads */
return (r == 1) ? 0 : -1;
}
void process_event(struct dm_task *dmt, enum dm_event_mask event,
void **unused __attribute((unused)))
{
void *next = NULL;
uint64_t start, length;
char *target_type = NULL;
char *params;
const char *device = dm_task_get_name(dmt);
if (pthread_mutex_trylock(&_event_mutex)) {
syslog(LOG_NOTICE, "Another thread is handling an event. Waiting...");
pthread_mutex_lock(&_event_mutex);
}
do {
next = dm_get_next_target(dmt, next, &start, &length,
&target_type, &params);
if (!target_type) {
syslog(LOG_INFO, "%s mapping lost.\n", device);
continue;
}
if (strcmp(target_type, "mirror")) {
syslog(LOG_INFO, "%s has unmirrored portion.\n", device);
continue;
}
switch(_get_mirror_event(params)) {
case ME_INSYNC:
/* FIXME: all we really know is that this
_part_ of the device is in sync
Also, this is not an error
*/
syslog(LOG_NOTICE, "%s is now in-sync\n", device);
break;
case ME_FAILURE:
syslog(LOG_ERR, "Device failure in %s\n", device);
if (_remove_failed_devices(device))
/* FIXME Why are all the error return codes unused? Get rid of them? */
syslog(LOG_ERR, "Failed to remove faulty devices in %s\n",
device);
/* Should check before warning user that device is now linear
else
syslog(LOG_NOTICE, "%s is now a linear device.\n",
device);
*/
break;
case ME_IGNORE:
break;
default:
/* FIXME Provide value then! */
syslog(LOG_INFO, "Unknown event received.\n");
}
} while (next);
pthread_mutex_unlock(&_event_mutex);
}
int register_device(const char *device, const char *uuid, int major, int minor,
void **unused __attribute((unused)))
{
int r = 0;
pthread_mutex_lock(&_register_mutex);
syslog(LOG_INFO, "Monitoring mirror device %s for events\n", device);
/*
* 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) {
lvm2_log_fn(_temporary_log_fn);
if (!(_lvm_handle = lvm2_init())) {
dm_pool_destroy(_mem_pool);
_mem_pool = NULL;
goto out;
}
lvm2_log_level(_lvm_handle, LVM2_LOG_SUPPRESS);
/* FIXME Temporary: move to dmeventd core */
lvm2_run(_lvm_handle, "_memlock_inc");
}
_register_count++;
r = 1;
out:
pthread_mutex_unlock(&_register_mutex);
return r;
}
int unregister_device(const char *device, const char *uuid, int major, int minor,
void **unused __attribute((unused)))
{
pthread_mutex_lock(&_register_mutex);
syslog(LOG_INFO, "No longer monitoring mirror device %s for events\n",
device);
if (!--_register_count) {
dm_pool_destroy(_mem_pool);
_mem_pool = NULL;
lvm2_run(_lvm_handle, "_memlock_dec");
lvm2_exit(_lvm_handle);
_lvm_handle = NULL;
}
pthread_mutex_unlock(&_register_mutex);
return 1;
}

View File

@@ -19,6 +19,14 @@ devices {
# to use with LVM2.
scan = [ "/dev" ]
# If several entries in the scanned directories correspond to the
# same block device and the tools need to display a name for device,
# all the pathnames are matched against each item in the following
# list of regular expressions in turn and the first match is used.
preferred_names = [ ]
# preferred_names = [ "^/dev/mpath/", "^/dev/[hs]d" ]
# A filter that tells LVM2 to only use a restricted set of devices.
# The filter consists of an array of regular expressions. These
# expressions can be delimited by a character of your choice, and
@@ -56,10 +64,14 @@ devices {
# filter = [ "a|^/dev/hda8$|", "r/.*/" ]
# The results of the filtering are cached on disk to avoid
# rescanning dud devices (which can take a very long time). By
# default this cache file is hidden in the /etc/lvm directory.
# It is safe to delete this file: the tools regenerate it.
cache = "/etc/lvm/.cache"
# rescanning dud devices (which can take a very long time).
# By default this cache is stored in the /etc/lvm/cache directory
# in a file called '.cache'.
# It is safe to delete the contents: the tools regenerate it.
# (The old setting 'cache' is still respected if neither of
# these new ones is present.)
cache_dir = "/etc/lvm/cache"
cache_file_prefix = ""
# You can turn off writing this cache file by setting this to 0.
write_cache_state = 1
@@ -79,6 +91,12 @@ devices {
# software RAID (md) devices by looking for md superblocks.
# 1 enables; 0 disables.
md_component_detection = 1
# If, while scanning the system for PVs, LVM2 encounters a device-mapper
# device that has its I/O suspended, it waits for it to become accessible.
# Set this to 1 to skip such devices. This should only be needed
# in recovery situations.
ignore_suspended_devices = 0
}
# This section that allows you to configure the nature of the
@@ -182,6 +200,9 @@ global {
# command. Defaults to off.
test = 0
# Default value for --units argument
units = "h"
# Whether or not to communicate with the kernel device-mapper.
# Set to 0 if you want to use the tools to manipulate LVM metadata
# without activating any logical volumes.
@@ -207,11 +228,26 @@ global {
# Location of proc filesystem
proc = "/proc"
# Type of locking to use. Defaults to file-based locking (1).
# Type of locking to use. Defaults to local file-based locking (1).
# Turn locking off by setting to 0 (dangerous: risks metadata corruption
# if LVM2 commands get run concurrently).
# Type 2 uses the external shared library locking_library.
# Type 3 uses built-in clustered locking.
locking_type = 1
# If using external locking (type 2) and initialisation fails,
# with this set to 1 an attempt will be made to use the built-in
# clustered locking.
# If you are using a customised locking_library you should set this to 0.
fallback_to_clustered_locking = 1
# If an attempt to initialise type 2 or type 3 locking failed, perhaps
# because cluster components such as clvmd are not running, with this set
# to 1 an attempt will be made to use local file-based locking (type 1).
# If this succeeds, only commands against local volume groups will proceed.
# Volume Groups marked as clustered will be ignored.
fallback_to_local_locking = 1
# Local non-LV directory that holds file-based locks while commands are
# in progress. A directory like /tmp that may get wiped on reboot is OK.
locking_dir = "/var/lock/lvm"
@@ -223,6 +259,9 @@ global {
# Search this directory first for shared libraries.
# library_dir = "/lib"
# The external locking library to load if locking_type is set to 2.
# locking_library = "liblvm2clusterlock.so"
}
activation {
@@ -232,9 +271,6 @@ activation {
# target or make it return zeros.
missing_stripe_filler = "/dev/ioerror"
# Size (in KB) of each copy operation when mirroring
mirror_region_size = 512
# How much stack (in KB) to reserve for use while devices suspended
reserved_stack = 256
@@ -251,6 +287,54 @@ activation {
# "@*" matches if any tag defined on the host is also set in the LV or VG
#
# volume_list = [ "vg1", "vg2/lvol1", "@tag1", "@*" ]
# Size (in KB) of each copy operation when mirroring
mirror_region_size = 512
# 'mirror_image_fault_policy' and 'mirror_log_fault_policy' define
# how a device failure affecting a mirror is handled.
# A mirror is composed of mirror images (copies) and a log.
# A disk log ensures that a mirror does not need to be re-synced
# (all copies made the same) every time a machine reboots or crashes.
#
# In the event of a failure, the specified policy will be used to
# determine what happens:
#
# "remove" - Simply remove the faulty device and run without it. If
# the log device fails, the mirror would convert to using
# an in-memory log. This means the mirror will not
# remember its sync status across crashes/reboots and
# the entire mirror will be re-synced. If a
# mirror image fails, the mirror will convert to a
# non-mirrored device if there is only one remaining good
# copy.
#
# "allocate" - Remove the faulty device and try to allocate space on
# a new device to be a replacement for the failed device.
# Using this policy for the log is fast and maintains the
# ability to remember sync state through crashes/reboots.
# Using this policy for a mirror device is slow, as it
# requires the mirror to resynchronize the devices, but it
# will preserve the mirror characteristic of the device.
# This policy acts like "remove" if no suitable device and
# space can be allocated for the replacement.
# Currently this is not implemented properly and behaves
# similarly to:
#
# "allocate_anywhere" - Operates like "allocate", but it does not
# require that the new space being allocated be on a
# device is not part of the mirror. For a log device
# failure, this could mean that the log is allocated on
# the same device as a mirror device. For a mirror
# device, this could mean that the mirror device is
# allocated on the same device as another mirror device.
# This policy would not be wise for mirror devices
# because it would break the redundant nature of the
# mirror. This policy acts like "remove" if no suitable
# device and space can be allocated for the replacement.
mirror_log_fault_policy = "allocate"
mirror_device_fault_policy = "remove"
}
@@ -289,4 +373,15 @@ activation {
# dirs = [ "/etc/lvm/metadata", "/mnt/disk2/lvm/metadata2" ]
#}
# Event daemon
#
# dmeventd {
# mirror_library is the library used when monitoring a mirror device.
#
# "libdevmapper-event-lvm2mirror.so" attempts to recover from failures.
# It removes failed devices from a volume group and reconfigures a
# mirror as necessary.
#
# mirror_library = "libdevmapper-event-lvm2mirror.so"
#}

View File

@@ -34,12 +34,14 @@
../lib/metadata/segtype.h
../lib/mm/memlock.h
../lib/mm/xlate.h
../lib/misc/configure.h
../lib/misc/crc.h
../lib/misc/intl.h
../lib/misc/lib.h
../lib/misc/lvm-exec.h
../lib/misc/lvm-file.h
../lib/misc/lvm-string.h
../lib/misc/lvm-wrappers.h
../lib/misc/sharedlib.h
../lib/regex/matcher.h
../lib/report/report.h

View File

@@ -41,3 +41,5 @@ install:
install_cluster:
cflow:

View File

@@ -38,6 +38,7 @@ SOURCES =\
commands/toolcontext.c \
config/config.c \
datastruct/btree.c \
datastruct/list.c \
datastruct/str_list.c \
device/dev-cache.c \
device/dev-io.c \
@@ -77,6 +78,8 @@ SOURCES =\
misc/lvm-exec.c \
misc/lvm-file.c \
misc/lvm-string.c \
misc/lvm-wrappers.c \
misc/timestamp.c \
mm/memlock.c \
regex/matcher.c \
regex/parse_rx.c \
@@ -133,9 +136,22 @@ ifeq ("@HAVE_LIBDL@", "yes")
misc/sharedlib.c
endif
ifeq ("@DMEVENTD@", "yes")
CLDFLAGS += -ldevmapper-event
endif
LIB_STATIC = liblvm.a
$(SUBDIRS): $(LIB_STATIC)
CLEAN_TARGETS += liblvm.cflow
include $(top_srcdir)/make.tmpl
liblvm.cflow: $(SOURCES)
set -e; (echo -n "SOURCES += "; \
echo $(SOURCES) | \
sed "s/^/ /;s/ / $(top_srcdir)\/lib\//g;s/$$//"; \
) > $@
cflow: liblvm.cflow

View File

@@ -27,6 +27,7 @@
#include "str_list.h"
#include "config.h"
#include "filter.h"
#include "segtype.h"
#include <limits.h>
#include <fcntl.h>
@@ -38,7 +39,7 @@ int lvm1_present(struct cmd_context *cmd)
{
char path[PATH_MAX];
if (lvm_snprintf(path, sizeof(path), "%s/lvm/global", cmd->proc_dir)
if (dm_snprintf(path, sizeof(path), "%s/lvm/global", cmd->proc_dir)
< 0) {
log_error("LVM1 proc global snprintf failed");
return 0;
@@ -50,6 +51,66 @@ int lvm1_present(struct cmd_context *cmd)
return 0;
}
int list_segment_modules(struct dm_pool *mem, const struct lv_segment *seg,
struct list *modules)
{
unsigned int s;
struct lv_segment *seg2, *snap_seg;
struct list *snh;
if (seg->segtype->ops->modules_needed &&
!seg->segtype->ops->modules_needed(mem, seg, modules)) {
log_error("module string allocation failed");
return 0;
}
if (lv_is_origin(seg->lv))
list_iterate(snh, &seg->lv->snapshot_segs)
if (!list_lv_modules(mem,
list_struct_base(snh,
struct lv_segment,
origin_list)->cow,
modules))
return_0;
if (lv_is_cow(seg->lv)) {
snap_seg = find_cow(seg->lv);
if (snap_seg->segtype->ops->modules_needed &&
!snap_seg->segtype->ops->modules_needed(mem, snap_seg,
modules)) {
log_error("snap_seg module string allocation failed");
return 0;
}
}
for (s = 0; s < seg->area_count; s++) {
switch (seg_type(seg, s)) {
case AREA_LV:
seg2 = find_seg_by_le(seg_lv(seg, s), seg_le(seg, s));
if (seg2 && !list_segment_modules(mem, seg2, modules))
return_0;
break;
case AREA_PV:
case AREA_UNASSIGNED:
;
}
}
return 1;
}
int list_lv_modules(struct dm_pool *mem, const struct logical_volume *lv,
struct list *modules)
{
struct lv_segment *seg;
list_iterate_items(seg, &lv->segments)
if (!list_segment_modules(mem, seg, modules))
return_0;
return 1;
}
#ifndef DEVMAPPER_SUPPORT
void set_activation(int act)
{
@@ -75,7 +136,12 @@ int driver_version(char *version, size_t size)
{
return 0;
}
int target_present(const char *target_name)
int target_version(const char *target_name, uint32_t *maj,
uint32_t *min, uint32_t *patchlevel)
{
return 0;
}
int target_present(const char *target_name, int use_modprobe)
{
return 0;
}
@@ -89,12 +155,12 @@ int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s,
{
return 0;
}
int lv_snapshot_percent(struct logical_volume *lv, float *percent)
int lv_snapshot_percent(const struct logical_volume *lv, float *percent)
{
return 0;
}
int lv_mirror_percent(struct logical_volume *lv, int wait, float *percent,
uint32_t *event_nr)
int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv,
int wait, float *percent, uint32_t *event_nr)
{
return 0;
}
@@ -102,6 +168,10 @@ int lvs_in_vg_activated(struct volume_group *vg)
{
return 0;
}
int lvs_in_vg_activated_by_uuid_only(struct volume_group *vg)
{
return 0;
}
int lvs_in_vg_opened(struct volume_group *vg)
{
return 0;
@@ -145,12 +215,17 @@ int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv)
return 1;
}
int pv_uses_vg(struct cmd_context *cmd, struct physical_volume *pv,
struct volume_group *vg)
int pv_uses_vg(struct physical_volume *pv,
struct volume_group *vg)
{
return 0;
}
void activation_release(void)
{
return;
}
void activation_exit(void)
{
return;
@@ -170,8 +245,8 @@ void set_activation(int act)
log_verbose("Activation enabled. Device-mapper kernel "
"driver will be used.");
else
log_verbose("Activation disabled. No device-mapper "
"interaction will be attempted.");
log_print("WARNING: Activation disabled. No device-mapper "
"interaction will be attempted.");
}
int activation(void)
@@ -187,7 +262,7 @@ static int _passes_activation_filter(struct cmd_context *cmd,
char *str;
char path[PATH_MAX];
if (!(cn = find_config_node(cmd->cft->root, "activation/volume_list"))) {
if (!(cn = find_config_tree_node(cmd, "activation/volume_list"))) {
/* If no host tags defined, activate */
if (list_empty(&cmd->tags))
return 1;
@@ -246,9 +321,9 @@ static int _passes_activation_filter(struct cmd_context *cmd,
continue;
}
/* vgname/lvname */
if (lvm_snprintf(path, sizeof(path), "%s/%s", lv->vg->name,
if (dm_snprintf(path, sizeof(path), "%s/%s", lv->vg->name,
lv->name) < 0) {
log_error("lvm_snprintf error from %s/%s", lv->vg->name,
log_error("dm_snprintf error from %s/%s", lv->vg->name,
lv->name);
continue;
}
@@ -277,7 +352,8 @@ int driver_version(char *version, size_t size)
return dm_driver_version(version, size);
}
static int _target_present(const char *target_name)
int target_version(const char *target_name, uint32_t *maj,
uint32_t *min, uint32_t *patchlevel)
{
int r = 0;
struct dm_task *dmt;
@@ -300,6 +376,9 @@ static int _target_present(const char *target_name)
if (!strcmp(target_name, target->name)) {
r = 1;
*maj = target->version[0];
*min = target->version[1];
*patchlevel = target->version[2];
goto out;
}
@@ -314,6 +393,7 @@ static int _target_present(const char *target_name)
int target_present(const char *target_name, int use_modprobe)
{
uint32_t maj, min, patchlevel;
#ifdef MODPROBE_CMD
char module[128];
#endif
@@ -323,10 +403,10 @@ int target_present(const char *target_name, int use_modprobe)
#ifdef MODPROBE_CMD
if (use_modprobe) {
if (_target_present(target_name))
if (target_version(target_name, &maj, &min, &patchlevel))
return 1;
if (lvm_snprintf(module, sizeof(module), "dm-%s", target_name)
if (dm_snprintf(module, sizeof(module), "dm-%s", target_name)
< 0) {
log_error("target_present module name too long: %s",
target_name);
@@ -338,28 +418,30 @@ int target_present(const char *target_name, int use_modprobe)
}
#endif
return _target_present(target_name);
return target_version(target_name, &maj, &min, &patchlevel);
}
/*
* Returns 1 if info structure populated, else 0 on failure.
*/
static int _lv_info(struct cmd_context *cmd, const struct logical_volume *lv, int with_mknodes,
struct lvinfo *info, int with_open_count)
struct lvinfo *info, int with_open_count, unsigned by_uuid_only)
{
struct dm_info dminfo;
char *name;
char *name = NULL;
if (!activation())
return 0;
if (!(name = build_dm_name(cmd->mem, lv->vg->name, lv->name, NULL)))
if (!by_uuid_only &&
!(name = build_dm_name(cmd->mem, lv->vg->name, lv->name, NULL)))
return_0;
log_debug("Getting device info for %s", name);
if (!dev_manager_info(lv->vg->cmd->mem, name, lv, with_mknodes,
with_open_count, &dminfo)) {
dm_pool_free(cmd->mem, name);
if (name)
dm_pool_free(cmd->mem, name);
return_0;
}
@@ -372,14 +454,16 @@ static int _lv_info(struct cmd_context *cmd, const struct logical_volume *lv, in
info->live_table = dminfo.live_table;
info->inactive_table = dminfo.inactive_table;
dm_pool_free(cmd->mem, name);
if (name)
dm_pool_free(cmd->mem, name);
return 1;
}
int lv_info(struct cmd_context *cmd, const struct logical_volume *lv, struct lvinfo *info,
int with_open_count)
{
return _lv_info(cmd, lv, 0, info, with_open_count);
return _lv_info(cmd, lv, 0, info, with_open_count, 0);
}
int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s,
@@ -390,13 +474,13 @@ int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s,
if (!(lv = lv_from_lvid(cmd, lvid_s, 0)))
return 0;
return _lv_info(cmd, lv, 0, info, with_open_count);
return _lv_info(cmd, lv, 0, info, with_open_count, 0);
}
/*
* Returns 1 if percent set, else 0 on failure.
*/
int lv_snapshot_percent(struct logical_volume *lv, float *percent)
int lv_snapshot_percent(const struct logical_volume *lv, float *percent)
{
int r;
struct dev_manager *dm;
@@ -416,8 +500,8 @@ int lv_snapshot_percent(struct logical_volume *lv, float *percent)
}
/* FIXME Merge with snapshot_percent */
int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv, int wait, float *percent,
uint32_t *event_nr)
int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv,
int wait, float *percent, uint32_t *event_nr)
{
int r;
struct dev_manager *dm;
@@ -443,11 +527,12 @@ int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv, int wa
return r;
}
static int _lv_active(struct cmd_context *cmd, struct logical_volume *lv)
static int _lv_active(struct cmd_context *cmd, struct logical_volume *lv,
unsigned by_uuid_only)
{
struct lvinfo info;
if (!lv_info(cmd, lv, &info, 0)) {
if (!_lv_info(cmd, lv, 0, &info, 0, by_uuid_only)) {
stack;
return -1;
}
@@ -512,7 +597,7 @@ static int _lv_deactivate(struct logical_volume *lv)
return r;
}
static int _lv_suspend_lv(struct logical_volume *lv)
static int _lv_suspend_lv(struct logical_volume *lv, int lockfs)
{
int r;
struct dev_manager *dm;
@@ -520,7 +605,7 @@ static int _lv_suspend_lv(struct logical_volume *lv)
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name)))
return_0;
if (!(r = dev_manager_suspend(dm, lv)))
if (!(r = dev_manager_suspend(dm, lv, lockfs)))
stack;
dev_manager_destroy(dm);
@@ -531,7 +616,7 @@ static int _lv_suspend_lv(struct logical_volume *lv)
* These two functions return the number of visible LVs in the state,
* or -1 on error.
*/
int lvs_in_vg_activated(struct volume_group *vg)
static int _lvs_in_vg_activated(struct volume_group *vg, unsigned by_uuid_only)
{
struct lv_list *lvl;
int count = 0;
@@ -541,12 +626,22 @@ int lvs_in_vg_activated(struct volume_group *vg)
list_iterate_items(lvl, &vg->lvs) {
if (lvl->lv->status & VISIBLE_LV)
count += (_lv_active(vg->cmd, lvl->lv) == 1);
count += (_lv_active(vg->cmd, lvl->lv, by_uuid_only) == 1);
}
return count;
}
int lvs_in_vg_activated_by_uuid_only(struct volume_group *vg)
{
return _lvs_in_vg_activated(vg, 1);
}
int lvs_in_vg_activated(struct volume_group *vg)
{
return _lvs_in_vg_activated(vg, 0);
}
int lvs_in_vg_opened(struct volume_group *vg)
{
struct lv_list *lvl;
@@ -563,18 +658,114 @@ int lvs_in_vg_opened(struct volume_group *vg)
return count;
}
/*
* Returns 0 if an attempt to (un)monitor the device failed.
* Returns 1 otherwise.
*/
int monitor_dev_for_events(struct cmd_context *cmd,
struct logical_volume *lv, int monitor)
{
#ifdef DMEVENTD
int i, pending = 0, monitored;
int r = 1;
struct list *tmp;
struct lv_segment *seg;
int (*monitor_fn) (struct lv_segment *s, int e);
/* skip dmeventd code altogether */
if (dmeventd_monitor_mode() == DMEVENTD_MONITOR_IGNORE)
return 1;
/*
* Nothing to do if dmeventd configured not to be used.
*/
if (monitor && !dmeventd_monitor_mode())
return 1;
list_iterate(tmp, &lv->segments) {
seg = list_item(tmp, struct lv_segment);
if (!seg_monitored(seg) || (seg->status & PVMOVE))
continue;
monitor_fn = NULL;
/* Check monitoring status */
if (seg->segtype->ops->target_monitored)
monitored = seg->segtype->ops->target_monitored(seg, &pending);
else
continue; /* segtype doesn't support registration */
/*
* FIXME: We should really try again if pending
*/
monitored = (pending) ? 0 : monitored;
if (monitor) {
if (monitored)
log_verbose("%s/%s already monitored.", lv->vg->name, lv->name);
else if (seg->segtype->ops->target_monitor_events)
monitor_fn = seg->segtype->ops->target_monitor_events;
} else {
if (!monitored)
log_verbose("%s/%s already not monitored.", lv->vg->name, lv->name);
else if (seg->segtype->ops->target_unmonitor_events)
monitor_fn = seg->segtype->ops->target_unmonitor_events;
}
/* Do [un]monitor */
if (!monitor_fn)
continue;
log_verbose("%sonitoring %s/%s", monitor ? "M" : "Not m", lv->vg->name, lv->name);
/* FIXME specify events */
if (!monitor_fn(seg, 0)) {
log_error("%s/%s: %s segment monitoring function failed.",
lv->vg->name, lv->name, seg->segtype->name);
return 0;
}
/* Check [un]monitor results */
/* Try a couple times if pending, but not forever... */
for (i = 0; i < 10; i++) {
pending = 0;
monitored = seg->segtype->ops->target_monitored(seg, &pending);
if (pending ||
(!monitored && monitor) ||
(monitored && !monitor))
log_very_verbose("%s/%s %smonitoring still pending: waiting...",
lv->vg->name, lv->name, monitor ? "" : "un");
else
break;
sleep(1);
}
r = (monitored && monitor) || (!monitored && !monitor);
}
return r;
#else
return 1;
#endif
}
static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
int error_if_not_suspended)
{
struct logical_volume *lv;
struct logical_volume *lv, *lv_pre;
struct lvinfo info;
int lockfs = 0;
if (!activation())
return 1;
if (!(lv = lv_from_lvid(cmd, lvid_s, 0)))
return_0;
/* Use precommitted metadata if present */
if (!(lv = lv_from_lvid(cmd, lvid_s, 1)))
return 0;
if (!(lv_pre = lv_from_lvid(cmd, lvid_s, 1)))
return_0;
if (test_mode()) {
_skip("Suspending '%s'.", lv->name);
@@ -588,15 +779,23 @@ static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
return error_if_not_suspended ? 0 : 1;
/* If VG was precommitted, preload devices for the LV */
if ((lv->vg->status & PRECOMMITTED)) {
if (!_lv_preload(lv)) {
if ((lv_pre->vg->status & PRECOMMITTED)) {
if (!_lv_preload(lv_pre)) {
/* FIXME Revert preloading */
return_0;
}
}
if (!monitor_dev_for_events(cmd, lv, 0))
/* FIXME Consider aborting here */
stack;
memlock_inc();
if (!_lv_suspend_lv(lv)) {
if (lv_is_origin(lv_pre) || lv_is_cow(lv_pre))
lockfs = 1;
if (!_lv_suspend_lv(lv, lockfs)) {
memlock_dec();
fs_unlock();
return 0;
@@ -645,6 +844,9 @@ static int _lv_resume(struct cmd_context *cmd, const char *lvid_s,
memlock_dec();
fs_unlock();
if (!monitor_dev_for_events(cmd, lv, 1))
stack;
return 1;
}
@@ -688,6 +890,9 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s)
return 0;
}
if (!monitor_dev_for_events(cmd, lv, 0))
stack;
memlock_inc();
r = _lv_deactivate(lv);
memlock_dec();
@@ -758,6 +963,9 @@ static int _lv_activate(struct cmd_context *cmd, const char *lvid_s,
memlock_dec();
fs_unlock();
if (!monitor_dev_for_events(cmd, lv, 1))
stack;
return r;
}
@@ -784,7 +992,7 @@ int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv)
return r;
}
if (!_lv_info(cmd, lv, 1, &info, 0))
if (!_lv_info(cmd, lv, 1, &info, 0, 0))
return_0;
if (info.exists)
@@ -801,28 +1009,21 @@ int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv)
* Does PV use VG somewhere in its construction?
* Returns 1 on failure.
*/
int pv_uses_vg(struct cmd_context *cmd, struct physical_volume *pv,
struct volume_group *vg)
int pv_uses_vg(struct physical_volume *pv,
struct volume_group *vg)
{
struct dev_manager *dm;
int r;
if (!activation())
return 0;
if (!dm_is_dm_major(MAJOR(pv->dev->dev)))
return 0;
if (!(dm = dev_manager_create(cmd, vg->name))) {
stack;
return 1;
}
return dev_manager_device_uses_vg(pv->dev, vg);
}
r = dev_manager_device_uses_vg(dm, pv->dev, vg);
dev_manager_destroy(dm);
return r;
void activation_release(void)
{
dev_manager_release();
}
void activation_exit(void)

View File

@@ -37,7 +37,14 @@ int library_version(char *version, size_t size);
int lvm1_present(struct cmd_context *cmd);
int target_present(const char *target_name, int use_modprobe);
int target_version(const char *target_name, uint32_t *maj,
uint32_t *min, uint32_t *patchlevel);
int list_segment_modules(struct dm_pool *mem, const struct lv_segment *seg,
struct list *modules);
int list_lv_modules(struct dm_pool *mem, const struct logical_volume *lv,
struct list *modules);
void activation_release(void);
void activation_exit(void);
int lv_suspend(struct cmd_context *cmd, const char *lvid_s);
@@ -68,20 +75,30 @@ int lv_activation_filter(struct cmd_context *cmd, const char *lvid_s,
/*
* Returns 1 if percent has been set, else 0.
*/
int lv_snapshot_percent(struct logical_volume *lv, float *percent);
int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv, int wait, float *percent,
uint32_t *event_nr);
int lv_snapshot_percent(const struct logical_volume *lv, float *percent);
int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv,
int wait, float *percent, uint32_t *event_nr);
/*
* Return number of LVs in the VG that are active.
*/
int lvs_in_vg_activated(struct volume_group *vg);
int lvs_in_vg_activated_by_uuid_only(struct volume_group *vg);
int lvs_in_vg_opened(struct volume_group *vg);
int monitor_dev_for_events(struct cmd_context *cmd,
struct logical_volume *lv, int do_reg);
/*
* Returns 1 if PV has a dependency tree that uses anything in VG.
*/
int pv_uses_vg(struct cmd_context *cmd, struct physical_volume *pv,
int pv_uses_vg(struct physical_volume *pv,
struct volume_group *vg);
/*
* Returns 1 if mapped device is not suspended.
*/
int device_is_usable(dev_t dev);
#endif

View File

@@ -25,6 +25,7 @@
#include "targets.h"
#include "config.h"
#include "filter.h"
#include "activate.h"
#include <limits.h>
#include <dirent.h>
@@ -37,6 +38,7 @@ typedef enum {
ACTIVATE,
DEACTIVATE,
SUSPEND,
SUSPEND_WITH_LOCKFS,
CLEAN
} action_t;
@@ -85,7 +87,7 @@ char *build_dlid(struct dev_manager *dm, const char *lvid, const char *layer)
return _build_dlid(dm->mem, lvid, layer);
}
static inline int _read_only_lv(struct logical_volume *lv)
static int _read_only_lv(struct logical_volume *lv)
{
return (!(lv->vg->status & LVM_WRITE) || !(lv->status & LVM_WRITE));
}
@@ -116,12 +118,10 @@ static struct dm_task *_setup_task(const char *name, const char *uuid,
}
static int _info_run(const char *name, const char *dlid, struct dm_info *info,
int mknodes, int with_open_count, struct dm_pool *mem,
char **uuid_out)
int mknodes, int with_open_count)
{
int r = 0;
struct dm_task *dmt;
const char *u;
int dmtask;
dmtask = mknodes ? DM_DEVICE_MKNODES : DM_DEVICE_INFO;
@@ -141,11 +141,58 @@ static int _info_run(const char *name, const char *dlid, struct dm_info *info,
if (!dm_task_get_info(dmt, info))
goto_out;
if (info->exists && uuid_out) {
if (!(u = dm_task_get_uuid(dmt)))
goto_out;
*uuid_out = dm_pool_strdup(mem, u);
r = 1;
out:
dm_task_destroy(dmt);
return r;
}
int device_is_usable(dev_t dev)
{
struct dm_task *dmt;
struct dm_info info;
const char *name;
uint64_t start, length;
char *target_type = NULL;
char *params;
void *next = NULL;
int r = 0;
if (!(dmt = dm_task_create(DM_DEVICE_STATUS))) {
log_error("Failed to allocate dm_task struct to check dev status");
return 0;
}
if (!dm_task_set_major(dmt, MAJOR(dev)) || !dm_task_set_minor(dmt, MINOR(dev)))
goto_out;
if (!dm_task_run(dmt)) {
log_error("Failed to get state of mapped device");
goto out;
}
if (!dm_task_get_info(dmt, &info))
goto_out;
if (!info.exists || info.suspended)
goto out;
name = dm_task_get_name(dmt);
/* FIXME Also check for mirror block_on_error and mpath no paths */
/* For now, we exclude all mirrors */
do {
next = dm_get_next_target(dmt, next, &start, &length,
&target_type, &params);
/* Skip if target type doesn't match */
if (!strcmp(target_type, "mirror"))
goto out;
} while (next);
/* FIXME Also check dependencies? */
r = 1;
out:
@@ -154,23 +201,20 @@ static int _info_run(const char *name, const char *dlid, struct dm_info *info,
}
static int _info(const char *name, const char *dlid, int mknodes,
int with_open_count, struct dm_info *info,
struct dm_pool *mem, char **uuid_out)
int with_open_count, struct dm_info *info)
{
if (!mknodes && dlid && *dlid) {
if (_info_run(NULL, dlid, info, 0, with_open_count, mem,
uuid_out) &&
if (_info_run(NULL, dlid, info, 0, with_open_count) &&
info->exists)
return 1;
else if (_info_run(NULL, dlid + sizeof(UUID_PREFIX) - 1, info,
0, with_open_count, mem, uuid_out) &&
0, with_open_count) &&
info->exists)
return 1;
}
if (name)
return _info_run(name, NULL, info, mknodes, with_open_count,
mem, uuid_out);
return _info_run(name, NULL, info, mknodes, with_open_count);
return 0;
}
@@ -186,8 +230,7 @@ int dev_manager_info(struct dm_pool *mem, const char *name,
return 0;
}
return _info(name, dlid, with_mknodes, with_open_count, info,
NULL, NULL);
return _info(name, dlid, with_mknodes, with_open_count, info);
}
/* FIXME Interface must cope with multiple targets */
@@ -329,7 +372,7 @@ static int _percent_run(struct dev_manager *dm, const char *name,
if (segtype->ops->target_percent &&
!segtype->ops->target_percent(&dm->target_state, dm->mem,
dm->cmd->cft, seg, params,
dm->cmd, seg, params,
&total_numerator,
&total_denominator,
percent))
@@ -392,25 +435,21 @@ struct dev_manager *dev_manager_create(struct cmd_context *cmd,
return NULL;
}
if (!(dm = dm_pool_alloc(mem, sizeof(*dm)))) {
stack;
goto bad;
}
if (!(dm = dm_pool_alloc(mem, sizeof(*dm))))
goto_bad;
dm->cmd = cmd;
dm->mem = mem;
if (!stripe_filler) {
stripe_filler = find_config_str(cmd->cft->root,
stripe_filler = find_config_tree_str(cmd,
"activation/missing_stripe_filler",
DEFAULT_STRIPE_FILLER);
}
dm->stripe_filler = stripe_filler;
if (!(dm->vg_name = dm_pool_strdup(dm->mem, vg_name))) {
stack;
goto bad;
}
if (!(dm->vg_name = dm_pool_strdup(dm->mem, vg_name)))
goto_bad;
dm->target_state = NULL;
@@ -426,13 +465,19 @@ void dev_manager_destroy(struct dev_manager *dm)
dm_pool_destroy(dm->mem);
}
void dev_manager_release(void)
{
dm_lib_release();
}
void dev_manager_exit(void)
{
dm_lib_exit();
}
int dev_manager_snapshot_percent(struct dev_manager *dm,
struct logical_volume *lv, float *percent)
const struct logical_volume *lv,
float *percent)
{
char *name;
const char *dlid;
@@ -586,7 +631,7 @@ static int _add_dev_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
return_0;
log_debug("Getting device info for %s [%s]", name, dlid);
if (!_info(name, dlid, 0, 1, &info, dm->mem, NULL)) {
if (!_info(name, dlid, 0, 1, &info)) {
log_error("Failed to get info for %s [%s].", name, dlid);
return 0;
}
@@ -615,6 +660,9 @@ static int _add_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree, struc
if (!_add_dev_to_dtree(dm, dtree, lv, "cow"))
return_0;
if (!_add_dev_to_dtree(dm, dtree, lv, "_mlog"))
return_0;
return 1;
}
@@ -622,6 +670,8 @@ static struct dm_tree *_create_partial_dtree(struct dev_manager *dm, struct logi
{
struct dm_tree *dtree;
struct list *snh, *snht;
struct lv_segment *seg;
uint32_t s;
if (!(dtree = dm_tree_create())) {
log_error("Partial dtree creation failed for %s.", lv->name);
@@ -640,6 +690,16 @@ static struct dm_tree *_create_partial_dtree(struct dev_manager *dm, struct logi
goto fail;
}
/* Add any LVs used by segments in this LV */
list_iterate_items(seg, &lv->segments)
for (s = 0; s < seg->area_count; s++)
if (seg_type(seg, s) == AREA_LV && seg_lv(seg, s)) {
if (!_add_lv_to_dtree(dm, dtree, seg_lv(seg, s))) {
stack;
goto fail;
}
}
return dtree;
fail:
@@ -648,7 +708,8 @@ fail:
}
int add_areas_line(struct dev_manager *dm, struct lv_segment *seg,
struct dm_tree_node *node, int start_area, int areas)
struct dm_tree_node *node, uint32_t start_area,
uint32_t areas)
{
uint64_t extent_size = seg->lv->vg->extent_size;
uint32_t s;
@@ -662,7 +723,7 @@ int add_areas_line(struct dev_manager *dm, struct lv_segment *seg,
(seg_type(seg, s) == AREA_LV && !seg_lv(seg, s)))
dm_tree_node_add_target_area(node,
dm->stripe_filler,
NULL, 0);
NULL, UINT64_C(0));
else if (seg_type(seg, s) == AREA_PV)
dm_tree_node_add_target_area(node,
dev_name(seg_dev(seg, s)),
@@ -687,7 +748,6 @@ int add_areas_line(struct dev_manager *dm, struct lv_segment *seg,
}
static int _add_origin_target_to_dtree(struct dev_manager *dm,
struct dm_tree *dtree,
struct dm_tree_node *dnode,
struct logical_volume *lv)
{
@@ -703,7 +763,6 @@ static int _add_origin_target_to_dtree(struct dev_manager *dm,
}
static int _add_snapshot_target_to_dtree(struct dev_manager *dm,
struct dm_tree *dtree,
struct dm_tree_node *dnode,
struct logical_volume *lv)
{
@@ -732,7 +791,6 @@ static int _add_snapshot_target_to_dtree(struct dev_manager *dm,
}
static int _add_target_to_dtree(struct dev_manager *dm,
struct dm_tree *dtree,
struct dm_tree_node *dnode,
struct lv_segment *seg)
{
@@ -744,7 +802,7 @@ static int _add_target_to_dtree(struct dev_manager *dm,
return 0;
}
return seg->segtype->ops->add_target_line(dm, dm->mem, dm->cmd->cft,
return seg->segtype->ops->add_target_line(dm, dm->mem, dm->cmd,
&dm->target_state, seg,
dnode,
extent_size * seg->len,
@@ -762,12 +820,19 @@ static int _add_segment_to_dtree(struct dev_manager *dm,
{
uint32_t s;
struct list *snh;
struct lv_segment *seg_present;
/* Ensure required device-mapper targets are loaded */
if (seg->segtype->ops->target_present &&
!seg->segtype->ops->target_present()) {
seg_present = find_cow(seg->lv) ? : seg;
log_debug("Checking kernel supports %s segment type for %s%s%s",
seg_present->segtype->name, seg->lv->name,
layer ? "-" : "", layer ? : "");
if (seg_present->segtype->ops->target_present &&
!seg_present->segtype->ops->target_present(seg_present)) {
log_error("Can't expand LV %s: %s target support missing "
"from kernel?", seg->lv->name, seg->segtype->name);
"from kernel?", seg->lv->name, seg_present->segtype->name);
return 0;
}
@@ -797,12 +862,12 @@ static int _add_segment_to_dtree(struct dev_manager *dm,
/* Now we've added its dependencies, we can add the target itself */
if (lv_is_origin(seg->lv) && !layer) {
if (!_add_origin_target_to_dtree(dm, dtree, dnode, seg->lv))
if (!_add_origin_target_to_dtree(dm, dnode, seg->lv))
return_0;
} else if (lv_is_cow(seg->lv) && !layer) {
if (!_add_snapshot_target_to_dtree(dm, dtree, dnode, seg->lv))
if (!_add_snapshot_target_to_dtree(dm, dnode, seg->lv))
return_0;
} else if (!_add_target_to_dtree(dm, dtree, dnode, seg))
} else if (!_add_target_to_dtree(dm, dnode, seg))
return_0;
if (lv_is_origin(seg->lv) && !layer)
@@ -833,7 +898,6 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
dm_tree_node_get_context(dnode))
return 1;
/* FIXME How do we determine whether a pre-existing node need reloading or not? */
if (!(lvlayer = dm_pool_alloc(dm->mem, sizeof(*lvlayer)))) {
log_error("_add_new_lv_to_dtree: pool alloc failed for %s %s.", lv->name, layer);
return 0;
@@ -848,10 +912,10 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
* Major/minor settings only apply to the visible layer.
*/
if (!(dnode = dm_tree_add_new_dev(dtree, name, dlid,
layer ? lv->major : 0,
layer ? lv->minor : 0,
layer ? UINT32_C(0) : (uint32_t) lv->major,
layer ? UINT32_C(0) : (uint32_t) lv->minor,
_read_only_lv(lv),
lv->vg->status & PRECOMMITTED,
(lv->vg->status & PRECOMMITTED) ? 1 : 0,
lvlayer)))
return_0;
@@ -893,7 +957,7 @@ static int _create_lv_symlinks(struct dev_manager *dm, struct dm_tree_node *root
name = dm_tree_node_get_name(child);
if (name && lvlayer->old_name && *lvlayer->old_name && strcmp(name, lvlayer->old_name)) {
if (!split_dm_name(dm->mem, lvlayer->old_name, &vgname, &lvname, &layer)) {
if (!dm_split_lvm_name(dm->mem, lvlayer->old_name, &vgname, &lvname, &layer)) {
log_error("_create_lv_symlinks: Couldn't split up old device name %s", lvlayer->old_name);
return 0;
}
@@ -905,7 +969,7 @@ static int _create_lv_symlinks(struct dev_manager *dm, struct dm_tree_node *root
return r;
}
static int _clean_tree(struct dev_manager *dm, struct logical_volume *lv, struct dm_tree_node *root)
static int _clean_tree(struct dev_manager *dm, struct dm_tree_node *root)
{
void *handle = NULL;
struct dm_tree_node *child;
@@ -919,7 +983,7 @@ static int _clean_tree(struct dev_manager *dm, struct logical_volume *lv, struct
if (!(uuid = dm_tree_node_get_uuid(child)))
continue;
if (!split_dm_name(dm->mem, name, &vgname, &lvname, &layer)) {
if (!dm_split_lvm_name(dm->mem, name, &vgname, &lvname, &layer)) {
log_error("_clean_tree: Couldn't split up device name %s.", name);
return 0;
}
@@ -957,7 +1021,7 @@ static int _tree_action(struct dev_manager *dm, struct logical_volume *lv, actio
switch(action) {
case CLEAN:
/* Deactivate any unused non-toplevel nodes */
if (!_clean_tree(dm, lv, root))
if (!_clean_tree(dm, root))
goto_out;
break;
case DEACTIVATE:
@@ -966,6 +1030,10 @@ static int _tree_action(struct dev_manager *dm, struct logical_volume *lv, actio
goto_out;
break;
case SUSPEND:
dm_tree_skip_lockfs(root);
if ((lv->status & MIRRORED) && !(lv->status & PVMOVE))
dm_tree_use_no_flush_suspend(root);
case SUSPEND_WITH_LOCKFS:
if (!dm_tree_suspend_children(root, dlid, ID_LEN + sizeof(UUID_PREFIX) - 1))
goto_out;
break;
@@ -1011,6 +1079,10 @@ int dev_manager_activate(struct dev_manager *dm, struct logical_volume *lv)
int dev_manager_preload(struct dev_manager *dm, struct logical_volume *lv)
{
/* FIXME Update the pvmove implementation! */
if ((lv->status & PVMOVE) || (lv->status & LOCKED))
return 1;
return _tree_action(dm, lv, PRELOAD);
}
@@ -1025,21 +1097,22 @@ int dev_manager_deactivate(struct dev_manager *dm, struct logical_volume *lv)
return r;
}
int dev_manager_suspend(struct dev_manager *dm, struct logical_volume *lv)
int dev_manager_suspend(struct dev_manager *dm, struct logical_volume *lv,
int lockfs)
{
return _tree_action(dm, lv, SUSPEND);
return _tree_action(dm, lv, lockfs ? SUSPEND_WITH_LOCKFS : SUSPEND);
}
/*
* Does device use VG somewhere in its construction?
* Returns 1 if uncertain.
*/
int dev_manager_device_uses_vg(struct dev_manager *dm, struct device *dev,
int dev_manager_device_uses_vg(struct device *dev,
struct volume_group *vg)
{
struct dm_tree *dtree;
struct dm_tree_node *root;
char dlid[sizeof(UUID_PREFIX) + sizeof(struct id) - 1];
char dlid[sizeof(UUID_PREFIX) + sizeof(struct id) - 1] __attribute((aligned(8)));
int r = 1;
if (!(dtree = dm_tree_create())) {
@@ -1047,7 +1120,7 @@ int dev_manager_device_uses_vg(struct dev_manager *dm, struct device *dev,
return r;
}
if (!dm_tree_add_dev(dtree, MAJOR(dev->dev), MINOR(dev->dev))) {
if (!dm_tree_add_dev(dtree, (uint32_t) MAJOR(dev->dev), (uint32_t) MINOR(dev->dev))) {
log_error("Failed to add device %s (%" PRIu32 ":%" PRIu32") to dtree",
dev_name(dev), (uint32_t) MAJOR(dev->dev), (uint32_t) MINOR(dev->dev));
goto out;

View File

@@ -29,6 +29,7 @@ struct device;
struct dev_manager *dev_manager_create(struct cmd_context *cmd,
const char *vg_name);
void dev_manager_destroy(struct dev_manager *dm);
void dev_manager_release(void);
void dev_manager_exit(void);
/*
@@ -41,11 +42,13 @@ int dev_manager_info(struct dm_pool *mem, const char *name,
const struct logical_volume *lv,
int mknodes, int with_open_count, struct dm_info *info);
int dev_manager_snapshot_percent(struct dev_manager *dm,
struct logical_volume *lv, float *percent);
const struct logical_volume *lv,
float *percent);
int dev_manager_mirror_percent(struct dev_manager *dm,
struct logical_volume *lv, int wait,
float *percent, uint32_t *event_nr);
int dev_manager_suspend(struct dev_manager *dm, struct logical_volume *lv);
int dev_manager_suspend(struct dev_manager *dm, struct logical_volume *lv,
int lockfs);
int dev_manager_activate(struct dev_manager *dm, struct logical_volume *lv);
int dev_manager_preload(struct dev_manager *dm, struct logical_volume *lv);
int dev_manager_deactivate(struct dev_manager *dm, struct logical_volume *lv);
@@ -58,7 +61,7 @@ int dev_manager_lv_rmnodes(const struct logical_volume *lv);
*/
int dev_manager_execute(struct dev_manager *dm);
int dev_manager_device_uses_vg(struct dev_manager *dm, struct device *dev,
int dev_manager_device_uses_vg(struct device *dev,
struct volume_group *vg);
#endif

View File

@@ -30,7 +30,7 @@ static int _mk_dir(const char *dev_dir, const char *vg_name)
{
char vg_path[PATH_MAX];
if (lvm_snprintf(vg_path, sizeof(vg_path), "%s%s",
if (dm_snprintf(vg_path, sizeof(vg_path), "%s%s",
dev_dir, vg_name) == -1) {
log_error("Couldn't construct name of volume "
"group directory.");
@@ -53,7 +53,7 @@ static int _rm_dir(const char *dev_dir, const char *vg_name)
{
char vg_path[PATH_MAX];
if (lvm_snprintf(vg_path, sizeof(vg_path), "%s%s",
if (dm_snprintf(vg_path, sizeof(vg_path), "%s%s",
dev_dir, vg_name) == -1) {
log_error("Couldn't construct name of volume "
"group directory.");
@@ -87,7 +87,7 @@ static void _rm_blks(const char *dir)
if (!strcmp(name, ".") || !strcmp(name, ".."))
continue;
if (lvm_snprintf(path, sizeof(path), "%s/%s", dir, name) == -1) {
if (dm_snprintf(path, sizeof(path), "%s/%s", dir, name) == -1) {
log_error("Couldn't create path for %s", name);
continue;
}
@@ -109,28 +109,28 @@ static int _mk_link(const char *dev_dir, const char *vg_name,
char vg_path[PATH_MAX];
struct stat buf;
if (lvm_snprintf(vg_path, sizeof(vg_path), "%s%s",
if (dm_snprintf(vg_path, sizeof(vg_path), "%s%s",
dev_dir, vg_name) == -1) {
log_error("Couldn't create path for volume group dir %s",
vg_name);
return 0;
}
if (lvm_snprintf(lv_path, sizeof(lv_path), "%s/%s", vg_path,
if (dm_snprintf(lv_path, sizeof(lv_path), "%s/%s", vg_path,
lv_name) == -1) {
log_error("Couldn't create source pathname for "
"logical volume link %s", lv_name);
return 0;
}
if (lvm_snprintf(link_path, sizeof(link_path), "%s/%s",
if (dm_snprintf(link_path, sizeof(link_path), "%s/%s",
dm_dir(), dev) == -1) {
log_error("Couldn't create destination pathname for "
"logical volume link for %s", lv_name);
return 0;
}
if (lvm_snprintf(lvm1_group_path, sizeof(lvm1_group_path), "%s/group",
if (dm_snprintf(lvm1_group_path, sizeof(lvm1_group_path), "%s/group",
vg_path) == -1) {
log_error("Couldn't create pathname for LVM1 group file for %s",
vg_name);
@@ -190,7 +190,7 @@ static int _rm_link(const char *dev_dir, const char *vg_name,
struct stat buf;
char lv_path[PATH_MAX];
if (lvm_snprintf(lv_path, sizeof(lv_path), "%s%s/%s",
if (dm_snprintf(lv_path, sizeof(lv_path), "%s%s/%s",
dev_dir, vg_name, lv_name) == -1) {
log_error("Couldn't determine link pathname.");
return 0;

View File

@@ -24,7 +24,7 @@ int compose_areas_line(struct dev_manager *dm, struct lv_segment *seg,
int start_area, int areas);
int add_areas_line(struct dev_manager *dm, struct lv_segment *seg,
struct dm_tree_node *node, int start_area, int areas);
struct dm_tree_node *node, uint32_t start_area, uint32_t areas);
int build_dev_string(struct dev_manager *dm, char *dlid, char *devbuf,
size_t bufsize, const char *desc);

385
lib/cache/lvmcache.c vendored
View File

@@ -50,7 +50,7 @@ int lvmcache_init(void)
return 1;
}
void lvmcache_lock_vgname(const char *vgname, int read_only)
void lvmcache_lock_vgname(const char *vgname, int read_only __attribute((unused)))
{
if (!_lock_hash && !lvmcache_init()) {
log_error("Internal cache initialisation failed");
@@ -86,7 +86,8 @@ int vgs_locked(void)
return _vgs_locked;
}
struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname)
/* If vgid supplied, require a match. */
struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname, const char *vgid)
{
struct lvmcache_vginfo *vginfo;
@@ -96,10 +97,16 @@ struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname)
if (!(vginfo = dm_hash_lookup(_vgname_hash, vgname)))
return NULL;
if (vgid)
do
if (!strncmp(vgid, vginfo->vgid, ID_LEN))
return vginfo;
while ((vginfo = vginfo->next));
return vginfo;
}
const struct format_type *fmt_from_vgname(const char *vgname)
const struct format_type *fmt_from_vgname(const char *vgname, const char *vgid)
{
struct lvmcache_vginfo *vginfo;
struct lvmcache_info *info;
@@ -107,33 +114,44 @@ const struct format_type *fmt_from_vgname(const char *vgname)
struct list *devh, *tmp;
struct list devs;
struct device_list *devl;
char vgid_found[ID_LEN + 1] __attribute((aligned(8)));
if (!(vginfo = vginfo_from_vgname(vgname)))
if (!(vginfo = vginfo_from_vgname(vgname, vgid)))
return NULL;
/* This function is normally called before reading metadata so
* we check cached labels here. Unfortunately vginfo is volatile. */
list_init(&devs);
list_iterate_items(info, &vginfo->infos) {
devl = dm_malloc(sizeof(*devl));
if (!(devl = dm_malloc(sizeof(*devl)))) {
log_error("device_list element allocation failed");
return NULL;
}
devl->dev = info->dev;
list_add(&devs, &devl->list);
}
memcpy(vgid_found, vginfo->vgid, sizeof(vgid_found));
list_iterate_safe(devh, tmp, &devs) {
devl = list_item(devh, struct device_list);
label_read(devl->dev, &label);
label_read(devl->dev, &label, UINT64_C(0));
list_del(&devl->list);
dm_free(devl);
}
/* If vginfo changed, caller needs to rescan */
if (!(vginfo = vginfo_from_vgname(vgname, vgid_found)) ||
strncmp(vginfo->vgid, vgid_found, ID_LEN))
return NULL;
return vginfo->fmt;
}
struct lvmcache_vginfo *vginfo_from_vgid(const char *vgid)
{
struct lvmcache_vginfo *vginfo;
char id[ID_LEN + 1];
char id[ID_LEN + 1] __attribute((aligned(8)));
if (!_vgid_hash || !vgid)
return NULL;
@@ -148,10 +166,27 @@ struct lvmcache_vginfo *vginfo_from_vgid(const char *vgid)
return vginfo;
}
const char *vgname_from_vgid(struct dm_pool *mem, const char *vgid)
{
struct lvmcache_vginfo *vginfo;
const char *vgname = NULL;
if (!*vgid)
vgname = ORPHAN;
if ((vginfo = vginfo_from_vgid(vgid)))
vgname = vginfo->vgname;
if (mem && vgname)
return dm_pool_strdup(mem, vgname);
return vgname;
}
struct lvmcache_info *info_from_pvid(const char *pvid)
{
struct lvmcache_info *info;
char id[ID_LEN + 1];
char id[ID_LEN + 1] __attribute((aligned(8)));
if (!_pvid_hash || !pvid)
return NULL;
@@ -170,7 +205,7 @@ static void _rescan_entry(struct lvmcache_info *info)
struct label *label;
if (info->status & CACHE_INVALID)
label_read(info->dev, &label);
label_read(info->dev, &label, UINT64_C(0));
}
static int _scan_invalid(void)
@@ -206,13 +241,13 @@ int lvmcache_label_scan(struct cmd_context *cmd, int full_scan)
goto out;
}
if (!(iter = dev_iter_create(cmd->filter, (full_scan == 2) ? 1: 0))) {
if (!(iter = dev_iter_create(cmd->filter, (full_scan == 2) ? 1 : 0))) {
log_error("dev_iter creation failed");
goto out;
}
while ((dev = dev_iter_get(iter)))
label_read(dev, &label);
label_read(dev, &label, UINT64_C(0));
dev_iter_destroy(iter);
@@ -232,10 +267,33 @@ int lvmcache_label_scan(struct cmd_context *cmd, int full_scan)
return r;
}
struct list *lvmcache_get_vgids(struct cmd_context *cmd, int full_scan)
{
struct list *vgids;
struct lvmcache_vginfo *vginfo;
lvmcache_label_scan(cmd, full_scan);
if (!(vgids = str_list_create(cmd->mem))) {
log_error("vgids list allocation failed");
return NULL;
}
list_iterate_items(vginfo, &_vginfos) {
if (!str_list_add(cmd->mem, vgids,
dm_pool_strdup(cmd->mem, vginfo->vgid))) {
log_error("strlist allocation failed");
return NULL;
}
}
return vgids;
}
struct list *lvmcache_get_vgnames(struct cmd_context *cmd, int full_scan)
{
struct list *vgnames;
struct lvmcache_vginfo *vgi;
struct lvmcache_vginfo *vginfo;
lvmcache_label_scan(cmd, full_scan);
@@ -244,9 +302,9 @@ struct list *lvmcache_get_vgnames(struct cmd_context *cmd, int full_scan)
return NULL;
}
list_iterate_items(vgi, &_vginfos) {
list_iterate_items(vginfo, &_vginfos) {
if (!str_list_add(cmd->mem, vgnames,
dm_pool_strdup(cmd->mem, vgi->vgname))) {
dm_pool_strdup(cmd->mem, vginfo->vgname))) {
log_error("strlist allocation failed");
return NULL;
}
@@ -255,6 +313,32 @@ struct list *lvmcache_get_vgnames(struct cmd_context *cmd, int full_scan)
return vgnames;
}
struct list *lvmcache_get_pvids(struct cmd_context *cmd, const char *vgname,
const char *vgid)
{
struct list *pvids;
struct lvmcache_vginfo *vginfo;
struct lvmcache_info *info;
if (!(pvids = str_list_create(cmd->mem))) {
log_error("pvids list allocation failed");
return NULL;
}
if (!(vginfo = vginfo_from_vgname(vgname, vgid)))
return pvids;
list_iterate_items(info, &vginfo->infos) {
if (!str_list_add(cmd->mem, pvids,
dm_pool_strdup(cmd->mem, info->dev->pvid))) {
log_error("strlist allocation failed");
return NULL;
}
}
return pvids;
}
struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid)
{
struct label *label;
@@ -262,7 +346,7 @@ struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid)
/* Already cached ? */
if ((info = info_from_pvid((char *) pvid))) {
if (label_read(info->dev, &label)) {
if (label_read(info->dev, &label, UINT64_C(0))) {
info = (struct lvmcache_info *) label->info;
if (id_equal(pvid, (struct id *) &info->dev->pvid))
return info->dev;
@@ -273,7 +357,7 @@ struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid)
/* Try again */
if ((info = info_from_pvid((char *) pvid))) {
if (label_read(info->dev, &label)) {
if (label_read(info->dev, &label, UINT64_C(0))) {
info = (struct lvmcache_info *) label->info;
if (id_equal(pvid, (struct id *) &info->dev->pvid))
return info->dev;
@@ -287,7 +371,7 @@ struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid)
/* Try again */
if ((info = info_from_pvid((char *) pvid))) {
if (label_read(info->dev, &label)) {
if (label_read(info->dev, &label, UINT64_C(0))) {
info = (struct lvmcache_info *) label->info;
if (id_equal(pvid, (struct id *) &info->dev->pvid))
return info->dev;
@@ -297,7 +381,7 @@ struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid)
return NULL;
}
static void _drop_vginfo(struct lvmcache_info *info)
static int _drop_vginfo(struct lvmcache_info *info)
{
if (!list_empty(&info->list)) {
list_del(&info->list);
@@ -306,8 +390,18 @@ static void _drop_vginfo(struct lvmcache_info *info)
if (info->vginfo && list_empty(&info->vginfo->infos)) {
dm_hash_remove(_vgname_hash, info->vginfo->vgname);
if (info->vginfo->next) {
if (!dm_hash_insert(_vgname_hash, info->vginfo->vgname, info->vginfo->next)) {
log_error("vg hash re-insertion failed: %s",
info->vginfo->vgname);
return 0;
}
}
if (info->vginfo->vgname)
dm_free(info->vginfo->vgname);
if (info->vginfo->creation_host)
dm_free(info->vginfo->creation_host);
if (*info->vginfo->vgid)
dm_hash_remove(_vgid_hash, info->vginfo->vgid);
list_del(&info->vginfo->list);
@@ -315,6 +409,8 @@ static void _drop_vginfo(struct lvmcache_info *info)
}
info->vginfo = NULL;
return 1;
}
/* Unused
@@ -350,36 +446,130 @@ static int _lvmcache_update_pvid(struct lvmcache_info *info, const char *pvid)
static int _lvmcache_update_vgid(struct lvmcache_info *info, const char *vgid)
{
if (!vgid || !info->vginfo || !strncmp(info->vginfo->vgid, vgid,
sizeof(info->vginfo->vgid)))
if (!vgid || !info->vginfo ||
!strncmp(info->vginfo->vgid, vgid, ID_LEN))
return 1;
if (info->vginfo && *info->vginfo->vgid)
dm_hash_remove(_vgid_hash, info->vginfo->vgid);
if (!vgid)
if (!vgid) {
log_debug("lvmcache: %s: clearing VGID", dev_name(info->dev));
return 1;
}
strncpy(info->vginfo->vgid, vgid, sizeof(info->vginfo->vgid));
info->vginfo->vgid[sizeof(info->vginfo->vgid) - 1] = '\0';
strncpy(info->vginfo->vgid, vgid, ID_LEN);
info->vginfo->vgid[ID_LEN] = '\0';
if (!dm_hash_insert(_vgid_hash, info->vginfo->vgid, info->vginfo)) {
log_error("_lvmcache_update: vgid hash insertion failed: %s",
info->vginfo->vgid);
return 0;
}
log_debug("lvmcache: %s: setting %s VGID to %s", dev_name(info->dev),
info->vginfo->vgname, info->vginfo->vgid);
return 1;
}
int lvmcache_update_vgname(struct lvmcache_info *info, const char *vgname)
static int _insert_vginfo(struct lvmcache_vginfo *new_vginfo, const char *vgid,
uint32_t vgstatus, const char *creation_host,
struct lvmcache_vginfo *primary_vginfo)
{
struct lvmcache_vginfo *vginfo;
struct lvmcache_vginfo *last_vginfo = primary_vginfo;
char uuid_primary[64] __attribute((aligned(8)));
char uuid_new[64] __attribute((aligned(8)));
int use_new = 0;
/* Pre-existing VG takes precedence. Unexported VG takes precedence. */
if (primary_vginfo) {
if (!id_write_format((const struct id *)vgid, uuid_new, sizeof(uuid_new)))
return_0;
if (!id_write_format((const struct id *)&primary_vginfo->vgid, uuid_primary,
sizeof(uuid_primary)))
return_0;
/*
* If Primary not exported, new exported => keep
* Else Primary exported, new not exported => change
* Else Primary has hostname for this machine => keep
* Else Primary has no hostname, new has one => change
* Else New has hostname for this machine => change
* Else Keep primary.
*/
if (!(primary_vginfo->status & EXPORTED_VG) &&
(vgstatus & EXPORTED_VG))
log_error("WARNING: Duplicate VG name %s: "
"Existing %s takes precedence over "
"exported %s", new_vginfo->vgname,
uuid_primary, uuid_new);
else if ((primary_vginfo->status & EXPORTED_VG) &&
!(vgstatus & EXPORTED_VG)) {
log_error("WARNING: Duplicate VG name %s: "
"%s takes precedence over exported %s",
new_vginfo->vgname, uuid_new,
uuid_primary);
use_new = 1;
} else if (primary_vginfo->creation_host &&
!strcmp(primary_vginfo->creation_host,
primary_vginfo->fmt->cmd->hostname))
log_error("WARNING: Duplicate VG name %s: "
"Existing %s (created here) takes precedence "
"over %s", new_vginfo->vgname, uuid_primary,
uuid_new);
else if (!primary_vginfo->creation_host && creation_host) {
log_error("WARNING: Duplicate VG name %s: "
"%s (with creation_host) takes precedence over %s",
new_vginfo->vgname, uuid_new,
uuid_primary);
use_new = 1;
} else if (creation_host &&
!strcmp(creation_host,
primary_vginfo->fmt->cmd->hostname)) {
log_error("WARNING: Duplicate VG name %s: "
"%s (created here) takes precedence over %s",
new_vginfo->vgname, uuid_new,
uuid_primary);
use_new = 1;
}
if (!use_new) {
while (last_vginfo->next)
last_vginfo = last_vginfo->next;
last_vginfo->next = new_vginfo;
return 1;
}
dm_hash_remove(_vgname_hash, primary_vginfo->vgname);
}
if (!dm_hash_insert(_vgname_hash, new_vginfo->vgname, new_vginfo)) {
log_error("cache_update: vg hash insertion failed: %s",
new_vginfo->vgname);
return 0;
}
if (primary_vginfo)
new_vginfo->next = primary_vginfo;
return 1;
}
static int _lvmcache_update_vgname(struct lvmcache_info *info,
const char *vgname, const char *vgid,
uint32_t vgstatus, const char *creation_host)
{
struct lvmcache_vginfo *vginfo, *primary_vginfo;
// struct lvmcache_vginfo *old_vginfo, *next;
/* If vgname is NULL and we don't already have a vgname,
* assume ORPHAN - we want every entry to have a vginfo
* attached for scanning reasons.
*/
if (!vgname && !info->vginfo)
if (!vgname && !info->vginfo) {
vgname = ORPHAN;
vgid = ORPHAN;
}
if (!vgname || (info->vginfo && !strcmp(info->vginfo->vgname, vgname)))
return 1;
@@ -388,7 +578,43 @@ int lvmcache_update_vgname(struct lvmcache_info *info, const char *vgname)
_drop_vginfo(info);
/* Get existing vginfo or create new one */
if (!(vginfo = vginfo_from_vgname(vgname))) {
if (!(vginfo = vginfo_from_vgname(vgname, vgid))) {
/*** FIXME - vginfo ends up duplicated instead of renamed.
// Renaming? This lookup fails.
if ((vginfo = vginfo_from_vgid(vgid))) {
next = vginfo->next;
old_vginfo = vginfo_from_vgname(vginfo->vgname, NULL);
if (old_vginfo == vginfo) {
dm_hash_remove(_vgname_hash, old_vginfo->vgname);
if (old_vginfo->next) {
if (!dm_hash_insert(_vgname_hash, old_vginfo->vgname, old_vginfo->next)) {
log_error("vg hash re-insertion failed: %s",
old_vginfo->vgname);
return 0;
}
}
} else do {
if (old_vginfo->next == vginfo) {
old_vginfo->next = vginfo->next;
break;
}
} while ((old_vginfo = old_vginfo->next));
vginfo->next = NULL;
dm_free(vginfo->vgname);
if (!(vginfo->vgname = dm_strdup(vgname))) {
log_error("cache vgname alloc failed for %s", vgname);
return 0;
}
// Rename so can assume new name does not already exist
if (!dm_hash_insert(_vgname_hash, vginfo->vgname, vginfo->next)) {
log_error("vg hash re-insertion failed: %s",
vginfo->vgname);
return 0;
}
} else {
***/
if (!(vginfo = dm_malloc(sizeof(*vginfo)))) {
log_error("lvmcache_update_vgname: list alloc failed");
return 0;
@@ -400,9 +626,9 @@ int lvmcache_update_vgname(struct lvmcache_info *info, const char *vgname)
return 0;
}
list_init(&vginfo->infos);
if (!dm_hash_insert(_vgname_hash, vginfo->vgname, vginfo)) {
log_error("cache_update: vg hash insertion failed: %s",
vginfo->vgname);
primary_vginfo = vginfo_from_vgname(vgname, NULL);
if (!_insert_vginfo(vginfo, vgid, vgstatus, creation_host,
primary_vginfo)) {
dm_free(vginfo->vgname);
dm_free(vginfo);
return 0;
@@ -412,6 +638,9 @@ int lvmcache_update_vgname(struct lvmcache_info *info, const char *vgname)
list_add(&_vginfos, &vginfo->list);
else
list_add_h(&_vginfos, &vginfo->list);
/***
}
***/
}
info->vginfo = vginfo;
@@ -420,8 +649,59 @@ int lvmcache_update_vgname(struct lvmcache_info *info, const char *vgname)
/* FIXME Check consistency of list! */
vginfo->fmt = info->fmt;
log_debug("lvmcache: %s now %s%s", dev_name(info->dev),
*vgname ? "in VG " : "orphaned", vgname);
log_debug("lvmcache: %s: now %s%s%s%s%s", dev_name(info->dev),
*vgname ? "in VG " : "orphaned", vgname,
vginfo->vgid[0] ? " (" : "",
vginfo->vgid[0] ? vginfo->vgid : "",
vginfo->vgid[0] ? ")" : "");
return 1;
}
static int _lvmcache_update_vgstatus(struct lvmcache_info *info, uint32_t vgstatus,
const char *creation_host)
{
if (!info || !info->vginfo)
return 1;
if ((info->vginfo->status & EXPORTED_VG) != (vgstatus & EXPORTED_VG))
log_debug("lvmcache: %s: VG %s %s exported",
dev_name(info->dev), info->vginfo->vgname,
vgstatus & EXPORTED_VG ? "now" : "no longer");
info->vginfo->status = vgstatus;
if (!creation_host)
return 1;
if (info->vginfo->creation_host && !strcmp(creation_host,
info->vginfo->creation_host))
return 1;
if (info->vginfo->creation_host)
dm_free(info->vginfo->creation_host);
if (!(info->vginfo->creation_host = dm_strdup(creation_host))) {
log_error("cache creation host alloc failed for %s",
creation_host);
return 0;
}
log_debug("lvmcache: %s: VG %s: Set creation host to %s.",
dev_name(info->dev), info->vginfo->vgname, creation_host);
return 1;
}
int lvmcache_update_vgname_and_id(struct lvmcache_info *info,
const char *vgname, const char *vgid,
uint32_t vgstatus, const char *creation_host)
{
if (!_lvmcache_update_vgname(info, vgname, vgid, vgstatus,
creation_host) ||
!_lvmcache_update_vgid(info, vgid) ||
!_lvmcache_update_vgstatus(info, vgstatus, creation_host))
return_0;
return 1;
}
@@ -430,21 +710,18 @@ int lvmcache_update_vg(struct volume_group *vg)
{
struct pv_list *pvl;
struct lvmcache_info *info;
char pvid_s[ID_LEN + 1];
int vgid_updated = 0;
char pvid_s[ID_LEN + 1] __attribute((aligned(8)));
pvid_s[sizeof(pvid_s) - 1] = '\0';
list_iterate_items(pvl, &vg->pvs) {
strncpy(pvid_s, (char *) &pvl->pv->id, sizeof(pvid_s) - 1);
/* FIXME Could pvl->pv->dev->pvid ever be different? */
if ((info = info_from_pvid(pvid_s))) {
lvmcache_update_vgname(info, vg->name);
if (!vgid_updated) {
_lvmcache_update_vgid(info, (char *) &vg->id);
vgid_updated = 1;
}
}
if ((info = info_from_pvid(pvid_s)) &&
!lvmcache_update_vgname_and_id(info, vg->name,
(char *) &vg->id,
vg->status, NULL))
return_0;
}
return 1;
@@ -452,11 +729,12 @@ int lvmcache_update_vg(struct volume_group *vg)
struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
struct device *dev,
const char *vgname, const char *vgid)
const char *vgname, const char *vgid,
uint32_t vgstatus)
{
struct label *label;
struct lvmcache_info *existing, *info;
char pvid_s[ID_LEN + 1];
char pvid_s[ID_LEN + 1] __attribute((aligned(8)));
if (!_vgname_hash && !lvmcache_init()) {
log_error("Internal cache initialisation failed");
@@ -548,7 +826,7 @@ struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
return NULL;
}
if (!lvmcache_update_vgname(info, vgname)) {
if (!lvmcache_update_vgname_and_id(info, vgname, vgid, vgstatus, NULL)) {
if (!existing) {
dm_hash_remove(_pvid_hash, pvid_s);
strcpy(info->dev->pvid, "");
@@ -558,10 +836,6 @@ struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
return NULL;
}
if (!_lvmcache_update_vgid(info, vgid))
/* Non-critical */
stack;
return info;
}
@@ -576,12 +850,19 @@ static void _lvmcache_destroy_entry(struct lvmcache_info *info)
static void _lvmcache_destroy_vgnamelist(struct lvmcache_vginfo *vginfo)
{
if (vginfo->vgname)
dm_free(vginfo->vgname);
dm_free(vginfo);
struct lvmcache_vginfo *next;
do {
next = vginfo->next;
if (vginfo->vgname)
dm_free(vginfo->vgname);
if (vginfo->creation_host)
dm_free(vginfo->creation_host);
dm_free(vginfo);
} while ((vginfo = next));
}
static void _lvmcache_destroy_lockname(int present)
static void _lvmcache_destroy_lockname(int present __attribute((unused)))
{
/* Nothing to do */
}

26
lib/cache/lvmcache.h vendored
View File

@@ -33,15 +33,20 @@ struct cmd_context;
struct format_type;
struct volume_group;
/* One per VG */
struct lvmcache_vginfo {
struct list list; /* Join these vginfos together */
struct list infos; /* List head for lvmcache_infos */
const struct format_type *fmt;
char *vgname; /* "" == orphan */
uint32_t status;
char vgid[ID_LEN + 1];
char _padding[7];
struct lvmcache_vginfo *next; /* Another VG with same name? */
char *creation_host;
};
/* One per device */
struct lvmcache_info {
struct list list; /* Join VG members together */
struct list mdas; /* list head for metadata areas */
@@ -64,21 +69,26 @@ int lvmcache_label_scan(struct cmd_context *cmd, int full_scan);
/* Add/delete a device */
struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
struct device *dev,
const char *vgname, const char *vgid);
const char *vgname, const char *vgid,
uint32_t vgstatus);
void lvmcache_del(struct lvmcache_info *info);
/* Update things */
int lvmcache_update_vgname(struct lvmcache_info *info, const char *vgname);
int lvmcache_update_vgname_and_id(struct lvmcache_info *info,
const char *vgname, const char *vgid,
uint32_t vgstatus, const char *hostname);
int lvmcache_update_vg(struct volume_group *vg);
void lvmcache_lock_vgname(const char *vgname, int read_only);
void lvmcache_unlock_vgname(const char *vgname);
/* Queries */
const struct format_type *fmt_from_vgname(const char *vgname);
struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname);
const struct format_type *fmt_from_vgname(const char *vgname, const char *vgid);
struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname,
const char *vgid);
struct lvmcache_vginfo *vginfo_from_vgid(const char *vgid);
struct lvmcache_info *info_from_pvid(const char *pvid);
const char *vgname_from_vgid(struct dm_pool *mem, const char *vgid);
struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid);
int vgs_locked(void);
int vgname_is_locked(const char *vgname);
@@ -87,4 +97,12 @@ int vgname_is_locked(const char *vgname);
/* Set full_scan to 1 to reread every filtered device label */
struct list *lvmcache_get_vgnames(struct cmd_context *cmd, int full_scan);
/* Returns list of struct str_lists containing pool-allocated copy of vgids */
/* Set full_scan to 1 to reread every filtered device label */
struct list *lvmcache_get_vgids(struct cmd_context *cmd, int full_scan);
/* Returns list of struct str_lists containing pool-allocated copy of pvids */
struct list *lvmcache_get_pvids(struct cmd_context *cmd, const char *vgname,
const char *vgid);
#endif

View File

@@ -59,15 +59,13 @@
# include <malloc.h>
#endif
static FILE *_log;
static int _get_env_vars(struct cmd_context *cmd)
{
const char *e;
/* Set to "" to avoid using any system directory */
if ((e = getenv("LVM_SYSTEM_DIR"))) {
if (lvm_snprintf(cmd->sys_dir, sizeof(cmd->sys_dir),
if (dm_snprintf(cmd->sys_dir, sizeof(cmd->sys_dir),
"%s", e) < 0) {
log_error("LVM_SYSTEM_DIR environment variable "
"is too long.");
@@ -84,10 +82,11 @@ static void _init_logging(struct cmd_context *cmd)
time_t t;
const char *log_file;
char timebuf[26];
/* Syslog */
cmd->default_settings.syslog =
find_config_int(cmd->cft->root, "log/syslog", DEFAULT_SYSLOG);
find_config_tree_int(cmd, "log/syslog", DEFAULT_SYSLOG);
if (cmd->default_settings.syslog != 1)
fin_syslog();
@@ -96,37 +95,37 @@ static void _init_logging(struct cmd_context *cmd)
/* Debug level for log file output */
cmd->default_settings.debug =
find_config_int(cmd->cft->root, "log/level", DEFAULT_LOGLEVEL);
find_config_tree_int(cmd, "log/level", DEFAULT_LOGLEVEL);
init_debug(cmd->default_settings.debug);
/* Verbose level for tty output */
cmd->default_settings.verbose =
find_config_int(cmd->cft->root, "log/verbose", DEFAULT_VERBOSE);
find_config_tree_int(cmd, "log/verbose", DEFAULT_VERBOSE);
init_verbose(cmd->default_settings.verbose + VERBOSE_BASE_LEVEL);
/* Log message formatting */
init_indent(find_config_int(cmd->cft->root, "log/indent",
init_indent(find_config_tree_int(cmd, "log/indent",
DEFAULT_INDENT));
cmd->default_settings.msg_prefix = find_config_str(cmd->cft->root,
cmd->default_settings.msg_prefix = find_config_tree_str(cmd,
"log/prefix",
DEFAULT_MSG_PREFIX);
init_msg_prefix(cmd->default_settings.msg_prefix);
cmd->default_settings.cmd_name = find_config_int(cmd->cft->root,
cmd->default_settings.cmd_name = find_config_tree_int(cmd,
"log/command_names",
DEFAULT_CMD_NAME);
init_cmd_name(cmd->default_settings.cmd_name);
/* Test mode */
cmd->default_settings.test =
find_config_int(cmd->cft->root, "global/test", 0);
find_config_tree_int(cmd, "global/test", 0);
/* Settings for logging to file */
if (find_config_int(cmd->cft->root, "log/overwrite", DEFAULT_OVERWRITE))
if (find_config_tree_int(cmd, "log/overwrite", DEFAULT_OVERWRITE))
append = 0;
log_file = find_config_str(cmd->cft->root, "log/file", 0);
log_file = find_config_tree_str(cmd, "log/file", 0);
if (log_file) {
release_log_memory();
@@ -134,15 +133,17 @@ static void _init_logging(struct cmd_context *cmd)
init_log_file(log_file, append);
}
log_file = find_config_str(cmd->cft->root, "log/activate_file", 0);
log_file = find_config_tree_str(cmd, "log/activate_file", 0);
if (log_file)
init_log_direct(log_file, append);
init_log_while_suspended(find_config_int(cmd->cft->root,
init_log_while_suspended(find_config_tree_int(cmd,
"log/activation", 0));
t = time(NULL);
log_verbose("Logging initialised at %s", ctime(&t));
ctime_r(&t, &timebuf[0]);
timebuf[24] = '\0';
log_verbose("Logging initialised at %s", timebuf);
/* Tell device-mapper about our logging */
#ifdef DEVMAPPER_SUPPORT
@@ -155,7 +156,7 @@ static int _process_config(struct cmd_context *cmd)
mode_t old_umask;
/* umask */
cmd->default_settings.umask = find_config_int(cmd->cft->root,
cmd->default_settings.umask = find_config_tree_int(cmd,
"global/umask",
DEFAULT_UMASK);
@@ -164,8 +165,8 @@ static int _process_config(struct cmd_context *cmd)
log_verbose("Set umask to %04o", cmd->default_settings.umask);
/* dev dir */
if (lvm_snprintf(cmd->dev_dir, sizeof(cmd->dev_dir), "%s/",
find_config_str(cmd->cft->root, "devices/dir",
if (dm_snprintf(cmd->dev_dir, sizeof(cmd->dev_dir), "%s/",
find_config_tree_str(cmd, "devices/dir",
DEFAULT_DEV_DIR)) < 0) {
log_error("Device directory given in config file too long");
return 0;
@@ -175,8 +176,8 @@ static int _process_config(struct cmd_context *cmd)
#endif
/* proc dir */
if (lvm_snprintf(cmd->proc_dir, sizeof(cmd->proc_dir), "%s",
find_config_str(cmd->cft->root, "global/proc",
if (dm_snprintf(cmd->proc_dir, sizeof(cmd->proc_dir), "%s",
find_config_tree_str(cmd, "global/proc",
DEFAULT_PROC_DIR)) < 0) {
log_error("Device directory given in config file too long");
return 0;
@@ -189,17 +190,17 @@ static int _process_config(struct cmd_context *cmd)
}
/* activation? */
cmd->default_settings.activation = find_config_int(cmd->cft->root,
cmd->default_settings.activation = find_config_tree_int(cmd,
"global/activation",
DEFAULT_ACTIVATION);
set_activation(cmd->default_settings.activation);
cmd->default_settings.suffix = find_config_int(cmd->cft->root,
cmd->default_settings.suffix = find_config_tree_int(cmd,
"global/suffix",
DEFAULT_SUFFIX);
if (!(cmd->default_settings.unit_factor =
units_to_bytes(find_config_str(cmd->cft->root,
units_to_bytes(find_config_tree_str(cmd,
"global/units",
DEFAULT_UNITS),
&cmd->default_settings.unit_type))) {
@@ -316,7 +317,7 @@ static int _load_config_file(struct cmd_context *cmd, const char *tag)
if (*tag)
filler = "_";
if (lvm_snprintf(config_file, sizeof(config_file), "%s/lvm%s%s.conf",
if (dm_snprintf(config_file, sizeof(config_file), "%s/lvm%s%s.conf",
cmd->sys_dir, filler, tag) < 0) {
log_error("LVM_SYSTEM_DIR or tag was too long");
return 0;
@@ -327,7 +328,7 @@ static int _load_config_file(struct cmd_context *cmd, const char *tag)
return 0;
}
if (!(cfl->cft = create_config_tree(config_file))) {
if (!(cfl->cft = create_config_tree(config_file, 0))) {
log_error("config_tree allocation failed");
return 0;
}
@@ -367,7 +368,7 @@ static int _init_lvm_conf(struct cmd_context *cmd)
{
/* No config file if LVM_SYSTEM_DIR is empty */
if (!*cmd->sys_dir) {
if (!(cmd->cft = create_config_tree(NULL))) {
if (!(cmd->cft = create_config_tree(NULL, 0))) {
log_error("Failed to create config tree");
return 0;
}
@@ -405,7 +406,7 @@ static int _merge_config_files(struct cmd_context *cmd)
/* Replace temporary duplicate copy of lvm.conf */
if (cmd->cft->root) {
if (!(cmd->cft = create_config_tree(NULL))) {
if (!(cmd->cft = create_config_tree(NULL, 0))) {
log_error("Failed to create config tree");
return 0;
}
@@ -464,12 +465,10 @@ static int _init_dev_cache(struct cmd_context *cmd)
const struct config_node *cn;
struct config_value *cv;
if (!dev_cache_init()) {
stack;
return 0;
}
if (!dev_cache_init(cmd))
return_0;
if (!(cn = find_config_node(cmd->cft->root, "devices/scan"))) {
if (!(cn = find_config_tree_node(cmd, "devices/scan"))) {
if (!dev_cache_add_dir("/dev")) {
log_error("Failed to add /dev to internal "
"device cache");
@@ -494,7 +493,7 @@ static int _init_dev_cache(struct cmd_context *cmd)
}
}
if (!(cn = find_config_node(cmd->cft->root, "devices/loopfiles")))
if (!(cn = find_config_tree_node(cmd, "devices/loopfiles")))
return 1;
for (cv = cn->v; cv; cv = cv->next) {
@@ -536,14 +535,14 @@ static struct dev_filter *_init_filter_components(struct cmd_context *cmd)
* Listed first because it's very efficient at eliminating
* unavailable devices.
*/
if (find_config_bool(cmd->cft->root, "devices/sysfs_scan",
if (find_config_tree_bool(cmd, "devices/sysfs_scan",
DEFAULT_SYSFS_SCAN)) {
if ((filters[nr_filt] = sysfs_filter_create(cmd->proc_dir)))
nr_filt++;
}
/* regex filter. Optional. */
if (!(cn = find_config_node(cmd->cft->root, "devices/filter")))
if (!(cn = find_config_tree_node(cmd, "devices/filter")))
log_very_verbose("devices/filter not found in config file: "
"no regex filter installed");
@@ -553,14 +552,14 @@ static struct dev_filter *_init_filter_components(struct cmd_context *cmd)
}
/* device type filter. Required. */
cn = find_config_node(cmd->cft->root, "devices/types");
cn = find_config_tree_node(cmd, "devices/types");
if (!(filters[nr_filt++] = lvm_type_filter_create(cmd->proc_dir, cn))) {
log_error("Failed to create lvm type filter");
return NULL;
}
/* md component filter. Optional, non-critical. */
if (find_config_bool(cmd->cft->root, "devices/md_component_detection",
if (find_config_tree_bool(cmd, "devices/md_component_detection",
DEFAULT_MD_COMPONENT_DETECTION)) {
init_md_filtering(1);
if ((filters[nr_filt] = md_filter_create()))
@@ -572,9 +571,9 @@ static struct dev_filter *_init_filter_components(struct cmd_context *cmd)
filters[0] : composite_filter_create(nr_filt, filters);
}
static int _init_filters(struct cmd_context *cmd)
static int _init_filters(struct cmd_context *cmd, unsigned load_persistent_cache)
{
const char *dev_cache;
const char *dev_cache = NULL, *cache_dir, *cache_file_prefix;
struct dev_filter *f3, *f4;
struct stat st;
char cache_file[PATH_MAX];
@@ -584,30 +583,54 @@ static int _init_filters(struct cmd_context *cmd)
if (!(f3 = _init_filter_components(cmd)))
return 0;
if (lvm_snprintf(cache_file, sizeof(cache_file),
"%s/.cache", cmd->sys_dir) < 0) {
log_error("Persistent cache filename too long ('%s/.cache').",
cmd->sys_dir);
init_ignore_suspended_devices(find_config_tree_int(cmd,
"devices/ignore_suspended_devices", DEFAULT_IGNORE_SUSPENDED_DEVICES));
/*
* If 'cache_dir' or 'cache_file_prefix' is set, ignore 'cache'.
*/
cache_dir = find_config_tree_str(cmd, "devices/cache_dir", NULL);
cache_file_prefix = find_config_tree_str(cmd, "devices/cache_file_prefix", NULL);
if (cache_dir || cache_file_prefix) {
if (dm_snprintf(cache_file, sizeof(cache_file),
"%s%s%s/%s.cache",
cache_dir ? "" : cmd->sys_dir,
cache_dir ? "" : "/",
cache_dir ? : DEFAULT_CACHE_SUBDIR,
cache_file_prefix ? : DEFAULT_CACHE_FILE_PREFIX) < 0) {
log_error("Persistent cache filename too long.");
return 0;
}
} else if (!(dev_cache = find_config_tree_str(cmd, "devices/cache", NULL)) &&
(dm_snprintf(cache_file, sizeof(cache_file),
"%s/%s/%s.cache",
cmd->sys_dir, DEFAULT_CACHE_SUBDIR,
DEFAULT_CACHE_FILE_PREFIX) < 0)) {
log_error("Persistent cache filename too long.");
return 0;
}
dev_cache = find_config_str(cmd->cft->root, "devices/cache",
cache_file);
if (!(f4 = persistent_filter_create(f3, dev_cache))) {
if (!(f4 = persistent_filter_create(f3, dev_cache ? : cache_file))) {
log_error("Failed to create persistent device filter");
return 0;
}
/* Should we ever dump persistent filter state? */
if (find_config_int(cmd->cft->root, "devices/write_cache_state", 1))
if (find_config_tree_int(cmd, "devices/write_cache_state", 1))
cmd->dump_filter = 1;
if (!*cmd->sys_dir)
cmd->dump_filter = 0;
if (!stat(dev_cache, &st) &&
(st.st_mtime > config_file_timestamp(cmd->cft)) &&
!persistent_filter_load(f4))
/*
* Only load persistent filter device cache on startup if it is newer
* than the config file and this is not a long-lived process.
*/
if (load_persistent_cache && !cmd->is_long_lived &&
!stat(dev_cache, &st) &&
(st.st_ctime > config_file_timestamp(cmd->cft)) &&
!persistent_filter_load(f4, NULL))
log_verbose("Failed to load existing device cache from %s",
dev_cache);
@@ -643,8 +666,9 @@ static int _init_formats(struct cmd_context *cmd)
#endif
#ifdef HAVE_LIBDL
/* Load any formats in shared libs */
if ((cn = find_config_node(cmd->cft->root, "global/format_libraries"))) {
/* Load any formats in shared libs if not static */
if (!cmd->is_static &&
(cn = find_config_tree_node(cmd, "global/format_libraries"))) {
struct config_value *cv;
struct format_type *(*init_format_fn) (struct cmd_context *);
@@ -656,8 +680,8 @@ static int _init_formats(struct cmd_context *cmd)
"global/format_libraries");
return 0;
}
if (!(lib = load_shared_library(cmd->cft, cv->v.str,
"format"))) {
if (!(lib = load_shared_library(cmd, cv->v.str,
"format", 0))) {
stack;
return 0;
}
@@ -684,7 +708,7 @@ static int _init_formats(struct cmd_context *cmd)
cmd->fmt_backup = fmt;
format = find_config_str(cmd->cft->root, "global/format",
format = find_config_tree_str(cmd, "global/format",
DEFAULT_FORMAT);
list_iterate_items(fmt, &cmd->formats) {
@@ -737,13 +761,13 @@ static int _init_segtypes(struct cmd_context *cmd)
#endif
#ifdef HAVE_LIBDL
/* Load any formats in shared libs */
if ((cn = find_config_node(cmd->cft->root, "global/segment_libraries"))) {
/* Load any formats in shared libs unless static */
if (!cmd->is_static &&
(cn = find_config_tree_node(cmd, "global/segment_libraries"))) {
struct config_value *cv;
struct segment_type *(*init_segtype_fn) (struct cmd_context *);
void *lib;
struct list *sgtl, *tmp;
struct segment_type *segtype2;
for (cv = cn->v; cv; cv = cv->next) {
@@ -752,8 +776,8 @@ static int _init_segtypes(struct cmd_context *cmd)
"global/segment_libraries");
return 0;
}
if (!(lib = load_shared_library(cmd->cft, cv->v.str,
"segment type"))) {
if (!(lib = load_shared_library(cmd, cv->v.str,
"segment type", 0))) {
stack;
return 0;
}
@@ -770,18 +794,16 @@ static int _init_segtypes(struct cmd_context *cmd)
segtype->library = lib;
list_add(&cmd->segtypes, &segtype->list);
list_iterate_safe(sgtl, tmp, &cmd->segtypes) {
segtype2 = list_item(sgtl, struct segment_type);
if (!strcmp(segtype2->name, segtype->name)) {
log_error("Duplicate segment type %s: "
"unloading shared library %s",
segtype->name, cv->v.str);
list_del(&segtype->list);
segtype->ops->destroy(segtype);
dlclose(lib);
break;
}
list_iterate_items(segtype2, &cmd->segtypes) {
if ((segtype == segtype2) ||
strcmp(segtype2->name, segtype->name))
continue;
log_error("Duplicate segment type %s: "
"unloading shared library %s",
segtype->name, cv->v.str);
list_del(&segtype->list);
segtype->ops->destroy(segtype);
dlclose(lib);
}
}
}
@@ -827,16 +849,16 @@ static int _init_backup(struct cmd_context *cmd)
/* set up archiving */
cmd->default_settings.archive =
find_config_bool(cmd->cft->root, "backup/archive",
find_config_tree_bool(cmd, "backup/archive",
DEFAULT_ARCHIVE_ENABLED);
days = (uint32_t) find_config_int(cmd->cft->root, "backup/retain_days",
days = (uint32_t) find_config_tree_int(cmd, "backup/retain_days",
DEFAULT_ARCHIVE_DAYS);
min = (uint32_t) find_config_int(cmd->cft->root, "backup/retain_min",
min = (uint32_t) find_config_tree_int(cmd, "backup/retain_min",
DEFAULT_ARCHIVE_NUMBER);
if (lvm_snprintf
if (dm_snprintf
(default_dir, sizeof(default_dir), "%s/%s", cmd->sys_dir,
DEFAULT_ARCHIVE_SUBDIR) == -1) {
log_err("Couldn't create default archive path '%s/%s'.",
@@ -844,7 +866,7 @@ static int _init_backup(struct cmd_context *cmd)
return 0;
}
dir = find_config_str(cmd->cft->root, "backup/archive_dir",
dir = find_config_tree_str(cmd, "backup/archive_dir",
default_dir);
if (!archive_init(cmd, dir, days, min)) {
@@ -854,10 +876,10 @@ static int _init_backup(struct cmd_context *cmd)
/* set up the backup */
cmd->default_settings.backup =
find_config_bool(cmd->cft->root, "backup/backup",
find_config_tree_bool(cmd, "backup/backup",
DEFAULT_BACKUP_ENABLED);
if (lvm_snprintf
if (dm_snprintf
(default_dir, sizeof(default_dir), "%s/%s", cmd->sys_dir,
DEFAULT_BACKUP_SUBDIR) == -1) {
log_err("Couldn't create default backup path '%s/%s'.",
@@ -865,7 +887,7 @@ static int _init_backup(struct cmd_context *cmd)
return 0;
}
dir = find_config_str(cmd->cft->root, "backup/backup_dir", default_dir);
dir = find_config_tree_str(cmd, "backup/backup_dir", default_dir);
if (!backup_init(cmd, dir)) {
log_debug("backup_init failed.");
@@ -876,7 +898,8 @@ static int _init_backup(struct cmd_context *cmd)
}
/* Entry point */
struct cmd_context *create_toolcontext(struct arg *the_args)
struct cmd_context *create_toolcontext(struct arg *the_args, unsigned is_static,
unsigned is_long_lived)
{
struct cmd_context *cmd;
@@ -899,6 +922,8 @@ struct cmd_context *create_toolcontext(struct arg *the_args)
}
memset(cmd, 0, sizeof(*cmd));
cmd->args = the_args;
cmd->is_static = is_static;
cmd->is_long_lived = is_long_lived;
cmd->hosttags = 0;
list_init(&cmd->formats);
list_init(&cmd->segtypes);
@@ -921,7 +946,7 @@ struct cmd_context *create_toolcontext(struct arg *the_args)
if (!(cmd->libmem = dm_pool_create("library", 4 * 1024))) {
log_error("Library memory pool creation failed");
return 0;
goto error;
}
if (!_init_lvm_conf(cmd))
@@ -947,12 +972,12 @@ struct cmd_context *create_toolcontext(struct arg *the_args)
if (!_init_dev_cache(cmd))
goto error;
if (!_init_filters(cmd))
if (!_init_filters(cmd, 1))
goto error;
if (!(cmd->mem = dm_pool_create("command", 4 * 1024))) {
log_error("Command memory pool creation failed");
return 0;
goto error;
}
memlock_init(cmd);
@@ -1016,12 +1041,12 @@ int refresh_toolcontext(struct cmd_context *cmd)
{
log_verbose("Reloading config files");
if (cmd->config_valid) {
if (cmd->dump_filter)
persistent_filter_dump(cmd->filter);
}
/*
* Don't update the persistent filter cache as we will
* perform a full rescan.
*/
activation_exit();
activation_release();
lvmcache_destroy();
label_exit();
_destroy_segtypes(&cmd->segtypes);
@@ -1058,7 +1083,7 @@ int refresh_toolcontext(struct cmd_context *cmd)
if (!_init_dev_cache(cmd))
return 0;
if (!_init_filters(cmd))
if (!_init_filters(cmd, 0))
return 0;
if (!_init_formats(cmd))
@@ -1067,6 +1092,13 @@ int refresh_toolcontext(struct cmd_context *cmd)
if (!_init_segtypes(cmd))
return 0;
/*
* If we are a long-lived process, write out the updated persistent
* device cache for the benefit of short-lived processes.
*/
if (cmd->is_long_lived && cmd->dump_filter)
persistent_filter_dump(cmd->filter);
cmd->config_valid = 1;
return 1;
}
@@ -1094,8 +1126,4 @@ void destroy_toolcontext(struct cmd_context *cmd)
activation_exit();
fin_log();
fin_syslog();
if (_log)
fclose(_log);
}

View File

@@ -64,6 +64,8 @@ struct cmd_context {
struct command *command;
struct arg *args;
char **argv;
unsigned is_static; /* Static binary? */
unsigned is_long_lived; /* Optimises persistent_filter handling */
struct dev_filter *filter;
int dump_filter; /* Dump filter when exiting? */
@@ -71,6 +73,7 @@ struct cmd_context {
struct list config_files;
int config_valid;
struct config_tree *cft;
struct config_tree *cft_override;
struct config_info default_settings;
struct config_info current_settings;
@@ -86,7 +89,7 @@ struct cmd_context {
char proc_dir[PATH_MAX];
};
struct cmd_context *create_toolcontext(struct arg *the_args);
struct cmd_context *create_toolcontext(struct arg *the_args, unsigned is_static, unsigned is_long_lived);
void destroy_toolcontext(struct cmd_context *cmd);
int refresh_toolcontext(struct cmd_context *cmd);
int config_files_changed(struct cmd_context *cmd);

View File

@@ -19,6 +19,7 @@
#include "device.h"
#include "str_list.h"
#include "toolcontext.h"
#include "lvm-string.h"
#include <sys/stat.h>
#include <sys/mman.h>
@@ -26,6 +27,9 @@
#include <fcntl.h>
#include <ctype.h>
#define SECTION_B_CHAR '{'
#define SECTION_E_CHAR '}'
enum {
TOK_INT,
TOK_FLOAT,
@@ -41,10 +45,10 @@ enum {
};
struct parser {
char *fb, *fe; /* file limits */
const char *fb, *fe; /* file limits */
int t; /* token limits and type */
char *tb, *te;
const char *tb, *te;
int fd; /* descriptor for file being parsed */
int line; /* line number we are on */
@@ -58,6 +62,8 @@ struct cs {
time_t timestamp;
char *filename;
int exists;
int keep_open;
struct device *dev;
};
static void _get_token(struct parser *p, int tok_prev);
@@ -77,7 +83,8 @@ static const int sep = '/';
#define match(t) do {\
if (!_match_aux(p, (t))) {\
log_error("Parse error at line %d: unexpected token", p->line); \
log_error("Parse error at byte %" PRIptrdiff_t " (line %d): unexpected token", \
p->tb - p->fb + 1, p->line); \
return 0;\
} \
} while(0);
@@ -95,18 +102,18 @@ static int _tok_match(const char *str, const char *b, const char *e)
/*
* public interface
*/
struct config_tree *create_config_tree(const char *filename)
struct config_tree *create_config_tree(const char *filename, int keep_open)
{
struct cs *c;
struct dm_pool *mem = dm_pool_create("config", 10 * 1024);
if (!mem) {
stack;
log_error("Failed to allocate config pool.");
return 0;
}
if (!(c = dm_pool_zalloc(mem, sizeof(*c)))) {
stack;
log_error("Failed to allocate config tree.");
dm_pool_destroy(mem);
return 0;
}
@@ -115,6 +122,8 @@ struct config_tree *create_config_tree(const char *filename)
c->cft.root = (struct config_node *) NULL;
c->timestamp = 0;
c->exists = 0;
c->keep_open = keep_open;
c->dev = 0;
if (filename)
c->filename = dm_pool_strdup(c->mem, filename);
return &c->cft;
@@ -122,7 +131,52 @@ struct config_tree *create_config_tree(const char *filename)
void destroy_config_tree(struct config_tree *cft)
{
dm_pool_destroy(((struct cs *) cft)->mem);
struct cs *c = (struct cs *) cft;
if (c->dev)
dev_close(c->dev);
dm_pool_destroy(c->mem);
}
static int _parse_config_file(struct parser *p, struct config_tree *cft)
{
p->tb = p->te = p->fb;
p->line = 1;
_get_token(p, TOK_SECTION_E);
if (!(cft->root = _file(p)))
return_0;
return 1;
}
struct config_tree *create_config_tree_from_string(struct cmd_context *cmd,
const char *config_settings)
{
struct cs *c;
struct config_tree *cft;
struct parser *p;
if (!(cft = create_config_tree(NULL, 0)))
return_NULL;
c = (struct cs *) cft;
if (!(p = dm_pool_alloc(c->mem, sizeof(*p)))) {
log_error("Failed to allocate config tree parser.");
destroy_config_tree(cft);
return NULL;
}
p->mem = c->mem;
p->fb = config_settings;
p->fe = config_settings + strlen(config_settings);
if (!_parse_config_file(p, cft)) {
destroy_config_tree(cft);
return_NULL;
}
return cft;
}
int read_config_fd(struct config_tree *cft, struct device *dev,
@@ -134,6 +188,7 @@ int read_config_fd(struct config_tree *cft, struct device *dev,
int r = 0;
int use_mmap = 1;
off_t mmap_offset = 0;
char *buf;
if (!(p = dm_pool_alloc(c->mem, sizeof(*p)))) {
stack;
@@ -146,7 +201,7 @@ int read_config_fd(struct config_tree *cft, struct device *dev,
use_mmap = 0;
if (use_mmap) {
mmap_offset = offset % getpagesize();
mmap_offset = offset % lvm_getpagesize();
/* memory map the file */
p->fb = mmap((caddr_t) 0, size + mmap_offset, PROT_READ,
MAP_PRIVATE, dev_fd(dev), offset - mmap_offset);
@@ -156,22 +211,15 @@ int read_config_fd(struct config_tree *cft, struct device *dev,
}
p->fb = p->fb + mmap_offset;
} else {
if (!(p->fb = dm_malloc(size + size2))) {
if (!(buf = dm_malloc(size + size2))) {
stack;
return 0;
}
if (!dev_read(dev, (uint64_t) offset, size, p->fb)) {
log_error("Read from %s failed", dev_name(dev));
if (!dev_read_circular(dev, (uint64_t) offset, size,
(uint64_t) offset2, size2, buf)) {
goto out;
}
if (size2) {
if (!dev_read(dev, (uint64_t) offset2, size2,
p->fb + size)) {
log_error("Circular read from %s failed",
dev_name(dev));
goto out;
}
}
p->fb = buf;
}
if (checksum_fn && checksum !=
@@ -183,11 +231,7 @@ int read_config_fd(struct config_tree *cft, struct device *dev,
p->fe = p->fb + size + size2;
/* parse */
p->tb = p->te = p->fb;
p->line = 1;
_get_token(p, TOK_SECTION_E);
if (!(cft->root = _file(p))) {
if (!_parse_config_file(p, cft)) {
stack;
goto out;
}
@@ -196,7 +240,7 @@ int read_config_fd(struct config_tree *cft, struct device *dev,
out:
if (!use_mmap)
dm_free(p->fb);
dm_free(buf);
else {
/* unmap the file */
if (munmap((char *) (p->fb - mmap_offset), size + mmap_offset)) {
@@ -212,7 +256,6 @@ int read_config_file(struct config_tree *cft)
{
struct cs *c = (struct cs *) cft;
struct stat info;
struct device *dev;
int r = 1;
if (stat(c->filename, &info)) {
@@ -234,22 +277,23 @@ int read_config_file(struct config_tree *cft)
return 1;
}
if (!(dev = dev_create_file(c->filename, NULL, NULL, 1))) {
stack;
return 0;
if (!c->dev) {
if (!(c->dev = dev_create_file(c->filename, NULL, NULL, 1)))
return_0;
if (!dev_open_flags(c->dev, O_RDONLY, 0, 0))
return_0;
}
if (!dev_open_flags(dev, O_RDONLY, 0, 0)) {
stack;
return 0;
}
r = read_config_fd(cft, dev, 0, (size_t) info.st_size, 0, 0,
r = read_config_fd(cft, c->dev, 0, (size_t) info.st_size, 0, 0,
(checksum_fn_t) NULL, 0);
dev_close(dev);
if (!c->keep_open) {
dev_close(c->dev);
c->dev = 0;
}
c->timestamp = info.st_mtime;
c->timestamp = info.st_ctime;
return r;
}
@@ -293,7 +337,7 @@ int config_file_changed(struct config_tree *cft)
}
/* Unchanged? */
if (c->timestamp == info.st_mtime)
if (c->timestamp == info.st_ctime)
return 0;
reload:
@@ -326,7 +370,8 @@ static void _write_value(FILE *fp, struct config_value *v)
}
}
static int _write_config(struct config_node *n, FILE *fp, int level)
static int _write_config(struct config_node *n, int only_one, FILE *fp,
int level)
{
char space[MAX_INDENT + 1];
int l = (level < MAX_INDENT) ? level : MAX_INDENT;
@@ -339,12 +384,12 @@ static int _write_config(struct config_node *n, FILE *fp, int level)
space[i] = '\t';
space[i] = '\0';
while (n) {
do {
fprintf(fp, "%s%s", space, n->key);
if (!n->v) {
/* it's a sub section */
fprintf(fp, " {\n");
_write_config(n->child, fp, level + 1);
_write_config(n->child, 0, fp, level + 1);
fprintf(fp, "%s}", space);
} else {
/* it's a value */
@@ -364,13 +409,15 @@ static int _write_config(struct config_node *n, FILE *fp, int level)
}
fprintf(fp, "\n");
n = n->sib;
}
} while (n && !only_one);
/* FIXME: add error checking */
return 1;
}
int write_config_file(struct config_tree *cft, const char *file)
int write_config_file(struct config_tree *cft, const char *file,
int argc, char **argv)
{
struct config_node *cn;
int r = 1;
FILE *fp;
@@ -383,13 +430,28 @@ int write_config_file(struct config_tree *cft, const char *file)
}
log_verbose("Dumping configuration to %s", file);
if (!_write_config(cft->root, fp, 0)) {
log_error("Failure while writing configuration");
r = 0;
if (!argc) {
if (!_write_config(cft->root, 0, fp, 0)) {
log_error("Failure while writing to %s", file);
r = 0;
}
} else while (argc--) {
if ((cn = find_config_node(cft->root, *argv))) {
if (!_write_config(cn, 1, fp, 0)) {
log_error("Failure while writing to %s", file);
r = 0;
}
} else {
log_error("Configuration node %s not found", *argv);
r = 0;
}
argv++;
}
if (fp != stdout)
fclose(fp);
if ((fp != stdout) && fclose(fp)) {
log_sys_error("fclose", file);
r = 0;
}
return r;
}
@@ -417,7 +479,7 @@ static struct config_node *_file(struct parser *p)
static struct config_node *_section(struct parser *p)
{
/* IDENTIFIER '{' VALUE* '}' */
/* IDENTIFIER SECTION_B_CHAR VALUE* SECTION_E_CHAR */
struct config_node *root, *n, *l = NULL;
if (!(root = _create_node(p))) {
stack;
@@ -529,7 +591,8 @@ static struct config_value *_type(struct parser *p)
break;
default:
log_error("Parse error at line %d: expected a value", p->line);
log_error("Parse error at byte %" PRIptrdiff_t " (line %d): expected a value",
p->tb - p->fb + 1, p->line);
return 0;
}
return v;
@@ -566,12 +629,12 @@ static void _get_token(struct parser *p, int tok_prev)
p->t = TOK_INT; /* fudge so the fall through for
floats works */
switch (*p->te) {
case '{':
case SECTION_B_CHAR:
p->t = TOK_SECTION_B;
p->te++;
break;
case '}':
case SECTION_E_CHAR:
p->t = TOK_SECTION_E;
p->te++;
break;
@@ -651,8 +714,9 @@ static void _get_token(struct parser *p, int tok_prev)
default:
p->t = TOK_IDENTIFIER;
while ((p->te != p->fe) && (*p->te) && !isspace(*p->te) &&
(*p->te != '#') && (*p->te != '=') && (*p->te != '{') &&
(*p->te != '}'))
(*p->te != '#') && (*p->te != '=') &&
(*p->te != SECTION_B_CHAR) &&
(*p->te != SECTION_E_CHAR))
p->te++;
break;
}
@@ -688,14 +752,20 @@ static void _eat_space(struct parser *p)
static struct config_value *_create_value(struct parser *p)
{
struct config_value *v = dm_pool_alloc(p->mem, sizeof(*v));
memset(v, 0, sizeof(*v));
if (v)
memset(v, 0, sizeof(*v));
return v;
}
static struct config_node *_create_node(struct parser *p)
{
struct config_node *n = dm_pool_alloc(p->mem, sizeof(*n));
memset(n, 0, sizeof(*n));
if (n)
memset(n, 0, sizeof(*n));
return n;
}
@@ -715,10 +785,11 @@ static char *_dup_tok(struct parser *p)
/*
* utility functions
*/
struct config_node *find_config_node(const struct config_node *cn,
const char *path)
static struct config_node *_find_config_node(const struct config_node *cn,
const char *path)
{
const char *e;
const struct config_node *cn_found = NULL;
while (cn) {
/* trim any leading slashes */
@@ -729,32 +800,62 @@ struct config_node *find_config_node(const struct config_node *cn,
for (e = path; *e && (*e != sep); e++) ;
/* hunt for the node */
cn_found = NULL;
while (cn) {
if (_tok_match(cn->key, path, e))
break;
if (_tok_match(cn->key, path, e)) {
/* Inefficient */
if (!cn_found)
cn_found = cn;
else
log_error("WARNING: Ignoring duplicate"
" config node: %s ("
"seeking %s)", cn->key, path);
}
cn = cn->sib;
}
if (cn && *e)
cn = cn->child;
if (cn_found && *e)
cn = cn_found->child;
else
break; /* don't move into the last node */
path = e;
}
return (struct config_node *) cn;
return (struct config_node *) cn_found;
}
const char *find_config_str(const struct config_node *cn,
const char *path, const char *fail)
static struct config_node *_find_first_config_node(const struct config_node *cn1,
const struct config_node *cn2,
const char *path)
{
const struct config_node *n = find_config_node(cn, path);
struct config_node *cn;
if (n && n->v->type == CFG_STRING) {
if (*n->v->v.str)
log_very_verbose("Setting %s to %s", path, n->v->v.str);
if (cn1 && (cn = _find_config_node(cn1, path)))
return cn;
if (cn2 && (cn = _find_config_node(cn2, path)))
return cn;
return NULL;
}
struct config_node *find_config_node(const struct config_node *cn,
const char *path)
{
return _find_config_node(cn, path);
}
static const char *_find_config_str(const struct config_node *cn1,
const struct config_node *cn2,
const char *path, const char *fail)
{
const struct config_node *n = _find_first_config_node(cn1, cn2, path);
/* Empty strings are ignored */
if ((n && n->v && n->v->type == CFG_STRING) && (*n->v->v.str)) {
log_very_verbose("Setting %s to %s", path, n->v->v.str);
return n->v->v.str;
}
@@ -764,11 +865,19 @@ const char *find_config_str(const struct config_node *cn,
return fail;
}
int find_config_int(const struct config_node *cn, const char *path, int fail)
const char *find_config_str(const struct config_node *cn,
const char *path, const char *fail)
{
const struct config_node *n = find_config_node(cn, path);
return _find_config_str(cn, NULL, path, fail);
}
if (n && n->v->type == CFG_INT) {
static int _find_config_int(const struct config_node *cn1,
const struct config_node *cn2,
const char *path, int fail)
{
const struct config_node *n = _find_first_config_node(cn1, cn2, path);
if (n && n->v && n->v->type == CFG_INT) {
log_very_verbose("Setting %s to %d", path, n->v->v.i);
return n->v->v.i;
}
@@ -778,12 +887,18 @@ int find_config_int(const struct config_node *cn, const char *path, int fail)
return fail;
}
float find_config_float(const struct config_node *cn, const char *path,
float fail)
int find_config_int(const struct config_node *cn, const char *path, int fail)
{
const struct config_node *n = find_config_node(cn, path);
return _find_config_int(cn, NULL, path, fail);
}
if (n && n->v->type == CFG_FLOAT) {
static float _find_config_float(const struct config_node *cn1,
const struct config_node *cn2,
const char *path, float fail)
{
const struct config_node *n = _find_first_config_node(cn1, cn2, path);
if (n && n->v && n->v->type == CFG_FLOAT) {
log_very_verbose("Setting %s to %f", path, n->v->v.r);
return n->v->v.r;
}
@@ -795,6 +910,36 @@ float find_config_float(const struct config_node *cn, const char *path,
}
float find_config_float(const struct config_node *cn, const char *path,
float fail)
{
return _find_config_float(cn, NULL, path, fail);
}
struct config_node *find_config_tree_node(struct cmd_context *cmd,
const char *path)
{
return _find_first_config_node(cmd->cft_override ? cmd->cft_override->root : NULL, cmd->cft->root, path);
}
const char *find_config_tree_str(struct cmd_context *cmd,
const char *path, const char *fail)
{
return _find_config_str(cmd->cft_override ? cmd->cft_override->root : NULL, cmd->cft->root, path, fail);
}
int find_config_tree_int(struct cmd_context *cmd, const char *path,
int fail)
{
return _find_config_int(cmd->cft_override ? cmd->cft_override->root : NULL, cmd->cft->root, path, fail);
}
float find_config_tree_float(struct cmd_context *cmd, const char *path,
float fail)
{
return _find_config_float(cmd->cft_override ? cmd->cft_override->root : NULL, cmd->cft->root, path, fail);
}
static int _str_in_array(const char *str, const char *values[])
{
int i;
@@ -821,9 +966,11 @@ static int _str_to_bool(const char *str, int fail)
return fail;
}
int find_config_bool(const struct config_node *cn, const char *path, int fail)
static int _find_config_bool(const struct config_node *cn1,
const struct config_node *cn2,
const char *path, int fail)
{
const struct config_node *n = find_config_node(cn, path);
const struct config_node *n = _find_first_config_node(cn1, cn2, path);
struct config_value *v;
if (!n)
@@ -842,6 +989,16 @@ int find_config_bool(const struct config_node *cn, const char *path, int fail)
return fail;
}
int find_config_bool(const struct config_node *cn, const char *path, int fail)
{
return _find_config_bool(cn, NULL, path, fail);
}
int find_config_tree_bool(struct cmd_context *cmd, const char *path, int fail)
{
return _find_config_bool(cmd->cft_override ? cmd->cft_override->root : NULL, cmd->cft->root, path, fail);
}
int get_config_uint32(const struct config_node *cn, const char *path,
uint32_t *result)
{
@@ -996,3 +1153,61 @@ int merge_config_tree(struct cmd_context *cmd, struct config_tree *cft,
return 1;
}
/*
* Convert a token type to the char it represents.
*/
static char _token_type_to_char(int type)
{
switch (type) {
case TOK_SECTION_B:
return SECTION_B_CHAR;
case TOK_SECTION_E:
return SECTION_E_CHAR;
default:
return 0;
}
}
/*
* Returns:
* # of 'type' tokens in 'str'.
*/
static unsigned _count_tokens (const char *str, unsigned len, int type)
{
char c;
c = _token_type_to_char(type);
return(count_chars_len(str, len, c));
}
/*
* Heuristic function to make a quick guess as to whether a text
* region probably contains a valid config "section". (Useful for
* scanning areas of the disk for old metadata.)
* Config sections contain various tokens, may contain other sections
* and strings, and are delimited by begin (type 'TOK_SECTION_B') and
* end (type 'TOK_SECTION_E') tokens. As a quick heuristic, we just
* count the number of begin and end tokens, and see if they are
* non-zero and the counts match.
* Full validation of the section should be done with another function
* (for example, read_config_fd).
*
* Returns:
* 0 - probably is not a valid config section
* 1 - probably _is_ a valid config section
*/
unsigned maybe_config_section(const char *str, unsigned len)
{
int begin_count;
int end_count;
begin_count = _count_tokens(str, len, TOK_SECTION_B);
end_count = _count_tokens(str, len, TOK_SECTION_E);
if (begin_count && end_count && (begin_count - end_count == 0))
return 1;
else
return 0;
}

View File

@@ -53,17 +53,20 @@ struct config_tree_list {
struct config_tree *cft;
};
struct config_tree *create_config_tree(const char *filename);
struct config_tree *create_config_tree(const char *filename, int keep_open);
struct config_tree *create_config_tree_from_string(struct cmd_context *cmd,
const char *config_settings);
void destroy_config_tree(struct config_tree *cft);
typedef uint32_t (*checksum_fn_t) (uint32_t initial, void *buf, uint32_t size);
typedef uint32_t (*checksum_fn_t) (uint32_t initial, const void *buf, uint32_t size);
int read_config_fd(struct config_tree *cft, struct device *dev,
off_t offset, size_t size, off_t offset2, size_t size2,
checksum_fn_t checksum_fn, uint32_t checksum);
int read_config_file(struct config_tree *cft);
int write_config_file(struct config_tree *cft, const char *file);
int write_config_file(struct config_tree *cft, const char *file,
int argc, char **argv);
time_t config_file_timestamp(struct config_tree *cft);
int config_file_changed(struct config_tree *cft);
int merge_config_tree(struct cmd_context *cmd, struct config_tree *cft,
@@ -71,20 +74,30 @@ int merge_config_tree(struct cmd_context *cmd, struct config_tree *cft,
struct config_node *find_config_node(const struct config_node *cn,
const char *path);
const char *find_config_str(const struct config_node *cn, const char *path,
const char *fail);
int find_config_int(const struct config_node *cn, const char *path, int fail);
float find_config_float(const struct config_node *cn, const char *path,
float fail);
/*
* These versions check an override tree, if present, first.
*/
struct config_node *find_config_tree_node(struct cmd_context *cmd,
const char *path);
const char *find_config_tree_str(struct cmd_context *cmd,
const char *path, const char *fail);
int find_config_tree_int(struct cmd_context *cmd, const char *path,
int fail);
float find_config_tree_float(struct cmd_context *cmd, const char *path,
float fail);
/*
* Understands (0, ~0), (y, n), (yes, no), (on,
* off), (true, false).
*/
int find_config_bool(const struct config_node *cn, const char *path, int fail);
int find_config_tree_bool(struct cmd_context *cmd, const char *path, int fail);
int get_config_uint32(const struct config_node *cn, const char *path,
uint32_t *result);
@@ -95,4 +108,6 @@ int get_config_uint64(const struct config_node *cn, const char *path,
int get_config_str(const struct config_node *cn, const char *path,
char **result);
unsigned maybe_config_section(const char *str, unsigned len);
#endif

View File

@@ -21,6 +21,8 @@
#define DEFAULT_ARCHIVE_SUBDIR "archive"
#define DEFAULT_BACKUP_SUBDIR "backup"
#define DEFAULT_CACHE_SUBDIR "cache"
#define DEFAULT_CACHE_FILE_PREFIX ""
#define DEFAULT_ARCHIVE_DAYS 30
#define DEFAULT_ARCHIVE_NUMBER 10
@@ -30,9 +32,17 @@
#define DEFAULT_PROC_DIR "/proc"
#define DEFAULT_SYSFS_SCAN 1
#define DEFAULT_MD_COMPONENT_DETECTION 1
#define DEFAULT_IGNORE_SUSPENDED_DEVICES 1
#define DEFAULT_LOCK_DIR "/var/lock/lvm"
#define DEFAULT_LOCKING_LIB "lvm2_locking.so"
#define DEFAULT_LOCKING_LIB "liblvm2clusterlock.so"
#define DEFAULT_FALLBACK_TO_LOCAL_LOCKING 1
#define DEFAULT_FALLBACK_TO_CLUSTERED_LOCKING 1
#define DEFAULT_MIRROR_LOG_FAULT_POLICY "allocate"
#define DEFAULT_MIRROR_DEV_FAULT_POLICY "remove"
#define DEFAULT_DMEVENTD_MIRROR_LIB "libdevmapper-event-lvm2mirror.so"
#define DEFAULT_DMEVENTD_MONITOR 1
#define DEFAULT_UMASK 0077

View File

@@ -107,7 +107,7 @@ void *btree_get_data(struct btree_iter *it)
return ((struct node *) it)->data;
}
static inline struct node *_left(struct node *n)
static struct node *_left(struct node *n)
{
while (n->l)
n = n->l;

136
lib/datastruct/list.c Normal file
View File

@@ -0,0 +1,136 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004 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 General Public License v.2.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "lib.h"
/*
* Initialise a list before use.
* The list head's next and previous pointers point back to itself.
*/
void list_init(struct list *head)
{
head->n = head->p = head;
}
/*
* Insert an element before 'head'.
* If 'head' is the list head, this adds an element to the end of the list.
*/
void list_add(struct list *head, struct list *elem)
{
assert(head->n);
elem->n = head;
elem->p = head->p;
head->p->n = elem;
head->p = elem;
}
/*
* Insert an element after 'head'.
* If 'head' is the list head, this adds an element to the front of the list.
*/
void list_add_h(struct list *head, struct list *elem)
{
assert(head->n);
elem->n = head->n;
elem->p = head;
head->n->p = elem;
head->n = elem;
}
/*
* Delete an element from its list.
* Note that this doesn't change the element itself - it may still be safe
* to follow its pointers.
*/
void list_del(struct list *elem)
{
elem->n->p = elem->p;
elem->p->n = elem->n;
}
/*
* Is the list empty?
*/
int list_empty(struct list *head)
{
return head->n == head;
}
/*
* Is this the first element of the list?
*/
int list_start(struct list *head, struct list *elem)
{
return elem->p == head;
}
/*
* Is this the last element of the list?
*/
int list_end(struct list *head, struct list *elem)
{
return elem->n == head;
}
/*
* Return first element of the list or NULL if empty
*/
struct list *list_first(struct list *head)
{
return (list_empty(head) ? NULL : head->n);
}
/*
* Return last element of the list or NULL if empty
*/
struct list *list_last(struct list *head)
{
return (list_empty(head) ? NULL : head->p);
}
/*
* Return the previous element of the list, or NULL if we've reached the start.
*/
struct list *list_prev(struct list *head, struct list *elem)
{
return (list_start(head, elem) ? NULL : elem->p);
}
/*
* Return the next element of the list, or NULL if we've reached the end.
*/
struct list *list_next(struct list *head, struct list *elem)
{
return (list_end(head, elem) ? NULL : elem->n);
}
/*
* Return the number of elements in a list by walking it.
*/
unsigned int list_size(const struct list *head)
{
unsigned int s = 0;
const struct list *v;
list_iterate(v, head)
s++;
return s;
}

View File

@@ -33,107 +33,61 @@ struct list {
* The list head's next and previous pointers point back to itself.
*/
#define LIST_INIT(name) struct list name = { &(name), &(name) }
static inline void list_init(struct list *head)
{
head->n = head->p = head;
}
void list_init(struct list *head);
/*
* Insert an element before 'head'.
* If 'head' is the list head, this adds an element to the end of the list.
*/
static inline void list_add(struct list *head, struct list *elem)
{
assert(head->n);
elem->n = head;
elem->p = head->p;
head->p->n = elem;
head->p = elem;
}
void list_add(struct list *head, struct list *elem);
/*
* Insert an element after 'head'.
* If 'head' is the list head, this adds an element to the front of the list.
*/
static inline void list_add_h(struct list *head, struct list *elem)
{
assert(head->n);
elem->n = head->n;
elem->p = head;
head->n->p = elem;
head->n = elem;
}
void list_add_h(struct list *head, struct list *elem);
/*
* Delete an element from its list.
* Note that this doesn't change the element itself - it may still be safe
* to follow its pointers.
*/
static inline void list_del(struct list *elem)
{
elem->n->p = elem->p;
elem->p->n = elem->n;
}
void list_del(struct list *elem);
/*
* Is the list empty?
*/
static inline int list_empty(struct list *head)
{
return head->n == head;
}
int list_empty(struct list *head);
/*
* Is this the first element of the list?
*/
static inline int list_start(struct list *head, struct list *elem)
{
return elem->p == head;
}
int list_start(struct list *head, struct list *elem);
/*
* Is this the last element of the list?
*/
static inline int list_end(struct list *head, struct list *elem)
{
return elem->n == head;
}
int list_end(struct list *head, struct list *elem);
/*
* Return first element of the list or NULL if empty
*/
static inline struct list *list_first(struct list *head)
{
return (list_empty(head) ? NULL : head->n);
}
struct list *list_first(struct list *head);
/*
* Return last element of the list or NULL if empty
*/
static inline struct list *list_last(struct list *head)
{
return (list_empty(head) ? NULL : head->p);
}
struct list *list_last(struct list *head);
/*
* Return the previous element of the list, or NULL if we've reached the start.
*/
static inline struct list *list_prev(struct list *head, struct list *elem)
{
return (list_start(head, elem) ? NULL : elem->p);
}
struct list *list_prev(struct list *head, struct list *elem);
/*
* Return the next element of the list, or NULL if we've reached the end.
*/
static inline struct list *list_next(struct list *head, struct list *elem)
{
return (list_end(head, elem) ? NULL : elem->n);
}
struct list *list_next(struct list *head, struct list *elem);
/*
* Given the address v of an instance of 'struct list' called 'head'
@@ -244,15 +198,6 @@ static inline struct list *list_next(struct list *head, struct list *elem)
/*
* Return the number of elements in a list by walking it.
*/
static inline unsigned int list_size(const struct list *head)
{
unsigned int s = 0;
const struct list *v;
list_iterate(v, head)
s++;
return s;
}
unsigned int list_size(const struct list *head);
#endif

View File

@@ -23,6 +23,7 @@
/* Define some portable printing types */
#define PRIsize_t "zu"
#define PRIptrdiff_t "td"
struct str_list {
struct list list;

View File

@@ -19,6 +19,8 @@
#include "btree.h"
#include "filter.h"
#include "filter-persistent.h"
#include "matcher.h"
#include "toolcontext.h"
#include <unistd.h>
#include <sys/param.h>
@@ -38,6 +40,7 @@ static struct {
struct dm_pool *mem;
struct dm_hash_table *names;
struct btree *devices;
struct matcher *preferred_names_matcher;
int has_scanned;
struct list dirs;
@@ -129,15 +132,52 @@ static struct device *_dev_create(dev_t d)
return dev;
}
void dev_set_preferred_name(struct str_list *sl, struct device *dev)
{
/*
* Don't interfere with ordering specified in config file.
*/
if (_cache.preferred_names_matcher)
return;
log_debug("%s: New preferred name", sl->str);
list_del(&sl->list);
list_add_h(&dev->aliases, &sl->list);
}
/* Return 1 if we prefer path1 else return 0 */
static int _compare_paths(const char *path0, const char *path1)
{
int slash0 = 0, slash1 = 0;
int m0, m1;
const char *p;
char p0[PATH_MAX], p1[PATH_MAX];
char *s0, *s1;
struct stat stat0, stat1;
/*
* FIXME Better to compare patterns one-at-a-time against all names.
*/
if (_cache.preferred_names_matcher) {
m0 = matcher_run(_cache.preferred_names_matcher, path0);
m1 = matcher_run(_cache.preferred_names_matcher, path1);
if (m0 != m1) {
if (m0 < 0)
return 1;
if (m1 < 0)
return 0;
if (m0 < m1)
return 1;
if (m1 < m0)
return 0;
}
}
/*
* Built-in rules.
*/
/* Return the path with fewer slashes */
for (p = path0; p++; p = (const char *) strchr(p, '/'))
slash0++;
@@ -441,7 +481,65 @@ void dev_cache_scan(int do_scan)
_full_scan(1);
}
int dev_cache_init(void)
static int _init_preferred_names(struct cmd_context *cmd)
{
const struct config_node *cn;
struct config_value *v;
struct dm_pool *scratch = NULL;
char **regex;
unsigned count = 0;
int i, r = 0;
_cache.preferred_names_matcher = NULL;
if (!(cn = find_config_tree_node(cmd, "devices/preferred_names")) ||
cn->v->type == CFG_EMPTY_ARRAY) {
log_very_verbose("devices/preferred_names not found in config file: "
"using built-in preferences");
return 1;
}
for (v = cn->v; v; v = v->next) {
if (v->type != CFG_STRING) {
log_error("preferred_names patterns must be enclosed in quotes");
return 0;
}
count++;
}
if (!(scratch = dm_pool_create("preferred device name matcher", 1024)))
return_0;
if (!(regex = dm_pool_alloc(scratch, sizeof(*regex) * count))) {
log_error("Failed to allocate preferred device name "
"pattern list.");
goto out;
}
for (v = cn->v, i = count - 1; v; v = v->next, i--) {
if (!(regex[i] = dm_pool_strdup(scratch, v->v.str))) {
log_error("Failed to allocate a preferred device name "
"pattern.");
goto out;
}
}
if (!(_cache.preferred_names_matcher =
matcher_create(_cache.mem,(const char **) regex, count))) {
log_error("Preferred device name pattern matcher creation failed.");
goto out;
}
r = 1;
out:
dm_pool_destroy(scratch);
return r;
}
int dev_cache_init(struct cmd_context *cmd)
{
_cache.names = NULL;
_cache.has_scanned = 0;
@@ -466,6 +564,9 @@ int dev_cache_init(void)
list_init(&_cache.dirs);
list_init(&_cache.files);
if (!_init_preferred_names(cmd))
goto_bad;
return 1;
bad:
@@ -479,7 +580,7 @@ static void _check_closed(struct device *dev)
log_err("Device '%s' has been left open.", dev_name(dev));
}
static inline void _check_for_open_devices(void)
static void _check_for_open_devices(void)
{
dm_hash_iter(_cache.names, (dm_hash_iterate_fn) _check_closed);
}
@@ -489,6 +590,9 @@ void dev_cache_exit(void)
if (_cache.names)
_check_for_open_devices();
if (_cache.preferred_names_matcher)
_cache.preferred_names_matcher = NULL;
if (_cache.mem) {
dm_pool_destroy(_cache.mem);
_cache.mem = NULL;
@@ -645,8 +749,7 @@ struct dev_iter *dev_iter_create(struct dev_filter *f, int dev_scan)
return NULL;
}
if (dev_scan) {
if (dev_scan && !trust_cache()) {
/* Flag gets reset between each command */
if (!full_scan_done())
persistent_filter_wipe(f); /* Calls _full_scan(1) */
@@ -664,7 +767,7 @@ void dev_iter_destroy(struct dev_iter *iter)
dm_free(iter);
}
static inline struct device *_iter_next(struct dev_iter *iter)
static struct device *_iter_next(struct dev_iter *iter)
{
struct device *d = btree_get_data(iter->current);
iter->current = btree_next(iter->current);
@@ -682,3 +785,14 @@ struct device *dev_iter_get(struct dev_iter *iter)
return NULL;
}
int dev_fd(struct device *dev)
{
return dev->fd;
}
const char *dev_name(const struct device *dev)
{
return (dev) ? list_item(dev->aliases.n, struct str_list)->str :
"unknown device";
}

View File

@@ -30,7 +30,8 @@ struct dev_filter {
/*
* The global device cache.
*/
int dev_cache_init(void);
struct cmd_context;
int dev_cache_init(struct cmd_context *cmd);
void dev_cache_exit(void);
/* Trigger(1) or avoid(0) a scan */
@@ -41,6 +42,8 @@ int dev_cache_add_dir(const char *path);
int dev_cache_add_loopfile(const char *path);
struct device *dev_cache_get(const char *name, struct dev_filter *f);
void dev_set_preferred_name(struct str_list *sl, struct device *dev);
/*
* Object for iterating through the cache.
*/

View File

@@ -176,7 +176,7 @@ static int _aligned_io(struct device_area *where, void *buffer,
}
if (!block_size)
block_size = getpagesize();
block_size = lvm_getpagesize();
_widen_region(block_size, where, &widened);
@@ -292,11 +292,14 @@ int dev_get_sectsize(struct device *dev, uint32_t *size)
if (ioctl(fd, BLKSSZGET, &s) < 0) {
log_sys_error("ioctl BLKSSZGET", name);
close(fd);
if (close(fd))
log_sys_error("close", name);
return 0;
}
close(fd);
if (close(fd))
log_sys_error("close", name);
*size = (uint32_t) s;
log_very_verbose("%s: sector size is %" PRIu32 " bytes", name, *size);
@@ -418,7 +421,6 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet)
((fstat(dev->fd, &buf) < 0) || (buf.st_rdev != dev->dev))) {
log_error("%s: fstat failed: Has device name changed?", name);
dev_close_immediate(dev);
dev->open_count = 0;
return 0;
}
@@ -509,11 +511,9 @@ static int _dev_close(struct device *dev, int immediate)
if (dev->open_count > 0)
dev->open_count--;
if (immediate && dev->open_count) {
if (immediate && dev->open_count)
log_debug("%s: Immediate close attempt while still referenced",
dev_name(dev));
dev->open_count = 0;
}
/* Close unless device is known to belong to a locked VG */
if (immediate ||
@@ -564,6 +564,35 @@ int dev_read(struct device *dev, uint64_t offset, size_t len, void *buffer)
return _aligned_io(&where, buffer, 0);
}
/*
* Read from 'dev' into 'buf', possibly in 2 distinct regions, denoted
* by (offset,len) and (offset2,len2). Thus, the total size of
* 'buf' should be len+len2.
*/
int dev_read_circular(struct device *dev, uint64_t offset, size_t len,
uint64_t offset2, size_t len2, void *buf)
{
if (!dev_read(dev, offset, len, buf)) {
log_error("Read from %s failed", dev_name(dev));
return 0;
}
/*
* The second region is optional, and allows for
* a circular buffer on the device.
*/
if (!len2)
return 1;
if (!dev_read(dev, offset2, len2, buf + len)) {
log_error("Circular read from %s failed",
dev_name(dev));
return 0;
}
return 1;
}
/* FIXME If O_DIRECT can't extend file, dev_extend first; dev_truncate after.
* But fails if concurrent processes writing
*/
@@ -605,10 +634,10 @@ int dev_write(struct device *dev, uint64_t offset, size_t len, void *buffer)
return _aligned_io(&where, buffer, 1);
}
int dev_zero(struct device *dev, uint64_t offset, size_t len)
int dev_set(struct device *dev, uint64_t offset, size_t len, int value)
{
size_t s;
char buffer[4096];
char buffer[4096] __attribute((aligned(8)));
if (!dev_open(dev)) {
stack;
@@ -623,7 +652,7 @@ int dev_zero(struct device *dev, uint64_t offset, size_t len)
" sectors", dev_name(dev), offset >> SECTOR_SHIFT,
len >> SECTOR_SHIFT);
memset(buffer, 0, sizeof(buffer));
memset(buffer, value, sizeof(buffer));
while (1) {
s = len > sizeof(buffer) ? sizeof(buffer) : len;
if (!dev_write(dev, offset, s, buffer))

View File

@@ -53,8 +53,10 @@ int dev_is_md(struct device *dev, uint64_t *sb)
sb_offset = MD_NEW_SIZE_SECTORS(size) << SECTOR_SHIFT;
/* Check if it is an md component device. */
/* Version 1 is little endian; version 0.90.0 is machine endian */
if (dev_read(dev, sb_offset, sizeof(uint32_t), &md_magic) &&
(md_magic == xlate32(MD_SB_MAGIC))) {
((md_magic == xlate32(MD_SB_MAGIC)) ||
(md_magic == MD_SB_MAGIC))) {
if (sb)
*sb = sb_offset;
ret = 1;

View File

@@ -53,7 +53,7 @@ static int _has_partition_table(struct device *dev)
{
int ret = 0;
unsigned p;
uint8_t buf[SECTOR_SIZE];
uint16_t buf[SECTOR_SIZE/sizeof(uint16_t)];
uint16_t *part_magic;
struct partition *part;
@@ -62,7 +62,7 @@ static int _has_partition_table(struct device *dev)
return -1;
}
if (!dev_read(dev, 0, sizeof(buf), &buf)) {
if (!dev_read(dev, UINT64_C(0), sizeof(buf), &buf)) {
stack;
goto out;
}
@@ -70,9 +70,9 @@ static int _has_partition_table(struct device *dev)
/* FIXME Check for other types of partition table too */
/* Check for msdos partition table */
part_magic = (uint16_t *)(buf + PART_MAGIC_OFFSET);
part_magic = buf + PART_MAGIC_OFFSET/sizeof(buf[0]);
if ((*part_magic == xlate16(PART_MAGIC))) {
part = (struct partition *) (buf + PART_OFFSET);
part = (struct partition *) (buf + PART_OFFSET/sizeof(buf[0]));
for (p = 0; p < 4; p++, part++) {
/* Table is invalid if boot indicator not 0 or 0x80 */
if ((part->boot_ind & 0x7f)) {

View File

@@ -74,26 +74,20 @@ int dev_close_immediate(struct device *dev);
void dev_close_all(void);
int dev_test_excl(struct device *dev);
static inline int dev_fd(struct device *dev)
{
return dev->fd;
}
int dev_fd(struct device *dev);
const char *dev_name(const struct device *dev);
int dev_read(struct device *dev, uint64_t offset, size_t len, void *buffer);
int dev_read_circular(struct device *dev, uint64_t offset, size_t len,
uint64_t offset2, size_t len2, void *buf);
int dev_write(struct device *dev, uint64_t offset, size_t len, void *buffer);
int dev_append(struct device *dev, size_t len, void *buffer);
int dev_zero(struct device *dev, uint64_t offset, size_t len);
int dev_set(struct device *dev, uint64_t offset, size_t len, int value);
void dev_flush(struct device *dev);
struct device *dev_create_file(const char *filename, struct device *dev,
struct str_list *alias, int use_malloc);
static inline const char *dev_name(const struct device *dev)
{
return (dev) ? list_item(dev->aliases.n, struct str_list)->str :
"unknown device";
}
/* Return a valid device name from the alias list; NULL otherwise */
const char *dev_name_confirmed(struct device *dev, int quiet);

View File

@@ -22,12 +22,15 @@
#define SIZE_BUF 128
typedef enum { SIZE_LONG = 0, SIZE_SHORT = 1, SIZE_UNIT = 2 } size_len_t;
static struct {
alloc_policy_t alloc;
const char *str;
} _policies[] = {
{
ALLOC_CONTIGUOUS, "contiguous"}, {
ALLOC_CLING, "cling"}, {
ALLOC_NORMAL, "normal"}, {
ALLOC_ANYWHERE, "anywhere"}, {
ALLOC_INHERIT, "inherit"}
@@ -79,6 +82,12 @@ uint64_t units_to_bytes(const char *units, char *unit_type)
case 't':
v *= KILO * KILO * KILO * KILO;
break;
case 'p':
v *= KILO * KILO * KILO * KILO * KILO;
break;
case 'e':
v *= KILO * KILO * KILO * KILO * KILO * KILO;
break;
#undef KILO
#define KILO UINT64_C(1000)
case 'K':
@@ -93,6 +102,12 @@ uint64_t units_to_bytes(const char *units, char *unit_type)
case 'T':
v *= KILO * KILO * KILO * KILO;
break;
case 'P':
v *= KILO * KILO * KILO * KILO * KILO;
break;
case 'E':
v *= KILO * KILO * KILO * KILO * KILO * KILO;
break;
#undef KILO
default:
return 0;
@@ -132,7 +147,7 @@ alloc_policy_t get_alloc_from_string(const char *str)
}
/* Size supplied in sectors */
const char *display_size(struct cmd_context *cmd, uint64_t size, size_len_t sl)
static const char *_display_size(struct cmd_context *cmd, uint64_t size, size_len_t sl)
{
int s;
int suffix = 1, precision;
@@ -140,6 +155,8 @@ const char *display_size(struct cmd_context *cmd, uint64_t size, size_len_t sl)
uint64_t units = UINT64_C(1024);
char *size_buf = NULL;
const char *size_str[][3] = {
{" Exabyte", " EB", "E"},
{" Petabyte", " PB", "P"},
{" Terabyte", " TB", "T"},
{" Gigabyte", " GB", "G"},
{" Megabyte", " MB", "M"},
@@ -158,7 +175,7 @@ const char *display_size(struct cmd_context *cmd, uint64_t size, size_len_t sl)
suffix = cmd->current_settings.suffix;
for (s = 0; s < 8; s++)
for (s = 0; s < 10; s++)
if (toupper((int) cmd->current_settings.unit_type) ==
*size_str[s][2])
break;
@@ -168,7 +185,7 @@ const char *display_size(struct cmd_context *cmd, uint64_t size, size_len_t sl)
return size_buf;
}
if (s < 8) {
if (s < 10) {
byte = cmd->current_settings.unit_factor;
size *= UINT64_C(512);
} else {
@@ -178,7 +195,7 @@ const char *display_size(struct cmd_context *cmd, uint64_t size, size_len_t sl)
units = UINT64_C(1000);
else
units = UINT64_C(1024);
byte = units * units * units;
byte = units * units * units * units * units;
s = 0;
while (size_str[s] && size < byte)
s++, byte /= units;
@@ -200,9 +217,24 @@ const char *display_size(struct cmd_context *cmd, uint64_t size, size_len_t sl)
return size_buf;
}
const char *display_size_long(struct cmd_context *cmd, uint64_t size)
{
return _display_size(cmd, size, SIZE_LONG);
}
const char *display_size_units(struct cmd_context *cmd, uint64_t size)
{
return _display_size(cmd, size, SIZE_UNIT);
}
const char *display_size(struct cmd_context *cmd, uint64_t size)
{
return _display_size(cmd, size, SIZE_SHORT);
}
void pvdisplay_colons(struct physical_volume *pv)
{
char uuid[64];
char uuid[64] __attribute((aligned(8)));
if (!pv)
return;
@@ -228,9 +260,9 @@ void pvdisplay_colons(struct physical_volume *pv)
/* FIXME Include label fields */
void pvdisplay_full(struct cmd_context *cmd, struct physical_volume *pv,
void *handle)
void *handle __attribute((unused)))
{
char uuid[64];
char uuid[64] __attribute((aligned(8)));
const char *size;
uint32_t pe_free;
@@ -248,18 +280,17 @@ void pvdisplay_full(struct cmd_context *cmd, struct physical_volume *pv,
log_print("VG Name %s%s", pv->vg_name,
pv->status & EXPORTED_VG ? " (exported)" : "");
size = display_size(cmd, (uint64_t) pv->size, SIZE_SHORT);
size = display_size(cmd, (uint64_t) pv->size);
if (pv->pe_size && pv->pe_count) {
/******** FIXME display LVM on-disk data size
size2 = display_size(pv->size, SIZE_SHORT);
size2 = display_size(cmd, pv->size);
********/
log_print("PV Size %s" " / not usable %s", /* [LVM: %s]", */
size,
display_size(cmd, (pv->size -
(uint64_t) pv->pe_count * pv->pe_size),
SIZE_SHORT));
(uint64_t) pv->pe_count * pv->pe_size)));
} else
log_print("PV Size %s", size);
@@ -288,10 +319,12 @@ void pvdisplay_full(struct cmd_context *cmd, struct physical_volume *pv,
return;
}
int pvdisplay_short(struct cmd_context *cmd, struct volume_group *vg,
struct physical_volume *pv, void *handle)
int pvdisplay_short(struct cmd_context *cmd __attribute((unused)),
struct volume_group *vg __attribute((unused)),
struct physical_volume *pv,
void *handle __attribute((unused)))
{
char uuid[64];
char uuid[64] __attribute((aligned(8)));
if (!pv)
return 0;
@@ -334,11 +367,11 @@ void lvdisplay_colons(struct logical_volume *lv)
}
int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv,
void *handle)
void *handle __attribute((unused)))
{
struct lvinfo info;
int inkernel, snap_active = 0;
char uuid[64];
char uuid[64] __attribute((aligned(8)));
struct lv_segment *snap_seg = NULL;
float snap_percent; /* fused, fsize; */
@@ -404,23 +437,21 @@ int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv,
log_print("LV Size %s",
display_size(cmd,
snap_seg ? snap_seg->origin->size : lv->size,
SIZE_SHORT));
snap_seg ? snap_seg->origin->size : lv->size));
log_print("Current LE %u",
snap_seg ? snap_seg->origin->le_count : lv->le_count);
if (snap_seg) {
log_print("COW-table size %s",
display_size(cmd, (uint64_t) lv->size, SIZE_SHORT));
display_size(cmd, (uint64_t) lv->size));
log_print("COW-table LE %u", lv->le_count);
if (snap_active)
log_print("Allocated to snapshot %.2f%% ", snap_percent);
log_print("Snapshot chunk size %s",
display_size(cmd, (uint64_t) snap_seg->chunk_size,
SIZE_SHORT));
display_size(cmd, (uint64_t) snap_seg->chunk_size));
}
log_print("Segments %u", list_size(&lv->segments));
@@ -497,7 +528,7 @@ int lvdisplay_segments(struct logical_volume *lv)
return 1;
}
void vgdisplay_extents(struct volume_group *vg)
void vgdisplay_extents(struct volume_group *vg __attribute((unused)))
{
return;
}
@@ -506,7 +537,7 @@ void vgdisplay_full(struct volume_group *vg)
{
uint32_t access;
uint32_t active_pvs;
char uuid[64];
char uuid[64] __attribute((aligned(8)));
if (vg->status & PARTIAL_VG)
active_pvs = list_size(&vg->pvs);
@@ -544,7 +575,7 @@ void vgdisplay_full(struct volume_group *vg)
log_print("Open LV %u", lvs_in_vg_opened(vg));
/****** FIXME Max LV Size
log_print ( "MAX LV Size %s",
( s1 = display_size ( LVM_LV_SIZE_MAX(vg), SIZE_SHORT)));
( s1 = display_size ( LVM_LV_SIZE_MAX(vg))));
free ( s1);
*********/
log_print("Max PV %u", vg->max_pv);
@@ -553,12 +584,10 @@ void vgdisplay_full(struct volume_group *vg)
log_print("VG Size %s",
display_size(vg->cmd,
(uint64_t) vg->extent_count * vg->extent_size,
SIZE_SHORT));
(uint64_t) vg->extent_count * vg->extent_size));
log_print("PE Size %s",
display_size(vg->cmd, (uint64_t) vg->extent_size,
SIZE_SHORT));
display_size(vg->cmd, (uint64_t) vg->extent_size));
log_print("Total PE %u", vg->extent_count);
@@ -566,12 +595,11 @@ void vgdisplay_full(struct volume_group *vg)
vg->extent_count - vg->free_count,
display_size(vg->cmd,
((uint64_t) vg->extent_count - vg->free_count) *
vg->extent_size, SIZE_SHORT));
vg->extent_size));
log_print("Free PE / Size %u / %s", vg->free_count,
display_size(vg->cmd,
(uint64_t) vg->free_count * vg->extent_size,
SIZE_SHORT));
(uint64_t) vg->free_count * vg->extent_size));
if (!id_write_format(&vg->id, uuid, sizeof(uuid))) {
stack;
@@ -588,7 +616,7 @@ void vgdisplay_colons(struct volume_group *vg)
{
uint32_t active_pvs;
const char *access;
char uuid[64];
char uuid[64] __attribute((aligned(8)));
if (vg->status & PARTIAL_VG)
active_pvs = list_size(&vg->pvs);
@@ -641,15 +669,12 @@ void vgdisplay_short(struct volume_group *vg)
log_print("\"%s\" %-9s [%-9s used / %s free]", vg->name,
/********* FIXME if "open" print "/used" else print "/idle"??? ******/
display_size(vg->cmd,
(uint64_t) vg->extent_count * vg->extent_size,
SIZE_SHORT),
(uint64_t) vg->extent_count * vg->extent_size),
display_size(vg->cmd,
((uint64_t) vg->extent_count -
vg->free_count) * vg->extent_size,
SIZE_SHORT),
vg->free_count) * vg->extent_size),
display_size(vg->cmd,
(uint64_t) vg->free_count * vg->extent_size,
SIZE_SHORT));
(uint64_t) vg->free_count * vg->extent_size));
return;
}

View File

@@ -20,12 +20,13 @@
#include <stdint.h>
typedef enum { SIZE_LONG = 0, SIZE_SHORT = 1, SIZE_UNIT = 2 } size_len_t;
uint64_t units_to_bytes(const char *units, char *unit_type);
/* Specify size in KB */
const char *display_size(struct cmd_context *cmd, uint64_t size, size_len_t sl);
const char *display_size(struct cmd_context *cmd, uint64_t size);
const char *display_size_long(struct cmd_context *cmd, uint64_t size);
const char *display_size_units(struct cmd_context *cmd, uint64_t size);
char *display_uuid(char *uuidstr);
void display_stripe(const struct lv_segment *seg, uint32_t s, const char *pre);

View File

@@ -23,13 +23,14 @@
#include "targets.h"
#include "lvm-string.h"
#include "activate.h"
#include "str_list.h"
static const char *_name(const struct lv_segment *seg)
static const char *_errseg_name(const struct lv_segment *seg)
{
return seg->segtype->name;
}
static int _merge_segments(struct lv_segment *seg1, struct lv_segment *seg2)
static int _errseg_merge_segments(struct lv_segment *seg1, struct lv_segment *seg2)
{
seg1->len += seg2->len;
seg1->area_len += seg2->area_len;
@@ -38,43 +39,58 @@ static int _merge_segments(struct lv_segment *seg1, struct lv_segment *seg2)
}
#ifdef DEVMAPPER_SUPPORT
static int _add_target_line(struct dev_manager *dm, struct dm_pool *mem,
struct config_tree *cft, void **target_state,
struct lv_segment *seg,
static int _errseg_add_target_line(struct dev_manager *dm __attribute((unused)),
struct dm_pool *mem __attribute((unused)),
struct cmd_context *cmd __attribute((unused)),
void **target_state __attribute((unused)),
struct lv_segment *seg __attribute((unused)),
struct dm_tree_node *node, uint64_t len,
uint32_t *pvmove_mirror_count)
uint32_t *pvmove_mirror_count __attribute((unused)))
{
return dm_tree_node_add_error_target(node, len);
}
static int _target_present(void)
static int _errseg_target_present(const struct lv_segment *seg __attribute((unused)))
{
static int checked = 0;
static int present = 0;
static int _errseg_checked = 0;
static int _errseg_present = 0;
/* Reported truncated in older kernels */
if (!checked &&
if (!_errseg_checked &&
(target_present("error", 0) || target_present("erro", 0)))
present = 1;
_errseg_present = 1;
checked = 1;
return present;
_errseg_checked = 1;
return _errseg_present;
}
#endif
static void _destroy(const struct segment_type *segtype)
static int _errseg_modules_needed(struct dm_pool *mem,
const struct lv_segment *seg,
struct list *modules)
{
dm_free((void *) segtype);
if (!str_list_add(mem, modules, "error")) {
log_error("error module string list allocation failed");
return 0;
}
return 1;
}
static void _errseg_destroy(const struct segment_type *segtype)
{
dm_free((void *)segtype);
}
static struct segtype_handler _error_ops = {
name:_name,
merge_segments:_merge_segments,
.name = _errseg_name,
.merge_segments = _errseg_merge_segments,
#ifdef DEVMAPPER_SUPPORT
add_target_line:_add_target_line,
target_present:_target_present,
.add_target_line = _errseg_add_target_line,
.target_present = _errseg_target_present,
#endif
destroy:_destroy,
.modules_needed = _errseg_modules_needed,
.destroy = _errseg_destroy,
};
struct segment_type *init_error_segtype(struct cmd_context *cmd)

View File

@@ -33,7 +33,7 @@ static int _and_p(struct dev_filter *f, struct device *dev)
return 1;
}
static void _destroy(struct dev_filter *f)
static void _composite_destroy(struct dev_filter *f)
{
struct dev_filter **filters = (struct dev_filter **) f->private;
@@ -70,7 +70,7 @@ struct dev_filter *composite_filter_create(int n, struct dev_filter **filters)
}
cft->passes_filter = _and_p;
cft->destroy = _destroy;
cft->destroy = _composite_destroy;
cft->private = filters_copy;
return cft;

View File

@@ -18,14 +18,6 @@
#ifdef linux
/* Lifted from <linux/raid/md_p.h> because of difficulty including it */
#define MD_SB_MAGIC 0xa92b4efc
#define MD_RESERVED_BYTES (64 * 1024)
#define MD_RESERVED_SECTORS (MD_RESERVED_BYTES / 512)
#define MD_NEW_SIZE_SECTORS(x) ((x & ~(MD_RESERVED_SECTORS - 1)) \
- MD_RESERVED_SECTORS)
static int _ignore_md(struct dev_filter *f, struct device *dev)
{
int ret;

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
* Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
@@ -17,6 +17,7 @@
#include "config.h"
#include "dev-cache.h"
#include "filter-persistent.h"
#include "lvm-file.h"
#include <sys/stat.h>
#include <fcntl.h>
@@ -26,11 +27,12 @@ struct pfilter {
char *file;
struct dm_hash_table *devices;
struct dev_filter *real;
time_t ctime;
};
/*
* entries in the table can be in one of these
* states.
* The hash table holds one of these two states
* against each entry.
*/
#define PF_BAD_DEVICE ((void *) 1)
#define PF_GOOD_DEVICE ((void *) 2)
@@ -93,22 +95,26 @@ static int _read_array(struct pfilter *pf, struct config_tree *cft,
return 1;
}
int persistent_filter_load(struct dev_filter *f)
int persistent_filter_load(struct dev_filter *f, struct config_tree **cft_out)
{
struct pfilter *pf = (struct pfilter *) f->private;
int r = 0;
struct config_tree *cft;
struct stat info;
int r = 0;
if (!(cft = create_config_tree(pf->file))) {
stack;
return 0;
if (!stat(pf->file, &info))
pf->ctime = info.st_ctime;
else {
log_very_verbose("%s: stat failed: %s", pf->file,
strerror(errno));
return_0;
}
if (!read_config_file(cft)) {
stack;
goto out;
}
if (!(cft = create_config_tree(pf->file, 1)))
return_0;
if (!read_config_file(cft))
goto_out;
_read_array(pf, cft, "persistent_filter_cache/valid_devices",
PF_GOOD_DEVICE);
@@ -126,7 +132,10 @@ int persistent_filter_load(struct dev_filter *f)
log_very_verbose("Loaded persistent filter cache from %s", pf->file);
out:
destroy_config_tree(cft);
if (r && cft_out)
*cft_out = cft;
else
destroy_config_tree(cft);
return r;
}
@@ -163,8 +172,12 @@ static void _write_array(struct pfilter *pf, FILE *fp, const char *path,
int persistent_filter_dump(struct dev_filter *f)
{
struct pfilter *pf = (struct pfilter *) f->private;
char *tmp_file;
struct stat info, info2;
struct config_tree *cft = NULL;
FILE *fp;
int lockfd;
int r = 0;
if (!dm_hash_get_num_entries(pf->devices)) {
log_very_verbose("Internal persistent device cache empty "
@@ -179,11 +192,43 @@ int persistent_filter_dump(struct dev_filter *f)
log_very_verbose("Dumping persistent device cache to %s", pf->file);
fp = fopen(pf->file, "w");
if (!fp) {
if (errno != EROFS)
log_sys_error("fopen", pf->file);
return 0;
while (1) {
if ((lockfd = fcntl_lock_file(pf->file, F_WRLCK, 0)) < 0)
return_0;
/*
* Ensure we locked the file we expected
*/
if (fstat(lockfd, &info)) {
log_sys_error("fstat", pf->file);
goto out;
}
if (stat(pf->file, &info2)) {
log_sys_error("stat", pf->file);
goto out;
}
if (!memcmp(&info.st_ino, &info2.st_ino, sizeof(ino_t)))
break;
fcntl_unlock_file(lockfd);
}
/*
* If file contents changed since we loaded it, merge new contents
*/
if (info.st_ctime != pf->ctime)
/* Keep cft open to avoid losing lock */
persistent_filter_load(f, &cft);
tmp_file = alloca(strlen(pf->file) + 5);
sprintf(tmp_file, "%s.tmp", pf->file);
if (!(fp = fopen(tmp_file, "w"))) {
/* EACCES has been reported over NFS */
if (errno != EROFS && errno != EACCES)
log_sys_error("fopen", tmp_file);
goto out;
}
fprintf(fp, "# This file is automatically maintained by lvm.\n\n");
@@ -194,8 +239,24 @@ int persistent_filter_dump(struct dev_filter *f)
/* _write_array(pf, fp, "invalid_devices", PF_BAD_DEVICE); */
fprintf(fp, "}\n");
fclose(fp);
return 1;
if (fclose(fp)) {
log_sys_error("fclose", tmp_file);
goto out;
}
if (rename(tmp_file, pf->file))
log_error("%s: rename to %s failed: %s", tmp_file, pf->file,
strerror(errno));
r = 1;
out:
fcntl_unlock_file(lockfd);
if (cft)
destroy_config_tree(cft);
return r;
}
static int _lookup_p(struct dev_filter *f, struct device *dev)
@@ -217,7 +278,7 @@ static int _lookup_p(struct dev_filter *f, struct device *dev)
return (l == PF_BAD_DEVICE) ? 0 : 1;
}
static void _destroy(struct dev_filter *f)
static void _persistent_destroy(struct dev_filter *f)
{
struct pfilter *pf = (struct pfilter *) f->private;
@@ -240,10 +301,9 @@ struct dev_filter *persistent_filter_create(struct dev_filter *real,
}
memset(pf, 0, sizeof(*pf));
if (!(pf->file = dm_malloc(strlen(file) + 1))) {
stack;
goto bad;
}
if (!(pf->file = dm_malloc(strlen(file) + 1)))
goto_bad;
strcpy(pf->file, file);
pf->real = real;
@@ -252,13 +312,11 @@ struct dev_filter *persistent_filter_create(struct dev_filter *real,
goto bad;
}
if (!(f = dm_malloc(sizeof(*f)))) {
stack;
goto bad;
}
if (!(f = dm_malloc(sizeof(*f))))
goto_bad;
f->passes_filter = _lookup_p;
f->destroy = _destroy;
f->destroy = _persistent_destroy;
f->private = pf;
return f;

View File

@@ -22,7 +22,7 @@ struct dev_filter *persistent_filter_create(struct dev_filter *f,
const char *file);
int persistent_filter_wipe(struct dev_filter *f);
int persistent_filter_load(struct dev_filter *f);
int persistent_filter_load(struct dev_filter *f, struct config_tree **cft_out);
int persistent_filter_dump(struct dev_filter *f);
#endif

View File

@@ -98,18 +98,15 @@ static int _build_matcher(struct rfilter *rf, struct config_value *val)
unsigned count = 0;
int i, r = 0;
if (!(scratch = dm_pool_create("filter matcher", 1024))) {
stack;
return 0;
}
if (!(scratch = dm_pool_create("filter matcher", 1024)))
return_0;
/*
* count how many patterns we have.
*/
for (v = val; v; v = v->next) {
if (v->type != CFG_STRING) {
log_info("filter patterns must be enclosed in quotes");
log_error("filter patterns must be enclosed in quotes");
goto out;
}
@@ -119,10 +116,8 @@ static int _build_matcher(struct rfilter *rf, struct config_value *val)
/*
* allocate space for them
*/
if (!(regex = dm_pool_alloc(scratch, sizeof(*regex) * count))) {
stack;
goto out;
}
if (!(regex = dm_pool_alloc(scratch, sizeof(*regex) * count)))
goto_out;
/*
* create the accept/reject bitset
@@ -136,7 +131,7 @@ static int _build_matcher(struct rfilter *rf, struct config_value *val)
*/
for (v = val, i = count - 1; v; v = v->next, i--)
if (!_extract_pattern(scratch, v->v.str, regex, rf->accept, i)) {
log_info("invalid filter pattern");
log_error("invalid filter pattern");
goto out;
}
@@ -164,13 +159,8 @@ static int _accept_p(struct dev_filter *f, struct device *dev)
if (m >= 0) {
if (dm_bit(rf->accept, m)) {
if (!first) {
log_debug("%s: New preferred name",
sl->str);
list_del(&sl->list);
list_add_h(&dev->aliases, &sl->list);
}
if (!first)
dev_set_preferred_name(sl, dev);
return 1;
}
@@ -191,7 +181,7 @@ static int _accept_p(struct dev_filter *f, struct device *dev)
return !rejected;
}
static void _destroy(struct dev_filter *f)
static void _regex_destroy(struct dev_filter *f)
{
struct rfilter *rf = (struct rfilter *) f->private;
dm_pool_destroy(rf->mem);
@@ -208,25 +198,19 @@ struct dev_filter *regex_filter_create(struct config_value *patterns)
return NULL;
}
if (!(rf = dm_pool_alloc(mem, sizeof(*rf)))) {
stack;
goto bad;
}
if (!(rf = dm_pool_alloc(mem, sizeof(*rf))))
goto_bad;
rf->mem = mem;
if (!_build_matcher(rf, patterns)) {
stack;
goto bad;
}
if (!_build_matcher(rf, patterns))
goto_bad;
if (!(f = dm_pool_zalloc(mem, sizeof(*f)))) {
stack;
goto bad;
}
if (!(f = dm_pool_zalloc(mem, sizeof(*f))))
goto_bad;
f->passes_filter = _accept_p;
f->destroy = _destroy;
f->destroy = _regex_destroy;
f->private = rf;
return f;

View File

@@ -32,7 +32,7 @@ static int _locate_sysfs_blocks(const char *proc, char *path, size_t len)
return 0;
}
if (lvm_snprintf(proc_mounts, sizeof(proc_mounts),
if (dm_snprintf(proc_mounts, sizeof(proc_mounts),
"%s/mounts", proc) < 0) {
log_error("Failed to create /proc/mounts string");
return 0;
@@ -44,9 +44,9 @@ static int _locate_sysfs_blocks(const char *proc, char *path, size_t len)
}
while (fgets(buffer, sizeof(buffer), fp)) {
if (split_words(buffer, 4, split) == 4 &&
if (dm_split_words(buffer, 4, 0, split) == 4 &&
!strcmp(split[2], "sysfs")) {
if (lvm_snprintf(path, len, "%s/%s", split[1],
if (dm_snprintf(path, len, "%s/%s", split[1],
"block") >= 0) {
r = 1;
}
@@ -54,7 +54,9 @@ static int _locate_sysfs_blocks(const char *proc, char *path, size_t len)
}
}
fclose(fp);
if (fclose(fp))
log_sys_error("fclose", proc_mounts);
return r;
}
@@ -88,7 +90,7 @@ static struct dev_set *_dev_set_create(struct dm_pool *mem, const char *sys_bloc
return ds;
}
static inline unsigned _hash_dev(dev_t dev)
static unsigned _hash_dev(dev_t dev)
{
return (major(dev) ^ minor(dev)) & (SET_BUCKETS - 1);
}
@@ -156,7 +158,9 @@ static int _read_dev(const char *file, dev_t *result)
}
r = _parse_dev(file, fp, result);
fclose(fp);
if (fclose(fp))
log_sys_error("fclose", file);
return r;
}
@@ -183,7 +187,7 @@ static int _read_devs(struct dev_set *ds, const char *dir)
if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
continue;
if (lvm_snprintf(path, sizeof(path), "%s/%s", dir,
if (dm_snprintf(path, sizeof(path), "%s/%s", dir,
d->d_name) < 0) {
log_error("sysfs path name too long: %s in %s",
d->d_name, dir);
@@ -280,10 +284,8 @@ struct dev_filter *sysfs_filter_create(const char *proc)
goto bad;
}
if (!(f = dm_pool_zalloc(mem, sizeof(*f)))) {
stack;
goto bad;
}
if (!(f = dm_pool_zalloc(mem, sizeof(*f))))
goto_bad;
f->passes_filter = _accept_p;
f->destroy = _destroy;

View File

@@ -19,6 +19,7 @@
#include "lvm-string.h"
#include "config.h"
#include "metadata.h"
#include "activate.h"
#include <dirent.h>
#include <unistd.h>
@@ -37,6 +38,7 @@ typedef struct {
} device_info_t;
static int _md_major = -1;
static int _device_mapper_major = -1;
int md_major(void)
{
@@ -90,6 +92,13 @@ static int _passes_lvm_type_device_filter(struct dev_filter *f,
return 0;
}
/* Skip suspended devices */
if (MAJOR(dev->dev) == _device_mapper_major &&
ignore_suspended_devices() && !device_is_usable(dev->dev)) {
log_debug("%s: Skipping: Suspended dm device", name);
return 0;
}
/* Check it's accessible */
if (!dev_open_flags(dev, O_RDONLY, 0, 1)) {
log_debug("%s: Skipping: open failed", name);
@@ -145,7 +154,7 @@ static int _scan_proc_dev(const char *proc, const struct config_node *cn)
/* All types unrecognised initially */
memset(_max_partitions_by_major, 0, sizeof(int) * NUMBER_OF_MAJORS);
if (lvm_snprintf(proc_devices, sizeof(proc_devices),
if (dm_snprintf(proc_devices, sizeof(proc_devices),
"%s/devices", proc) < 0) {
log_error("Failed to create /proc/devices string");
return 0;
@@ -182,10 +191,14 @@ static int _scan_proc_dev(const char *proc, const struct config_node *cn)
if (!strncmp("md", line + i, 2) && isspace(*(line + i + 2)))
_md_major = line_maj;
/* Look for device-mapper device */
/* FIXME Cope with multiple majors */
if (!strncmp("device-mapper", line + i, 13) && isspace(*(line + i + 13)))
_device_mapper_major = line_maj;
/* Go through the valid device names and if there is a
match store max number of partitions */
for (j = 0; device_info[j].name != NULL; j++) {
dev_len = strlen(device_info[j].name);
if (dev_len <= strlen(line + i) &&
!strncmp(device_info[j].name, line + i, dev_len) &&
@@ -204,6 +217,8 @@ static int _scan_proc_dev(const char *proc, const struct config_node *cn)
if (cv->type != CFG_STRING) {
log_error("Expecting string in devices/types "
"in config file");
if (fclose(pd))
log_sys_error("fclose", proc_devices);
return 0;
}
dev_len = strlen(cv->v.str);
@@ -213,12 +228,16 @@ static int _scan_proc_dev(const char *proc, const struct config_node *cn)
log_error("Max partition count missing for %s "
"in devices/types in config file",
name);
if (fclose(pd))
log_sys_error("fclose", proc_devices);
return 0;
}
if (!cv->v.i) {
log_error("Zero partition count invalid for "
"%s in devices/types in config file",
name);
if (fclose(pd))
log_sys_error("fclose", proc_devices);
return 0;
}
if (dev_len <= strlen(line + i) &&
@@ -229,7 +248,10 @@ static int _scan_proc_dev(const char *proc, const struct config_node *cn)
}
}
}
fclose(pd);
if (fclose(pd))
log_sys_error("fclose", proc_devices);
return 1;
}
@@ -254,6 +276,7 @@ struct dev_filter *lvm_type_filter_create(const char *proc,
if (!_scan_proc_dev(proc, cn)) {
stack;
dm_free(f);
return NULL;
}

View File

@@ -102,7 +102,7 @@ static void _xlate_vgd(struct vg_disk *disk)
static void _xlate_extents(struct pe_disk *extents, uint32_t count)
{
int i;
unsigned i;
for (i = 0; i < count; i++) {
extents[i].lv_num = xlate16(extents[i].lv_num);
@@ -116,7 +116,7 @@ static void _xlate_extents(struct pe_disk *extents, uint32_t count)
static int _munge_formats(struct pv_disk *pvd)
{
uint32_t pe_start;
int b, e;
unsigned b, e;
switch (pvd->version) {
case 1:
@@ -153,8 +153,10 @@ static int _munge_formats(struct pv_disk *pvd)
}
/* If UUID is missing, create one */
if (pvd->pv_uuid[0] == '\0')
uuid_from_num(pvd->pv_uuid, pvd->pv_number);
if (pvd->pv_uuid[0] == '\0') {
uuid_from_num((char *)pvd->pv_uuid, pvd->pv_number);
pvd->pv_uuid[ID_LEN] = '\0';
}
return 1;
}
@@ -172,9 +174,9 @@ static void _munge_exported_vg(struct pv_disk *pvd)
return;
/* FIXME also check vgd->status & VG_EXPORTED? */
l = strlen(pvd->vg_name);
l = strlen((char *)pvd->vg_name);
s = sizeof(EXPORTED_TAG);
if (!strncmp(pvd->vg_name + l - s + 1, EXPORTED_TAG, s)) {
if (!strncmp((char *)pvd->vg_name + l - s + 1, EXPORTED_TAG, s)) {
pvd->vg_name[l - s + 1] = '\0';
pvd->pv_status |= VG_EXPORTED;
}
@@ -223,11 +225,11 @@ static int _read_lvd(struct device *dev, uint64_t pos, struct lv_disk *disk)
return 1;
}
static int _read_vgd(struct disk_list *data)
int read_vgd(struct device *dev, struct vg_disk *vgd, struct pv_disk *pvd)
{
struct vg_disk *vgd = &data->vgd;
uint64_t pos = data->pvd.vg_on_disk.base;
if (!dev_read(data->dev, pos, sizeof(*vgd), vgd))
uint64_t pos = pvd->vg_on_disk.base;
if (!dev_read(dev, pos, sizeof(*vgd), vgd))
fail;
_xlate_vgd(vgd);
@@ -237,16 +239,16 @@ static int _read_vgd(struct disk_list *data)
/* If UUID is missing, create one */
if (vgd->vg_uuid[0] == '\0')
uuid_from_num(vgd->vg_uuid, vgd->vg_number);
uuid_from_num((char *)vgd->vg_uuid, vgd->vg_number);
return 1;
}
static int _read_uuids(struct disk_list *data)
{
int num_read = 0;
unsigned num_read = 0;
struct uuid_list *ul;
char buffer[NAME_LEN];
char buffer[NAME_LEN] __attribute((aligned(8)));
uint64_t pos = data->pvd.pv_uuidlist_on_disk.base;
uint64_t end = pos + data->pvd.pv_uuidlist_on_disk.size;
@@ -269,7 +271,7 @@ static int _read_uuids(struct disk_list *data)
return 1;
}
static inline int _check_lvd(struct lv_disk *lvd)
static int _check_lvd(struct lv_disk *lvd)
{
return !(lvd->lv_name[0] == '\0');
}
@@ -319,13 +321,31 @@ static int _read_extents(struct disk_list *data)
return 1;
}
static void __update_lvmcache(const struct format_type *fmt,
struct disk_list *dl,
struct device *dev, const char *vgid,
unsigned exported)
{
struct lvmcache_info *info;
if (!(info = lvmcache_add(fmt->labeller, (char *)dl->pvd.pv_uuid, dev,
(char *)dl->pvd.vg_name, vgid,
exported ? EXPORTED_VG : 0))) {
stack;
return;
}
info->device_size = xlate32(dl->pvd.pv_size) << SECTOR_SHIFT;
list_init(&info->mdas);
info->status &= ~CACHE_INVALID;
}
static struct disk_list *__read_disk(const struct format_type *fmt,
struct device *dev, struct dm_pool *mem,
const char *vg_name)
{
struct disk_list *dl = dm_pool_alloc(mem, sizeof(*dl));
struct disk_list *dl = dm_pool_zalloc(mem, sizeof(*dl));
const char *name = dev_name(dev);
struct lvmcache_info *info;
if (!dl) {
stack;
@@ -337,19 +357,8 @@ static struct disk_list *__read_disk(const struct format_type *fmt,
list_init(&dl->uuids);
list_init(&dl->lvds);
if (!_read_pvd(dev, &dl->pvd)) {
stack;
goto bad;
}
if (!(info = lvmcache_add(fmt->labeller, dl->pvd.pv_uuid, dev,
dl->pvd.vg_name, NULL)))
stack;
else {
info->device_size = xlate32(dl->pvd.pv_size) << SECTOR_SHIFT;
list_init(&info->mdas);
info->status &= ~CACHE_INVALID;
}
if (!_read_pvd(dev, &dl->pvd))
goto_bad;
/*
* is it an orphan ?
@@ -357,26 +366,26 @@ static struct disk_list *__read_disk(const struct format_type *fmt,
if (!*dl->pvd.vg_name) {
log_very_verbose("%s is not a member of any format1 VG", name);
/* Update VG cache */
/* vgcache_add(dl->pvd.vg_name, NULL, dev, fmt); */
__update_lvmcache(fmt, dl, dev, NULL, 0);
return (vg_name) ? NULL : dl;
}
if (!_read_vgd(dl)) {
if (!read_vgd(dl->dev, &dl->vgd, &dl->pvd)) {
log_error("Failed to read VG data from PV (%s)", name);
__update_lvmcache(fmt, dl, dev, NULL, 0);
goto bad;
}
/* Update VG cache with what we found */
/* vgcache_add(dl->pvd.vg_name, dl->vgd.vg_uuid, dev, fmt); */
if (vg_name && strcmp(vg_name, dl->pvd.vg_name)) {
if (vg_name && strcmp(vg_name, (char *)dl->pvd.vg_name)) {
log_very_verbose("%s is not a member of the VG %s",
name, vg_name);
__update_lvmcache(fmt, dl, dev, NULL, 0);
goto bad;
}
__update_lvmcache(fmt, dl, dev, (char *)dl->vgd.vg_uuid,
dl->vgd.vg_status & VG_EXPORTED);
if (!_read_uuids(dl)) {
log_error("Failed to read PV uuid list from %s", name);
goto bad;
@@ -428,7 +437,7 @@ static void _add_pv_to_list(struct list *head, struct disk_list *data)
list_iterate_items(diskl, head) {
pvd = &diskl->pvd;
if (!strncmp(data->pvd.pv_uuid, pvd->pv_uuid,
if (!strncmp((char *)data->pvd.pv_uuid, (char *)pvd->pv_uuid,
sizeof(pvd->pv_uuid))) {
if (MAJOR(data->dev->dev) != md_major()) {
log_very_verbose("Ignoring duplicate PV %s on "
@@ -447,7 +456,7 @@ static void _add_pv_to_list(struct list *head, struct disk_list *data)
/*
* Build a list of pv_d's structures, allocated from mem.
* We keep track of the first object allocated form the pool
* We keep track of the first object allocated from the pool
* so we can free off all the memory if something goes wrong.
*/
int read_pvs_in_vg(const struct format_type *fmt, const char *vg_name,
@@ -461,7 +470,7 @@ int read_pvs_in_vg(const struct format_type *fmt, const char *vg_name,
struct lvmcache_info *info;
/* Fast path if we already saw this VG and cached the list of PVs */
if (vg_name && (vginfo = vginfo_from_vgname(vg_name)) &&
if (vg_name && (vginfo = vginfo_from_vgname(vg_name, NULL)) &&
vginfo->infos.n) {
list_iterate_items(info, &vginfo->infos) {
dev = info->dev;
@@ -565,7 +574,7 @@ static int _write_lvs(struct disk_list *data)
pos = data->pvd.lv_on_disk.base;
if (!dev_zero(data->dev, pos, data->pvd.lv_on_disk.size)) {
if (!dev_set(data->dev, pos, data->pvd.lv_on_disk.size, 0)) {
log_error("Couldn't zero lv area on device '%s'",
dev_name(data->dev));
return 0;

View File

@@ -73,16 +73,16 @@ struct data_area {
} __attribute__ ((packed));
struct pv_disk {
uint8_t id[2];
int8_t id[2];
uint16_t version; /* lvm version */
struct data_area pv_on_disk;
struct data_area vg_on_disk;
struct data_area pv_uuidlist_on_disk;
struct data_area lv_on_disk;
struct data_area pe_on_disk;
uint8_t pv_uuid[NAME_LEN];
uint8_t vg_name[NAME_LEN];
uint8_t system_id[NAME_LEN]; /* for vgexport/vgimport */
int8_t pv_uuid[NAME_LEN];
int8_t vg_name[NAME_LEN];
int8_t system_id[NAME_LEN]; /* for vgexport/vgimport */
uint32_t pv_major;
uint32_t pv_number;
uint32_t pv_status;
@@ -98,8 +98,8 @@ struct pv_disk {
} __attribute__ ((packed));
struct lv_disk {
uint8_t lv_name[NAME_LEN];
uint8_t vg_name[NAME_LEN];
int8_t lv_name[NAME_LEN];
int8_t vg_name[NAME_LEN];
uint32_t lv_access;
uint32_t lv_status;
uint32_t lv_open;
@@ -122,8 +122,8 @@ struct lv_disk {
} __attribute__ ((packed));
struct vg_disk {
uint8_t vg_uuid[ID_LEN]; /* volume group UUID */
uint8_t vg_name_dummy[NAME_LEN - ID_LEN]; /* rest of v1 VG name */
int8_t vg_uuid[ID_LEN]; /* volume group UUID */
int8_t vg_name_dummy[NAME_LEN - ID_LEN]; /* rest of v1 VG name */
uint32_t vg_number; /* volume group number */
uint32_t vg_access; /* read/write */
uint32_t vg_status; /* active or not */
@@ -148,7 +148,7 @@ struct pe_disk {
struct uuid_list {
struct list list;
char uuid[NAME_LEN];
char uuid[NAME_LEN] __attribute((aligned(8)));
};
struct lvd_list {
@@ -161,17 +161,18 @@ struct disk_list {
struct dm_pool *mem;
struct device *dev;
struct pv_disk pvd;
struct vg_disk vgd;
struct list uuids;
struct list lvds;
struct pe_disk *extents;
struct pv_disk pvd __attribute((aligned(8)));
struct vg_disk vgd __attribute((aligned(8)));
struct list uuids __attribute((aligned(8)));
struct list lvds __attribute((aligned(8)));
struct pe_disk *extents __attribute((aligned(8)));
};
/*
* Layout constants.
*/
#define METADATA_ALIGN 4096UL
#define LVM1_PE_ALIGN (65536UL >> SECTOR_SHIFT) /* PE alignment */
#define METADATA_BASE 0UL
#define PV_SIZE 1024UL
@@ -202,9 +203,10 @@ int write_disks(const struct format_type *fmt, struct list *pvds);
* Functions to translate to between disk and in
* core structures.
*/
int import_pv(struct dm_pool *mem, struct device *dev,
struct volume_group *vg,
struct physical_volume *pv, struct pv_disk *pvd);
int import_pv(const struct format_type *fmt, struct dm_pool *mem,
struct device *dev, struct volume_group *vg,
struct physical_volume *pv, struct pv_disk *pvd,
struct vg_disk *vgd);
int export_pv(struct cmd_context *cmd, struct dm_pool *mem,
struct volume_group *vg,
struct pv_disk *pvd, struct physical_volume *pv);
@@ -222,7 +224,7 @@ int export_extents(struct disk_list *dl, uint32_t lv_num,
int import_pvs(const struct format_type *fmt, struct dm_pool *mem,
struct volume_group *vg,
struct list *pvds, struct list *results, int *count);
struct list *pvds, struct list *results, uint32_t *count);
int import_lvs(struct dm_pool *mem, struct volume_group *vg, struct list *pvds);
int export_lvs(struct disk_list *dl, struct volume_group *vg,
@@ -237,6 +239,7 @@ void export_numbers(struct list *pvds, struct volume_group *vg);
void export_pv_act(struct list *pvds);
int munge_pvd(struct device *dev, struct pv_disk *pvd);
int read_vgd(struct device *dev, struct vg_disk *vgd, struct pv_disk *pvd);
/* blech */
int get_free_vg_number(struct format_instance *fid, struct dev_filter *filter,

View File

@@ -131,10 +131,10 @@ static struct volume_group *_build_vg(struct format_instance *fid,
int partial;
if (!vg)
goto bad;
goto_bad;
if (list_empty(pvs))
goto bad;
goto_bad;
memset(vg, 0, sizeof(*vg));
@@ -146,24 +146,24 @@ static struct volume_group *_build_vg(struct format_instance *fid,
list_init(&vg->tags);
if (!_check_vgs(pvs, &partial))
goto bad;
goto_bad;
dl = list_item(pvs->n, struct disk_list);
if (!import_vg(mem, vg, dl, partial))
goto bad;
goto_bad;
if (!import_pvs(fid->fmt, mem, vg, pvs, &vg->pvs, &vg->pv_count))
goto bad;
goto_bad;
if (!import_lvs(mem, vg, pvs))
goto bad;
goto_bad;
if (!import_extents(fid->fmt->cmd, vg, pvs))
goto bad;
goto_bad;
if (!import_snapshots(mem, vg, pvs))
goto bad;
goto_bad;
return vg;
@@ -173,7 +173,7 @@ static struct volume_group *_build_vg(struct format_instance *fid,
return NULL;
}
static struct volume_group *_vg_read(struct format_instance *fid,
static struct volume_group *_format1_vg_read(struct format_instance *fid,
const char *vg_name,
struct metadata_area *mda)
{
@@ -191,15 +191,11 @@ static struct volume_group *_vg_read(struct format_instance *fid,
vg_name = strip_dir(vg_name, fid->fmt->cmd->dev_dir);
if (!read_pvs_in_vg
(fid->fmt, vg_name, fid->fmt->cmd->filter, mem, &pvs)) {
stack;
goto bad;
}
(fid->fmt, vg_name, fid->fmt->cmd->filter, mem, &pvs))
goto_bad;
if (!(vg = _build_vg(fid, &pvs))) {
stack;
goto bad;
}
if (!(vg = _build_vg(fid, &pvs)))
goto_bad;
bad:
dm_pool_destroy(mem);
@@ -264,7 +260,7 @@ static int _flatten_vg(struct format_instance *fid, struct dm_pool *mem,
return 1;
}
static int _vg_write(struct format_instance *fid, struct volume_group *vg,
static int _format1_vg_write(struct format_instance *fid, struct volume_group *vg,
struct metadata_area *mda)
{
struct dm_pool *mem = dm_pool_create("lvm1 vg_write", 1024 * 10);
@@ -287,7 +283,7 @@ static int _vg_write(struct format_instance *fid, struct volume_group *vg,
return r;
}
static int _pv_read(const struct format_type *fmt, const char *pv_name,
static int _format1_pv_read(const struct format_type *fmt, const char *pv_name,
struct physical_volume *pv, struct list *mdas)
{
struct dm_pool *mem = dm_pool_create("lvm1 pv_read", 1024);
@@ -312,7 +308,7 @@ static int _pv_read(const struct format_type *fmt, const char *pv_name,
goto out;
}
if (!import_pv(fmt->cmd->mem, dl->dev, NULL, pv, &dl->pvd)) {
if (!import_pv(fmt, fmt->cmd->mem, dl->dev, NULL, pv, &dl->pvd, &dl->vgd)) {
stack;
goto out;
}
@@ -326,7 +322,7 @@ static int _pv_read(const struct format_type *fmt, const char *pv_name,
return r;
}
static int _pv_setup(const struct format_type *fmt,
static int _format1_pv_setup(const struct format_type *fmt,
uint64_t pe_start, uint32_t extent_count,
uint32_t extent_size,
int pvmetadatacopies,
@@ -337,8 +333,7 @@ static int _pv_setup(const struct format_type *fmt,
pv->size--;
if (pv->size > MAX_PV_SIZE) {
log_error("Physical volumes cannot be bigger than %s",
display_size(fmt->cmd, (uint64_t) MAX_PV_SIZE,
SIZE_SHORT));
display_size(fmt->cmd, (uint64_t) MAX_PV_SIZE));
return 0;
}
@@ -364,7 +359,7 @@ static int _pv_setup(const struct format_type *fmt,
return 1;
}
static int _lv_setup(struct format_instance *fid, struct logical_volume *lv)
static int _format1_lv_setup(struct format_instance *fid, struct logical_volume *lv)
{
uint64_t max_size = UINT_MAX;
@@ -378,15 +373,14 @@ static int _lv_setup(struct format_instance *fid, struct logical_volume *lv)
}
if (lv->size > max_size) {
log_error("logical volumes cannot be larger than %s",
display_size(fid->fmt->cmd, max_size,
SIZE_SHORT));
display_size(fid->fmt->cmd, max_size));
return 0;
}
return 1;
}
static int _pv_write(const struct format_type *fmt, struct physical_volume *pv,
static int _format1_pv_write(const struct format_type *fmt, struct physical_volume *pv,
struct list *mdas, int64_t sector)
{
struct dm_pool *mem;
@@ -396,7 +390,7 @@ static int _pv_write(const struct format_type *fmt, struct physical_volume *pv,
struct lvmcache_info *info;
if (!(info = lvmcache_add(fmt->labeller, (char *) &pv->id, pv->dev,
pv->vg_name, NULL))) {
pv->vg_name, NULL, 0))) {
stack;
return 0;
}
@@ -410,36 +404,31 @@ static int _pv_write(const struct format_type *fmt, struct physical_volume *pv,
/* Ensure any residual PE structure is gone */
pv->pe_size = pv->pe_count = 0;
pv->pe_start = PE_ALIGN;
pv->pe_start = LVM1_PE_ALIGN;
if (!(mem = dm_pool_create("lvm1 pv_write", 1024))) {
stack;
return 0;
}
if (!(dl = dm_pool_alloc(mem, sizeof(*dl)))) {
stack;
goto bad;
}
if (!(dl = dm_pool_alloc(mem, sizeof(*dl))))
goto_bad;
dl->mem = mem;
dl->dev = pv->dev;
if (!export_pv(fmt->cmd, mem, NULL, &dl->pvd, pv)) {
stack;
goto bad;
}
if (!export_pv(fmt->cmd, mem, NULL, &dl->pvd, pv))
goto_bad;
/* must be set to be able to zero gap after PV structure in
dev_write in order to make other disk tools happy */
dl->pvd.pv_on_disk.base = METADATA_BASE;
dl->pvd.pv_on_disk.size = PV_SIZE;
dl->pvd.pe_on_disk.base = PE_ALIGN << SECTOR_SHIFT;
dl->pvd.pe_on_disk.base = LVM1_PE_ALIGN << SECTOR_SHIFT;
list_add(&pvs, &dl->list);
if (!write_disks(fmt, &pvs)) {
stack;
goto bad;
}
if (!write_disks(fmt, &pvs))
goto_bad;
dm_pool_destroy(mem);
return 1;
@@ -449,7 +438,7 @@ static int _pv_write(const struct format_type *fmt, struct physical_volume *pv,
return 0;
}
static int _vg_setup(struct format_instance *fid, struct volume_group *vg)
static int _format1_vg_setup(struct format_instance *fid, struct volume_group *vg)
{
/* just check max_pv and max_lv */
if (!vg->max_lv || vg->max_lv >= MAX_LV)
@@ -460,18 +449,15 @@ static int _vg_setup(struct format_instance *fid, struct volume_group *vg)
if (vg->extent_size > MAX_PE_SIZE || vg->extent_size < MIN_PE_SIZE) {
log_error("Extent size must be between %s and %s",
display_size(fid->fmt->cmd, (uint64_t) MIN_PE_SIZE,
SIZE_SHORT),
display_size(fid->fmt->cmd, (uint64_t) MAX_PE_SIZE,
SIZE_SHORT));
display_size(fid->fmt->cmd, (uint64_t) MIN_PE_SIZE),
display_size(fid->fmt->cmd, (uint64_t) MAX_PE_SIZE));
return 0;
}
if (vg->extent_size % MIN_PE_SIZE) {
log_error("Extent size must be multiple of %s",
display_size(fid->fmt->cmd, (uint64_t) MIN_PE_SIZE,
SIZE_SHORT));
display_size(fid->fmt->cmd, (uint64_t) MIN_PE_SIZE));
return 0;
}
@@ -484,8 +470,8 @@ static int _vg_setup(struct format_instance *fid, struct volume_group *vg)
return 1;
}
static int _segtype_supported (struct format_instance *fid,
struct segment_type *segtype)
static int _format1_segtype_supported(struct format_instance *fid,
const struct segment_type *segtype)
{
if (!(segtype->flags & SEG_FORMAT1_SUPPORT)) {
stack;
@@ -496,12 +482,13 @@ static int _segtype_supported (struct format_instance *fid,
}
static struct metadata_area_ops _metadata_format1_ops = {
vg_read:_vg_read,
vg_write:_vg_write,
.vg_read = _format1_vg_read,
.vg_write = _format1_vg_write,
};
static struct format_instance *_create_instance(const struct format_type *fmt,
static struct format_instance *_format1_create_instance(const struct format_type *fmt,
const char *vgname,
const char *vgid,
void *private)
{
struct format_instance *fid;
@@ -529,26 +516,26 @@ static struct format_instance *_create_instance(const struct format_type *fmt,
return fid;
}
static void _destroy_instance(struct format_instance *fid)
static void _format1_destroy_instance(struct format_instance *fid)
{
return;
}
static void _destroy(const struct format_type *fmt)
static void _format1_destroy(const struct format_type *fmt)
{
dm_free((void *) fmt);
}
static struct format_handler _format1_ops = {
pv_read:_pv_read,
pv_setup:_pv_setup,
pv_write:_pv_write,
lv_setup:_lv_setup,
vg_setup:_vg_setup,
segtype_supported:_segtype_supported,
create_instance:_create_instance,
destroy_instance:_destroy_instance,
destroy:_destroy,
.pv_read = _format1_pv_read,
.pv_setup = _format1_pv_setup,
.pv_write = _format1_pv_write,
.lv_setup = _format1_lv_setup,
.vg_setup = _format1_vg_setup,
.segtype_supported = _format1_segtype_supported,
.create_instance = _format1_create_instance,
.destroy_instance = _format1_destroy_instance,
.destroy = _format1_destroy,
};
#ifdef LVM1_INTERNAL

View File

@@ -24,6 +24,7 @@
#include "toolcontext.h"
#include "segtype.h"
#include "pv_alloc.h"
#include "display.h"
#include <time.h>
@@ -47,25 +48,30 @@ static char *_create_lv_name(struct dm_pool *mem, const char *full_name)
return dm_pool_strdup(mem, ptr);
}
int import_pv(struct dm_pool *mem, struct device *dev,
struct volume_group *vg,
struct physical_volume *pv, struct pv_disk *pvd)
int import_pv(const struct format_type *fmt, struct dm_pool *mem,
struct device *dev, struct volume_group *vg,
struct physical_volume *pv, struct pv_disk *pvd,
struct vg_disk *vgd)
{
uint64_t size;
memset(pv, 0, sizeof(*pv));
memcpy(&pv->id, pvd->pv_uuid, ID_LEN);
pv->dev = dev;
if (!(pv->vg_name = dm_pool_strdup(mem, pvd->vg_name))) {
if (!(pv->vg_name = dm_pool_strdup(mem, (char *)pvd->vg_name))) {
stack;
return 0;
}
memcpy(&pv->vgid, vgd->vg_uuid, sizeof(vg->id));
/* Store system_id from first PV if PV belongs to a VG */
if (vg && !*vg->system_id)
strncpy(vg->system_id, pvd->system_id, NAME_LEN);
strncpy(vg->system_id, (char *)pvd->system_id, NAME_LEN);
if (vg &&
strncmp(vg->system_id, pvd->system_id, sizeof(pvd->system_id)))
strncmp(vg->system_id, (char *)pvd->system_id, sizeof(pvd->system_id)))
log_very_verbose("System ID %s on %s differs from %s for "
"volume group", pvd->system_id,
dev_name(pv->dev), vg->system_id);
@@ -86,6 +92,25 @@ int import_pv(struct dm_pool *mem, struct device *dev,
pv->pe_count = pvd->pe_total;
pv->pe_alloc_count = 0;
/* Fix up pv size if missing */
if (!pv->size) {
if (!dev_get_size(dev, &pv->size)) {
log_error("%s: Couldn't get size.", dev_name(pv->dev));
return 0;
}
log_verbose("Fixing up missing format1 size (%s) "
"for PV %s", display_size(fmt->cmd, pv->size),
dev_name(pv->dev));
if (vg) {
size = pv->pe_count * (uint64_t) vg->extent_size +
pv->pe_start;
if (size > pv->size)
log_error("WARNING: Physical Volume %s is too "
"large for underlying device",
dev_name(pv->dev));
}
}
list_init(&pv->tags);
list_init(&pv->segments);
@@ -100,7 +125,7 @@ int import_pv(struct dm_pool *mem, struct device *dev,
static int _system_id(struct cmd_context *cmd, char *s, const char *prefix)
{
if (lvm_snprintf(s, NAME_LEN, "%s%s%lu",
if (dm_snprintf(s, NAME_LEN, "%s%s%lu",
prefix, cmd->hostname, time(NULL)) < 0) {
log_error("Generated system_id too long");
return 0;
@@ -121,19 +146,17 @@ int export_pv(struct cmd_context *cmd, struct dm_pool *mem,
memcpy(pvd->pv_uuid, pv->id.uuid, ID_LEN);
if (!_check_vg_name(pv->vg_name)) {
stack;
return 0;
if (pv->vg_name) {
if (!_check_vg_name(pv->vg_name)) {
stack;
return 0;
}
strncpy((char *)pvd->vg_name, pv->vg_name, sizeof(pvd->vg_name));
}
memset(pvd->vg_name, 0, sizeof(pvd->vg_name));
if (pv->vg_name)
strncpy(pvd->vg_name, pv->vg_name, sizeof(pvd->vg_name));
/* Preserve existing system_id if it exists */
if (vg && *vg->system_id)
strncpy(pvd->system_id, vg->system_id, sizeof(pvd->system_id));
strncpy((char *)pvd->system_id, vg->system_id, sizeof(pvd->system_id));
/* Is VG already exported or being exported? */
if (vg && (vg->status & EXPORTED_VG)) {
@@ -141,24 +164,24 @@ int export_pv(struct cmd_context *cmd, struct dm_pool *mem,
if (!*vg->system_id ||
strncmp(vg->system_id, EXPORTED_TAG,
sizeof(EXPORTED_TAG) - 1)) {
if (!_system_id(cmd, pvd->system_id, EXPORTED_TAG)) {
if (!_system_id(cmd, (char *)pvd->system_id, EXPORTED_TAG)) {
stack;
return 0;
}
}
if (strlen(pvd->vg_name) + sizeof(EXPORTED_TAG) >
if (strlen((char *)pvd->vg_name) + sizeof(EXPORTED_TAG) >
sizeof(pvd->vg_name)) {
log_error("Volume group name %s too long to export",
pvd->vg_name);
return 0;
}
strcat(pvd->vg_name, EXPORTED_TAG);
strcat((char *)pvd->vg_name, EXPORTED_TAG);
}
/* Is VG being imported? */
if (vg && !(vg->status & EXPORTED_VG) && *vg->system_id &&
!strncmp(vg->system_id, EXPORTED_TAG, sizeof(EXPORTED_TAG) - 1)) {
if (!_system_id(cmd, pvd->system_id, IMPORTED_TAG)) {
if (!_system_id(cmd, (char *)pvd->system_id, IMPORTED_TAG)) {
stack;
return 0;
}
@@ -166,7 +189,7 @@ int export_pv(struct cmd_context *cmd, struct dm_pool *mem,
/* Generate system_id if PV is in VG */
if (!pvd->system_id || !*pvd->system_id)
if (!_system_id(cmd, pvd->system_id, "")) {
if (!_system_id(cmd, (char *)pvd->system_id, "")) {
stack;
return 0;
}
@@ -174,8 +197,8 @@ int export_pv(struct cmd_context *cmd, struct dm_pool *mem,
/* Update internal system_id if we changed it */
if (vg &&
(!*vg->system_id ||
strncmp(vg->system_id, pvd->system_id, sizeof(pvd->system_id))))
strncpy(vg->system_id, pvd->system_id, NAME_LEN);
strncmp(vg->system_id, (char *)pvd->system_id, sizeof(pvd->system_id))))
strncpy(vg->system_id, (char *)pvd->system_id, NAME_LEN);
//pvd->pv_major = MAJOR(pv->dev);
@@ -201,12 +224,12 @@ int import_vg(struct dm_pool *mem,
struct vg_disk *vgd = &dl->vgd;
memcpy(vg->id.uuid, vgd->vg_uuid, ID_LEN);
if (!_check_vg_name(dl->pvd.vg_name)) {
if (!_check_vg_name((char *)dl->pvd.vg_name)) {
stack;
return 0;
}
if (!(vg->name = dm_pool_strdup(mem, dl->pvd.vg_name))) {
if (!(vg->name = dm_pool_strdup(mem, (char *)dl->pvd.vg_name))) {
stack;
return 0;
}
@@ -289,7 +312,7 @@ int import_lv(struct dm_pool *mem, struct logical_volume *lv, struct lv_disk *lv
{
lvid_from_lvnum(&lv->lvid, &lv->vg->id, lvd->lv_number);
if (!(lv->name = _create_lv_name(mem, lvd->lv_name))) {
if (!(lv->name = _create_lv_name(mem, (char *)lvd->lv_name))) {
stack;
return 0;
}
@@ -339,10 +362,10 @@ static void _export_lv(struct lv_disk *lvd, struct volume_group *vg,
struct logical_volume *lv, const char *dev_dir)
{
memset(lvd, 0, sizeof(*lvd));
snprintf(lvd->lv_name, sizeof(lvd->lv_name), "%s%s/%s",
snprintf((char *)lvd->lv_name, sizeof(lvd->lv_name), "%s%s/%s",
dev_dir, vg->name, lv->name);
strcpy(lvd->vg_name, vg->name);
strcpy((char *)lvd->vg_name, vg->name);
if (lv->status & LVM_READ)
lvd->lv_access |= LV_READ;
@@ -413,7 +436,7 @@ int export_extents(struct disk_list *dl, uint32_t lv_num,
int import_pvs(const struct format_type *fmt, struct dm_pool *mem,
struct volume_group *vg,
struct list *pvds, struct list *results, int *count)
struct list *pvds, struct list *results, uint32_t *count)
{
struct disk_list *dl;
struct pv_list *pvl;
@@ -426,7 +449,7 @@ int import_pvs(const struct format_type *fmt, struct dm_pool *mem,
return 0;
}
if (!import_pv(mem, dl->dev, vg, pvl->pv, &dl->pvd)) {
if (!import_pv(fmt, mem, dl->dev, vg, pvl->pv, &dl->pvd, &dl->vgd)) {
stack;
return 0;
}
@@ -475,7 +498,7 @@ int import_lvs(struct dm_pool *mem, struct volume_group *vg, struct list *pvds)
list_iterate_items(ll, &dl->lvds) {
lvd = &ll->lvd;
if (!find_lv(vg, lvd->lv_name) &&
if (!find_lv(vg, (char *)lvd->lv_name) &&
!_add_lv(mem, vg, lvd)) {
stack;
return 0;
@@ -583,14 +606,14 @@ int import_snapshots(struct dm_pool *mem, struct volume_group *vg,
lvnum = lvd->lv_number;
if (lvnum > MAX_LV) {
if (lvnum >= MAX_LV) {
log_err("Logical volume number "
"out of bounds.");
return 0;
}
if (!lvs[lvnum] &&
!(lvs[lvnum] = find_lv(vg, lvd->lv_name))) {
!(lvs[lvnum] = find_lv(vg, (char *)lvd->lv_name))) {
log_err("Couldn't find logical volume '%s'.",
lvd->lv_name);
return 0;

View File

@@ -59,22 +59,16 @@ static struct dm_hash_table *_create_lv_maps(struct dm_pool *mem,
if (ll->lv->status & SNAPSHOT)
continue;
if (!(lvm = dm_pool_alloc(mem, sizeof(*lvm)))) {
stack;
goto bad;
}
if (!(lvm = dm_pool_alloc(mem, sizeof(*lvm))))
goto_bad;
lvm->lv = ll->lv;
if (!(lvm->map = dm_pool_zalloc(mem, sizeof(*lvm->map)
* ll->lv->le_count))) {
stack;
goto bad;
}
* ll->lv->le_count)))
goto_bad;
if (!dm_hash_insert(maps, ll->lv->name, lvm)) {
stack;
goto bad;
}
if (!dm_hash_insert(maps, ll->lv->name, lvm))
goto_bad;
}
return maps;
@@ -93,7 +87,7 @@ static int _fill_lv_array(struct lv_map **lvs,
memset(lvs, 0, sizeof(*lvs) * MAX_LV);
list_iterate_items(ll, &dl->lvds) {
if (!(lvm = dm_hash_lookup(maps, strrchr(ll->lvd.lv_name, '/')
if (!(lvm = dm_hash_lookup(maps, strrchr((char *)ll->lvd.lv_name, '/')
+ 1))) {
log_err("Physical volume (%s) contains an "
"unknown logical volume (%s).",
@@ -140,7 +134,12 @@ static int _fill_maps(struct dm_hash_table *maps, struct volume_group *vg,
lvm = lvms[lv_num];
if (!lvm) {
log_err("invalid lv in extent map");
log_error("Invalid LV in extent map "
"(PV %s, PE %" PRIu32
", LV %" PRIu32
", LE %" PRIu32 ")",
dev_name(pv->dev), i,
lv_num, e[i].le_num);
return 0;
}
@@ -198,6 +197,19 @@ static int _check_maps_are_complete(struct dm_hash_table *maps)
return 1;
}
static uint32_t _area_length(struct lv_map *lvm, uint32_t le)
{
uint32_t len = 0;
do
len++;
while ((lvm->map[le + len].pv == lvm->map[le].pv) &&
(lvm->map[le].pv &&
lvm->map[le + len].pe == lvm->map[le].pe + len));
return len;
}
static int _read_linear(struct cmd_context *cmd, struct lv_map *lvm)
{
uint32_t le = 0, len;
@@ -210,13 +222,7 @@ static int _read_linear(struct cmd_context *cmd, struct lv_map *lvm)
}
while (le < lvm->lv->le_count) {
len = 0;
do
len++;
while ((lvm->map[le + len].pv == lvm->map[le].pv) &&
(lvm->map[le].pv &&
lvm->map[le + len].pe == lvm->map[le].pe + len));
len = _area_length(lvm, le);
if (!(seg = alloc_lv_segment(cmd->mem, segtype, lvm->lv, le,
len, 0, 0, NULL, 1, len, 0, 0, 0))) {
@@ -225,10 +231,8 @@ static int _read_linear(struct cmd_context *cmd, struct lv_map *lvm)
}
if (!set_lv_segment_area_pv(seg, 0, lvm->map[le].pv,
lvm->map[le].pe)) {
stack;
return 0;
}
lvm->map[le].pe))
return_0;
list_add(&lvm->lv->segments, &seg->list);
@@ -239,7 +243,8 @@ static int _read_linear(struct cmd_context *cmd, struct lv_map *lvm)
}
static int _check_stripe(struct lv_map *lvm, uint32_t area_count,
uint32_t seg_len, uint32_t base_le, uint32_t len)
uint32_t area_len, uint32_t base_le,
uint32_t total_area_len)
{
uint32_t st;
@@ -247,11 +252,11 @@ static int _check_stripe(struct lv_map *lvm, uint32_t area_count,
* Is the next physical extent in every stripe adjacent to the last?
*/
for (st = 0; st < area_count; st++)
if ((lvm->map[base_le + st * len + seg_len].pv !=
lvm->map[base_le + st * len].pv) ||
(lvm->map[base_le + st * len].pv &&
lvm->map[base_le + st * len + seg_len].pe !=
lvm->map[base_le + st * len].pe + seg_len))
if ((lvm->map[base_le + st * total_area_len + area_len].pv !=
lvm->map[base_le + st * total_area_len].pv) ||
(lvm->map[base_le + st * total_area_len].pv &&
lvm->map[base_le + st * total_area_len + area_len].pe !=
lvm->map[base_le + st * total_area_len].pe + area_len))
return 0;
return 1;
@@ -259,7 +264,7 @@ static int _check_stripe(struct lv_map *lvm, uint32_t area_count,
static int _read_stripes(struct cmd_context *cmd, struct lv_map *lvm)
{
uint32_t st, le = 0, len;
uint32_t st, first_area_le = 0, total_area_len;
uint32_t area_len;
struct lv_segment *seg;
struct segment_type *segtype;
@@ -272,26 +277,25 @@ static int _read_stripes(struct cmd_context *cmd, struct lv_map *lvm)
"with logical extent count (%u) for %s",
lvm->stripes, lvm->lv->le_count, lvm->lv->name);
}
len = lvm->lv->le_count / lvm->stripes;
if (!(segtype = get_segtype_from_string(cmd, "striped"))) {
stack;
return 0;
}
total_area_len = lvm->lv->le_count / lvm->stripes;
while (le < len) {
if (!(segtype = get_segtype_from_string(cmd, "striped")))
return_0;
while (first_area_le < total_area_len) {
area_len = 1;
/*
* Find how many blocks are contiguous in all stripes
* Find how many extents are contiguous in all stripes
* and so can form part of this segment
*/
while (_check_stripe(lvm, lvm->stripes,
area_len * lvm->stripes, le, len))
area_len, first_area_le, total_area_len))
area_len++;
if (!(seg = alloc_lv_segment(cmd->mem, segtype, lvm->lv,
lvm->stripes * le,
lvm->stripes * first_area_le,
lvm->stripes * area_len,
0, lvm->stripe_size, NULL,
lvm->stripes,
@@ -305,15 +309,13 @@ static int _read_stripes(struct cmd_context *cmd, struct lv_map *lvm)
*/
for (st = 0; st < seg->area_count; st++)
if (!set_lv_segment_area_pv(seg, st,
lvm->map[le + st * len].pv,
lvm->map[le + st * len].pe)) {
stack;
return 0;
}
lvm->map[first_area_le + st * total_area_len].pv,
lvm->map[first_area_le + st * total_area_len].pe))
return_0;
list_add(&lvm->lv->segments, &seg->list);
le += seg->len;
first_area_le += area_len;
}
return 1;

View File

@@ -19,16 +19,18 @@
/*
* Only works with powers of 2.
*/
static inline uint32_t _round_up(uint32_t n, uint32_t size)
static uint32_t _round_up(uint32_t n, uint32_t size)
{
size--;
return (n + size) & ~size;
}
static inline uint32_t _div_up(uint32_t n, uint32_t size)
/* Unused.
static uint32_t _div_up(uint32_t n, uint32_t size)
{
return _round_up(n, size) / size;
}
*/
/*
* Each chunk of metadata should be aligned to
@@ -151,7 +153,7 @@ int calculate_extent_count(struct physical_volume *pv, uint32_t extent_size,
if (pe_start && end < pe_start)
end = pe_start;
pvd->pe_start = _round_up(end, PE_ALIGN);
pvd->pe_start = _round_up(end, LVM1_PE_ALIGN);
} while ((pvd->pe_start + (pvd->pe_total * extent_size))
> pv->size);

View File

@@ -30,7 +30,7 @@ static void _not_supported(const char *op)
op);
}
static int _can_handle(struct labeller *l, char *buf, uint64_t sector)
static int _lvm1_can_handle(struct labeller *l, void *buf, uint64_t sector)
{
struct pv_disk *pvd = (struct pv_disk *) buf;
uint32_t version;
@@ -48,21 +48,30 @@ static int _can_handle(struct labeller *l, char *buf, uint64_t sector)
return 0;
}
static int _write(struct label *label, char *buf)
static int _lvm1_write(struct label *label, void *buf)
{
_not_supported("write");
return 0;
}
static int _read(struct labeller *l, struct device *dev, char *buf,
static int _lvm1_read(struct labeller *l, struct device *dev, void *buf,
struct label **label)
{
struct pv_disk *pvd = (struct pv_disk *) buf;
struct vg_disk vgd;
struct lvmcache_info *info;
const char *vgid = NULL;
unsigned exported = 0;
munge_pvd(dev, pvd);
if (!(info = lvmcache_add(l, pvd->pv_uuid, dev, pvd->vg_name, NULL))) {
if (*pvd->vg_name && read_vgd(dev, &vgd, pvd)) {
vgid = (char *) vgd.vg_uuid;
exported = pvd->pv_status & VG_EXPORTED;
}
if (!(info = lvmcache_add(l, (char *)pvd->pv_uuid, dev, (char *)pvd->vg_name, vgid,
exported))) {
stack;
return 0;
}
@@ -76,31 +85,31 @@ static int _read(struct labeller *l, struct device *dev, char *buf,
return 1;
}
static int _initialise_label(struct labeller *l, struct label *label)
static int _lvm1_initialise_label(struct labeller *l, struct label *label)
{
strcpy(label->type, "LVM1");
return 1;
}
static void _destroy_label(struct labeller *l, struct label *label)
static void _lvm1_destroy_label(struct labeller *l, struct label *label)
{
return;
}
static void _destroy(struct labeller *l)
static void _lvm1_destroy(struct labeller *l)
{
dm_free(l);
}
struct label_ops _lvm1_ops = {
can_handle:_can_handle,
write:_write,
read:_read,
verify:_can_handle,
initialise_label:_initialise_label,
destroy_label:_destroy_label,
destroy:_destroy
.can_handle = _lvm1_can_handle,
.write = _lvm1_write,
.read = _lvm1_read,
.verify = _lvm1_can_handle,
.initialise_label = _lvm1_initialise_label,
.destroy_label = _lvm1_destroy_label,
.destroy = _lvm1_destroy,
};
struct labeller *lvm1_labeller_create(struct format_type *fmt)

View File

@@ -46,7 +46,7 @@ int get_free_vg_number(struct format_instance *fid, struct dev_filter *filter,
memset(numbers, 0, sizeof(numbers));
list_iterate_items(dl, &all_pvs) {
if (!*dl->pvd.vg_name || !strcmp(dl->pvd.vg_name, candidate_vg))
if (!*dl->pvd.vg_name || !strcmp((char *)dl->pvd.vg_name, candidate_vg))
continue;
numbers[dl->vgd.vg_number] = 1;

View File

@@ -36,7 +36,7 @@ static int __read_pool_disk(const struct format_type *fmt, struct device *dev,
struct dm_pool *mem, struct pool_list *pl,
const char *vg_name)
{
char buf[512];
char buf[512] __attribute((aligned(8)));
/* FIXME: Need to check the cache here first */
if (!dev_read(dev, UINT64_C(0), 512, buf)) {
@@ -59,7 +59,7 @@ static void _add_pl_to_list(struct list *head, struct pool_list *data)
list_iterate_items(pl, head) {
if (id_equal(&data->pv_uuid, &pl->pv_uuid)) {
char uuid[ID_LEN + 7];
char uuid[ID_LEN + 7] __attribute((aligned(8)));
id_write_format(&pl->pv_uuid, uuid, ID_LEN + 7);
@@ -84,7 +84,7 @@ int read_pool_label(struct pool_list *pl, struct labeller *l,
struct lvmcache_info *info;
struct id pvid;
struct id vgid;
char uuid[ID_LEN + 7];
char uuid[ID_LEN + 7] __attribute((aligned(8)));
struct pool_disk *pd = &pl->pd;
pool_label_in(pd, buf);
@@ -98,7 +98,7 @@ int read_pool_label(struct pool_list *pl, struct labeller *l,
log_debug("Calculated uuid %s for %s", uuid, pd->pl_pool_name);
if (!(info = lvmcache_add(l, (char *) &pvid, dev, pd->pl_pool_name,
(char *) &vgid))) {
(char *) &vgid, 0))) {
stack;
return 0;
}
@@ -128,7 +128,7 @@ int read_pool_label(struct pool_list *pl, struct labeller *l,
* be able to interpret ondisk labels correctly. Always use
* this function before writing to disk.
*/
void pool_label_out(struct pool_disk *pl, char *buf)
void pool_label_out(struct pool_disk *pl, void *buf)
{
struct pool_disk *bufpl = (struct pool_disk *) buf;
@@ -163,7 +163,7 @@ void pool_label_out(struct pool_disk *pl, char *buf)
* correctly. Always use this function before using labels that
* were read from disk.
*/
void pool_label_in(struct pool_disk *pl, char *buf)
void pool_label_in(struct pool_disk *pl, void *buf)
{
struct pool_disk *bufpl = (struct pool_disk *) buf;
@@ -248,7 +248,7 @@ static int _read_vg_pds(const struct format_type *fmt, struct dm_pool *mem,
uint32_t sp_count = 0;
uint32_t *sp_devs = NULL;
int i;
uint32_t i;
/* FIXME: maybe should return a different error in memory
* allocation failure */
@@ -314,7 +314,7 @@ int read_pool_pds(const struct format_type *fmt, const char *vg_name,
/*
* If the cache scanning doesn't work, this will never work
*/
if (vg_name && (vginfo = vginfo_from_vgname(vg_name)) &&
if (vg_name && (vginfo = vginfo_from_vgname(vg_name, NULL)) &&
vginfo->infos.n) {
if (_read_vg_pds(fmt, mem, vginfo, pdhead, &totaldevs)) {

View File

@@ -134,8 +134,8 @@ struct user_device {
int read_pool_label(struct pool_list *pl, struct labeller *l,
struct device *dev, char *buf, struct label **label);
void pool_label_out(struct pool_disk *pl, char *buf);
void pool_label_in(struct pool_disk *pl, char *buf);
void pool_label_out(struct pool_disk *pl, void *buf);
void pool_label_in(struct pool_disk *pl, void *buf);
void get_pool_uuid(char *uuid, uint64_t poolid, uint32_t spid, uint32_t devid);
int import_pool_vg(struct volume_group *vg, struct dm_pool *mem, struct list *pls);
int import_pool_lvs(struct volume_group *vg, struct dm_pool *mem,

View File

@@ -79,7 +79,8 @@ static struct user_subpool *_build_usp(struct list *pls, struct dm_pool *mem,
static int _check_usp(char *vgname, struct user_subpool *usp, int sp_count)
{
int i, j;
int i;
unsigned j;
for (i = 0; i < sp_count; i++) {
if (!usp[i].initialized) {
@@ -88,7 +89,7 @@ static int _check_usp(char *vgname, struct user_subpool *usp, int sp_count)
}
for (j = 0; j < usp[i].num_devs; j++) {
if (!usp[i].devs[j].initialized) {
log_error("Missing device %d for subpool %d"
log_error("Missing device %u for subpool %d"
" in pool %s", j, i, vgname);
return 0;
}
@@ -169,7 +170,7 @@ static struct volume_group *_build_vg_from_pds(struct format_instance
return vg;
}
static struct volume_group *_vg_read(struct format_instance *fid,
static struct volume_group *_pool_vg_read(struct format_instance *fid,
const char *vg_name,
struct metadata_area *mda)
{
@@ -206,7 +207,7 @@ static struct volume_group *_vg_read(struct format_instance *fid,
return vg;
}
static int _pv_setup(const struct format_type *fmt,
static int _pool_pv_setup(const struct format_type *fmt,
uint64_t pe_start, uint32_t extent_count,
uint32_t extent_size,
int pvmetadatacopies,
@@ -216,7 +217,7 @@ static int _pv_setup(const struct format_type *fmt,
return 1;
}
static int _pv_read(const struct format_type *fmt, const char *pv_name,
static int _pool_pv_read(const struct format_type *fmt, const char *pv_name,
struct physical_volume *pv, struct list *mdas)
{
struct dm_pool *mem = dm_pool_create("pool pv_read", 1024);
@@ -262,12 +263,13 @@ static int _pv_read(const struct format_type *fmt, const char *pv_name,
/* *INDENT-OFF* */
static struct metadata_area_ops _metadata_format_pool_ops = {
vg_read:_vg_read,
.vg_read = _pool_vg_read,
};
/* *INDENT-ON* */
static struct format_instance *_create_instance(const struct format_type *fmt,
static struct format_instance *_pool_create_instance(const struct format_type *fmt,
const char *vgname,
const char *vgid,
void *private)
{
struct format_instance *fid;
@@ -297,23 +299,23 @@ static struct format_instance *_create_instance(const struct format_type *fmt,
return fid;
}
static void _destroy_instance(struct format_instance *fid)
static void _pool_destroy_instance(struct format_instance *fid)
{
return;
}
static void _destroy(const struct format_type *fmt)
static void _pool_destroy(const struct format_type *fmt)
{
dm_free((void *) fmt);
}
/* *INDENT-OFF* */
static struct format_handler _format_pool_ops = {
pv_read:_pv_read,
pv_setup:_pv_setup,
create_instance:_create_instance,
destroy_instance:_destroy_instance,
destroy:_destroy,
.pv_read = _pool_pv_read,
.pv_setup = _pool_pv_setup,
.create_instance = _pool_create_instance,
.destroy_instance = _pool_destroy_instance,
.destroy = _pool_destroy,
};
/* *INDENT-ON */

View File

@@ -165,6 +165,7 @@ int import_pool_pv(const struct format_type *fmt, struct dm_pool *mem,
log_error("Unable to duplicate vg_name string");
return 0;
}
memcpy(&pv->vgid, &vg->id, sizeof(vg->id));
pv->status = 0;
pv->size = pd->pl_blocks;
pv->pe_size = POOL_PE_SIZE;
@@ -202,7 +203,7 @@ static int _add_stripe_seg(struct dm_pool *mem,
{
struct lv_segment *seg;
struct segment_type *segtype;
int j;
unsigned j;
uint32_t area_len;
if (usp->striping & (usp->striping - 1)) {
@@ -248,7 +249,7 @@ static int _add_linear_seg(struct dm_pool *mem,
{
struct lv_segment *seg;
struct segment_type *segtype;
int j;
unsigned j;
uint32_t area_len;
if (!(segtype = get_segtype_from_string(lv->vg->cmd, "striped"))) {

View File

@@ -23,13 +23,13 @@
#include <sys/stat.h>
#include <fcntl.h>
static void _not_supported(const char *op)
static void _pool_not_supported(const char *op)
{
log_error("The '%s' operation is not supported for the pool labeller.",
op);
}
static int _can_handle(struct labeller *l, char *buf, uint64_t sector)
static int _pool_can_handle(struct labeller *l, void *buf, uint64_t sector)
{
struct pool_disk pd;
@@ -50,13 +50,13 @@ static int _can_handle(struct labeller *l, char *buf, uint64_t sector)
return 0;
}
static int _write(struct label *label, char *buf)
static int _pool_write(struct label *label, void *buf)
{
_not_supported("write");
_pool_not_supported("write");
return 0;
}
static int _read(struct labeller *l, struct device *dev, char *buf,
static int _pool_read(struct labeller *l, struct device *dev, void *buf,
struct label **label)
{
struct pool_list pl;
@@ -64,31 +64,31 @@ static int _read(struct labeller *l, struct device *dev, char *buf,
return read_pool_label(&pl, l, dev, buf, label);
}
static int _initialise_label(struct labeller *l, struct label *label)
static int _pool_initialise_label(struct labeller *l, struct label *label)
{
strcpy(label->type, "POOL");
return 1;
}
static void _destroy_label(struct labeller *l, struct label *label)
static void _pool_destroy_label(struct labeller *l, struct label *label)
{
return;
}
static void _destroy(struct labeller *l)
static void _label_pool_destroy(struct labeller *l)
{
dm_free(l);
}
struct label_ops _pool_ops = {
can_handle:_can_handle,
write:_write,
read:_read,
verify:_can_handle,
initialise_label:_initialise_label,
destroy_label:_destroy_label,
destroy:_destroy
.can_handle = _pool_can_handle,
.write = _pool_write,
.read = _pool_read,
.verify = _pool_can_handle,
.initialise_label = _pool_initialise_label,
.destroy_label = _pool_destroy_label,
.destroy = _label_pool_destroy,
};
struct labeller *pool_labeller_create(struct format_type *fmt)

View File

@@ -87,7 +87,7 @@ static int _split_vg(const char *filename, char *vgname, size_t vg_size,
return 1;
}
static void _insert_file(struct list *head, struct archive_file *b)
static void _insert_archive_file(struct list *head, struct archive_file *b)
{
struct archive_file *bf = NULL;
@@ -107,7 +107,7 @@ static void _insert_file(struct list *head, struct archive_file *b)
list_add_h(&bf->list, &b->list);
}
static char *_join(struct dm_pool *mem, const char *dir, const char *name)
static char *_join_file_to_dir(struct dm_pool *mem, const char *dir, const char *name)
{
if (!dm_pool_begin_object(mem, 32) ||
!dm_pool_grow_object(mem, dir, strlen(dir)) ||
@@ -161,7 +161,7 @@ static struct list *_scan_archive(struct dm_pool *mem,
if (strcmp(vgname, vgname_found))
continue;
if (!(path = _join(mem, dir, dirent[i]->d_name))) {
if (!(path = _join_file_to_dir(mem, dir, dirent[i]->d_name))) {
stack;
goto out;
}
@@ -181,7 +181,7 @@ static struct list *_scan_archive(struct dm_pool *mem,
/*
* Insert it to the correct part of the list.
*/
_insert_file(results, af);
_insert_archive_file(results, af);
}
out:
@@ -207,8 +207,8 @@ static void _remove_expired(struct list *archives, uint32_t archives_size,
/* Convert retain_days into the time after which we must retain */
retain_time = time(NULL) - (time_t) retain_days *SECS_PER_DAY;
/* Assume list is ordered oldest first (by index) */
list_iterate_items(bf, archives) {
/* Assume list is ordered newest first (by index) */
list_iterate_back_items(bf, archives) {
/* Get the mtime of the file and unlink if too old */
if (stat(bf->path, &sb)) {
log_sys_error("stat", bf->path);
@@ -249,17 +249,23 @@ int archive_vg(struct volume_group *vg,
if (!(fp = fdopen(fd, "w"))) {
log_err("Couldn't create FILE object for archive.");
close(fd);
if (close(fd))
log_sys_error("close", temp_file);
return 0;
}
if (!text_vg_export_file(vg, desc, fp)) {
stack;
fclose(fp);
if (fclose(fp))
log_sys_error("fclose", temp_file);
return 0;
}
fclose(fp);
if (fclose(fp)) {
log_sys_error("fclose", temp_file);
/* Leave file behind as evidence of failure */
return 0;
}
/*
* Now we want to rename this file to <vg>_index.vg.
@@ -277,7 +283,7 @@ int archive_vg(struct volume_group *vg,
}
for (i = 0; i < 10; i++) {
if (lvm_snprintf(archive_name, sizeof(archive_name),
if (dm_snprintf(archive_name, sizeof(archive_name),
"%s/%s_%05u.vg", dir, vg->name, ix) < 0) {
log_error("Archive file name too long.");
return 0;
@@ -311,7 +317,7 @@ static void _display_archive(struct cmd_context *cmd, struct archive_file *af)
if (!(context = create_text_context(cmd, af->path, NULL)) ||
!(tf = cmd->fmt_backup->ops->create_instance(cmd->fmt_backup, NULL,
context))) {
NULL, context))) {
log_error("Couldn't create text instance object.");
return;
}
@@ -328,7 +334,7 @@ static void _display_archive(struct cmd_context *cmd, struct archive_file *af)
}
log_print("VG name: \t%s", vg->name);
log_print("Description:\t%s", desc ? desc : "<No description>");
log_print("Description:\t%s", desc ? : "<No description>");
log_print("Backup Time:\t%s", ctime(&when));
dm_pool_free(cmd->mem, vg);
@@ -360,7 +366,7 @@ int backup_list(struct cmd_context *cmd, const char *dir, const char *vgname)
{
struct archive_file af;
if (!(af.path = _join(cmd->mem, dir, vgname))) {
if (!(af.path = _join_file_to_dir(cmd->mem, dir, vgname))) {
stack;
return 0;
}

View File

@@ -190,7 +190,7 @@ static int __backup(struct volume_group *vg)
return 0;
}
if (lvm_snprintf(name, sizeof(name), "%s/%s",
if (dm_snprintf(name, sizeof(name), "%s/%s",
vg->cmd->backup_params->dir, vg->name) < 0) {
log_error("Failed to generate volume group metadata backup "
"filename.");
@@ -233,7 +233,7 @@ int backup_remove(struct cmd_context *cmd, const char *vg_name)
{
char path[PATH_MAX];
if (lvm_snprintf(path, sizeof(path), "%s/%s",
if (dm_snprintf(path, sizeof(path), "%s/%s",
cmd->backup_params->dir, vg_name) < 0) {
log_err("Failed to generate backup filename (for removal).");
return 0;
@@ -257,7 +257,7 @@ struct volume_group *backup_read_vg(struct cmd_context *cmd,
if (!(context = create_text_context(cmd, file,
cmd->cmd_line)) ||
!(tf = cmd->fmt_backup->ops->create_instance(cmd->fmt_backup, NULL,
context))) {
NULL, context))) {
log_error("Couldn't create text format object.");
return NULL;
}
@@ -286,7 +286,7 @@ int backup_restore_vg(struct cmd_context *cmd, struct volume_group *vg)
/* Attempt to write out using currently active format */
if (!(vg->fid = cmd->fmt->ops->create_instance(cmd->fmt, vg->name,
NULL))) {
NULL, NULL))) {
log_error("Failed to allocate format instance");
return 0;
}
@@ -342,7 +342,7 @@ int backup_restore(struct cmd_context *cmd, const char *vg_name)
{
char path[PATH_MAX];
if (lvm_snprintf(path, sizeof(path), "%s/%s",
if (dm_snprintf(path, sizeof(path), "%s/%s",
cmd->backup_params->dir, vg_name) < 0) {
log_err("Failed to generate backup filename (for restore).");
return 0;
@@ -365,7 +365,7 @@ int backup_to_file(const char *file, const char *desc, struct volume_group *vg)
if (!(context = create_text_context(cmd, file, desc)) ||
!(tf = cmd->fmt_backup->ops->create_instance(cmd->fmt_backup, NULL,
context))) {
NULL, context))) {
log_error("Couldn't create backup object.");
return 0;
}
@@ -397,7 +397,7 @@ void check_current_backup(struct volume_group *vg)
if ((vg->status & PARTIAL_VG) || (vg->status & EXPORTED_VG))
return;
if (lvm_snprintf(path, sizeof(path), "%s/%s",
if (dm_snprintf(path, sizeof(path), "%s/%s",
vg->cmd->backup_params->dir, vg->name) < 0) {
log_debug("Failed to generate backup filename.");
return;

View File

@@ -183,7 +183,8 @@ static int _out_with_comment_file(struct formatter *f, const char *comment,
return 1;
}
static int _out_with_comment_raw(struct formatter *f, const char *comment,
static int _out_with_comment_raw(struct formatter *f,
const char *comment __attribute((unused)),
const char *fmt, va_list ap)
{
int n;
@@ -220,6 +221,8 @@ static int _sectors_to_units(uint64_t sectors, char *buffer, size_t s)
"Megabytes",
"Gigabytes",
"Terabytes",
"Petabytes",
"Exabytes",
NULL
};
@@ -232,7 +235,7 @@ static int _sectors_to_units(uint64_t sectors, char *buffer, size_t s)
for (i = 0; (d > 1024.0) && _units[i]; i++)
d /= 1024.0;
return lvm_snprintf(buffer, s, "# %g %s", d, _units[i]) > 0;
return dm_snprintf(buffer, s, "# %g %s", d, _units[i]) > 0;
}
/*
@@ -281,7 +284,7 @@ int out_text(struct formatter *f, const char *fmt, ...)
}
static int _print_header(struct formatter *f,
struct volume_group *vg, const char *desc)
const char *desc)
{
time_t t;
@@ -354,8 +357,7 @@ static int _print_vg(struct formatter *f, struct volume_group *vg)
* Get the pv%d name from the formatters hash
* table.
*/
static inline const char *_get_pv_name(struct formatter *f,
struct physical_volume *pv)
static const char *_get_pv_name(struct formatter *f, struct physical_volume *pv)
{
return (pv) ? (const char *)
dm_hash_lookup(f->pv_names, dev_name(pv->dev)) : "Missing";
@@ -409,6 +411,11 @@ static int _print_pvs(struct formatter *f, struct volume_group *vg)
outf(f, "tags = %s", buffer);
}
if (!out_size(f, pv->size, "dev_size = %" PRIu64, pv->size)) {
stack;
return 0;
}
outf(f, "pe_start = %" PRIu64, pv->pe_start);
if (!out_size(f, vg->extent_size * (uint64_t) pv->pe_count,
"pe_count = %u", pv->pe_count)) {
@@ -613,46 +620,27 @@ static int _build_pv_names(struct formatter *f, struct volume_group *vg)
struct physical_volume *pv;
char buffer[32], *name;
if (!(f->mem = dm_pool_create("text pv_names", 512))) {
stack;
goto bad;
}
if (!(f->mem = dm_pool_create("text pv_names", 512)))
return_0;
if (!(f->pv_names = dm_hash_create(128))) {
stack;
goto bad;
}
if (!(f->pv_names = dm_hash_create(128)))
return_0;
list_iterate_items(pvl, &vg->pvs) {
pv = pvl->pv;
/* FIXME But skip if there's already an LV called pv%d ! */
if (lvm_snprintf(buffer, sizeof(buffer), "pv%d", count++) < 0) {
stack;
goto bad;
}
if (dm_snprintf(buffer, sizeof(buffer), "pv%d", count++) < 0)
return_0;
if (!(name = dm_pool_strdup(f->mem, buffer))) {
stack;
goto bad;
}
if (!(name = dm_pool_strdup(f->mem, buffer)))
return_0;
if (!dm_hash_insert(f->pv_names, dev_name(pv->dev), name)) {
stack;
goto bad;
}
if (!dm_hash_insert(f->pv_names, dev_name(pv->dev), name))
return_0;
}
return 1;
bad:
if (f->mem)
dm_pool_destroy(f->mem);
if (f->pv_names)
dm_hash_destroy(f->pv_names);
return 0;
}
static int _text_vg_export(struct formatter *f,
@@ -664,35 +652,33 @@ static int _text_vg_export(struct formatter *f,
stack;
goto out;
}
#define fail do {stack; goto out;} while(0)
if (f->header && !_print_header(f, vg, desc))
fail;
if (f->header && !_print_header(f, desc))
goto_out;
if (!out_text(f, "%s {", vg->name))
fail;
goto_out;
_inc_indent(f);
if (!_print_vg(f, vg))
fail;
goto_out;
outnl(f);
if (!_print_pvs(f, vg))
fail;
goto_out;
outnl(f);
if (!_print_lvs(f, vg))
fail;
goto_out;
_dec_indent(f);
if (!out_text(f, "}"))
fail;
goto_out;
if (!f->header && !_print_header(f, vg, desc))
fail;
if (!f->header && !_print_header(f, desc))
goto_out;
#undef fail
r = 1;
out:

View File

@@ -53,6 +53,7 @@ static struct flag _lv_flags[] = {
{VISIBLE_LV, "VISIBLE"},
{PVMOVE, "PVMOVE"},
{LOCKED, "LOCKED"},
{MIRROR_NOTSYNCED, "NOTSYNCED"},
{MIRROR_IMAGE, NULL},
{MIRROR_LOG, NULL},
{MIRRORED, NULL},

View File

@@ -39,8 +39,12 @@
#define FMT_TEXT_NAME "lvm2"
#define FMT_TEXT_ALIAS "text"
static struct format_instance *_create_text_instance(const struct format_type
static struct mda_header *_raw_read_mda_header(const struct format_type *fmt,
struct device_area *dev_area);
static struct format_instance *_text_create_text_instance(const struct format_type
*fmt, const char *vgname,
const char *vgid,
void *context);
struct text_fid_context {
@@ -68,7 +72,8 @@ struct text_context {
* NOTE: Currently there can be only one vg per text file.
*/
static int _vg_setup(struct format_instance *fid, struct volume_group *vg)
static int _text_vg_setup(struct format_instance *fid __attribute((unused)),
struct volume_group *vg)
{
if (vg->extent_size & (vg->extent_size - 1)) {
log_error("Extent size must be power of 2");
@@ -78,13 +83,172 @@ static int _vg_setup(struct format_instance *fid, struct volume_group *vg)
return 1;
}
static int _lv_setup(struct format_instance *fid, struct logical_volume *lv)
/*
* Check if metadata area belongs to vg
*/
static int _mda_in_vg_raw(struct format_instance *fid __attribute((unused)),
struct volume_group *vg, struct metadata_area *mda)
{
struct mda_context *mdac = (struct mda_context *) mda->metadata_locn;
struct pv_list *pvl;
list_iterate_items(pvl, &vg->pvs)
if (pvl->pv->dev == mdac->area.dev)
return 1;
return 0;
}
/*
* For circular region between region_start and region_start + region_size,
* back up one SECTOR_SIZE from 'region_ptr' and return the value.
* This allows reverse traversal through text metadata area to find old
* metadata.
*
* Parameters:
* region_start: start of the region (bytes)
* region_size: size of the region (bytes)
* region_ptr: pointer within the region (bytes)
* NOTE: region_start <= region_ptr <= region_start + region_size
*/
static uint64_t _get_prev_sector_circular(uint64_t region_start,
uint64_t region_size,
uint64_t region_ptr)
{
if (region_ptr >= region_start + SECTOR_SIZE)
return region_ptr - SECTOR_SIZE;
else
return (region_start + region_size - SECTOR_SIZE);
}
/*
* Analyze a metadata area for old metadata records in the circular buffer.
* This function just looks through and makes a first pass at the data in
* the sectors for particular things.
* FIXME: do something with each metadata area (try to extract vg, write
* raw data to file, etc)
*/
static int _pv_analyze_mda_raw (const struct format_type * fmt,
struct metadata_area *mda)
{
struct mda_header *mdah;
struct raw_locn *rlocn;
uint64_t area_start;
uint64_t area_size;
uint64_t prev_sector;
uint64_t latest_mrec_offset;
int i;
uint64_t offset;
uint64_t offset2;
uint64_t size;
uint64_t size2;
char *buf=NULL;
struct device_area *area;
struct mda_context *mdac;
int r=0;
mdac = (struct mda_context *) mda->metadata_locn;
log_print("Found text metadata area, offset=%"PRIu64", size=%"PRIu64,
mdac->area.start,
mdac->area.size);
area = &mdac->area;
if (!dev_open(area->dev))
return_0;
if (!(mdah = _raw_read_mda_header(fmt, area)))
goto_out;
rlocn = mdah->raw_locns;
/*
* The device area includes the metadata header as well as the
* records, so remove the metadata header from the start and size
*/
area_start = area->start + MDA_HEADER_SIZE;
area_size = area->size - MDA_HEADER_SIZE;
latest_mrec_offset = rlocn->offset + area->start;
/*
* Start searching at rlocn (point of live metadata) and go
* backwards.
*/
prev_sector = _get_prev_sector_circular(area_start, area_size,
latest_mrec_offset);
offset = prev_sector;
size = SECTOR_SIZE;
offset2 = size2 = 0;
i = 0;
while (prev_sector != latest_mrec_offset) {
prev_sector = _get_prev_sector_circular(area_start, area_size,
prev_sector);
/*
* FIXME: for some reason, the whole metadata region from
* area->start to area->start+area->size is not used.
* Only ~32KB seems to contain valid metadata records
* (LVM2 format - format_text). As a result, I end up with
* "maybe_config_section" returning true when there's no valid
* metadata in a sector (sectors with all nulls).
*/
if (!(buf = dm_pool_alloc(fmt->cmd->mem, size + size2)))
goto_out;
if (!dev_read_circular(area->dev, offset, size,
offset2, size2, buf))
goto_out;
/*
* FIXME: We could add more sophisticated metadata detection
*/
if (maybe_config_section(buf, size+size2)) {
/* FIXME: Validate region, pull out timestamp?, etc */
/* FIXME: Do something with this region */
log_verbose ("Found LVM2 metadata record at "
"offset=%"PRIu64", size=%"PRIu64", "
"offset2=%"PRIu64" size2=%"PRIu64,
offset, size, offset2, size2);
offset = prev_sector;
size = SECTOR_SIZE;
offset2 = size2 = 0;
} else {
/*
* Not a complete metadata record, assume we have
* metadata and just increase the size and offset.
* Start the second region if the previous sector is
* wrapping around towards the end of the disk.
*/
if (prev_sector > offset) {
offset2 = prev_sector;
size2 += SECTOR_SIZE;
} else {
offset = prev_sector;
size += SECTOR_SIZE;
}
}
dm_pool_free(fmt->cmd->mem, buf);
buf = NULL;
}
r = 1;
out:
if (buf)
dm_pool_free(fmt->cmd->mem, buf);
if (!dev_close(area->dev))
stack;
return r;
}
static int _text_lv_setup(struct format_instance *fid __attribute((unused)),
struct logical_volume *lv)
{
/******** FIXME Any LV size restriction?
uint64_t max_size = UINT_MAX;
if (lv->size > max_size) {
char *dummy = display_size(max_size, SIZE_SHORT);
char *dummy = display_size(max_size);
log_error("logical volumes cannot be larger than %s", dummy);
dm_free(dummy);
return 0;
@@ -129,44 +293,47 @@ static struct mda_header *_raw_read_mda_header(const struct format_type *fmt,
if (!dev_read(dev_area->dev, dev_area->start, MDA_HEADER_SIZE, mdah)) {
stack;
dm_pool_free(fmt->cmd->mem, mdah);
return NULL;
goto error;
}
if (mdah->checksum_xl != xlate32(calc_crc(INITIAL_CRC, mdah->magic,
MDA_HEADER_SIZE -
sizeof(mdah->checksum_xl)))) {
log_error("Incorrect metadata area header checksum");
return NULL;
goto error;
}
_xlate_mdah(mdah);
if (strncmp(mdah->magic, FMTT_MAGIC, sizeof(mdah->magic))) {
if (strncmp((char *)mdah->magic, FMTT_MAGIC, sizeof(mdah->magic))) {
log_error("Wrong magic number in metadata area header");
return NULL;
goto error;
}
if (mdah->version != FMTT_VERSION) {
log_error("Incompatible metadata area header version: %d",
mdah->version);
return NULL;
goto error;
}
if (mdah->start != dev_area->start) {
log_error("Incorrect start sector in metadata area header: %"
PRIu64, mdah->start);
return NULL;
goto error;
}
return mdah;
error:
dm_pool_free(fmt->cmd->mem, mdah);
return NULL;
}
static int _raw_write_mda_header(const struct format_type *fmt,
struct device *dev,
uint64_t start_byte, struct mda_header *mdah)
{
strncpy(mdah->magic, FMTT_MAGIC, sizeof(mdah->magic));
strncpy((char *)mdah->magic, FMTT_MAGIC, sizeof(mdah->magic));
mdah->version = FMTT_VERSION;
mdah->start = start_byte;
@@ -190,7 +357,7 @@ static struct raw_locn *_find_vg_rlocn(struct device_area *dev_area,
int *precommitted)
{
size_t len;
char vgnamebuf[NAME_LEN + 2];
char vgnamebuf[NAME_LEN + 2] __attribute((aligned(8)));
struct raw_locn *rlocn, *rlocn_precommitted;
struct lvmcache_info *info;
@@ -219,7 +386,7 @@ static struct raw_locn *_find_vg_rlocn(struct device_area *dev_area,
error:
if ((info = info_from_pvid(dev_area->dev->pvid)))
lvmcache_update_vgname(info, ORPHAN);
lvmcache_update_vgname_and_id(info, ORPHAN, ORPHAN, 0, NULL);
return NULL;
}
@@ -704,7 +871,8 @@ static int _vg_write_file(struct format_instance *fid, struct volume_group *vg,
if (!(fp = fdopen(fd, "w"))) {
log_sys_error("fdopen", temp_file);
close(fd);
if (close(fd))
log_sys_error("fclose", temp_file);
return 0;
}
@@ -712,13 +880,15 @@ static int _vg_write_file(struct format_instance *fid, struct volume_group *vg,
if (!text_vg_export_file(vg, tc->desc, fp)) {
log_error("Failed to write metadata to %s.", temp_file);
fclose(fp);
if (fclose(fp))
log_sys_error("fclose", temp_file);
return 0;
}
if (fsync(fd) && (errno != EROFS) && (errno != EINVAL)) {
log_sys_error("fsync", tc->path_edit);
fclose(fp);
if (fclose(fp))
log_sys_error("fclose", tc->path_edit);
return 0;
}
@@ -850,7 +1020,7 @@ static int _scan_file(const struct format_type *fmt)
tmp != dirent->d_name + strlen(dirent->d_name)
- 4)) {
vgname = dirent->d_name;
if (lvm_snprintf(path, PATH_MAX, "%s/%s",
if (dm_snprintf(path, PATH_MAX, "%s/%s",
dl->dir, vgname) < 0) {
log_error("Name too long %s/%s",
dl->dir, vgname);
@@ -858,9 +1028,11 @@ static int _scan_file(const struct format_type *fmt)
}
/* FIXME stat file to see if it's changed */
fid = _create_text_instance(fmt, NULL, NULL);
fid = _text_create_text_instance(fmt, NULL, NULL,
NULL);
if ((vg = _vg_read_file_name(fid, vgname,
path)))
/* FIXME Store creation host in vg */
lvmcache_update_vg(vg);
}
@@ -871,65 +1043,99 @@ static int _scan_file(const struct format_type *fmt)
return 1;
}
int vgname_from_mda(const struct format_type *fmt, struct device_area *dev_area,
char *buf, uint32_t size)
const char *vgname_from_mda(const struct format_type *fmt,
struct device_area *dev_area, struct id *vgid,
uint32_t *vgstatus, char **creation_host)
{
struct raw_locn *rlocn;
struct mda_header *mdah;
unsigned int len;
int r = 0;
uint32_t wrap = 0;
const char *vgname = NULL;
unsigned int len = 0;
char buf[NAME_LEN + 1] __attribute((aligned(8)));
char uuid[64] __attribute((aligned(8)));
if (!dev_open(dev_area->dev)) {
stack;
return 0;
return NULL;
}
if (!(mdah = _raw_read_mda_header(fmt, dev_area))) {
stack;
if (!(mdah = _raw_read_mda_header(fmt, dev_area)))
goto_out;
/* FIXME Cope with returning a list */
rlocn = mdah->raw_locns;
/* Do quick check for a vgname */
if (!dev_read(dev_area->dev, dev_area->start + rlocn->offset,
NAME_LEN, buf))
goto_out;
while (buf[len] && !isspace(buf[len]) && buf[len] != '{' &&
len < (NAME_LEN - 1))
len++;
buf[len] = '\0';
/* Ignore this entry if the characters aren't permissible */
if (!validate_name(buf))
goto_out;
/* We found a VG - now check the metadata */
if (rlocn->offset + rlocn->size > mdah->size)
wrap = (uint32_t) ((rlocn->offset + rlocn->size) - mdah->size);
if (wrap > rlocn->offset) {
log_error("%s: metadata too large for circular buffer",
dev_name(dev_area->dev));
goto out;
}
rlocn = mdah->raw_locns;
/* FIXME 64-bit */
if (!(vgname = text_vgname_import(fmt, dev_area->dev,
(off_t) (dev_area->start +
rlocn->offset),
(uint32_t) (rlocn->size - wrap),
(off_t) (dev_area->start +
MDA_HEADER_SIZE),
wrap, calc_crc, rlocn->checksum,
vgid, vgstatus, creation_host)))
goto_out;
while (rlocn->offset) {
if (!dev_read(dev_area->dev, dev_area->start + rlocn->offset,
size, buf)) {
stack;
goto out;
}
len = 0;
while (buf[len] && !isspace(buf[len]) && buf[len] != '{' &&
len < (size - 1))
len++;
buf[len] = '\0';
/* Ignore this entry if the characters aren't permissible */
if (!validate_name(buf)) {
stack;
goto out;
}
r = 1;
break;
/* FIXME Cope with returning a list */
rlocn++;
/* Ignore this entry if the characters aren't permissible */
if (!validate_name(vgname)) {
stack;
vgname = NULL;
goto out;
}
if (!id_write_format(vgid, uuid, sizeof(uuid))) {
stack;
vgname = NULL;
goto out;
}
log_debug("%s: Found metadata at %" PRIu64 " size %" PRIu64
" for %s (%s)",
dev_name(dev_area->dev), dev_area->start + rlocn->offset,
rlocn->size, vgname, uuid);
out:
if (!dev_close(dev_area->dev))
stack;
return r;
return vgname;
}
static int _scan_raw(const struct format_type *fmt)
{
struct raw_list *rl;
struct list *raw_list;
char vgnamebuf[NAME_LEN + 2];
const char *vgname;
struct volume_group *vg;
struct format_instance fid;
struct id vgid;
uint32_t vgstatus;
raw_list = &((struct mda_lists *) fmt->private)->raws;
@@ -938,9 +1144,9 @@ static int _scan_raw(const struct format_type *fmt)
list_iterate_items(rl, raw_list) {
/* FIXME We're reading mdah twice here... */
if (vgname_from_mda(fmt, &rl->dev_area, vgnamebuf,
sizeof(vgnamebuf))) {
if ((vg = _vg_read_raw_area(&fid, vgnamebuf,
if ((vgname = vgname_from_mda(fmt, &rl->dev_area, &vgid, &vgstatus,
NULL))) {
if ((vg = _vg_read_raw_area(&fid, vgname,
&rl->dev_area, 0)))
lvmcache_update_vg(vg);
}
@@ -949,13 +1155,13 @@ static int _scan_raw(const struct format_type *fmt)
return 1;
}
static int _scan(const struct format_type *fmt)
static int _text_scan(const struct format_type *fmt)
{
return (_scan_file(fmt) & _scan_raw(fmt));
}
/* For orphan, creates new mdas according to policy.
Always have an mda between end-of-label and PE_ALIGN boundary */
Always have an mda between end-of-label and pe_align() boundary */
static int _mda_setup(const struct format_type *fmt,
uint64_t pe_start, uint64_t pe_end,
int pvmetadatacopies,
@@ -966,15 +1172,12 @@ static int _mda_setup(const struct format_type *fmt,
uint64_t start1, mda_size1; /* First area - start of disk */
uint64_t start2, mda_size2; /* Second area - end of disk */
uint64_t wipe_size = 8 << SECTOR_SHIFT;
size_t pagesize = getpagesize();
size_t pagesize = lvm_getpagesize();
if (!pvmetadatacopies) {
/* Space available for PEs */
pv->size -= PE_ALIGN;
if (!pvmetadatacopies)
return 1;
}
alignment = PE_ALIGN << SECTOR_SHIFT;
alignment = pe_align() << SECTOR_SHIFT;
disk_size = pv->size << SECTOR_SHIFT;
pe_start <<= SECTOR_SHIFT;
pe_end <<= SECTOR_SHIFT;
@@ -988,9 +1191,6 @@ static int _mda_setup(const struct format_type *fmt,
/* Requested metadatasize */
mda_size1 = pvmetadatasize << SECTOR_SHIFT;
/* Space available for PEs (before any mdas created) */
pv->size -= LABEL_SCAN_SECTORS;
/* Place mda straight after label area at start of disk */
start1 = LABEL_SCAN_SIZE;
@@ -998,11 +1198,8 @@ static int _mda_setup(const struct format_type *fmt,
if ((!pe_start && !pe_end) ||
((pe_start > start1) && (pe_start - start1 >= MDA_SIZE_MIN))) {
mda_adjustment = start1 % pagesize;
if (mda_adjustment) {
if (mda_adjustment)
start1 += (pagesize - mda_adjustment);
pv->size -= ((pagesize - mda_adjustment) >>
SECTOR_SHIFT);
}
}
/* Ensure it's not going to be bigger than the disk! */
@@ -1016,7 +1213,7 @@ static int _mda_setup(const struct format_type *fmt,
pvmetadatacopies = 1;
}
/* Round up to PE_ALIGN boundary */
/* Round up to pe_align() boundary */
mda_adjustment = (mda_size1 + start1) % alignment;
if (mda_adjustment)
mda_size1 += (alignment - mda_adjustment);
@@ -1032,16 +1229,16 @@ static int _mda_setup(const struct format_type *fmt,
/* FIXME If creating new mdas, wipe them! */
if (mda_size1) {
if (!add_mda(fmt, fmt->cmd->mem, mdas, pv->dev, start1,
mda_size1)) return 0;
mda_size1))
return 0;
if (!dev_zero((struct device *) pv->dev, start1,
(size_t) (mda_size1 >
wipe_size ? wipe_size : mda_size1))) {
if (!dev_set((struct device *) pv->dev, start1,
(size_t) (mda_size1 >
wipe_size ? : mda_size1), 0)) {
log_error("Failed to wipe new metadata area");
return 0;
}
pv->size -= mda_size1 >> SECTOR_SHIFT;
if (pvmetadatacopies == 1)
return 1;
} else
@@ -1080,13 +1277,12 @@ static int _mda_setup(const struct format_type *fmt,
if (mda_size2) {
if (!add_mda(fmt, fmt->cmd->mem, mdas, pv->dev, start2,
mda_size2)) return 0;
if (!dev_zero(pv->dev, start2,
(size_t) (mda_size1 >
wipe_size ? wipe_size : mda_size1))) {
if (!dev_set(pv->dev, start2,
(size_t) (mda_size1 >
wipe_size ? : mda_size1), 0)) {
log_error("Failed to wipe new metadata area");
return 0;
}
pv->size -= mda_size2 >> SECTOR_SHIFT;
} else
return 0;
@@ -1095,21 +1291,21 @@ static int _mda_setup(const struct format_type *fmt,
/* Only for orphans */
/* Set label_sector to -1 if rewriting existing label into same sector */
static int _pv_write(const struct format_type *fmt, struct physical_volume *pv,
static int _text_pv_write(const struct format_type *fmt, struct physical_volume *pv,
struct list *mdas, int64_t label_sector)
{
struct label *label;
struct lvmcache_info *info;
struct mda_context *mdac;
struct metadata_area *mda;
char buf[MDA_HEADER_SIZE];
char buf[MDA_HEADER_SIZE] __attribute((aligned(8)));
struct mda_header *mdah = (struct mda_header *) buf;
uint64_t adjustment;
/* FIXME Test mode don't update cache? */
if (!(info = lvmcache_add(fmt->labeller, (char *) &pv->id, pv->dev,
ORPHAN, NULL))) {
ORPHAN, NULL, 0))) {
stack;
return 0;
}
@@ -1150,22 +1346,22 @@ static int _pv_write(const struct format_type *fmt, struct physical_volume *pv,
/* Set pe_start to first aligned sector after any metadata
* areas that begin before pe_start */
pv->pe_start = PE_ALIGN;
pv->pe_start = pe_align();
list_iterate_items(mda, &info->mdas) {
mdac = (struct mda_context *) mda->metadata_locn;
if (pv->dev == mdac->area.dev &&
(mdac->area.start < (pv->pe_start << SECTOR_SHIFT)) &&
(mdac->area.start <= (pv->pe_start << SECTOR_SHIFT)) &&
(mdac->area.start + mdac->area.size >
(pv->pe_start << SECTOR_SHIFT))) {
pv->pe_start = (mdac->area.start + mdac->area.size)
>> SECTOR_SHIFT;
adjustment = pv->pe_start % PE_ALIGN;
adjustment = pv->pe_start % pe_align();
if (adjustment)
pv->pe_start += (PE_ALIGN - adjustment);
pv->pe_start += (pe_align() - adjustment);
}
}
if (!add_da
(fmt, NULL, &info->das, pv->pe_start << SECTOR_SHIFT, UINT64_C(0))) {
(NULL, &info->das, pv->pe_start << SECTOR_SHIFT, UINT64_C(0))) {
stack;
return 0;
}
@@ -1220,7 +1416,7 @@ static int _add_raw(struct list *raw_list, struct device_area *dev_area)
return 1;
}
static int _pv_read(const struct format_type *fmt, const char *pv_name,
static int _text_pv_read(const struct format_type *fmt, const char *pv_name,
struct physical_volume *pv, struct list *mdas)
{
struct label *label;
@@ -1236,7 +1432,7 @@ static int _pv_read(const struct format_type *fmt, const char *pv_name,
}
/* FIXME Optimise out repeated reading when cache lock held */
if (!(label_read(dev, &label))) {
if (!(label_read(dev, &label, UINT64_C(0)))) {
stack;
return 0;
}
@@ -1245,7 +1441,7 @@ static int _pv_read(const struct format_type *fmt, const char *pv_name,
/* Have we already cached vgname? */
if (info->vginfo && info->vginfo->vgname && *info->vginfo->vgname &&
get_pv_from_vg_by_id(info->fmt, info->vginfo->vgname,
info->dev->pvid, pv)) {
info->vginfo->vgid, info->dev->pvid, pv)) {
return 1;
}
@@ -1256,6 +1452,7 @@ static int _pv_read(const struct format_type *fmt, const char *pv_name,
if (info->vginfo && info->vginfo->vgname &&
*info->vginfo->vgname &&
get_pv_from_vg_by_id(info->fmt, info->vginfo->vgname,
info->vginfo->vgid,
info->dev->pvid, pv)) {
return 1;
}
@@ -1301,7 +1498,7 @@ static int _pv_read(const struct format_type *fmt, const char *pv_name,
return 1;
}
static void _destroy_instance(struct format_instance *fid)
static void _text_destroy_instance(struct format_instance *fid __attribute((unused)))
{
return;
}
@@ -1326,7 +1523,7 @@ static void _free_raws(struct list *raw_list)
}
}
static void _destroy(const struct format_type *fmt)
static void _text_destroy(const struct format_type *fmt)
{
if (fmt->private) {
_free_dirs(&((struct mda_lists *) fmt->private)->dirs);
@@ -1334,36 +1531,38 @@ static void _destroy(const struct format_type *fmt)
dm_free(fmt->private);
}
dm_free((void *) fmt);
dm_free((void *)fmt);
}
static struct metadata_area_ops _metadata_text_file_ops = {
vg_read:_vg_read_file,
vg_read_precommit:_vg_read_precommit_file,
vg_write:_vg_write_file,
vg_remove:_vg_remove_file,
vg_commit:_vg_commit_file
.vg_read = _vg_read_file,
.vg_read_precommit = _vg_read_precommit_file,
.vg_write = _vg_write_file,
.vg_remove = _vg_remove_file,
.vg_commit = _vg_commit_file
};
static struct metadata_area_ops _metadata_text_file_backup_ops = {
vg_read:_vg_read_file,
vg_write:_vg_write_file,
vg_remove:_vg_remove_file,
vg_commit:_vg_commit_file_backup
.vg_read = _vg_read_file,
.vg_write = _vg_write_file,
.vg_remove = _vg_remove_file,
.vg_commit = _vg_commit_file_backup
};
static struct metadata_area_ops _metadata_text_raw_ops = {
vg_read:_vg_read_raw,
vg_read_precommit:_vg_read_precommit_raw,
vg_write:_vg_write_raw,
vg_remove:_vg_remove_raw,
vg_precommit:_vg_precommit_raw,
vg_commit:_vg_commit_raw,
vg_revert:_vg_revert_raw
.vg_read = _vg_read_raw,
.vg_read_precommit = _vg_read_precommit_raw,
.vg_write = _vg_write_raw,
.vg_remove = _vg_remove_raw,
.vg_precommit = _vg_precommit_raw,
.vg_commit = _vg_commit_raw,
.vg_revert = _vg_revert_raw,
.mda_in_vg = _mda_in_vg_raw,
.pv_analyze_mda = _pv_analyze_mda_raw,
};
/* pvmetadatasize in sectors */
static int _pv_setup(const struct format_type *fmt,
static int _text_pv_setup(const struct format_type *fmt,
uint64_t pe_start, uint32_t extent_count,
uint32_t extent_size,
int pvmetadatacopies,
@@ -1376,11 +1575,12 @@ static int _pv_setup(const struct format_type *fmt,
struct lvmcache_info *info;
int found;
uint64_t pe_end = 0;
/* FIXME if vg, adjust start/end of pe area to avoid mdas! */
unsigned mda_count = 0;
uint64_t mda_size2 = 0;
uint64_t pe_count;
/* FIXME Cope with pvchange */
/* FIXME Merge code with _create_text_instance */
/* FIXME Merge code with _text_create_text_instance */
/* If new vg, add any further mdas on this PV to the fid's mda list */
if (vg) {
@@ -1388,11 +1588,16 @@ static int _pv_setup(const struct format_type *fmt,
if ((info = info_from_pvid(pv->dev->pvid))) {
pvmdas = &info->mdas;
list_iterate_items(mda, pvmdas) {
mda_count++;
mdac =
(struct mda_context *) mda->metadata_locn;
/* FIXME Check it isn't already in use */
/* Reduce usable device size */
if (mda_count > 1)
mda_size2 = mdac->area.size >> SECTOR_SHIFT;
/* Ensure it isn't already on list */
found = 0;
list_iterate_items(mda2, mdas) {
@@ -1430,6 +1635,26 @@ static int _pv_setup(const struct format_type *fmt,
}
}
/* FIXME Cope with genuine pe_count 0 */
/* If missing, estimate pv->size from file-based metadata */
if (!pv->size && pv->pe_count)
pv->size = pv->pe_count * (uint64_t) vg->extent_size +
pv->pe_start + mda_size2;
/* Recalculate number of extents that will fit */
if (!pv->pe_count) {
pe_count = (pv->size - pv->pe_start - mda_size2) /
vg->extent_size;
if (pe_count > UINT32_MAX) {
log_error("PV %s too large for extent size %s.",
dev_name(pv->dev),
display_size(vg->cmd, (uint64_t) vg->extent_size));
return 0;
}
pv->pe_count = (uint32_t) pe_count;
}
/* Unlike LVM1, we don't store this outside a VG */
/* FIXME Default from config file? vgextend cmdline flag? */
pv->status |= ALLOCATABLE_PV;
@@ -1448,8 +1673,9 @@ static int _pv_setup(const struct format_type *fmt,
}
/* NULL vgname means use only the supplied context e.g. an archive file */
static struct format_instance *_create_text_instance(const struct format_type
static struct format_instance *_text_create_text_instance(const struct format_type
*fmt, const char *vgname,
const char *vgid,
void *context)
{
struct format_instance *fid;
@@ -1492,7 +1718,7 @@ static struct format_instance *_create_text_instance(const struct format_type
dir_list = &((struct mda_lists *) fmt->private)->dirs;
list_iterate_items(dl, dir_list) {
if (lvm_snprintf(path, PATH_MAX, "%s/%s",
if (dm_snprintf(path, PATH_MAX, "%s/%s",
dl->dir, vgname) < 0) {
log_error("Name too long %s/%s", dl->dir,
vgname);
@@ -1535,7 +1761,7 @@ static struct format_instance *_create_text_instance(const struct format_type
/* Scan PVs in VG for any further MDAs */
lvmcache_label_scan(fmt->cmd, 0);
if (!(vginfo = vginfo_from_vgname(vgname))) {
if (!(vginfo = vginfo_from_vgname(vgname, vgid))) {
stack;
goto out;
}
@@ -1569,7 +1795,6 @@ static struct format_instance *_create_text_instance(const struct format_type
out:
return fid;
}
void *create_text_context(struct cmd_context *cmd, const char *path,
@@ -1618,15 +1843,15 @@ void *create_text_context(struct cmd_context *cmd, const char *path,
}
static struct format_handler _text_handler = {
scan:_scan,
pv_read:_pv_read,
pv_setup:_pv_setup,
pv_write:_pv_write,
vg_setup:_vg_setup,
lv_setup:_lv_setup,
create_instance:_create_text_instance,
destroy_instance:_destroy_instance,
destroy:_destroy
.scan = _text_scan,
.pv_read = _text_pv_read,
.pv_setup = _text_pv_setup,
.pv_write = _text_pv_write,
.vg_setup = _text_vg_setup,
.lv_setup = _text_lv_setup,
.create_instance = _text_create_text_instance,
.destroy_instance = _text_destroy_instance,
.destroy = _text_destroy
};
static int _add_dir(const char *dir, struct list *dir_list)
@@ -1686,7 +1911,7 @@ static int _get_config_disk_area(struct cmd_context *cmd,
}
if (!(dev_area.dev = device_from_pvid(cmd, &id))) {
char buffer[64];
char buffer[64] __attribute((aligned(8)));
if (!id_write_format(&id, buffer, sizeof(buffer)))
log_err("Couldn't find device.");
@@ -1716,10 +1941,12 @@ struct format_type *create_text_format(struct cmd_context *cmd)
fmt->name = FMT_TEXT_NAME;
fmt->alias = FMT_TEXT_ALIAS;
fmt->features = FMT_SEGMENTS | FMT_MDAS | FMT_TAGS | FMT_PRECOMMIT |
FMT_UNLIMITED_VOLS | FMT_RESIZE_PV;
FMT_UNLIMITED_VOLS | FMT_RESIZE_PV |
FMT_UNLIMITED_STRIPESIZE;
if (!(mda_lists = dm_malloc(sizeof(struct mda_lists)))) {
log_error("Failed to allocate dir_list");
dm_free(fmt);
return NULL;
}
@@ -1731,15 +1958,17 @@ struct format_type *create_text_format(struct cmd_context *cmd)
if (!(fmt->labeller = text_labeller_create(fmt))) {
log_error("Couldn't create text label handler.");
dm_free(fmt);
return NULL;
}
if (!(label_register_handler(FMT_TEXT_NAME, fmt->labeller))) {
log_error("Couldn't register text label handler.");
dm_free(fmt);
return NULL;
}
if ((cn = find_config_node(cmd->cft->root, "metadata/dirs"))) {
if ((cn = find_config_tree_node(cmd, "metadata/dirs"))) {
for (cv = cn->v; cv; cv = cv->next) {
if (cv->type != CFG_STRING) {
log_error("Invalid string in config file: "
@@ -1755,7 +1984,7 @@ struct format_type *create_text_format(struct cmd_context *cmd)
}
}
if ((cn = find_config_node(cmd->cft->root, "metadata/disk_areas"))) {
if ((cn = find_config_tree_node(cmd, "metadata/disk_areas"))) {
for (cn = cn->child; cn; cn = cn->sib) {
if (!_get_config_disk_area(cmd, cn, &mda_lists->raws))
goto err;

View File

@@ -46,7 +46,7 @@ struct labeller *text_labeller_create(const struct format_type *fmt);
int pvhdr_read(struct device *dev, char *buf);
int add_da(const struct format_type *fmt, struct dm_pool *mem, struct list *das,
int add_da(struct dm_pool *mem, struct list *das,
uint64_t start, uint64_t size);
void del_das(struct list *das);
@@ -54,7 +54,8 @@ int add_mda(const struct format_type *fmt, struct dm_pool *mem, struct list *mda
struct device *dev, uint64_t start, uint64_t size);
void del_mdas(struct list *mdas);
int vgname_from_mda(const struct format_type *fmt, struct device_area *dev_area,
char *buf, uint32_t size);
const char *vgname_from_mda(const struct format_type *fmt,
struct device_area *dev_area, struct id *vgid,
uint32_t *vgstatus, char **creation_host);
#endif

View File

@@ -47,6 +47,10 @@ struct text_vg_version_ops {
struct config_tree * cf);
void (*read_desc) (struct dm_pool * mem, struct config_tree * cf,
time_t *when, char **desc);
const char *(*read_vgname) (const struct format_type *fmt,
struct config_tree *cft,
struct id *vgid, uint32_t *vgstatus,
char **creation_host);
};
struct text_vg_version_ops *text_vg_vsn1_init(void);
@@ -70,5 +74,12 @@ struct volume_group *text_vg_import_fd(struct format_instance *fid,
checksum_fn_t checksum_fn,
uint32_t checksum,
time_t *when, char **desc);
const char *text_vgname_import(const struct format_type *fmt,
struct device *dev,
off_t offset, uint32_t size,
off_t offset2, uint32_t size2,
checksum_fn_t checksum_fn, uint32_t checksum,
struct id *vgid, uint32_t *vgstatus,
char **creation_host);
#endif

View File

@@ -23,6 +23,53 @@
/* FIXME Use tidier inclusion method */
static struct text_vg_version_ops *(_text_vsn_list[2]);
const char *text_vgname_import(const struct format_type *fmt,
struct device *dev,
off_t offset, uint32_t size,
off_t offset2, uint32_t size2,
checksum_fn_t checksum_fn, uint32_t checksum,
struct id *vgid, uint32_t *vgstatus,
char **creation_host)
{
struct config_tree *cft;
struct text_vg_version_ops **vsn;
const char *vgname = NULL;
static int _text_import_initialised = 0;
if (!_text_import_initialised) {
_text_vsn_list[0] = text_vg_vsn1_init();
_text_vsn_list[1] = NULL;
_text_import_initialised = 1;
}
if (!(cft = create_config_tree(NULL, 0)))
return_NULL;
if ((!dev && !read_config_file(cft)) ||
(dev && !read_config_fd(cft, dev, offset, size,
offset2, size2, checksum_fn, checksum)))
goto_out;
/*
* Find a set of version functions that can read this file
*/
for (vsn = &_text_vsn_list[0]; *vsn; vsn++) {
if (!(*vsn)->check_version(cft))
continue;
if (!(vgname = (*vsn)->read_vgname(fmt, cft, vgid, vgstatus,
creation_host)))
goto_out;
break;
}
out:
destroy_config_tree(cft);
return vgname;
}
struct volume_group *text_vg_import_fd(struct format_instance *fid,
const char *file,
struct device *dev,
@@ -36,21 +83,19 @@ struct volume_group *text_vg_import_fd(struct format_instance *fid,
struct config_tree *cft;
struct text_vg_version_ops **vsn;
static int _initialised = 0;
static int _text_vg_import_initialised = 0;
if (!_initialised) {
if (!_text_vg_import_initialised) {
_text_vsn_list[0] = text_vg_vsn1_init();
_text_vsn_list[1] = NULL;
_initialised = 1;
_text_vg_import_initialised = 1;
}
*desc = NULL;
*when = 0;
if (!(cft = create_config_tree(file))) {
stack;
goto out;
}
if (!(cft = create_config_tree(file, 0)))
return_NULL;
if ((!dev && !read_config_file(cft)) ||
(dev && !read_config_fd(cft, dev, offset, size,
@@ -84,6 +129,6 @@ struct volume_group *text_vg_import_file(struct format_instance *fid,
const char *file,
time_t *when, char **desc)
{
return text_vg_import_fd(fid, file, NULL, 0, 0, 0, 0, NULL, 0,
return text_vg_import_fd(fid, file, NULL, (off_t)0, 0, (off_t)0, 0, NULL, 0,
when, desc);
}

View File

@@ -116,6 +116,7 @@ static int _read_pv(struct format_instance *fid, struct dm_pool *mem,
struct physical_volume *pv;
struct pv_list *pvl;
struct config_node *cn;
uint64_t size;
if (!(pvl = dm_pool_zalloc(mem, sizeof(*pvl))) ||
!(pvl->pv = dm_pool_zalloc(mem, sizeof(*pvl->pv)))) {
@@ -148,7 +149,7 @@ static int _read_pv(struct format_instance *fid, struct dm_pool *mem,
* Convert the uuid into a device.
*/
if (!(pv->dev = device_from_pvid(fid->fmt->cmd, &pv->id))) {
char buffer[64];
char buffer[64] __attribute((aligned(8)));
if (!id_write_format(&pv->id, buffer, sizeof(buffer)))
log_error("Couldn't find device.");
@@ -167,6 +168,8 @@ static int _read_pv(struct format_instance *fid, struct dm_pool *mem,
return 0;
}
memcpy(&pv->vgid, &vg->id, sizeof(vg->id));
if (!(cn = find_config_node(pvn, "status"))) {
log_error("Couldn't find status flags for physical volume.");
return 0;
@@ -177,6 +180,9 @@ static int _read_pv(struct format_instance *fid, struct dm_pool *mem,
return 0;
}
/* Late addition */
_read_int64(pvn, "dev_size", &pv->size);
if (!_read_int64(pvn, "pe_start", &pv->pe_start)) {
log_error("Couldn't read extent size for volume group.");
return 0;
@@ -204,10 +210,29 @@ static int _read_pv(struct format_instance *fid, struct dm_pool *mem,
vg->free_count += pv->pe_count;
pv->pe_size = vg->extent_size;
pv->size = vg->extent_size * (uint64_t) pv->pe_count;
pv->pe_alloc_count = 0;
pv->fmt = fid->fmt;
/* Fix up pv size if missing */
if (!pv->size && pv->dev) {
if (!dev_get_size(pv->dev, &pv->size)) {
log_error("%s: Couldn't get size.", dev_name(pv->dev));
return 0;
}
log_verbose("Fixing up missing format1 size (%s) "
"for PV %s", display_size(fid->fmt->cmd, pv->size),
dev_name(pv->dev));
if (vg) {
size = pv->pe_count * (uint64_t) vg->extent_size +
pv->pe_start;
if (size > pv->size)
log_error("WARNING: Physical Volume %s is too "
"large for underlying device",
dev_name(pv->dev));
}
}
if (!alloc_pv_segment_whole_pv(mem, pv)) {
stack;
return 0;
@@ -368,7 +393,7 @@ int text_import_areas(struct lv_segment *seg, const struct config_node *sn,
} else {
log_error("Couldn't find volume '%s' "
"for segment '%s'.",
cv->v.str ? cv->v.str : "NULL", seg_name);
cv->v.str ? : "NULL", seg_name);
return 0;
}
@@ -635,15 +660,11 @@ static struct volume_group *_read_vg(struct format_instance *fid,
/* eg Set to instance of fmt1 here if reading a format1 backup? */
vg->fid = fid;
if (!(vg->name = dm_pool_strdup(mem, vgn->key))) {
stack;
goto bad;
}
if (!(vg->name = dm_pool_strdup(mem, vgn->key)))
goto_bad;
if (!(vg->system_id = dm_pool_zalloc(mem, NAME_LEN))) {
stack;
goto bad;
}
if (!(vg->system_id = dm_pool_zalloc(mem, NAME_LEN)))
goto_bad;
vgn = vgn->child;
@@ -798,13 +819,62 @@ static void _read_desc(struct dm_pool *mem,
*when = u;
}
static const char *_read_vgname(const struct format_type *fmt,
struct config_tree *cft, struct id *vgid,
uint32_t *vgstatus, char **creation_host)
{
struct config_node *vgn, *cn;
struct dm_pool *mem = fmt->cmd->mem;
char *vgname;
int old_suppress;
old_suppress = log_suppress(2);
*creation_host = dm_pool_strdup(mem,
find_config_str(cft->root,
"creation_host", ""));
log_suppress(old_suppress);
/* skip any top-level values */
for (vgn = cft->root; (vgn && vgn->v); vgn = vgn->sib) ;
if (!vgn) {
log_error("Couldn't find volume group in file.");
return 0;
}
if (!(vgname = dm_pool_strdup(mem, vgn->key)))
return_0;
vgn = vgn->child;
if (!_read_id(vgid, vgn, "id")) {
log_error("Couldn't read uuid for volume group %s.", vgname);
return 0;
}
if (!(cn = find_config_node(vgn, "status"))) {
log_error("Couldn't find status flags for volume group %s.",
vgname);
return 0;
}
if (!(read_flags(vgstatus, VG_FLAGS, cn->v))) {
log_error("Couldn't read status flags for volume group %s.",
vgname);
return 0;
}
return vgname;
}
static struct text_vg_version_ops _vsn1_ops = {
check_version:_check_version,
read_vg:_read_vg,
read_desc:_read_desc
.check_version = _check_version,
.read_vg = _read_vg,
.read_desc = _read_desc,
.read_vgname = _read_vgname,
};
struct text_vg_version_ops *text_vg_vsn1_init(void)
{
return &_vsn1_ops;
};
}

View File

@@ -36,7 +36,7 @@ struct data_area_list {
/* Fields with the suffix _xl should be xlate'd wherever they appear */
/* On disk */
struct pv_header {
uint8_t pv_uuid[ID_LEN];
int8_t pv_uuid[ID_LEN];
/* This size can be overridden if PV belongs to a VG */
uint64_t device_size_xl; /* Bytes */
@@ -58,7 +58,7 @@ struct raw_locn {
/* Structure size limited to one sector */
struct mda_header {
uint32_t checksum_xl; /* Checksum of rest of mda_header */
uint8_t magic[16]; /* To aid scans for metadata */
int8_t magic[16]; /* To aid scans for metadata */
uint32_t version;
uint64_t start; /* Absolute start byte of mda_header */
uint64_t size; /* Size of metadata area */
@@ -83,6 +83,6 @@ struct mda_context {
#define FMTT_VERSION 1
#define MDA_HEADER_SIZE 512
#define LVM2_LABEL "LVM2 001"
#define MDA_SIZE_MIN (8 * getpagesize())
#define MDA_SIZE_MIN (8 * (unsigned) lvm_getpagesize())
#endif

View File

@@ -23,17 +23,19 @@
#include <sys/stat.h>
#include <fcntl.h>
static int _can_handle(struct labeller *l, char *buf, uint64_t sector)
static int _text_can_handle(struct labeller *l __attribute((unused)),
void *buf,
uint64_t sector __attribute((unused)))
{
struct label_header *lh = (struct label_header *) buf;
if (!strncmp(lh->type, LVM2_LABEL, sizeof(lh->type)))
if (!strncmp((char *)lh->type, LVM2_LABEL, sizeof(lh->type)))
return 1;
return 0;
}
static int _write(struct label *label, char *buf)
static int _text_write(struct label *label, void *buf)
{
struct label_header *lh = (struct label_header *) buf;
struct pv_header *pvhdr;
@@ -46,7 +48,7 @@ static int _write(struct label *label, char *buf)
/* FIXME Move to where label is created */
strncpy(label->type, LVM2_LABEL, sizeof(label->type));
strncpy(lh->type, label->type, sizeof(label->type));
strncpy((char *)lh->type, label->type, sizeof(label->type));
pvhdr = (struct pv_header *) ((void *) buf + xlate32(lh->offset_xl));
info = (struct lvmcache_info *) label->info;
@@ -86,7 +88,7 @@ static int _write(struct label *label, char *buf)
return 1;
}
int add_da(const struct format_type *fmt, struct dm_pool *mem, struct list *das,
int add_da(struct dm_pool *mem, struct list *das,
uint64_t start, uint64_t size)
{
struct data_area_list *dal;
@@ -179,14 +181,15 @@ void del_mdas(struct list *mdas)
}
}
static int _initialise_label(struct labeller *l, struct label *label)
static int _text_initialise_label(struct labeller *l __attribute((unused)),
struct label *label)
{
strncpy(label->type, LVM2_LABEL, sizeof(label->type));
return 1;
}
static int _read(struct labeller *l, struct device *dev, char *buf,
static int _text_read(struct labeller *l, struct device *dev, void *buf,
struct label **label)
{
struct label_header *lh = (struct label_header *) buf;
@@ -195,13 +198,16 @@ static int _read(struct labeller *l, struct device *dev, char *buf,
struct disk_locn *dlocn_xl;
uint64_t offset;
struct metadata_area *mda;
char vgnamebuf[NAME_LEN + 2];
struct id vgid;
struct mda_context *mdac;
const char *vgname;
uint32_t vgstatus;
char *creation_host;
pvhdr = (struct pv_header *) ((void *) buf + xlate32(lh->offset_xl));
if (!(info = lvmcache_add(l, pvhdr->pv_uuid, dev, NULL, NULL)))
return 0;
if (!(info = lvmcache_add(l, (char *)pvhdr->pv_uuid, dev, NULL, NULL, 0)))
return_0;
*label = info->label;
info->device_size = xlate64(pvhdr->device_size_xl);
@@ -217,7 +223,7 @@ static int _read(struct labeller *l, struct device *dev, char *buf,
/* Data areas holding the PEs */
dlocn_xl = pvhdr->disk_areas_xl;
while ((offset = xlate64(dlocn_xl->offset))) {
add_da(info->fmt, NULL, &info->das, offset,
add_da(NULL, &info->das, offset,
xlate64(dlocn_xl->size));
dlocn_xl++;
}
@@ -232,10 +238,12 @@ static int _read(struct labeller *l, struct device *dev, char *buf,
list_iterate_items(mda, &info->mdas) {
mdac = (struct mda_context *) mda->metadata_locn;
if (vgname_from_mda(info->fmt, &mdac->area, vgnamebuf,
sizeof(vgnamebuf))) {
lvmcache_update_vgname(info, vgnamebuf);
}
if ((vgname = vgname_from_mda(info->fmt, &mdac->area,
&vgid, &vgstatus, &creation_host)) &&
!lvmcache_update_vgname_and_id(info, vgname,
(char *) &vgid, vgstatus,
creation_host))
return_0;
}
info->status &= ~CACHE_INVALID;
@@ -243,7 +251,8 @@ static int _read(struct labeller *l, struct device *dev, char *buf,
return 1;
}
static void _destroy_label(struct labeller *l, struct label *label)
static void _text_destroy_label(struct labeller *l __attribute((unused)),
struct label *label)
{
struct lvmcache_info *info = (struct lvmcache_info *) label->info;
@@ -253,19 +262,19 @@ static void _destroy_label(struct labeller *l, struct label *label)
del_das(&info->das);
}
static void _destroy(struct labeller *l)
static void _fmt_text_destroy(struct labeller *l)
{
dm_free(l);
}
struct label_ops _text_ops = {
can_handle:_can_handle,
write:_write,
read:_read,
verify:_can_handle,
initialise_label:_initialise_label,
destroy_label:_destroy_label,
destroy:_destroy
.can_handle = _text_can_handle,
.write = _text_write,
.read = _text_read,
.verify = _text_can_handle,
.initialise_label = _text_initialise_label,
.destroy_label = _text_destroy_label,
.destroy = _fmt_text_destroy,
};
struct labeller *text_labeller_create(const struct format_type *fmt)

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