1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-09-24 21:44:22 +03:00

Compare commits

...

758 Commits

Author SHA1 Message Date
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
Alasdair Kergon
0b43754d60 rename deptree 2005-11-09 14:10:50 +00:00
Alasdair Kergon
8b3b26b813 rename deptree 2005-11-09 13:08:41 +00:00
Alasdair Kergon
5426af4f81 rename deptree 2005-11-09 13:05:17 +00:00
Alasdair Kergon
4e2c3a579d xen xvd 2005-11-09 12:47:16 +00:00
Patrick Caulfield
5ae2693241 Use hash functions in libdevmapper. 2005-11-09 09:24:10 +00:00
Alasdair Kergon
41c86b0d19 Replacement activation code. [Don't use this yet!] 2005-11-08 22:52:26 +00:00
Alasdair Kergon
40788e8c3d New activation code. [Not ready to be used yet.] 2005-11-08 22:50:11 +00:00
Alasdair Kergon
0d29120033 precommitted flag 2005-10-31 20:18:50 +00:00
Alasdair Kergon
4be598f865 Clear up precommitted metadata better on disk after use.
[Some activation-related features will stop working for a while now.
Some types of activation are getting split into two steps, with the
first step using the precommitted metadata.]
2005-10-31 20:15:28 +00:00
Alasdair Kergon
558a6d509e pvresize man 2005-10-31 15:49:07 +00:00
Alasdair Kergon
75cd02aad2 revert unfinished change 2005-10-31 15:46:29 +00:00
Alasdair Kergon
e4c4451482 missing vg_revert 2005-10-31 15:43:11 +00:00
Alasdair Kergon
0671632477 A pvresize implementation (Zak Kipling). 2005-10-31 02:37:29 +00:00
Alasdair Kergon
54c230c264 reorder commit 2005-10-28 14:38:20 +00:00
Alasdair Kergon
64ba878eda more mirror library functions 2005-10-28 12:48:50 +00:00
Alasdair Kergon
01acd6dd76 Fix contiguous allocation when there are no preceding segments. 2005-10-27 22:21:10 +00:00
Alasdair Kergon
9d819b52d3 Fix contiguous allocation without preceding segments. 2005-10-27 22:20:33 +00:00
Alasdair Kergon
37bac5cdc9 Fix new mirror_seg pointer. 2005-10-27 21:51:28 +00:00
Alasdair Kergon
78c718c591 Add mirror_seg pointer to lv_segment struct. (incomplete & untested) 2005-10-27 19:58:22 +00:00
Alasdair Kergon
284b8bf6ca Only keep a device open if it's known to belong to a locked VG. 2005-10-27 17:45:34 +00:00
Alasdair Kergon
5a5084b837 Only keep devices open if known to belong to a locked VG now. 2005-10-27 17:44:55 +00:00
Alasdair Kergon
3b8058e1f1 Export vgname_is_locked 2005-10-27 17:41:41 +00:00
Alasdair Kergon
2a3168e0d6 remove unused suspend code path 2005-10-26 19:50:00 +00:00
Alasdair Kergon
a8ac6e4a15 fix strncmps 2005-10-26 18:33:47 +00:00
Alasdair Kergon
6172cf9fba Fix incorrect checkin 2005-10-26 18:32:57 +00:00
Alasdair Kergon
b728ec3909 Fix strncmps. 2005-10-26 18:17:36 +00:00
Alasdair Kergon
61a53bbcff suppress status err mesg when LVM- uuid prefix is missing 2005-10-26 17:56:31 +00:00
Alasdair Kergon
17d13dd084 Also suppress error if device doesn't exist with DM_DEVICE_STATUS. 2005-10-26 17:51:10 +00:00
Alasdair Kergon
edcb28d591 also suppress error if device doesn't exist with STATUS 2005-10-26 17:50:15 +00:00
Alasdair Kergon
ad101119a7 remove remaining hard-coded prefix lengths 2005-10-26 17:31:12 +00:00
Alasdair Kergon
bc36676d31 Fix lvdisplay to show all mirror destinations. 2005-10-26 16:12:36 +00:00
Alasdair Kergon
d76fe120ab a missing lvid/dlid conversion 2005-10-26 15:54:50 +00:00
Alasdair Kergon
2e95949b80 attempt to cope with uuid transition 2005-10-26 15:21:13 +00:00
Alasdair Kergon
ae14d85e24 Attempt to cope with LVM- prefix transition. 2005-10-26 15:00:51 +00:00
Alasdair Kergon
fad6304c60 new suspend code 2005-10-26 14:14:30 +00:00
Alasdair Kergon
a4dd3c8ce9 switch in new suspend code (untested) 2005-10-26 14:13:52 +00:00
Alasdair Kergon
6d1a5d45e2 check parents suspended 2005-10-26 14:08:24 +00:00
Alasdair Kergon
a6c7043e03 unfinished suspend functions 2005-10-25 19:09:41 +00:00
Alasdair Kergon
bcc400dafa Use dm_is_dm_major instead of local copy.
Allow mapped devices to be used as PVs safely.
2005-10-25 19:08:21 +00:00
Alasdair Kergon
8fbedf3441 Add DEFS 2005-10-25 19:03:59 +00:00
Alasdair Kergon
2e8a9c9874 Export dm_set_selinux_context. 2005-10-25 17:30:00 +00:00
Alasdair Kergon
44fc41b3e5 Move set_selinux_context into libdevmapper 2005-10-25 17:28:46 +00:00
Alasdair Kergon
7212c20a1b Fix automatic text metadata buffer expansion (using macro). [stdarg usage bug]
Cache formatted text metadata buffer between metadata area writes.
  [improves write performance when lots of metadata area clones]
2005-10-23 00:14:48 +00:00
Alasdair Kergon
7ff142de1c Add pe_start to pvs. 2005-10-20 22:24:46 +00:00
Alasdair Kergon
e67efb199d Fix LVM2- prefix changes; export build_dlid. 2005-10-20 21:07:57 +00:00
Alasdair Kergon
20128bd04b zero suppress 2005-10-20 20:38:18 +00:00
Alasdair Kergon
c0fefdde28 fix dev no printf 2005-10-20 20:29:58 +00:00
Alasdair Kergon
f6ee160e66 Add 'LVM-' prefix to uuids. 2005-10-19 13:59:18 +00:00
Alasdair Kergon
06acc2004f cope with null uuid_prefix 2005-10-18 13:57:11 +00:00
Alasdair Kergon
43ac2ce4c8 use seg_type macro 2005-10-18 13:45:25 +00:00
Alasdair Kergon
b32bf72b5f Split lv_segment_area from lv_segment to permit extension. 2005-10-18 13:43:40 +00:00
Alasdair Kergon
c6880c957e Tidy some log mesgs. 2005-10-18 13:07:41 +00:00
Alasdair Kergon
095b71ed96 Move deactivation code into libdevmapper. 2005-10-18 12:39:20 +00:00
Alasdair Kergon
9160e496bc Add deactivation functions 2005-10-18 12:37:53 +00:00
Alasdair Kergon
2a7ac78f02 some deactivation fixes 2005-10-17 19:06:20 +00:00
Alasdair Kergon
64efa4627d Replacement deactivation code - untested. 2005-10-17 18:21:57 +00:00
Alasdair Kergon
f7e35569ce Only one dump_memory. 2005-10-17 18:21:05 +00:00
Alasdair Kergon
e8af32ec2b dm_driver_version 2005-10-17 18:05:39 +00:00
Alasdair Kergon
e092ce51f6 Attempt to load missing targets using modprobe.
Simplify dev_manager_info().
2005-10-17 18:00:02 +00:00
Alasdair Kergon
7b78edb1b7 Attempt to load missing targets using modprobe. 2005-10-17 17:56:27 +00:00
Alasdair Kergon
b332e7090e lvscan -a 2005-10-17 16:41:38 +00:00
Alasdair Kergon
67eb7723d6 Use hash, bitset, malloc, pool from libdevmapper. 2005-10-16 23:03:59 +00:00
Alasdair Kergon
251d138474 export bitset, pool, hash, malloc 2005-10-16 22:57:20 +00:00
Alasdair Kergon
1170dfac05 post-release 2005-10-16 20:09:42 +00:00
Alasdair Kergon
4157f141c7 pre-release 2005-10-16 20:06:54 +00:00
Alasdair Kergon
f569abd28a Code to build and display device dependency tree. 2005-10-16 14:33:22 +00:00
Alasdair Kergon
088f9687c0 Add dmsetup --nolockfs support for suspend/reload.
Requires kernel patches to have any effect.
Library version incremented.
2005-10-04 20:12:32 +00:00
Alasdair Kergon
e23df1f07a Refuse to run pvcreate/pvremove on devices we can't open exclusively. 2005-10-03 21:10:41 +00:00
Alasdair Kergon
c818540dfd Use ORPHAN lock definition throughout. 2005-10-03 18:16:44 +00:00
Alasdair Kergon
21365cbe1a Validate chunksize in lvcreate. 2005-09-30 22:21:01 +00:00
Alasdair Kergon
5471a80a96 Impose chunk size limitation. 2005-09-30 22:20:14 +00:00
Alasdair Kergon
d7b6fa9cd0 Reduce chunksize limit to 512k. 2005-09-29 15:50:51 +00:00
Alasdair Kergon
dfdc2e02ef post-release 2005-09-26 20:52:00 +00:00
Alasdair Kergon
893ec9a302 1.01.05 2005-09-26 20:44:12 +00:00
Alasdair Kergon
05f65c38e6 Fix chunksize field in reports. 2005-09-23 17:06:01 +00:00
Alasdair Kergon
2e9d062ec0 Don't hide snapshots from default 'lvs' output. 2005-09-23 16:22:17 +00:00
Alasdair Kergon
6b0b394e61 Resync list.h with LVM2. 2005-09-22 12:06:34 +00:00
Alasdair Kergon
25621396c9 Remember increased buffer size and use for subsequent calls. 2005-09-20 18:04:28 +00:00
Alasdair Kergon
82aa0271f3 Explicitly initialise no_open_count 2005-09-20 16:39:12 +00:00
Alasdair Kergon
653cab13f8 On 'buffer full' condition, double buffer size and repeat ioctl. [Untested] 2005-09-19 14:29:17 +00:00
Alasdair Kergon
b526f86b49 Add is_dm_major() for use in duplicate device detection in lvmcache_add(). 2005-09-16 18:53:01 +00:00
Alasdair Kergon
53c0f00888 Really switch device number in lvmcache when it says it is doing so. 2005-09-16 18:44:52 +00:00
Alasdair Kergon
f0c4d9de40 Option for bitset memory allocation using malloc as well as pool. 2005-09-16 18:40:53 +00:00
Alasdair Kergon
03ef8cec83 Don't assume exactly two mirrors when parsing mirror status 2005-09-02 16:59:46 +00:00
Alasdair Kergon
85f2a2e8c2 Suppress fsync() error message on filesystems that don't support it. 2005-09-01 18:37:22 +00:00
Alasdair Kergon
584b3e6642 Fix yes_no_prompt() error handling. 2005-08-31 19:32:10 +00:00
Alasdair Kergon
39b7ef841d add comments to example conf file to warn about common filter line mistakes 2005-08-31 15:05:47 +00:00
Alasdair Kergon
aa16a9098d Fix termination of getopt_long() option array. 2005-08-18 19:40:19 +00:00
Alasdair Kergon
7b8c2707bc lvmconf.sh 2005-08-16 20:42:28 +00:00
Alasdair Kergon
60e26a31a7 Add copyright notice to lvmconf.sh and use unique exit codes. 2005-08-16 20:38:33 +00:00
Alasdair Kergon
3473c25c14 Add format1 dev_write debug messages. 2005-08-16 19:00:55 +00:00
Patrick Caulfield
e52f022026 clvmd no longer takes out locks for non-clusteed LVs,
and non-clustered LVs are only activated on the local node.
2005-08-16 08:25:09 +00:00
Alasdair Kergon
b1a7df8e43 Add clustered VG attribute to report. 2005-08-15 23:34:11 +00:00
Alasdair Kergon
0fd2479b7c Move lvconvert parameters into struct lvconvert_params. 2005-08-15 14:10:28 +00:00
Alasdair Kergon
273857f914 Add clustered VG flag to LV lock requests. 2005-08-15 13:24:46 +00:00
Alasdair Kergon
a08b85dbc8 Change LV locking macros to take lv instead of lvid. 2005-08-15 12:00:04 +00:00
Alasdair Kergon
a0aedf299a Prepare tools to support clustered mirrors. 2005-08-14 23:18:28 +00:00
Alasdair Kergon
3c61426844 Factor out generate_log_name_format(). 2005-08-12 20:02:21 +00:00
Alasdair Kergon
786f228076 Factor out adjusted_mirror_region_size() 2005-08-12 19:23:08 +00:00
Alasdair Kergon
004da28792 Move compose_log_line() into mirror directory. 2005-08-10 17:19:46 +00:00
Alasdair Kergon
6e2be6efb6 Don't kill idling clvmd threads. 2005-08-09 17:29:04 +00:00
Alasdair Kergon
a994dfcfbc Factor out _get_library_path(). 2005-08-09 17:24:21 +00:00
Patrick Caulfield
7a8ea2ac93 Don't send a signal to kill threads that are idling nicely as it upsets them.
This seems to cure bz#159727 on SMP systems.

Alasdair, can you include this patch in the lvm2-cluster package please ?
2005-08-09 10:39:57 +00:00
Alasdair Kergon
0da3965d19 Report 'buffer full' condition with v4 ioctl as well as with v1. 2005-08-08 18:40:17 +00:00
Alasdair Kergon
885fd7bb46 aoe 2005-08-08 17:55:35 +00:00
Alasdair Kergon
08771f9c89 Recognise aoe devices. 2005-08-08 17:54:23 +00:00
Alasdair Kergon
8be48195a5 post-release 2005-08-04 02:07:34 +00:00
Alasdair Kergon
98ce2d650e update po 2005-08-04 02:02:37 +00:00
Alasdair Kergon
3af327116a Fix lvconvert PV parameter in help string. 2005-08-04 01:50:17 +00:00
Alasdair Kergon
b75434db93 fix last checkin 2005-08-04 01:29:18 +00:00
Alasdair Kergon
04e912aacd Prevent snapshots getting activated in a clustered VG. 2005-08-04 01:27:25 +00:00
Alasdair Kergon
d7be352f87 Separate out _build_dev_string. 2005-08-04 01:15:30 +00:00
Alasdair Kergon
96be3ec22c Move zero_lv to toollib. 2005-08-04 01:14:36 +00:00
Alasdair Kergon
32e7e0d790 post-release 2005-08-02 21:46:49 +00:00
Alasdair Kergon
becc320e62 update vsn 2005-08-02 18:00:32 +00:00
Alasdair Kergon
7666ed57d1 Fix dmsetup ls -j and status --target with empty table. 2005-07-29 16:11:23 +00:00
AJ Lewis
5e61d0955e fix pool format handler to work with pvseg code 2005-07-26 21:48:18 +00:00
Alasdair Kergon
e8a4662ae7 post-release 2005-07-13 19:28:09 +00:00
Alasdair Kergon
a48da3bd3b update po 2005-07-13 19:23:48 +00:00
Alasdair Kergon
5f1a5d7b99 2.01.13 2005-07-13 19:15:09 +00:00
Alasdair Kergon
3e28a9db8f Fix pvmove segment splitting.
Abstract vg_validate.
2005-07-12 19:40:59 +00:00
Alasdair Kergon
ebf6071d77 Only make one attempt at contiguous allocation. 2005-07-12 14:50:45 +00:00
Alasdair Kergon
47a35fb9fb Fix lvm1 format metadata read. 2005-06-22 15:31:29 +00:00
Alasdair Kergon
48e88aba44 fix lvm1 non-mirror lvcreate 2005-06-22 14:56:14 +00:00
Benjamin Marzinski
b85f99c140 Fixing some makesfiles, so that the correct things link against pthreads.
Also changed dmevent so that in no longer links against pthreads, and
dynamically loads libdmevent.so.  Everything seems to work just fine like this.
2005-06-14 19:06:26 +00:00
Alasdair Kergon
0a5e0e1f71 preset pl to NULL 2005-06-14 18:29:12 +00:00
Alasdair Kergon
85dc22ebb7 missing fn defs 2005-06-14 18:22:31 +00:00
Alasdair Kergon
5c21526009 post-release 2005-06-14 18:22:22 +00:00
Alasdair Kergon
14dff1cefc 2.01.12 2005-06-14 17:59:57 +00:00
Alasdair Kergon
39fbb844f9 Various allocation-related pvmove fixes. 2005-06-14 17:54:48 +00:00
Patrick Caulfield
ca4e0c973a Log an error if clvmd can't resolve a host name got from CCS
Fix potential spin loop in clvmd
2005-06-14 10:35:02 +00:00
Alasdair Kergon
ecb42bee80 post-release 2005-06-13 14:53:07 +00:00
Alasdair Kergon
674ed2a9f3 2.01.11 2005-06-13 14:43:28 +00:00
Alasdair Kergon
252daf9717 Use matchpathcon mode parameter. 2005-06-13 13:13:15 +00:00
Alasdair Kergon
196b8eaad3 Use matchpathcon mode parameter 2005-06-13 13:11:48 +00:00
Patrick Caulfield
8e526ba1bf Don't defer closing of FDs in clvmd as it can cause trouble. 2005-06-13 10:16:21 +00:00
Alasdair Kergon
19225828d9 update version 2005-06-10 22:00:44 +00:00
Alasdair Kergon
7e594126be fix configure script to reenable selinux 2005-06-10 21:57:49 +00:00
AJ Lewis
d2529e6334 o print the context along with the path when setting selinux context 2005-06-10 21:30:21 +00:00
AJ Lewis
97344f18e2 o set umask and make tempfiles a bit nicer to deal with 2005-06-10 19:10:45 +00:00
AJ Lewis
33934db629 o script to adjust items in lvm.conf file - currently only handles turning
cluster lvm on and off
2005-06-10 17:11:48 +00:00
Patrick Caulfield
6c6165c9f5 Be a bit smarter about reading stuff from the sockets 2005-06-10 09:11:01 +00:00
Benjamin Marzinski
853460b20d Timeout event implementation:
The daemon side of this is mostly the same as the patch I sent out.  To select
a timeout period different than the default and to get the timeout period,
I added two library calls, dm_set_event_timeout() and dm_get_event_timeout().
If people are against them, the other option is to tack extra arguments onto
dm_regiser_for_event() and dm_get_registered_device().  I also added a
-t option to dmevent, so people can try out timeouts.
2005-06-09 18:40:49 +00:00
Alasdair Kergon
cc4d9676c5 Remove hard-coded 64k text metadata writing restriction. 2005-06-07 11:00:07 +00:00
Alasdair Kergon
1cf1b819f4 Make VG name restrictions consistent. 2005-06-06 18:16:33 +00:00
Alasdair Kergon
f916c66d2b Introduce lvconvert. So far only removes mirror images. 2005-06-06 17:12:08 +00:00
Alasdair Kergon
550aa86b45 prevent active mirror resize for now 2005-06-03 22:26:09 +00:00
Alasdair Kergon
014e764758 Allow mirror images to be resized. 2005-06-03 19:48:19 +00:00
Alasdair Kergon
d1fc28432b Allow mirror images to have more than one segment. 2005-06-03 18:07:13 +00:00
Alasdair Kergon
879576f0a2 lvremove mirror images 2005-06-03 15:44:12 +00:00
Alasdair Kergon
69098210be Always insert an intermediate layer for mirrors.
Suppress hidden LVs from reports unless --all is given.
Use square brackets for hidden LVs in reports.
Centralise restrictions on LV names.
2005-06-03 14:49:51 +00:00
Alasdair Kergon
99df4f892d Basic support for mirrors. 2005-06-01 16:51:55 +00:00
AJ Lewis
7bc04fbad3 Change the multilog code to toggle between async and sync writes for all
log types.  This means the threaded_syslog type is no longer valid.  A new
fxn multilog_async is available to toggle between the two modes.  If an
app is compiled without pthreads and tries to use async logging, no logging
will occur while async is enabled.

dmeventd has been modified to use the new code

I'm not positive I like the way the async_logger code calls the log fxn,
but it works for now.  Suggestions for other ways to do it would be helpful
2005-05-25 21:08:36 +00:00
Alasdair Kergon
8a74ce578d Fix non-orphan pvchange -u. 2005-05-24 17:38:26 +00:00
Alasdair Kergon
0805e4e5de Fix mem allocs after archiver code move. 2005-05-24 17:37:39 +00:00
Heinz Mauelshagen
f1060fc88e Exit after last unregister_for_event() 2005-05-20 13:53:26 +00:00
Alasdair Kergon
7d3d3d0a3a Fix vgmerge to handle duplicate LVIDs. 2005-05-19 16:48:51 +00:00
Alasdair Kergon
40377032e3 1.01.02 2005-05-17 15:50:25 +00:00
Alasdair Kergon
b2971edd7d Start merging cloned allocation functions. 2005-05-17 13:49:45 +00:00
Alasdair Kergon
c37d723692 Move archiver code from tools into library. 2005-05-17 13:46:38 +00:00
Alasdair Kergon
30f9026e1d vgscan/change/display/vgs automatically create metadata backup if out-of-date or missing. 2005-05-17 13:44:02 +00:00
Alasdair Kergon
332286072e Add dmsetup ls --exec. 2005-05-16 20:46:46 +00:00
Alasdair Kergon
d6da172a2a Add --target to dmsetup ls. 2005-05-16 16:04:34 +00:00
Alasdair Kergon
ebfe584afc Call dm_lib_exit() and dm_lib_release() automatically now. 2005-05-16 15:15:34 +00:00
Alasdair Kergon
6250023583 Add --target <target_type> filter to dmsetup table/status.
Fix dmsetup getopt_long usage.
2005-05-16 14:53:23 +00:00
Alasdair Kergon
6b4f3d63b8 Fix contiguous allocations with linear. 2005-05-11 16:46:59 +00:00
AJ Lewis
56db773a09 more clvmd rhel4 initscript cleanup
- don't echo after an 'action' call - action does the echo itself
 - use vgdisplay/vgs to determine which VGs are marked clustered and only
   deactivate those VGs (unless the LVM_VGS var is set in
   /etc/sysconfig/cluster)
2005-05-11 15:21:44 +00:00
Alasdair Kergon
fc6c472401 Cope with missing format1 PVs again. 2005-05-11 15:04:06 +00:00
Alasdair Kergon
2cd42a6866 Remove lists of free PV segments.
Simplify pv_maps code and remove slow bitset algorithm.
2005-05-11 15:02:49 +00:00
AJ Lewis
36a90c345c updated to reflect clvmd rhel4 initscript being redhatified 2005-05-10 20:15:39 +00:00
AJ Lewis
ef1e82c72c Fixes bz#155478
Redhatify the rhel4 initscript (use /etc/init.d/functions)
2005-05-10 20:14:33 +00:00
AJ Lewis
88f9534685 o Changed the multilog API a bit (I warned you)
- multilog_add_type, multilog_del_type, multilog_custom, and
     multilog_init_verbose all have different arguments.
   - Primary change is that caller only passes in config info, and the
     lib keeps track of state internally.  No more exporting of
     'struct log_data'.
   - Custom callers now only get the custom data pointer passed into their
     log fxn (that is set with multilog_custom)
   - Added basic README that describes libmultilog
2005-05-09 18:44:35 +00:00
Alasdair Kergon
68254a052a %Zu->zu 2005-05-09 17:45:06 +00:00
Alasdair Kergon
2425b3a166 fix compiler warnings 2005-05-09 17:41:36 +00:00
Alasdair Kergon
5524ed753b Fix loopfiles mem alloc. 2005-05-09 17:02:52 +00:00
Alasdair Kergon
89711723da Un-inline dbg_strdup. 2005-05-09 17:01:06 +00:00
Alasdair Kergon
bed2740ffd lv_reduce tidying.
Remove some unnecessary parameters.
Introduce seg_is macros.
2005-05-09 16:59:01 +00:00
Alasdair Kergon
751d633c3d post-release 2005-05-09 16:41:48 +00:00
Benjamin Marzinski
45952cbdf2 oops. Those are char **'s not char *'s 2005-05-04 19:24:03 +00:00
Benjamin Marzinski
b355dd7b23 fixed dmevent so that it doesn't do a double free when you run
# dmevent -l

Also, changed the behaviour of dm_get_registered_device(), so that it doesn't
change the pointer you passed in without freeing the memory on a non-next call,
and doesn't free your pointer without setting it to NULL on a failed next call.
2005-05-04 18:53:28 +00:00
Heinz Mauelshagen
48a186f172 o libmultilog needs introducing of list locking in order to stand
multilog_add_type()/multilog_del_type cycles correctly.
o fixed segfault in multilog_add_type()
o fixed test-multilog.c
o cleaned up libmultilog (list macros, indentation, braces, comments)
2005-05-04 11:52:07 +00:00
Jonathan Earl Brassow
39dc7ec2ab - make noop use multilog
- add event_nr to thread_status struct and set appropriately so that the
  thread actually waits for an event
- essentially make error_detected return true.  Let the DSOs determine
  how to interpret the status info
2005-05-04 01:57:31 +00:00
AJ Lewis
2fedabd3b9 o stick multilog into the dm-event lib and dmeventd code again
o more tweaks to libmultilog calls - the api isn't set in stone yet, so
   don't get too comfortable.
 o not sure the dmeventd in device-mapper/dmeventd works - i've been using
   the one in lib/event/
 o currently both daemons are set to log only to syslog
2005-05-03 21:29:13 +00:00
Alasdair Kergon
6d719e9480 2.01.10 2005-05-03 17:43:47 +00:00
Alasdair Kergon
05e278afda Don't create backup and archive dirs till needed. 2005-05-03 17:31:56 +00:00
Alasdair Kergon
87dbf462cb Reinstate full PV size when removing from VG.
Support loopfiles for testing.
Complete the pv_segment support.
2005-05-03 17:28:23 +00:00
Heinz Mauelshagen
40e896bc5b working dm_get_registered_device(). dmevent.c update to use it. 2005-05-03 16:15:20 +00:00
Heinz Mauelshagen
3e940f80c7 more dm_get_registered_device() code 2005-05-03 13:50:42 +00:00
Benjamin Marzinski
dbf2888d43 dmeventd was looking for dsos with libdmeventd<name>.so
The Makefile turned noop.c into    libdmeventnoop.so
The Makefile now turns noop.c into libdmeventdnoop.so
2005-05-02 19:34:25 +00:00
Benjamin Marzinski
d412355324 stopped printing a string after we erased the pointer to it. 2005-05-02 18:43:23 +00:00
Benjamin Marzinski
178732217f removed the -lmultilog for now. 2005-05-02 18:42:07 +00:00
Benjamin Marzinski
de17b95c3d get the makefile to clean up the .o's 2005-05-02 17:41:54 +00:00
Heinz Mauelshagen
d14e774525 Introduce exit() in main() and cleanup signal settings for parent/child 2005-05-02 11:02:19 +00:00
Benjamin Marzinski
ca5402a7fa more variable initialization. 2005-04-29 22:12:09 +00:00
Benjamin Marzinski
7a6fa7c5b4 changed client_path and sever_path from 'char *' to 'const char *' to stop
compiler warning messages.
2005-04-29 21:52:46 +00:00
Heinz Mauelshagen
da36c286a6 o checking in instrumented code for AJ to follow up on comms and logging
o changed

  int dm_get_next_registered_device(char **dso_name, char **device,
                                    enum event_type *events);

  to

  int dm_get_registered_device(char **dso_name, char **device,
                               enum event_type *events, int next)

  so that the daemon is able to retrive the next one of the list without
  running into locking issues.

o changed dmevent.c to use dm_get_registered_device()

o couldn't test this yet because of the comms issues
  (daemon exits in do_process_request())
2005-04-29 14:56:35 +00:00
Heinz Mauelshagen
d3901bcf2e first changes to get comms back to work after flock changes 2005-04-29 13:41:25 +00:00
Heinz Mauelshagen
94c8d4fdfb minor cleanup 2005-04-29 10:58:34 +00:00
AJ Lewis
ab8bdc18bb o Build dmeventd against multilog 2005-04-28 22:47:52 +00:00
Alasdair Kergon
c9dcd7442a build libdmeventnoop.so for testing 2005-04-28 17:32:27 +00:00
Alasdair Kergon
34c8f13346 test.c->dmevent.c 2005-04-28 14:49:41 +00:00
Alasdair Kergon
7a8ccda95c o adds dm_get_next_registered_device() (not functional yet)
to retrieve which devices got registered with the daemon;
  needs locking changes as well
2005-04-28 14:02:30 +00:00
Alasdair Kergon
44a1448542 Prototype for a device-mapper event-handling daemon. 2005-04-27 22:32:00 +00:00
Alasdair Kergon
c87d89ffaf extend alloc_lv_segment 2005-04-22 15:44:00 +00:00
Alasdair Kergon
0868749d42 set_lv_segment_area_pv/lv 2005-04-22 15:43:02 +00:00
Alasdair Kergon
1d40ee23f0 Initial pv_segment code. 2005-04-19 20:58:25 +00:00
Alasdair Kergon
8893f32603 initial pv_segment defns 2005-04-19 20:52:35 +00:00
Alasdair Kergon
adcf7e8dc3 _copy_pv -> int 2005-04-19 20:44:21 +00:00
Patrick Caulfield
901f7c5c36 Tidy clvmd's SIGHUP handler so it doesn't do all that work. 2005-04-19 10:36:42 +00:00
Alasdair Kergon
775bb413b3 vgchange --physicalextentsize (but only if it's an exact fit - may need to
use pvmove first)
2005-04-18 14:56:42 +00:00
Alasdair Kergon
64cd5b5a46 extract compose_log_line 2005-04-17 23:59:04 +00:00
Alasdair Kergon
ae356609b1 get_pv_from_vg_by_id 2005-04-17 23:57:44 +00:00
Patrick Caulfield
6102a5d2b0 Make clvmd work around some "limitations" in gulm's node state notifications.
Also make clvmd debuglog timestamps a little more helpful.
2005-04-13 13:50:07 +00:00
Alasdair Kergon
f8782ee2d7 Internal snapshot code restructuring. 2005-04-07 12:39:44 +00:00
Alasdair Kergon
6181ec4c77 add lvid to lv_create_empty 2005-04-07 12:29:46 +00:00
Alasdair Kergon
e0e7a685ef Remove unused internal non-persistent snapshot option. 2005-04-07 12:27:57 +00:00
Alasdair Kergon
ae1f8cdad2 fix unused o_direct label 2005-04-07 12:25:33 +00:00
Alasdair Kergon
a4cf792e6d store snapshot id as lvid internally 2005-04-07 12:24:48 +00:00
Alasdair Kergon
89109ded53 Allow offline extension of snapshot volumes.
NB Requires kernel patch that is not upstream.
2005-04-07 12:17:46 +00:00
Alasdair Kergon
e20e52a4b2 Move from 2-step to 3-step on-disk metadata commit. 2005-04-06 18:59:55 +00:00
Alasdair Kergon
20c4b1cbec Add ramdisk. 2005-04-06 16:43:59 +00:00
Alasdair Kergon
5238b0241d _vg_posn -> _find_vg_rlocn 2005-04-06 16:35:33 +00:00
Alasdair Kergon
9cdf6c203d more refinements 2005-04-06 15:21:28 +00:00
Alasdair Kergon
839335cae6 Annotate, tidy and extend list.h. 2005-04-06 14:50:37 +00:00
Alasdair Kergon
a99b2ce167 Alignment tidying. 2005-04-06 13:47:41 +00:00
Alasdair Kergon
b695141d87 post-release 2005-04-04 15:46:14 +00:00
Alasdair Kergon
92d5c9f866 2.01.09 2005-04-04 15:41:51 +00:00
Alasdair Kergon
7f18a1ffe0 Add --ignorelockingfailure to vgmknodes. 2005-04-04 14:44:49 +00:00
Patrick Caulfield
8c3fdaaa62 set SO_KEEPALIVE on sockets 2005-04-01 16:03:00 +00:00
Patrick Caulfield
5ac1c69710 Don't allow user operations to start until the lvm thread is fully up.
Hopefully finally nails bz#146056
2005-04-01 13:01:01 +00:00
Alasdair Kergon
de2d5fba63 post-release 2005-03-29 18:10:57 +00:00
Alasdair Kergon
33d516748f 1.01.01 2005-03-29 14:47:39 +00:00
Alasdair Kergon
de17f6f0fd Update dmsetup man page. 2005-03-29 14:46:30 +00:00
Alasdair Kergon
756731fc02 Drop-in devmap_name replacement. 2005-03-27 11:37:46 +00:00
Alasdair Kergon
e46be0415f post-release 2005-03-22 16:50:17 +00:00
Alasdair Kergon
aa02fb50bf update pofile 2005-03-22 15:13:48 +00:00
Alasdair Kergon
8b6cd9c772 2.01.08 2005-03-22 15:12:37 +00:00
Alasdair Kergon
cdd0d3351a Add clustered attribute so vgchange can identify clustered VGs w/o locking. 2005-03-21 22:55:12 +00:00
Alasdair Kergon
8b6d584529 Improve detection of external changes affecting internal cache. 2005-03-21 22:40:35 +00:00
Alasdair Kergon
f49fdd4141 Add 'already in device cache' debug message. 2005-03-21 14:51:49 +00:00
Alasdair Kergon
b26e1be81a Add -a to pvdisplay -C. 2005-03-21 14:47:36 +00:00
Alasdair Kergon
bacab38d7f Avoid rmdir opendir error messsages when dir was already removed. 2005-03-21 14:43:02 +00:00
Alasdair Kergon
701c05ce96 Tighten signal handlers. 2005-03-21 14:16:16 +00:00
Alasdair Kergon
438c452585 Fix WHATS_NEW. 2005-03-10 23:04:42 +00:00
Alasdair Kergon
0a7a1eff3f Avoid some compiler warnings. 2005-03-10 22:34:17 +00:00
Alasdair Kergon
87e743e381 Additional rename failure error message. 2005-03-10 22:31:10 +00:00
Alasdair Kergon
a03f1b3d55 read/write may be macros 2005-03-10 20:23:36 +00:00
Alasdair Kergon
2d8dc3d243 post-release 2005-03-10 20:22:40 +00:00
Patrick Caulfield
b982232cc5 Don't take out the lvm_thread_lock at startup - it only protects the jobs list.
DEBUGLOG() message now print threadid rather than PID which is more useful.
2005-03-09 14:08:11 +00:00
Alasdair Kergon
61c8d728ac update pofile 2005-03-08 13:48:13 +00:00
Alasdair Kergon
851a2bf855 Cope with new devices appearing by rescanning /dev if a uuid can't be found. 2005-03-08 13:46:17 +00:00
Alasdair Kergon
e0bdde3630 Remove DESTDIR from LVM_SHARED_PATH. 2005-03-08 13:39:39 +00:00
Patrick Caulfield
6a0dcd7f0e make clvmd FDs close-on-exec, to avoid warnings when running lvm via popen.
clvmd-gulm unlocks VG & orphan locks at startup in case they are stale.
clvmd-gulm now unlocks VG & orphan locks if client dies.
2005-03-07 17:03:44 +00:00
Alasdair Kergon
75f0b4c879 post-release 2005-03-03 22:31:01 +00:00
Alasdair Kergon
db536a9504 2.01.06 2005-03-03 22:26:34 +00:00
Alasdair Kergon
0fb114dede Option to suppress warnings of file descriptors left open. 2005-03-03 22:09:20 +00:00
Alasdair Kergon
e703342179 Suppress 'open failed' error messages during scanning. 2005-03-03 21:54:35 +00:00
Alasdair Kergon
35c8f4a611 Fix default value of metadatacopies in documentation (2->1). 2005-03-03 21:52:58 +00:00
Patrick Caulfield
7c89ae44a9 Fix clvmd-gulm node up/down code so it actually works.
clvmd-gulm now releases locks when shut down.
2005-02-22 16:26:21 +00:00
Patrick Caulfield
84fe06da22 ./configure --enable-debug now enables debugging code in clvmd 2005-02-21 15:58:06 +00:00
Patrick Caulfield
806318c8b3 Always manipulate both locks in sync_lock() otherwise they get left
hanging around and cause trouble.
2005-02-21 14:36:09 +00:00
Alasdair Kergon
3aac2e1822 post-release 2005-02-18 19:06:16 +00:00
Alasdair Kergon
168baef433 Static binary invokes dynamic binary if appropriate. 2005-02-18 18:58:31 +00:00
Patrick Caulfield
6dba6cd78d Cope with more than one message arriving at the TCP socket, also
fix some instances where the length in the message was wrong (cman
code didn't notice this because it is packet-based comms anyway)
2005-02-18 15:31:32 +00:00
Patrick Caulfield
502250d08f Fix gulm->errno error number conversion. 2005-02-17 12:56:19 +00:00
Patrick Caulfield
7395f0e680 Make config check a little more tolerant of library names. 2005-02-14 09:07:14 +00:00
Alasdair Kergon
494d3fdaca post-release 2005-02-09 18:26:38 +00:00
Alasdair Kergon
7b86a157de Add fixed offset to imported pool minor numbers. 2005-02-09 17:49:36 +00:00
Adam Manthei
0988c41785 o cluster lvm requires that /usr/sbin/$TOOL is used instead of
/sbin/lvm.static $TOOL

o made variables LVDISPLAY, VGSCAN and VGCHANGE configurable in
  /etc/sysconfig/cluster
2005-02-08 17:20:24 +00:00
Patrick Caulfield
522db1bf01 Fix thread shutdown race which could cause clvmd to hang in pthread_join. 2005-02-08 09:05:58 +00:00
Patrick Caulfield
06f066f90d Revert last clvmd patch. More testing reveals that this just doesn't
work yet.
2005-02-07 14:45:38 +00:00
Patrick Caulfield
f37b20677b Make clvmd use the command library rather than popen() to
preload the lock state.
2005-02-07 10:04:27 +00:00
Alasdair Kergon
cd2eac1032 lvm2cmd.so should skip the check for open fds. 2005-02-03 16:34:53 +00:00
Alasdair Kergon
8ac38d58d7 Remove unused -f from pvmove 2005-02-02 14:31:48 +00:00
Patrick Caulfield
4c80cc313a Make clvmd do a quick sanity check on the clustering bits of lvm.conf 2005-02-02 11:42:29 +00:00
Patrick Caulfield
1c65fee9b4 Get rid of "connection refused" message because Corey doesn't like it. 2005-02-02 09:17:56 +00:00
Alasdair Kergon
90dda7edc1 post-release 2005-02-01 16:40:16 +00:00
Alasdair Kergon
da054fae20 pofile 2005-02-01 16:33:45 +00:00
Alasdair Kergon
bdb6611e30 2.01.03 2005-02-01 16:29:22 +00:00
Alasdair Kergon
9284f973f1 More 64-bit display/report fixes. 2005-02-01 16:19:48 +00:00
Alasdair Kergon
2bfd64c3c9 Add option to compile without ioctl for testing. 2005-01-27 16:16:54 +00:00
Alasdair Kergon
939d24cce5 Fix DM_LIB_VERSION sed 2005-01-27 15:53:28 +00:00
Alasdair Kergon
27b0183c46 More informative startup mesg if can't create /etc/lvm. 2005-01-27 15:50:34 +00:00
Alasdair Kergon
d14efacac7 Fix snapshot device size bug (since 2.01.01). 2005-01-27 15:48:49 +00:00
Patrick Caulfield
150a002c40 Don't print CMAN error if initial probe fails - we could be running with GULM. 2005-01-26 09:30:52 +00:00
Patrick Caulfield
ce0def3bd8 Remove superflous &
Gulm clvmd no longer hangs trying to talk to a rebooted node.
2005-01-25 16:46:29 +00:00
Patrick Caulfield
ee20fa97c2 Make clvmd announce it's startup and cluster connection in syslog. 2005-01-24 15:31:13 +00:00
Alasdair Kergon
7403b7d700 postrelease 2005-01-21 19:03:48 +00:00
Alasdair Kergon
87ef173e0a update pofile 2005-01-21 18:51:48 +00:00
Alasdair Kergon
52a3fb6bc7 pre-release 2005-01-21 18:49:06 +00:00
Patrick Caulfield
92e2a257a6 Get rid of libclvm as it's out-of-date and not used at all. 2005-01-21 11:56:30 +00:00
Patrick Caulfield
32e175752c Fix clvmd startup bug introduced in cman/gulm amalgamation. bz#145729
Improve reporting of node-specific locking errors so you'll get
somthing a little more helpfiul than "host is down" - it will now tell
you /which/ host it thinks is down.
2005-01-21 11:35:24 +00:00
Alasdair Kergon
d43f7180dc Update clvmd_init_rhel4: use lvm.static and don't load dlm. 2005-01-20 22:16:55 +00:00
Alasdair Kergon
0129c2b0fc Fix some size_t printing. 2005-01-20 18:14:04 +00:00
Alasdair Kergon
4ed1990001 Fix 64 bit xlate consts. 2005-01-20 18:13:17 +00:00
Alasdair Kergon
5bd6ab27ae Split out pool sptype_names to avoid unused const. 2005-01-20 18:12:41 +00:00
Alasdair Kergon
f3593b89fa Always fail if random id generation fails. 2005-01-20 18:11:53 +00:00
Alasdair Kergon
23d84b2310 Recognise gnbd. 2005-01-19 18:56:01 +00:00
Alasdair Kergon
fdc49402ec fix clvmd lv_info_by_lvid open_count 2005-01-19 18:10:09 +00:00
Alasdair Kergon
5457c133e1 Add some comments. 2005-01-19 17:31:51 +00:00
Alasdair Kergon
292e588ee3 move recover_vg 2005-01-19 17:30:50 +00:00
Alasdair Kergon
243494c25e Store snapshot and origin sizes separately. 2005-01-19 17:19:39 +00:00
Alasdair Kergon
e4365f3706 Update vgcreate man page. 2005-01-19 17:01:18 +00:00
Alasdair Kergon
310f3038d3 Post-2.01.00 2005-01-17 20:45:05 +00:00
Alasdair Kergon
4e6033273d update po 2005-01-17 20:16:37 +00:00
Alasdair Kergon
73718586d3 2.01.00 2005-01-17 20:13:01 +00:00
Alasdair Kergon
011abe61e8 post-1.01.00 2005-01-17 20:12:12 +00:00
Alasdair Kergon
fe3a37f89d 1.01.00 2005-01-17 20:00:28 +00:00
Alasdair Kergon
8aea44e77b Fix vgscan metadata auto-correction. 2005-01-17 18:24:28 +00:00
Patrick Caulfield
5529aec0d6 You can now build clvmd with cman & gulm support in the same binary.
./configure --with-clvmd
wil do this by default. Or you can choose which you want with
./configure --with-clvmd=gulm    or
./configure --with-clvmd=cman

When clvmd with both included is run, it will automatically detect the cluster
manager in use.
2005-01-13 13:24:02 +00:00
Alasdair Kergon
369549d23f Only ask libdevmapper for open_count when we need it. 2005-01-12 22:58:21 +00:00
290 changed files with 32012 additions and 12502 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.00.34-cvs (2005-01-07)
2.02.20-cvs (2007-01-17)

524
WHATS_NEW
View File

@@ -1,6 +1,528 @@
Version 2.00.34 -
Version 2.02.20 -
===================================
Change remaining dmeventd terminology 'register' to 'monitor'.
Update reporting man pages.
No longer necessary to specify alignment 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.
Moved activation functions into libdevmapper.
Fixed build_dm_name.
Add return macros.
Added xen xvd devices.
Clear up precommitted metadata better.
A pvresize implementation.
Fix contiguous allocation when there are no preceding segments.
Add mirror_seg pointer to lv_segment struct.
Only keep a device open if it's known to belong to a locked VG.
Fix lvdisplay to show all mirror destinations.
Replacement suspend code using libdevmapper dependency tree.
Add DEFS to make.tmpl.
Use dm_is_dm_major instead of local copy.
Allow mapped devices to be used as PVs.
Move set_selinux_context into libdevmapper.
Fix automatic text metadata buffer expansion (using macro).
Cache formatted text metadata buffer between metadata area writes.
Add pe_start field to pvs.
Add 'LVM-' prefix to uuids.
Split lv_segment_area from lv_segment to permit extension.
Replacement deactivation code using libdevmapper dependency tree.
Simplify dev_manager_info().
Attempt to load missing targets using modprobe.
Add -a to lvscan.
Move mknodes into libdevmapper.
Move bitset, hash, pool and dbg_malloc into libdevmapper.
Version 2.01.15 - 16th October 2005
===================================
Refuse to run pvcreate/pvremove on devices we can't open exclusively.
Use ORPHAN lock definition throughout.
Validate chunksize in lvcreate.
Reduce chunksize limit to 512k.
Fix chunksize field in reports.
Don't hide snapshots from default 'lvs' output.
Add is_dm_major() for use in duplicate device detection in lvmcache_add().
Really switch device number in lvmcache when it says it is doing so.
Option for bitset memory allocation using malloc as well as pool.
Don't assume exactly two mirrors when parsing mirror status.
Suppress fsync() error message on filesystems that don't support it.
Fix yes_no_prompt() error handling.
Add lvm.conf comment warning against multiple filter lines.
Tidy lvmconf.sh.
Add format1 dev_write debug messages.
Add clustered VG attribute to report.
Move lvconvert parameters into struct lvconvert_params.
Add clustered VG flag to LV lock requests.
Change LV locking macros to take lv instead of lvid.
Prepend 'cluster' activation parameter to mirror log when appropriate.
Pass exclusive flag to lv_activate and on to target activation code.
Prevent snapshot creation in a clustered VG for now.
Factor out adjusted_mirror_region_size() and generate_log_name_format().
Move compose_log_line() into mirror directory.
Factor out _get_library_path().
Don't kill idling clvmd threads.
clvmd no longer takes out locks for non-clustered LVs.
Recognise ATA over Ethernet (aoe) devices.
Version 2.01.14 - 4th August 2005
=================================
Fix lvconvert PV parameter in help string.
Prevent snapshots getting activated in a clustered VG.
Separate out _build_dev_string.
Move zero_lv to toollib.
Fix pool format handler to work with pv segment code.
Version 2.01.13 - 13th July 2005
================================
Fix pvmove segment splitting.
Abstract vg_validate.
Only make one attempt at contiguous allocation.
Fix lvm1 format metadata read.
Fix lvm1 format non-mirror lvcreate.
Version 2.01.12 - 14th June 2005
================================
Various allocation-related pvmove fixes.
Log an error if clvmd can't resolve a host name got from CCS.
Fix potential spin loop in clvmd.
Version 2.01.11 - 13th June 2005
================================
Added lvmconf.sh.
Use matchpathcon mode parameter.
Don't defer closing dead FDs in clvmd.
Remove hard-coded 64k text metadata writing restriction.
Make VG name restrictions consistent.
Introduce lvconvert. So far only removes mirror images.
Allow mirror images to be resized.
Allow mirror images to have more than one segment.
Centralise restrictions on LV names.
Always insert an intermediate layer for mirrors.
Suppress hidden LVs from reports unless --all is given.
Use square brackets for hidden LVs in reports.
Allow the creation of mirrors with contiguous extents.
Always perform sanity checks against metadata before committing it to disk.
Split lv_extend into two steps: choosing extents + allocation to LV(s).
Add mirror log region size to metadata.
Use list_iterate_items throughout and add list*back macros.
Introduce seg_ macros to access areas.
Add segtype_is_ macros.
Support tiny metadata areas for pool conversions.
Mirror activation handles disk log as well as core.
Activation code recognises mirror log dependency.
Add mirror_log and regionsize fields to report.
Fix non-orphan pvchange -u.
Fix vgmerge to handle duplicate LVIDs.
Move archiver code from tools into library.
vgscan/change/display/vgs automatically create metadata backups if needed.
Merge cloned allocation functions.
Fix contiguous allocation policy with linear.
Cope with missing format1 PVs again.
Remove lists of free PV segments.
Simplify pv_maps code and remove slow bitset algorithm.
Red-Hat-ify the clvmd rhel4 initscript.
%Zu->%zu
Fix loopfiles alias alloc & mem debugging.
Un-inline dbg_strdup.
lv_reduce tidying.
Remove some unnecessary parameters.
Introduce seg_is macros.
Version 2.01.10 - 3rd May 2005
==============================
Don't create backup and archive dirs till needed.
Reinstate full PV size when removing from VG.
Support loopfiles for testing.
Tidy lv_segment interface.
pv_segment support.
vgchange --physicalextentsize
Internal snapshot restructuring.
Remove unused internal non-persistent snapshot option.
Allow offline extension of snapshot volumes.
Move from 2-step to 3-step on-disk metadata commit.
Scan ramdisks too and allow non-O_DIRECT fallback.
Annotate, tidy and extend list.h.
Alignment tidying.
Make clvmd work around some "bugs" in gulm's node state notifications.
Tidy clvmd's SIGHUP handler
Version 2.01.09 - 4th April 2005
================================
Add --ignorelockingfailure to vgmknodes.
clvmd: Don't allow user operations to start until the lvm thread is fully up.
clvmd-gulm: set KEEPALIVE on sockets.
Version 2.01.08 - 22nd March 2005
=================================
Add clustered attribute so vgchange can identify clustered VGs w/o locking.
Improve detection of external changes affecting internal cache.
Add 'already in device cache' debug message.
Add -a to pvdisplay -C.
Avoid rmdir opendir error messsages when dir was already removed.
Tighten signal handlers.
Avoid some compiler warnings.
Additional rename failure error message.
read/write may be macros.
clvmd: don't take out lvm thread lock at startup, it only protects jobs list.
Version 2.01.07 - 8th March 2005
================================
Cope with new devices appearing by rescanning /dev if a uuid can't be found.
Remove DESTDIR from LVM_SHARED_PATH.
clvmd fixes: make FDs close-on-exec
gulm unlocks VG & orphan locks at startup in case they are stale
gulm now unlocks VG & orphan locks if client dies.
Version 2.01.06 - 1st March 2005
================================
Suppress 'open failed' error messages during scanning.
Option to suppress warnings of file descriptors left open.
Fix default value of metadatacopies in documentation (2->1).
Fix clvmd-gulm locking.
./configure --enable-debug now enables debugging code in clvmd.
Fix clvmd-gulm node up/down code so it actually works.
clvmd-gulm now releases locks when shut down.
Version 2.01.05 - 18th February 2005
====================================
Static binary invokes dynamic binary if appropriate.
Make clvmd config check a little more tolerant.
gulm clvmd can now cope with >1 message arriving in a TCP message.
Version 2.01.04 - 9th February 2005
===================================
Add fixed offset to imported pool minor numbers.
Update binary pathnames in clvmd_init_rhel4.
lvm2cmd.so should skip the check for open fds.
Remove unused -f from pvmove.
Gulm clvmd doesn't report "connection refused" errors.
clvmd does a basic config file sanity check at startup.
Fix potential thread shutdown race in clvmd.
Version 2.01.03 - 1st February 2005
===================================
More 64-bit display/report fixes.
More informative startup mesg if can't create /etc/lvm.
Fix snapshot device size bug (since 2.01.01).
clvmd announces startup and cluster connection in syslog.
Gulm clvmd doesn't hang trying to talk to a rebooted node.
Gulm clvmd doesn't print cman error on startup.
Version 2.01.02 - 21st January 2005
===================================
Update clvmd_init_rhel4: use lvm.static and don't load dlm.
Fix some size_t printing.
Fix 64 bit xlate consts.
Split out pool sptype_names to avoid unused const.
Always fail if random id generation fails.
Recognise gnbd devices.
Fix clvmd startup bug introduced in cman/gulm amalgamation.
Improve reporting of node-specific locking errors.
Version 2.01.01 - 19th January 2005
===================================
Fix clvmd lv_info_by_lvid open_count.
Store snapshot and origin sizes separately.
Update vgcreate man page.
Version 2.01.00 - 17th January 2005
===================================
Fix vgscan metadata auto-correction.
Only ask libdevmapper for open_count when we need it.
Adjust RHEL4 clvmd init script priority.
Enable building of CMAN & GULM versions of clvmd into a single binary
Version 2.00.33 - 7th January 2005
==================================

View File

@@ -1,5 +1,170 @@
Version 1.01.00 -
Version 1.02.16 -
===================================
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.
Also suppress error if device doesn't exist with DM_DEVICE_STATUS.
Export dm_set_selinux_context().
Add dm_driver_version().
Added dependency tree functions to library.
Added hash, bitset, pool, dbg_malloc to library.
Added ls --tree to dmsetup.
Added dmsetup --nolockfs support for suspend/reload.
Version 1.01.05 - 26 Sep 2005
=============================
Resync list.h with LVM2.
Remember increased buffer size and use for subsequent calls.
On 'buffer full' condition, double buffer size and repeat ioctl.
Fix termination of getopt_long() option array.
Report 'buffer full' condition with v4 ioctl as well as with v1.
Version 1.01.04 - 2 Aug 2005
============================
Fix dmsetup ls -j and status --target with empty table.
Version 1.01.03 - 13 Jun 2005
=============================
Use matchpathcon mode parameter.
Fix configure script to re-enable selinux.
Version 1.01.02 - 17 May 2005
=============================
Call dm_lib_exit() and dm_lib_release() automatically now.
Add --target <target_type> filter to dmsetup table/status/ls.
Add --exec <command> to dmsetup ls.
Fix dmsetup getopt_long usage.
Version 1.01.01 - 29 Mar 2005
=============================
Update dmsetup man page.
Drop-in devmap_name replacement.
Add option to compile without ioctl for testing.
Fix DM_LIB_VERSION sed.
Version 1.01.00 - 17 Jan 2005
=============================
Add dm_task_no_open_count() to skip getting open_count.
Version 1.00.21 - 7 Jan 2005

3179
configure vendored

File diff suppressed because it is too large Load Diff

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"
DEVMAPPER=no
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,16 +284,23 @@ 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)
AC_ARG_WITH(clvmd,
[ --with-clvmd=TYPE Build cluster LVM Daemon: cman/gulm/none
[ --with-clvmd=TYPE Build cluster LVM Daemon: cman/gulm/none/all
[TYPE=none] ],
[ CLVMD="$withval" ],
[ CLVMD="none" ])
if test x$CLVMD = xyes; then
CLVMD=cman
CLVMD=all
fi
AC_MSG_RESULT($CLVMD)
@@ -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,13 +520,18 @@ 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
AC_CHECK_HEADERS(readline/readline.h readline/history.h,,AC_MSG_ERROR(bailing out))
fi
if test x$CLVMD = xyes; then
if test x$CLVMD != xnone; then
AC_CHECK_HEADERS(mntent.h netdb.h netinet/in.h pthread.h search.h sys/mount.h sys/socket.h sys/uio.h sys/un.h utmpx.h,,AC_MSG_ERROR(bailing out))
AC_CHECK_FUNCS(dup2 getmntent memmove select socket,,AC_MSG_ERROR(bailing out))
AC_FUNC_GETMNTENT
@@ -507,14 +557,19 @@ 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))
fi
################################################################################
AC_PATH_PROG(MODPROBE_CMD, modprobe)
if test x$MODPROBE_CMD != x; then
AC_DEFINE_UNQUOTED([MODPROBE_CMD], ["$MODPROBE_CMD"], [The path to 'modprobe', if available.])
fi
################################################################################
if test "-f VERSION"; then
LVM_VERSION="\"`cat VERSION`\""
@@ -538,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)
@@ -546,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
@@ -565,6 +625,8 @@ Makefile \
make.tmpl \
daemons/Makefile \
daemons/clvmd/Makefile \
dmeventd/Makefile \
dmeventd/mirror/Makefile \
doc/Makefile \
include/Makefile \
lib/Makefile \
@@ -575,6 +637,7 @@ lib/mirror/Makefile \
lib/snapshot/Makefile \
man/Makefile \
po/Makefile \
scripts/Makefile \
tools/Makefile \
tools/version.h \
tools/fsadm/Makefile \
@@ -592,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

@@ -18,34 +18,61 @@ VPATH = @srcdir@
SOURCES = \
clvmd-command.c \
clvmd.c \
libclvm.c \
lvm-functions.c \
refresh_clvmd.c \
system-lv.c
ifeq ("@CLVMD@", "gulm")
SOURCES += clvmd-gulm.c tcp-comms.c
LMLIBS += -lccs -lgulm
CFLAGS += -DUSE_GULM
GULM = yes
endif
ifeq ("@CLVMD@", "cman")
CMAN = yes
endif
ifeq ("@CLVMD@", "all")
GULM = yes
CMAN = yes
endif
ifeq ("@DEBUG@", "yes")
DEFS += -DDEBUG
endif
ifeq ("$(GULM)", "yes")
SOURCES += clvmd-gulm.c tcp-comms.c
LMLIBS += -lccs -lgulm
DEFS += -DUSE_GULM
endif
ifeq ("$(CMAN)", "yes")
SOURCES += clvmd-cman.c
LMLIBS += -ldlm
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

@@ -43,6 +43,7 @@ struct clvm_header {
/* Flags */
#define CLVMD_FLAG_LOCAL 1 /* Only do this on the local node */
#define CLVMD_FLAG_SYSTEMLV 2 /* Data in system LV under my node name */
#define CLVMD_FLAG_NODEERRS 4 /* Reply has errors in node-specific portion */
/* Name of the local socket to communicate between libclvm and clvmd */
//static const char CLVMD_SOCKNAME[]="/var/run/clvmd";
@@ -62,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

@@ -46,19 +46,23 @@
#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;
@@ -66,30 +70,25 @@ struct lock_wait {
struct dlm_lksb lksb;
};
int init_cluster()
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) {
c_handle = cman_init(NULL);
if (!c_handle) {
syslog(LOG_ERR, "Can't open cluster manager socket: %m");
return -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();
@@ -101,160 +100,136 @@ int init_cluster()
return -1;
}
dlm_ls_pthread_init(lockspace);
return 0;
}
int get_main_cluster_fd()
static void _cluster_init_completed(void)
{
return cluster_sock;
clvmd_cluster_init_completed();
}
int get_num_nodes()
static int _get_main_cluster_fd()
{
return num_nodes;
return cman_get_fd(c_handle);
}
static int _get_num_nodes()
{
int i;
int nnodes = 0;
/* return number of ACTIVE nodes */
for (i=0; i<num_nodes; i++) {
if (nodes[i].cn_member)
nnodes++;
}
return nnodes;
}
/* send_message with the fd check removed */
int cluster_send_message(void *buf, int msglen, char *csid, const char *errtext)
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, 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;
}
void get_our_csid(char *csid)
static void _get_our_csid(char *csid)
{
int i;
memset(csid, 0, MAX_CSID_LEN);
for (i = 0; i < num_nodes; i++) {
if (nodes[i].us)
memcpy(csid, &nodes[i].node_id, 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) */
int cluster_do_node_callback(struct local_client *client,
void (*callback) (struct local_client *, char *,
int))
/* 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))
{
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;
for (i = 0; i < _get_num_nodes(); i++) {
if (nodes[i].cn_member) {
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)
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;
}
}
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;
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;
return cman_dispatch(c_handle, 0);
}
void add_up_node(char *csid)
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)
{
/* It's up ! */
int nodeid = nodeid_from_csid(csid);
@@ -270,7 +245,7 @@ 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);
}
}
@@ -278,23 +253,19 @@ void add_up_node(char *csid)
DEBUGLOG("Added new node %d to updown list\n", nodeid);
}
void cluster_closedown()
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 */
@@ -307,72 +278,66 @@ static int is_listening(int nodeid)
/* Populate the list of CLVMDs running.
called only at startup time */
void count_clvmds_running(void)
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);
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);
}
}
/* 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);
}
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));
}
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 */
int csid_from_name(char *csid, char *name)
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, MAX_CSID_LEN);
if (strcmp(name, nodes[i].cn_name) == 0) {
memcpy(csid, &nodes[i].cn_nodeid, CMAN_MAX_CSID_LEN);
return 0;
}
}
@@ -380,13 +345,13 @@ int csid_from_name(char *csid, char *name)
}
/* Convert a CSID to a node name */
int name_from_csid(char *csid, char *name)
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, 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;
}
}
@@ -396,13 +361,13 @@ int name_from_csid(char *csid, char *name)
}
/* Convert a node ID to a node name */
int name_from_nodeid(int nodeid, char *name)
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;
}
}
@@ -416,14 +381,14 @@ static int nodeid_from_csid(char *csid)
{
int nodeid;
memcpy(&nodeid, csid, MAX_CSID_LEN);
memcpy(&nodeid, csid, CMAN_MAX_CSID_LEN);
return nodeid;
}
int is_quorate()
static int _is_quorate()
{
return ioctl(cluster_sock, SIOCCLUSTER_ISQUORATE, 0);
return cman_is_quorate(c_handle);
}
static void sync_ast_routine(void *arg)
@@ -435,7 +400,7 @@ static void sync_ast_routine(void *arg)
pthread_mutex_unlock(&lwait->mutex);
}
int sync_lock(const char *resource, int mode, int flags, int *lockid)
static int _sync_lock(const char *resource, int mode, int flags, int *lockid)
{
int status;
struct lock_wait lwait;
@@ -478,7 +443,7 @@ int sync_lock(const char *resource, int mode, int flags, int *lockid)
return 0;
}
int sync_unlock(const char *resource /* UNUSED */, int lockid)
static int _sync_unlock(const char *resource /* UNUSED */, int lockid)
{
int status;
struct lock_wait lwait;
@@ -505,3 +470,41 @@ int sync_unlock(const char *resource /* UNUSED */, int lockid)
return 0;
}
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,
.name_from_csid = _name_from_csid,
.csid_from_name = _csid_from_name,
.get_num_nodes = _get_num_nodes,
.cluster_fd_callback = _cluster_fd_callback,
.get_main_cluster_fd = _get_main_cluster_fd,
.cluster_do_node_callback = _cluster_do_node_callback,
.is_quorate = _is_quorate,
.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,
};
struct cluster_ops *init_cman_cluster(void)
{
if (!_init_cluster())
return &_cluster_cman_ops;
else
return NULL;
}

View File

@@ -65,8 +65,8 @@
#include <unistd.h>
#include <errno.h>
#include "libdevmapper.h"
#include "list.h"
#include "hash.h"
#include "locking.h"
#include "log.h"
#include "lvm-functions.h"
@@ -75,6 +75,8 @@
#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 */
int do_command(struct local_client *client, struct clvm_header *msg, int msglen,
@@ -109,7 +111,7 @@ int do_command(struct local_client *client, struct clvm_header *msg, int msglen,
case CLVMD_CMD_LOCK_LV:
/* This is the biggie */
lock_cmd = args[0];
lock_cmd = args[0] & 0x3F;
lock_flags = args[1];
lockname = &args[2];
status = do_lock_lv(lock_cmd, lock_flags, lockname);
@@ -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;
@@ -138,7 +150,7 @@ int do_command(struct local_client *client, struct clvm_header *msg, int msglen,
static int lock_vg(struct local_client *client)
{
struct hash_table *lock_hash;
struct dm_hash_table *lock_hash;
struct clvm_header *header =
(struct clvm_header *) client->bits.localsock.cmd;
unsigned char lock_cmd;
@@ -152,23 +164,23 @@ static int lock_vg(struct local_client *client)
practice there should only ever be more than two VGs locked
if a user tries to merge lots of them at once */
if (client->bits.localsock.private) {
lock_hash = (struct hash_table *)client->bits.localsock.private;
lock_hash = (struct dm_hash_table *)client->bits.localsock.private;
}
else {
lock_hash = hash_create(3);
lock_hash = dm_hash_create(3);
if (!lock_hash)
return ENOMEM;
client->bits.localsock.private = (void *)lock_hash;
}
lock_cmd = args[0];
lock_cmd = args[0] & 0x3F;
lock_flags = args[1];
lockname = &args[2];
DEBUGLOG("doing PRE command LOCK_VG '%s' at %x (client=%p)\n", lockname, lock_cmd, client);
if (lock_cmd == LCK_UNLOCK) {
lkid = (int)(long)hash_lookup(lock_hash, lockname);
lkid = (int)(long)dm_hash_lookup(lock_hash, lockname);
if (lkid == 0)
return EINVAL;
@@ -176,15 +188,19 @@ static int lock_vg(struct local_client *client)
if (status)
status = errno;
else
hash_remove(lock_hash, lockname);
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
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;
@@ -268,18 +288,19 @@ void cmd_client_cleanup(struct local_client *client)
{
if (client->bits.localsock.private) {
struct hash_node *v;
struct hash_table *lock_hash =
(struct hash_table *)client->bits.localsock.private;
struct dm_hash_node *v;
struct dm_hash_table *lock_hash =
(struct dm_hash_table *)client->bits.localsock.private;
hash_iterate(v, lock_hash) {
int lkid = (int)(long)hash_get_data(lock_hash, v);
dm_hash_iterate(v, lock_hash) {
int lkid = (int)(long)dm_hash_get_data(lock_hash, v);
char *lockname = dm_hash_get_key(lock_hash, v);
DEBUGLOG("cleanup: Unlocking lkid %x\n", lkid);
sync_unlock("DUMMY", lkid);
DEBUGLOG("cleanup: Unlocking lock %s %x\n", lockname, lkid);
sync_unlock(lockname, lkid);
}
hash_destroy(lock_hash);
dm_hash_destroy(lock_hash);
client->bits.localsock.private = 0;
}
}

View File

@@ -22,34 +22,55 @@
struct local_client;
extern int cluster_send_message(void *buf, int msglen, char *csid,
struct cluster_ops {
void (*cluster_init_completed) (void);
int (*cluster_send_message) (void *buf, int msglen, char *csid,
const char *errtext);
extern int name_from_csid(char *csid, char *name);
extern int csid_from_name(char *csid, char *name);
extern int get_num_nodes(void);
extern int cluster_fd_callback(struct local_client *fd, char *buf, int len,
int (*name_from_csid) (char *csid, char *name);
int (*csid_from_name) (char *csid, char *name);
int (*get_num_nodes) (void);
int (*cluster_fd_callback) (struct local_client *fd, char *buf, int len,
char *csid, struct local_client **new_client);
extern int init_cluster(void);
extern int get_main_cluster_fd(void); /* gets accept FD or cman cluster socket */
extern int cluster_do_node_callback(struct local_client *client,
int (*get_main_cluster_fd) (void); /* gets accept FD or cman cluster socket */
int (*cluster_do_node_callback) (struct local_client *client,
void (*callback) (struct local_client *,
char *csid, int node_up));
extern int is_quorate(void);
int (*is_quorate) (void);
extern void get_our_csid(char *csid);
extern void add_up_node(char *csid);
extern void cluster_closedown(void);
void (*get_our_csid) (char *csid);
void (*add_up_node) (char *csid);
void (*reread_config) (void);
void (*cluster_closedown) (void);
extern int sync_lock(const char *resource, int mode, int flags, int *lockid);
extern int sync_unlock(const char *resource, int lockid);
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);
};
#ifdef USE_GULM
#include "tcp-comms.h"
#else
/* cman */
#include "cnxman-socket.h"
#define MAX_CSID_LEN 4
# include "tcp-comms.h"
struct cluster_ops *init_gulm_cluster(void);
#define MAX_CSID_LEN GULM_MAX_CSID_LEN
#define MAX_CLUSTER_MEMBER_NAME_LEN GULM_MAX_CLUSTER_MEMBER_NAME_LEN
#endif
#ifdef USE_CMAN
# 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_NODENAME_LEN
# define CMAN_MAX_CLUSTER_MESSAGE 1500
# define CLUSTER_PORT_CLVMD 11
struct cluster_ops *init_cman_cluster(void);
#endif
#endif

View File

@@ -2,6 +2,7 @@
*******************************************************************************
**
** Copyright (C) Sistina Software, Inc. 2002-2003 All rights reserved.
** Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
**
*******************************************************************************
******************************************************************************/
@@ -40,31 +41,33 @@
#include <syslog.h>
#include <assert.h>
#include "libdevmapper.h"
#include "ccs.h"
#include "list.h"
#include "locking.h"
#include "log.h"
#include "clvm.h"
#include "clvmd-comms.h"
#include "lvm-functions.h"
#include "clvmd.h"
#include "hash.h"
#include "clvmd-gulm.h"
#include "libgulm.h"
#include "hash.h"
/* Hash list of nodes in the cluster */
static struct hash_table *node_hash;
static struct dm_hash_table *node_hash;
/* hash list of outstanding lock requests */
static struct hash_table *lock_hash;
static struct dm_hash_table *lock_hash;
/* Copy of the current core state */
static uint8_t current_corestate;
/* Copy of the current quorate state */
static uint8_t gulm_quorate = 0;
static enum {INIT_NOTDONE, INIT_DONE, INIT_WAITQUORATE} init_state = INIT_NOTDONE;
/* Number of active nodes */
static int num_nodes;
static char *cluster_name;
static int in_shutdown = 0;
static pthread_mutex_t lock_start_mutex;
static volatile int lock_start_flag;
@@ -72,7 +75,7 @@ static volatile int lock_start_flag;
struct node_info
{
enum {NODE_UNKNOWN, NODE_DOWN, NODE_UP, NODE_CLVMD} state;
char name[MAX_CLUSTER_MEMBER_NAME_LEN];
char name[GULM_MAX_CLUSTER_MEMBER_NAME_LEN];
};
struct lock_wait
@@ -88,9 +91,11 @@ static int read_from_core_sock(struct local_client *client, char *buf, int len,
static int read_from_lock_sock(struct local_client *client, char *buf, int len, char *csid,
struct local_client **new_client);
static int get_all_cluster_nodes(void);
static int _csid_from_name(char *csid, char *name);
static void _cluster_closedown(void);
/* In tcp-comms.c */
extern struct hash_table *sock_hash;
extern struct dm_hash_table *sock_hash;
static int add_internal_client(int fd, fd_callback_t callback)
{
@@ -112,6 +117,9 @@ static int add_internal_client(int fd, fd_callback_t callback)
client->callback = callback;
add_client(client);
/* Set Close-on-exec */
fcntl(fd, F_SETFD, 1);
return 0;
}
@@ -123,19 +131,18 @@ static lg_lockspace_callbacks_t lock_callbacks;
static void badsig_handler(int sig)
{
DEBUGLOG("got sig %d\n", sig);
cluster_closedown();
_cluster_closedown();
exit(0);
}
static void sighup_handler(int sig)
static void _reread_config(void)
{
DEBUGLOG("got SIGHUP\n");
/* Re-read CCS node list */
get_all_cluster_nodes();
/* Re-read CCS node list */
DEBUGLOG("Re-reading CCS config\n");
get_all_cluster_nodes();
}
int init_cluster()
static int _init_cluster(void)
{
int status;
int ccs_h;
@@ -170,8 +177,8 @@ int init_cluster()
pthread_mutex_lock(&lock_start_mutex);
lock_start_flag = 1;
node_hash = hash_create(100);
lock_hash = hash_create(10);
node_hash = dm_hash_create(100);
lock_hash = dm_hash_create(10);
/* Get all nodes from CCS */
if (get_all_cluster_nodes())
@@ -222,7 +229,7 @@ int init_cluster()
exit(status);
}
/* Request a list of nodes, we can;t really do anything until
/* Request a list of nodes, we can't really do anything until
this comes back */
status = lg_core_nodelist(gulm_if);
if (status)
@@ -235,15 +242,14 @@ int init_cluster()
signal(SIGINT, badsig_handler);
signal(SIGTERM, badsig_handler);
/* Re-read the node list on SIGHUP */
signal(SIGHUP, sighup_handler);
return 0;
}
void cluster_closedown()
static void _cluster_closedown(void)
{
DEBUGLOG("cluster_closedown\n");
in_shutdown = 1;
unlock_all();
lg_lock_logout(gulm_if);
lg_core_logout(gulm_if);
lg_release(gulm_if);
@@ -256,6 +262,7 @@ static void drop_expired_locks(char *nodename)
struct utsname nodeinfo;
uint8_t mask[GIO_KEY_SIZE];
DEBUGLOG("Dropping expired locks for %s\n", nodename?nodename:"(null)");
memset(mask, 0xff, GIO_KEY_SIZE);
if (!nodename)
@@ -301,7 +308,9 @@ static int core_login_reply(void *misc, uint64_t gen, uint32_t error, uint32_t r
if (error)
exit(error);
current_corestate = corestate;
/* Get the current core state (for quorum) */
lg_core_corestate(gulm_if);
return 0;
}
@@ -328,10 +337,16 @@ static void set_node_state(struct node_info *ninfo, char *csid, uint8_t nodestat
if (ninfo->state != NODE_DOWN)
num_nodes--;
ninfo->state = NODE_DOWN;
tcp_remove_client(csid);
}
}
DEBUGLOG("set_node_state, '%s' state = %d, num_nodes=%d\n",
/* Gulm doesn't always send node DOWN events, so even if this a a node UP we must
* assume (ahem) that it prevously went down at some time. So we close
* the sockets here to make sure that we don't have any dead connections
* to that node.
*/
tcp_remove_client(csid);
DEBUGLOG("set_node_state, '%s' state = %d num_nodes=%d\n",
ninfo->name, ninfo->state, num_nodes);
}
@@ -339,7 +354,7 @@ static struct node_info *add_or_set_node(char *name, struct in6_addr *ip, uint8_
{
struct node_info *ninfo;
ninfo = hash_lookup_binary(node_hash, (char *)ip, MAX_CSID_LEN);
ninfo = dm_hash_lookup_binary(node_hash, (char *)ip, GULM_MAX_CSID_LEN);
if (!ninfo)
{
/* If we can't find that node then re-read the config file in case it
@@ -348,7 +363,7 @@ static struct node_info *add_or_set_node(char *name, struct in6_addr *ip, uint8_
get_all_cluster_nodes();
/* Now try again */
ninfo = hash_lookup_binary(node_hash, (char *)ip, MAX_CSID_LEN);
ninfo = dm_hash_lookup_binary(node_hash, (char *)ip, GULM_MAX_CSID_LEN);
if (!ninfo)
{
DEBUGLOG("Ignoring node %s, not part of the SAN cluster\n", name);
@@ -356,11 +371,16 @@ static struct node_info *add_or_set_node(char *name, struct in6_addr *ip, uint8_
}
}
set_node_state(ninfo, (char *)&ip, state);
set_node_state(ninfo, (char *)ip, state);
return ninfo;
}
static void _get_our_csid(char *csid)
{
get_our_gulm_csid(csid);
}
static int core_nodelist(void *misc, lglcb_t type, char *name, struct in6_addr *ip, uint8_t state)
{
DEBUGLOG("CORE nodelist\n");
@@ -381,14 +401,23 @@ static int core_nodelist(void *misc, lglcb_t type, char *name, struct in6_addr *
{
if (type == lglcb_stop)
{
char ourcsid[MAX_CSID_LEN];
char ourcsid[GULM_MAX_CSID_LEN];
DEBUGLOG("Got Nodelist, stop\n");
clvmd_cluster_init_completed();
if (gulm_quorate)
{
clvmd_cluster_init_completed();
init_state = INIT_DONE;
}
else
{
if (init_state == INIT_NOTDONE)
init_state = INIT_WAITQUORATE;
}
/* Mark ourself as up */
get_our_csid(ourcsid);
add_up_node(ourcsid);
_get_our_csid(ourcsid);
gulm_add_up_node(ourcsid);
}
else
{
@@ -402,10 +431,15 @@ static int core_nodelist(void *misc, lglcb_t type, char *name, struct in6_addr *
static int core_statechange(void *misc, uint8_t corestate, uint8_t quorate, struct in6_addr *masterip, char *mastername)
{
DEBUGLOG("CORE Got statechange corestate:%#x mastername:%s\n",
corestate, mastername);
DEBUGLOG("CORE Got statechange. quorate:%d, corestate:%x mastername:%s\n",
quorate, corestate, mastername);
current_corestate = corestate;
gulm_quorate = quorate;
if (quorate && init_state == INIT_WAITQUORATE)
{
clvmd_cluster_init_completed();
init_state = INIT_DONE;
}
return 0;
}
@@ -417,7 +451,7 @@ static int core_nodechange(void *misc, char *nodename, struct in6_addr *nodeip,
/* If we don't get nodeip here, try a lookup by name */
if (!nodeip)
csid_from_name((char *)nodeip, nodename);
_csid_from_name((char *)nodeip, nodename);
if (!nodeip)
return 0;
@@ -471,7 +505,11 @@ static int lock_lock_state(void *misc, uint8_t *key, uint16_t keylen,
DEBUGLOG("LOCK lock state: %s, error = %d\n", key, error);
lwait = hash_lookup(lock_hash, key);
/* No waiting process to wake up when we are shutting down */
if (in_shutdown)
return 0;
lwait = dm_hash_lookup(lock_hash, key);
if (!lwait)
{
DEBUGLOG("Can't find hash entry for resource %s\n", key);
@@ -516,22 +554,22 @@ int get_next_node_csid(void **context, char *csid)
/* First node */
if (!*context)
{
*context = hash_get_first(node_hash);
*context = dm_hash_get_first(node_hash);
}
else
{
*context = hash_get_next(node_hash, *context);
*context = dm_hash_get_next(node_hash, *context);
}
if (*context)
ninfo = hash_get_data(node_hash, *context);
ninfo = dm_hash_get_data(node_hash, *context);
/* Find a node that is UP */
while (*context && ninfo->state == NODE_DOWN)
{
*context = hash_get_next(node_hash, *context);
*context = dm_hash_get_next(node_hash, *context);
if (*context)
{
ninfo = hash_get_data(node_hash, *context);
ninfo = dm_hash_get_data(node_hash, *context);
}
}
@@ -540,15 +578,15 @@ int get_next_node_csid(void **context, char *csid)
return 0;
}
memcpy(csid, hash_get_key(node_hash, *context), MAX_CSID_LEN);
memcpy(csid, dm_hash_get_key(node_hash, *context), GULM_MAX_CSID_LEN);
return 1;
}
int name_from_csid(char *csid, char *name)
int gulm_name_from_csid(char *csid, char *name)
{
struct node_info *ninfo;
ninfo = hash_lookup_binary(node_hash, csid, MAX_CSID_LEN);
ninfo = dm_hash_lookup_binary(node_hash, csid, GULM_MAX_CSID_LEN);
if (!ninfo)
{
sprintf(name, "UNKNOWN %s", print_csid(csid));
@@ -560,39 +598,46 @@ int name_from_csid(char *csid, char *name)
}
int csid_from_name(char *csid, char *name)
static int _csid_from_name(char *csid, char *name)
{
struct hash_node *hn;
struct dm_hash_node *hn;
struct node_info *ninfo;
hash_iterate(hn, node_hash)
dm_hash_iterate(hn, node_hash)
{
ninfo = hash_get_data(node_hash, hn);
ninfo = dm_hash_get_data(node_hash, hn);
if (strcmp(ninfo->name, name) == 0)
{
memcpy(csid, hash_get_key(node_hash, hn), MAX_CSID_LEN);
memcpy(csid, dm_hash_get_key(node_hash, hn), GULM_MAX_CSID_LEN);
return 0;
}
}
return -1;
}
int get_num_nodes()
static int _get_num_nodes()
{
DEBUGLOG("num_nodes = %d\n", num_nodes);
return num_nodes;
}
/* Node is now known to be running a clvmd */
void add_up_node(char *csid)
void gulm_add_up_node(char *csid)
{
struct node_info *ninfo;
ninfo = hash_lookup_binary(node_hash, csid, MAX_CSID_LEN);
if (!ninfo)
ninfo = dm_hash_lookup_binary(node_hash, csid, GULM_MAX_CSID_LEN);
if (!ninfo) {
DEBUGLOG("gulm_add_up_node no node_hash entry for csid %s\n", print_csid(csid));
return;
}
DEBUGLOG("gulm_add_up_node %s\n", ninfo->name);
if (ninfo->state == NODE_DOWN)
num_nodes++;
ninfo->state = NODE_CLVMD;
return;
}
@@ -601,7 +646,7 @@ void add_down_node(char *csid)
{
struct node_info *ninfo;
ninfo = hash_lookup_binary(node_hash, csid, MAX_CSID_LEN);
ninfo = dm_hash_lookup_binary(node_hash, csid, GULM_MAX_CSID_LEN);
if (!ninfo)
return;
@@ -609,30 +654,42 @@ void add_down_node(char *csid)
running clvmd - gulm may set it DOWN quite soon */
if (ninfo->state == NODE_CLVMD)
ninfo->state = NODE_UP;
drop_expired_locks(ninfo->name);
return;
}
/* Call a callback for each node, so the caller knows whether it's up or down */
int cluster_do_node_callback(struct local_client *master_client,
void (*callback)(struct local_client *, char *csid, int node_up))
static int _cluster_do_node_callback(struct local_client *master_client,
void (*callback)(struct local_client *, char *csid, int node_up))
{
struct hash_node *hn;
struct dm_hash_node *hn;
struct node_info *ninfo;
hash_iterate(hn, node_hash)
dm_hash_iterate(hn, node_hash)
{
char csid[MAX_CSID_LEN];
char csid[GULM_MAX_CSID_LEN];
struct local_client *client;
ninfo = hash_get_data(node_hash, hn);
memcpy(csid, hash_get_key(node_hash, hn), MAX_CSID_LEN);
ninfo = dm_hash_get_data(node_hash, hn);
memcpy(csid, dm_hash_get_key(node_hash, hn), GULM_MAX_CSID_LEN);
DEBUGLOG("down_callback. node %s, state = %d\n", ninfo->name, ninfo->state);
client = hash_lookup_binary(sock_hash, csid, MAX_CSID_LEN);
if (client)
callback(master_client, csid, ninfo->state == NODE_CLVMD);
client = dm_hash_lookup_binary(sock_hash, csid, GULM_MAX_CSID_LEN);
if (!client)
{
/* If it's up but not connected, try to make contact */
if (ninfo->state == NODE_UP)
gulm_connect_csid(csid, &client);
client = dm_hash_lookup_binary(sock_hash, csid, GULM_MAX_CSID_LEN);
}
if (ninfo->state != NODE_DOWN)
callback(master_client, csid, ninfo->state == NODE_CLVMD);
}
return 0;
}
@@ -643,15 +700,13 @@ static int gulm_to_errno(int gulm_ret)
switch (gulm_ret)
{
case lg_err_TryFailed:
errno = EAGAIN;
break;
case lg_err_AlreadyPend:
errno = EBUSY;
errno = EAGAIN;
break;
/* More?? */
default:
errno = EINVAL;
errno = EINVAL;
}
return gulm_ret ? -1 : 0;
@@ -675,9 +730,9 @@ 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;
hash_insert(lock_hash, resource, &lwait);
dm_hash_insert(lock_hash, resource, &lwait);
DEBUGLOG("lock_resource '%s', flags=%d, mode=%d\n", resource, flags, mode);
status = lg_lock_state_req(gulm_if, resource, strlen(resource)+1,
@@ -693,7 +748,7 @@ static int _lock_resource(char *resource, int mode, int flags, int *lockid)
pthread_cond_wait(&lwait.cond, &lwait.mutex);
pthread_mutex_unlock(&lwait.mutex);
hash_remove(lock_hash, resource);
dm_hash_remove(lock_hash, resource);
DEBUGLOG("lock-resource returning %d\n", lwait.status);
return gulm_to_errno(lwait.status);
@@ -709,7 +764,7 @@ static int _unlock_resource(char *resource, int lockid)
pthread_mutex_init(&lwait.mutex, NULL);
pthread_mutex_lock(&lwait.mutex);
hash_insert(lock_hash, resource, &lwait);
dm_hash_insert(lock_hash, resource, &lwait);
DEBUGLOG("unlock_resource %s\n", resource);
status = lg_lock_state_req(gulm_if, resource, strlen(resource)+1,
@@ -722,12 +777,17 @@ static int _unlock_resource(char *resource, int lockid)
return status;
}
/* When we are shutting down, don't wait for unlocks
to be acknowledged, just do it. */
if (in_shutdown)
return status;
/* Wait for it to complete */
pthread_cond_wait(&lwait.cond, &lwait.mutex);
pthread_mutex_unlock(&lwait.mutex);
hash_remove(lock_hash, resource);
dm_hash_remove(lock_hash, resource);
return gulm_to_errno(lwait.status);
}
@@ -742,7 +802,7 @@ static int _unlock_resource(char *resource, int lockid)
To aid unlocking, we store the lock mode in the lockid (as GULM
doesn't use this).
*/
int sync_lock(const char *resource, int mode, int flags, int *lockid)
static int _sync_lock(const char *resource, int mode, int flags, int *lockid)
{
int status;
char lock1[strlen(resource)+3];
@@ -758,7 +818,7 @@ int sync_lock(const char *resource, int mode, int flags, int *lockid)
if (status)
goto out;
/* If we can't get this lock then bail out */
/* If we can't get this lock too then bail out */
status = _lock_resource(lock2, lg_lock_state_Exclusive, LCK_NONBLOCK, lockid);
if (status == lg_err_TryFailed)
{
@@ -768,12 +828,19 @@ 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)
goto out;
status = _unlock_resource(lock2, *lockid);
break;
case LCK_WRITE:
status = _lock_resource(lock2, lg_lock_state_Exclusive, flags, lockid);
if (status)
goto out;
status = _unlock_resource(lock1, *lockid);
break;
default:
@@ -786,7 +853,7 @@ int sync_lock(const char *resource, int mode, int flags, int *lockid)
return status;
}
int sync_unlock(const char *resource, int lockid)
static int _sync_unlock(const char *resource, int lockid)
{
int status = 0;
char lock1[strlen(resource)+3];
@@ -798,38 +865,19 @@ 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);
switch (lockid)
{
case LCK_EXCL:
status = _unlock_resource(lock1, lockid);
if (status)
goto out;
status = _unlock_resource(lock2, lockid);
break;
status = _unlock_resource(lock1, lockid);
if (!status)
status = _unlock_resource(lock2, lockid);
case LCK_READ:
status = _unlock_resource(lock1, lockid);
break;
case LCK_WRITE:
status = _unlock_resource(lock2, lockid);
break;
}
out:
return status;
}
int is_quorate()
static int _is_quorate()
{
if (current_corestate == lg_core_Slave ||
current_corestate == lg_core_Master ||
current_corestate == lg_core_Client)
return 1;
else
return 0;
return gulm_quorate;
}
/* Get all the cluster node names & IPs from CCS and
@@ -854,7 +902,7 @@ static int get_all_cluster_nodes()
for (i=1;;i++)
{
char nodekey[256];
char nodeip[MAX_CSID_LEN];
char nodeip[GULM_MAX_CSID_LEN];
int clvmflag = 1;
char *clvmflagstr;
char key[256];
@@ -877,7 +925,7 @@ static int get_all_cluster_nodes()
struct node_info *ninfo;
/* If it's not in the list, then add it */
ninfo = hash_lookup_binary(node_hash, nodeip, MAX_CSID_LEN);
ninfo = dm_hash_lookup_binary(node_hash, nodeip, GULM_MAX_CSID_LEN);
if (!ninfo)
{
ninfo = malloc(sizeof(struct node_info));
@@ -890,12 +938,18 @@ static int get_all_cluster_nodes()
strcpy(ninfo->name, nodename);
ninfo->state = NODE_DOWN;
hash_insert_binary(node_hash, nodeip, MAX_CSID_LEN, ninfo);
dm_hash_insert_binary(node_hash, nodeip, GULM_MAX_CSID_LEN, ninfo);
}
}
else
{
DEBUGLOG("node %s has clvm disabled\n", nodename);
if (!clvmflag) {
DEBUGLOG("node %s has clvm disabled\n", nodename);
}
else {
DEBUGLOG("Cannot resolve host name %s\n", nodename);
log_err("Cannot resolve host name %s\n", nodename);
}
}
free(nodename);
}
@@ -906,3 +960,50 @@ static int get_all_cluster_nodes()
return 0;
}
static int _get_main_cluster_fd(void)
{
return get_main_gulm_cluster_fd();
}
static int _cluster_fd_callback(struct local_client *fd, char *buf, int len, char *csid, struct local_client **new_client)
{
return cluster_fd_gulm_callback(fd, buf, len, csid, new_client);
}
static int _cluster_send_message(void *buf, int msglen, char *csid, const char *errtext)
{
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,
.name_from_csid = gulm_name_from_csid,
.csid_from_name = _csid_from_name,
.get_num_nodes = _get_num_nodes,
.cluster_fd_callback = _cluster_fd_callback,
.get_main_cluster_fd = _get_main_cluster_fd,
.cluster_do_node_callback = _cluster_do_node_callback,
.is_quorate = _is_quorate,
.get_our_csid = _get_our_csid,
.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,
};
struct cluster_ops *init_gulm_cluster(void)
{
if (!_init_cluster())
return &_cluster_gulm_ops;
else
return NULL;
}

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);
@@ -7,3 +8,6 @@ extern int gulm_fd(void);
extern int get_ip_address(char *node, char *addr);
extern void tcp_remove_client(char *csid);
extern int alloc_client(int fd, char *csid, struct local_client **new_client);
void gulm_add_up_node(char *csid);
int gulm_name_from_csid(char *csid, char *name);

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
* Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
@@ -30,10 +30,12 @@
#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 "clvmd-comms.h"
@@ -41,6 +43,7 @@
#include "clvm.h"
#include "version.h"
#include "clvmd.h"
#include "refresh_clvmd.h"
#include "libdlm.h"
#include "system-lv.h"
#include "list.h"
@@ -55,9 +58,9 @@
/* 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))
#define MAX_INLINE_MESSAGE (max_cluster_message-sizeof(struct clvm_header))
#define ISLOCAL_CSID(c) (memcmp(c, our_csid, MAX_CSID_LEN) == 0)
#define ISLOCAL_CSID(c) (memcmp(c, our_csid, max_csid_len) == 0)
/* Head of the fd list. Also contains
the cluster_socket details */
@@ -65,7 +68,12 @@ static struct local_client local_client_head;
static unsigned short global_xid = 0; /* Last transaction ID issued */
struct cluster_ops *clops = NULL;
static char our_csid[MAX_CSID_LEN];
static unsigned max_csid_len;
static unsigned max_cluster_message;
static unsigned max_cluster_member_name_len;
/* Structure of items on the LVM thread list */
struct lvm_thread_cmd {
@@ -78,11 +86,14 @@ 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;
static pthread_mutex_t lvm_start_mutex;
static struct list lvm_cmd_head;
static int quit = 0;
static volatile sig_atomic_t quit = 0;
static volatile sig_atomic_t reread_config = 0;
static int child_pipe[2];
/* Reasons the daemon failed initialisation */
@@ -90,10 +101,12 @@ 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 */
static void sigusr2_handler(int sig);
static void sighup_handler(int sig);
static void sigterm_handler(int sig);
static void send_local_reply(struct local_client *client, int status,
int clientid);
@@ -112,7 +125,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,
@@ -134,7 +147,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");
}
@@ -150,20 +165,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);
@@ -173,6 +204,9 @@ int main(int argc, char *argv[])
usage(argv[0], stderr);
exit(0);
case 'R':
return refresh_clvmd();
case 'd':
debug++;
break;
@@ -185,6 +219,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);
@@ -199,7 +241,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");
@@ -214,8 +256,10 @@ int main(int argc, char *argv[])
/* Set up signal handlers, USR1 is for cluster change notifications (in cman)
USR2 causes child threads to exit.
HUP causes gulm version to re-read nodes list from CCS.
PIPE should be ignored */
signal(SIGUSR2, sigusr2_handler);
signal(SIGHUP, sighup_handler);
signal(SIGPIPE, SIG_IGN);
/* Block SIGUSR2 in the main process */
@@ -227,10 +271,30 @@ int main(int argc, char *argv[])
list_init(&lvm_cmd_head);
pthread_mutex_init(&lvm_thread_mutex, NULL);
pthread_cond_init(&lvm_thread_cond, NULL);
pthread_mutex_init(&lvm_start_mutex, NULL);
init_lvhash();
/* Start the cluster interface */
if (init_cluster()) {
#ifdef USE_CMAN
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_NODENAME_LEN;
syslog(LOG_NOTICE, "Cluster LVM daemon started - connected to CMAN");
}
#endif
#ifdef USE_GULM
if (!clops)
if ((clops = init_gulm_cluster())) {
max_csid_len = GULM_MAX_CSID_LEN;
max_cluster_message = GULM_MAX_CLUSTER_MESSAGE;
max_cluster_member_name_len = GULM_MAX_CLUSTER_MEMBER_NAME_LEN;
using_gulm = 1;
syslog(LOG_NOTICE, "Cluster LVM daemon started - connected to GULM");
}
#endif
if (!clops) {
DEBUGLOG("Can't initialise cluster interface\n");
log_error("Can't initialise cluster interface\n");
child_init_signal(DFAIL_CLUSTER_IF);
@@ -239,12 +303,12 @@ int main(int argc, char *argv[])
/* Save our CSID */
uname(&nodeinfo);
get_our_csid(our_csid);
clops->get_our_csid(our_csid);
/* Initialise the FD list head */
local_client_head.fd = get_main_cluster_fd();
local_client_head.fd = clops->get_main_cluster_fd();
local_client_head.type = CLUSTER_MAIN_SOCK;
local_client_head.callback = cluster_fd_callback;
local_client_head.callback = clops->cluster_fd_callback;
/* Add the local socket to the list */
newfd = malloc(sizeof(struct local_client));
@@ -252,6 +316,7 @@ int main(int argc, char *argv[])
child_init_signal(DFAIL_MALLOC);
newfd->fd = local_sock;
newfd->removeme = 0;
newfd->type = LOCAL_RENDEZVOUS;
newfd->callback = local_rendezvous_callback;
newfd->next = local_client_head.next;
@@ -260,15 +325,15 @@ 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, nodeinfo.nodename);
pthread_create(&lvm_thread, NULL, lvm_thread_fn,
(void *)(long)using_gulm);
#ifndef USE_GULM
/* Tell the rest of the cluster our version number */
/* CMAN can do this immediately, gulm needs to wait until
the core initialisation has finished and the node list
has been gathered */
send_version_message();
#endif
if (clops->cluster_init_completed)
clops->cluster_init_completed();
DEBUGLOG("clvmd ready for work\n");
child_init_signal(SUCCESS);
@@ -319,6 +384,7 @@ static int local_rendezvous_callback(struct local_client *thisfd, char *buf,
newfd->fd = client_fd;
newfd->type = LOCAL_SOCK;
newfd->xid = 0;
newfd->removeme = 0;
newfd->callback = local_sock_callback;
newfd->bits.localsock.replies = NULL;
newfd->bits.localsock.expected_replies = 0;
@@ -347,16 +413,17 @@ static int local_pipe_callback(struct local_client *thisfd, char *buf,
len = read(thisfd->fd, buffer, sizeof(int));
DEBUGLOG("read on PIPE %d: %d bytes: status: %d\n",
thisfd->fd, len, *(int *) buffer);
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 */
@@ -366,9 +433,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.
@@ -417,9 +482,9 @@ static void timedout_callback(struct local_client *client, char *csid,
{
if (node_up) {
struct node_reply *reply;
char nodename[MAX_CLUSTER_MEMBER_NAME_LEN];
char nodename[max_cluster_member_name_len];
name_from_csid(csid, nodename);
clops->name_from_csid(csid, nodename);
DEBUGLOG("PJC: checking for a reply from %s\n", nodename);
pthread_mutex_lock(&client->bits.localsock.reply_mutex);
@@ -448,7 +513,7 @@ static void timedout_callback(struct local_client *client, char *csid,
static void request_timed_out(struct local_client *client)
{
DEBUGLOG("Request timed-out. padding\n");
cluster_do_node_callback(client, timedout_callback);
clops->cluster_do_node_callback(client, timedout_callback);
if (client->bits.localsock.num_replies !=
client->bits.localsock.expected_replies) {
@@ -473,25 +538,55 @@ static void main_loop(int local_sock, int cmd_timeout)
int select_status;
struct local_client *thisfd;
struct timeval tv = { cmd_timeout, 0 };
int quorate = is_quorate();
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) {
if (thisfd->removeme)
continue;
/* if the cluster is not quorate then don't listen for new requests */
if ((thisfd->type != LOCAL_RENDEZVOUS &&
thisfd->type != LOCAL_SOCK) || quorate)
FD_SET(thisfd->fd, &in);
}
if ((select_status = select(FD_SETSIZE, &in, NULL, NULL, &tv)) > 0) {
select_status = select(FD_SETSIZE, &in, NULL, NULL, &tv);
if (reread_config) {
int saved_errno = errno;
reread_config = 0;
if (clops->reread_config)
clops->reread_config();
errno = saved_errno;
}
if (select_status > 0) {
struct local_client *lastfd = NULL;
char csid[MAX_CSID_LEN];
char buf[MAX_CLUSTER_MESSAGE];
char buf[max_cluster_message];
for (thisfd = &local_client_head; thisfd != NULL;
thisfd = thisfd->next) {
if (thisfd->removeme) {
struct local_client *free_fd;
lastfd->next = thisfd->next;
free_fd = thisfd;
thisfd = lastfd;
DEBUGLOG("removeme set for fd %d\n", free_fd->fd);
/* Queue cleanup, this also frees the client struct */
add_to_lvmqueue(free_fd, NULL, 0, NULL);
break;
}
if (FD_ISSET(thisfd->fd, &in)) {
struct local_client *newfd;
int ret;
@@ -520,8 +615,10 @@ static void main_loop(int local_sock, int cmd_timeout)
lastfd->next = thisfd->next;
free_fd = thisfd;
thisfd = lastfd;
cmd_client_cleanup(free_fd);
free(free_fd);
close(free_fd->fd);
/* Queue cleanup, this also frees the client struct */
add_to_lvmqueue(free_fd, NULL, 0, NULL);
break;
}
@@ -573,20 +670,70 @@ static void main_loop(int local_sock, int cmd_timeout)
}
closedown:
cluster_closedown();
clops->cluster_closedown();
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");
@@ -606,36 +753,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 */
@@ -683,6 +801,7 @@ static int read_from_local_sock(struct local_client *thisfd)
/* If the client went away in mid command then tidy up */
if (thisfd->bits.localsock.in_progress) {
pthread_kill(thisfd->bits.localsock.threadid, SIGUSR2);
pthread_mutex_lock(&thisfd->bits.localsock.mutex);
thisfd->bits.localsock.state = POST_COMMAND;
pthread_cond_signal(&thisfd->bits.localsock.cond);
@@ -696,10 +815,9 @@ static int read_from_local_sock(struct local_client *thisfd)
if (thisfd->bits.localsock.threadid) {
DEBUGLOG("Waiting for child thread\n");
pthread_mutex_lock(&thisfd->bits.localsock.mutex);
thisfd->bits.localsock.state = POST_COMMAND;
thisfd->bits.localsock.state = PRE_COMMAND;
pthread_cond_signal(&thisfd->bits.localsock.cond);
pthread_mutex_unlock(&thisfd->bits.localsock.mutex);
pthread_kill(thisfd->bits.localsock.threadid, SIGUSR2);
jstat =
pthread_join(thisfd->bits.localsock.threadid,
@@ -765,7 +883,7 @@ static int read_from_local_sock(struct local_client *thisfd)
if (thisfd->bits.localsock.in_progress) {
struct clvm_header reply;
reply.cmd = CLVMD_CMD_REPLY;
reply.status = -EBUSY;
reply.status = EBUSY;
reply.arglen = 0;
reply.flags = 0;
send_message(&reply, sizeof(reply), our_csid,
@@ -788,7 +906,7 @@ static int read_from_local_sock(struct local_client *thisfd)
if (!thisfd->bits.localsock.cmd) {
struct clvm_header reply;
reply.cmd = CLVMD_CMD_REPLY;
reply.status = -ENOMEM;
reply.status = ENOMEM;
reply.arglen = 0;
reply.flags = 0;
send_message(&reply, sizeof(reply), our_csid,
@@ -829,13 +947,13 @@ static int read_from_local_sock(struct local_client *thisfd)
}
/* Check the node name for validity */
if (inheader->node[0] && csid_from_name(csid, inheader->node)) {
if (inheader->node[0] && clops->csid_from_name(csid, inheader->node)) {
/* Error, node is not in the cluster */
struct clvm_header reply;
DEBUGLOG("Unknown node: '%s'\n", inheader->node);
reply.cmd = CLVMD_CMD_REPLY;
reply.status = -ENOENT;
reply.status = ENOENT;
reply.flags = 0;
reply.arglen = 0;
send_message(&reply, sizeof(reply), our_csid,
@@ -866,7 +984,7 @@ static int read_from_local_sock(struct local_client *thisfd)
close(comms_pipe[1]);
reply.cmd = CLVMD_CMD_REPLY;
reply.status = -ENOMEM;
reply.status = ENOMEM;
reply.arglen = 0;
reply.flags = 0;
send_message(&reply, sizeof(reply), our_csid,
@@ -877,6 +995,7 @@ static int read_from_local_sock(struct local_client *thisfd)
DEBUGLOG("creating pipe, [%d, %d]\n", comms_pipe[0],
comms_pipe[1]);
newfd->fd = comms_pipe[0];
newfd->removeme = 0;
newfd->type = THREAD_PIPE;
newfd->callback = local_pipe_callback;
newfd->next = thisfd->next;
@@ -961,7 +1080,7 @@ static int distribute_command(struct local_client *thisfd)
/* if node is empty then do it on the whole cluster */
if (inheader->node[0] == '\0') {
thisfd->bits.localsock.expected_replies =
get_num_nodes();
clops->get_num_nodes();
thisfd->bits.localsock.num_replies = 0;
thisfd->bits.localsock.sent_time = time(NULL);
thisfd->bits.localsock.in_progress = TRUE;
@@ -982,7 +1101,7 @@ static int distribute_command(struct local_client *thisfd)
/* Do it on a single node */
char csid[MAX_CSID_LEN];
if (csid_from_name(csid, inheader->node)) {
if (clops->csid_from_name(csid, inheader->node)) {
/* This has already been checked so should not happen */
return 0;
} else {
@@ -992,7 +1111,7 @@ static int distribute_command(struct local_client *thisfd)
thisfd->bits.localsock.in_progress = TRUE;
/* Are we the requested node ?? */
if (memcmp(csid, our_csid, MAX_CSID_LEN) == 0) {
if (memcmp(csid, our_csid, max_csid_len) == 0) {
DEBUGLOG("Doing command on local node only\n");
add_to_lvmqueue(thisfd, inheader, len, NULL);
} else {
@@ -1020,21 +1139,21 @@ 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];
char nodename[max_cluster_member_name_len];
int replylen = 0;
int buflen = MAX_CLUSTER_MESSAGE - sizeof(struct clvm_header) - 1;
int buflen = max_cluster_message - sizeof(struct clvm_header) - 1;
int status;
int msg_malloced = 0;
/* Get the node name as we /may/ need it later */
name_from_csid(csid, nodename);
clops->name_from_csid(csid, nodename);
DEBUGLOG("process_remote_command %d for clientid 0x%x on node %s\n",
msg->cmd, msg->clientid, nodename);
DEBUGLOG("process_remote_command %d for clientid 0x%x XID %d on node %s\n",
msg->cmd, msg->clientid, msg->xid, nodename);
/* Is the data to be found in the system LV ? */
if (msg->flags & CLVMD_FLAG_SYSTEMLV) {
@@ -1045,18 +1164,19 @@ 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");
/* Return a failure response */
head.cmd = CLVMD_CMD_REPLY;
head.status = -EFBIG;
head.status = EFBIG;
head.flags = 0;
head.clientid = msg->clientid;
head.arglen = 0;
@@ -1073,7 +1193,7 @@ void process_remote_command(struct clvm_header *msg, int msglen, int fd,
msg->arglen);
/* Return a failure response */
head.cmd = CLVMD_CMD_REPLY;
head.status = -ENOMEM;
head.status = ENOMEM;
head.flags = 0;
head.clientid = msg->clientid;
head.arglen = 0;
@@ -1095,9 +1215,12 @@ 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];
name_from_csid(csid, node);
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,
ntohl(version_nums[0]),
@@ -1118,17 +1241,17 @@ void process_remote_command(struct clvm_header *msg, int msglen, int fd,
byebyemsg.flags = 0;
byebyemsg.arglen = 0;
byebyemsg.clientid = 0;
cluster_send_message(&byebyemsg, sizeof(byebyemsg),
clops->cluster_send_message(&byebyemsg, sizeof(byebyemsg),
our_csid,
"Error Sending GOAWAY message");
} else {
add_up_node(csid);
clops->add_up_node(csid);
}
return;
}
/* Allocate a default reply buffer */
replyargs = malloc(MAX_CLUSTER_MESSAGE - sizeof(struct clvm_header));
replyargs = malloc(max_cluster_message - sizeof(struct clvm_header));
if (replyargs != NULL) {
/* Run the command */
@@ -1136,7 +1259,7 @@ void process_remote_command(struct clvm_header *msg, int msglen, int fd,
do_command(NULL, msg, msglen, &replyargs, buflen,
&replylen);
} else {
status = -ENOMEM;
status = ENOMEM;
}
/* If it wasn't a reply, then reply */
@@ -1167,11 +1290,10 @@ void process_remote_command(struct clvm_header *msg, int msglen, int fd,
/* If System LV operation failed then report it as EFBIG but only do it
if the data buffer has something in it. */
if (system_lv_write_data
(aggreply,
replylen + sizeof(struct clvm_header)) < 0
if (system_lv_write_data(aggreply,
replylen + sizeof(struct clvm_header)) < 0
&& replylen > 0)
agghead->status = -EFBIG;
agghead->status = EFBIG;
send_message(agghead,
sizeof(struct clvm_header), csid,
@@ -1187,7 +1309,7 @@ void process_remote_command(struct clvm_header *msg, int msglen, int fd,
agghead->node[0] = '\0';
send_message(aggreply,
sizeof(struct clvm_header) +
replylen + 2, csid, fd,
replylen, csid, fd,
"Error sending command reply");
}
} else {
@@ -1196,7 +1318,7 @@ void process_remote_command(struct clvm_header *msg, int msglen, int fd,
DEBUGLOG("Error attempting to realloc return buffer\n");
/* Return a failure response */
head.cmd = CLVMD_CMD_REPLY;
head.status = -ENOMEM;
head.status = ENOMEM;
head.flags = 0;
head.clientid = msg->clientid;
head.arglen = 0;
@@ -1228,13 +1350,13 @@ static void add_reply_to_list(struct local_client *client, int status,
reply = malloc(sizeof(struct node_reply));
if (reply) {
reply->status = status;
name_from_csid(csid, reply->node);
clops->name_from_csid(csid, reply->node);
DEBUGLOG("Reply from node %s: %d bytes\n", reply->node, len);
if (len > 0) {
reply->replymsg = malloc(len);
if (!reply->replymsg) {
reply->status = -ENOMEM;
reply->status = ENOMEM;
} else {
memcpy(reply->replymsg, buf, len);
}
@@ -1269,7 +1391,7 @@ 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;
@@ -1278,6 +1400,11 @@ static void *pre_and_post_thread(void *arg)
DEBUGLOG("in sub thread: client = %p\n", client);
/* Don't start until the LVM thread is ready */
pthread_mutex_lock(&lvm_start_mutex);
pthread_mutex_unlock(&lvm_start_mutex);
DEBUGLOG("Sub thread ready for work.\n");
/* Ignore SIGUSR1 (handled by master process) but enable
SIGUSR2 (kills subthreads) */
sigemptyset(&ss);
@@ -1299,6 +1426,8 @@ static void *pre_and_post_thread(void *arg)
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));
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);
@@ -1313,14 +1442,12 @@ static void *pre_and_post_thread(void *arg)
DEBUGLOG("Got post command condition...\n");
/* POST function must always run, even if the client aborts */
status = 0;
do_post_command(client);
write(pipe_fd, &status, sizeof(int));
if (client->bits.localsock.finished)
break;
DEBUGLOG("Waiting for next pre command\n");
pthread_mutex_lock(&client->bits.localsock.mutex);
@@ -1334,7 +1461,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 */
@@ -1342,8 +1468,8 @@ static int process_local_command(struct clvm_header *msg, int msglen,
struct local_client *client,
unsigned short xid)
{
char *replybuf = malloc(MAX_CLUSTER_MESSAGE);
int buflen = MAX_CLUSTER_MESSAGE - sizeof(struct clvm_header) - 1;
char *replybuf = malloc(max_cluster_message);
int buflen = max_cluster_message - sizeof(struct clvm_header) - 1;
int replylen = 0;
int status;
@@ -1425,9 +1551,10 @@ static void send_local_reply(struct local_client *client, int status, int fd)
replybuf = malloc(message_len);
clientreply = (struct clvm_header *) replybuf;
clientreply->status = -status;
clientreply->status = status;
clientreply->cmd = CLVMD_CMD_REPLY;
clientreply->node[0] = '\0';
clientreply->flags = 0;
ptr = clientreply->args;
@@ -1439,7 +1566,10 @@ static void send_local_reply(struct local_client *client, int status, int fd)
strcpy(ptr, thisreply->node);
ptr += strlen(thisreply->node) + 1;
*(int *) ptr = thisreply->status;
if (thisreply->status)
clientreply->flags |= CLVMD_FLAG_NODEERRS;
memcpy(ptr, &thisreply->status, sizeof(int));
ptr += sizeof(int);
if (thisreply->replymsg) {
@@ -1495,19 +1625,23 @@ 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);
cluster_send_message(message, sizeof(message), NULL,
memcpy(&msg->args, version_nums, sizeof(version_nums));
hton_clvm(msg);
clops->cluster_send_message(message, sizeof(message), NULL,
"Error Sending version number");
}
@@ -1519,8 +1653,8 @@ static int send_message(void *buf, int msglen, char *csid, int fd,
/* Send remote messages down the cluster socket */
if (csid == NULL || !ISLOCAL_CSID(csid)) {
hton_clvm((struct clvm_header *) buf); /* Byte swap if necessary */
return cluster_send_message(buf, msglen, csid, errtext);
hton_clvm((struct clvm_header *) buf);
return clops->cluster_send_message(buf, msglen, csid, errtext);
} else {
int ptr = 0;
@@ -1540,6 +1674,14 @@ static int send_message(void *buf, int msglen, char *csid, int fd,
static int process_work_item(struct lvm_thread_cmd *cmd)
{
/* If msg is NULL then this is a cleanup request */
if (cmd->msg == NULL) {
DEBUGLOG("process_work_item: free fd %d\n", cmd->client->fd);
cmd_client_cleanup(cmd->client);
free(cmd->client);
return 0;
}
if (!cmd->remote) {
DEBUGLOG("process_work_item: local\n");
process_local_command(cmd->msg, cmd->msglen, cmd->client,
@@ -1555,13 +1697,16 @@ 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)(long)arg;
/* Don't let anyone else to do work until we are started */
pthread_mutex_lock(&lvm_start_mutex);
DEBUGLOG("LVM thread function started\n");
pthread_mutex_lock(&lvm_thread_mutex);
/* Ignore SIGUSR1 & 2 */
sigemptyset(&ss);
@@ -1570,8 +1715,10 @@ static void *lvm_thread_fn(void *arg)
pthread_sigmask(SIG_BLOCK, &ss, NULL);
/* Initialise the interface to liblvm */
init_lvm();
pthread_mutex_unlock(&lvm_thread_mutex);
init_lvm(using_gulm);
/* Allow others to get moving */
pthread_mutex_unlock(&lvm_start_mutex);
/* Now wait for some actual work */
for (;;) {
@@ -1590,7 +1737,8 @@ static void *lvm_thread_fn(void *arg)
pthread_mutex_unlock(&lvm_thread_mutex);
process_work_item(cmd);
free(cmd->msg);
if (cmd->msg)
free(cmd->msg);
free(cmd);
pthread_mutex_lock(&lvm_thread_mutex);
@@ -1607,21 +1755,26 @@ static int add_to_lvmqueue(struct local_client *client, struct clvm_header *msg,
cmd = malloc(sizeof(struct lvm_thread_cmd));
if (!cmd)
return -ENOMEM;
return ENOMEM;
cmd->msg = malloc(msglen);
if (!cmd->msg) {
log_error("Unable to allocate buffer space\n");
free(cmd);
return -1;
if (msglen) {
cmd->msg = malloc(msglen);
if (!cmd->msg) {
log_error("Unable to allocate buffer space\n");
free(cmd);
return -1;
}
memcpy(cmd->msg, msg, msglen);
}
else {
cmd->msg = NULL;
}
cmd->client = client;
cmd->msglen = msglen;
cmd->xid = client->xid;
memcpy(cmd->msg, msg, msglen);
if (csid) {
memcpy(cmd->csid, csid, MAX_CSID_LEN);
memcpy(cmd->csid, csid, max_csid_len);
cmd->remote = 1;
} else {
cmd->remote = 0;
@@ -1652,6 +1805,8 @@ static int open_local_sock()
log_error("Can't create local socket: %m");
return -1;
}
/* Set Close-on-exec */
fcntl(local_socket, F_SETFD, 1);
memset(&sockaddr, 0, sizeof(sockaddr));
memcpy(sockaddr.sun_path, CLVMD_SOCKNAME, sizeof(CLVMD_SOCKNAME));
@@ -1689,7 +1844,7 @@ static void check_all_callback(struct local_client *client, char *csid,
int node_up)
{
if (!node_up)
add_reply_to_list(client, -EHOSTDOWN, csid, "CLVMD not running",
add_reply_to_list(client, EHOSTDOWN, csid, "CLVMD not running",
18);
}
@@ -1699,7 +1854,7 @@ static void check_all_callback(struct local_client *client, char *csid,
static int check_all_clvmds_running(struct local_client *client)
{
DEBUGLOG("check_all_clvmds_running\n");
return cluster_do_node_callback(client, check_all_callback);
return clops->cluster_do_node_callback(client, check_all_callback);
}
/* Return a local_client struct given a client ID.
@@ -1745,3 +1900,20 @@ static void sigterm_handler(int sig)
quit = 1;
return;
}
static void sighup_handler(int sig)
{
DEBUGLOG("got SIGHUP\n");
reread_config = 1;
}
int sync_lock(const char *resource, int mode, int flags, int *lockid)
{
return clops->sync_lock(resource, mode, flags, lockid);
}
int sync_unlock(const char *resource, int lockid)
{
return clops->sync_unlock(resource, lockid);
}

View File

@@ -86,6 +86,7 @@ struct local_client {
struct local_client *next;
unsigned short xid;
fd_callback_t callback;
uint8_t removeme;
union {
struct localsock_bits localsock;
@@ -94,11 +95,7 @@ struct local_client {
} bits;
};
#ifdef DEBUG
#define DEBUGLOG(fmt, args...) fprintf(stderr, "CLVMD[%d]: %ld ", getpid(), time(NULL) ); 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))
@@ -116,4 +113,9 @@ 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);
#endif

View File

@@ -63,8 +63,8 @@
/* Maximum size of a cluster message */
#define MAX_CLUSTER_MESSAGE 1500
#define MAX_CLUSTER_MEMBER_NAME_LEN 255
#define CMAN_MAX_CLUSTER_MESSAGE 1500
#define CMAN_MAX_CLUSTER_MEMBER_NAME_LEN 255
#define MAX_BARRIER_NAME_LEN 33
#define MAX_SA_ADDR_LEN 12
#define MAX_CLUSTER_NAME_LEN 16
@@ -147,7 +147,7 @@ struct cl_cluster_node {
unsigned int leave_reason;
unsigned int incarnation;
nodestate_t state;
char name[MAX_CLUSTER_MEMBER_NAME_LEN];
char name[CMAN_MAX_CLUSTER_MEMBER_NAME_LEN];
unsigned char votes;
};

View File

@@ -1,446 +0,0 @@
/*
* Copyright (C) 1997-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
*/
/* library functions for Cluster LVM Daemon */
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/uio.h>
#include <sys/un.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <sys/utsname.h>
#include <syslog.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <signal.h>
#include <unistd.h>
#include <fcntl.h>
#include <search.h>
#include <errno.h>
#include "clvm.h"
#include "libclvm.h"
/* CLVM in hex! */
#define LVM_SIGNATURE 0x434C564D
#define MAX_CLUSTER_MEMBER_NAME_LEN 255
/* NOTE: the LVMD uses the socket FD as the client ID, this means
that any client that calls fork() will inherit the context of
it's parent. */
static int clvmd_sock = -1;
static int open_local_sock(void)
{
int local_socket;
struct sockaddr_un sockaddr;
/* Open local socket */
local_socket = socket(PF_UNIX, SOCK_STREAM, 0);
if (local_socket < 0) {
perror("Can't create local socket");
return -1;
}
fcntl(local_socket, F_SETFD, !FD_CLOEXEC);
strcpy(sockaddr.sun_path, CLVMD_SOCKNAME);
sockaddr.sun_family = AF_UNIX;
if (connect
(local_socket, (struct sockaddr *) &sockaddr, sizeof(sockaddr))) {
int saved_errno = errno;
close(local_socket);
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;
fd_set fds;
FD_ZERO(&fds);
FD_SET(clvmd_sock, &fds);
/* Send it to CLVMD */
if (write(clvmd_sock, inbuf, inlen) != inlen) {
perror("Error writing to CLVMD");
return -1;
}
/* Get the response */
if ((len = read(clvmd_sock, outbuf, sizeof(struct clvm_header))) < 0) {
perror("Error reading CLVMD");
return -1;
}
if (len == 0) {
fprintf(stderr, "EOF reading CLVMD");
errno = ENOTCONN;
return -1;
}
/* Allocate buffer */
*retbuf = malloc(len + outheader->arglen);
if (!*retbuf) {
errno = ENOMEM;
return -1;
}
/* 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, PIPE_BUF);
if (len > 0)
off += len;
}
/* Was it an error ? */
if (outheader->status < 0) {
errno = -outheader->status;
return -2;
}
return 0;
}
/* Build the structure header and parse-out wildcard node names */
static void build_header(struct clvm_header *head, int cmd, const char *node,
void *data, 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 */
int lvm_cluster_write(char cmd, char *node, void *data, int len)
{
char outbuf[sizeof(struct clvm_header) + len + strlen(node) + 1];
char *retbuf = NULL;
int status;
struct clvm_header *head = (struct clvm_header *) outbuf;
if (clvmd_sock == -1)
clvmd_sock = open_local_sock();
if (clvmd_sock == -1)
return -1;
build_header(head, cmd, node, data, len);
memcpy(head->node + strlen(head->node) + 1, data, len);
status =
send_request(outbuf,
sizeof(struct clvm_header) + strlen(head->node) + len,
&retbuf);
if (retbuf)
free(retbuf);
return status;
}
/* API: Send a message to a(or all) node(s) in the cluster
and wait for replies */
int lvm_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];
int *outptr;
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 -1;
build_header(head, cmd, node, data, 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 == 0 || status == -2) {
/* 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 */
outptr =
malloc(sizeof(lvm_response_t) * num_responses +
sizeof(int) * 2);
if (!outptr) {
if (retbuf)
free(retbuf);
errno = ENOMEM;
return -1;
}
*response = (lvm_response_t *) (outptr + 2);
outptr[0] = LVM_SIGNATURE;
outptr[1] = num_responses;
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;
rarray[i].status = *(int *) inptr;
inptr += sizeof(int);
rarray[i].response = malloc(strlen(inptr) + 1);
if (rarray[i].response == NULL) {
/* Free up everything else and return error */
int j;
for (j = 0; j < i; j++)
free(rarray[i].response);
free(outptr);
errno = ENOMEM;
return -1;
}
strcpy(rarray[i].response, inptr);
rarray[i].len = strlen(inptr);
inptr += strlen(inptr) + 1;
i++;
}
*num = num_responses;
*response = rarray;
}
if (retbuf)
free(retbuf);
return status;
}
/* API: Free reply array */
int lvm_cluster_free_request(lvm_response_t * response)
{
int *ptr = (int *) response - 2;
int i;
int num;
/* Check it's ours to free */
if (response == NULL || *ptr != LVM_SIGNATURE) {
errno = EINVAL;
return -1;
}
num = ptr[1];
for (i = 0; i < num; i++) {
free(response[i].response);
}
free(ptr);
return 0;
}
/* These are a "higher-level" API providing black-box lock/unlock
functions for cluster LVM...maybe */
/* Set by lock(), used by unlock() */
static int num_responses;
static lvm_response_t *response;
int lvm_lock_for_cluster(char scope, char *name, int verbosity)
{
int status;
int i;
char *args;
int len;
if (name) {
len = strlen(name) + 2;
args = alloca(len);
strcpy(args + 1, name);
} else {
len = 2;
args = alloca(len);
args[1] = '\0';
}
args[0] = scope;
status = lvm_cluster_request(CLVMD_CMD_LOCK,
"", args, len, &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) {
if (verbosity)
fprintf(stderr,
"clvmd not running on node %s\n",
response[i].node);
status = -1;
}
}
/* If there was an error then free the memory now as the caller won't
want to do the unlock */
if (status) {
int saved_errno = errno;
lvm_cluster_free_request(response);
num_responses = 0;
errno = saved_errno;
}
return status;
}
int lvm_unlock_for_cluster(char scope, char *name, int verbosity)
{
int status;
int i;
int len;
int failed;
int num_unlock_responses;
char *args;
lvm_response_t *unlock_response;
/* We failed - this should not have been called */
if (num_responses == 0)
return 0;
if (name) {
len = strlen(name) + 2;
args = alloca(len);
strcpy(args + 1, name);
} else {
len = 2;
args = alloca(len);
args[1] = '\0';
}
args[0] = scope;
/* See if it failed anywhere */
failed = 0;
for (i = 0; i < num_responses; i++) {
if (response[i].status != 0)
failed++;
}
/* If it failed on any nodes then we only unlock on
the nodes that succeeded */
if (failed) {
for (i = 0; i < num_responses; i++) {
/* Unlock the ones that succeeded */
if (response[i].status == 0) {
status = lvm_cluster_request(CLVMD_CMD_UNLOCK,
response[i].node,
args, len,
&unlock_response,
&num_unlock_responses);
if (status) {
if (verbosity)
fprintf(stderr,
"cluster command to node %s failed: %s\n",
response[i].node,
strerror(errno));
} else if (unlock_response[0].status != 0) {
if (verbosity > 1)
fprintf(stderr,
"unlock on node %s failed: %s\n",
response[i].node,
strerror(unlock_response
[0].status));
}
lvm_cluster_free_request(unlock_response);
} else {
if (verbosity)
fprintf(stderr,
"command on node %s failed: '%s' - will be left locked\n",
response[i].node,
strerror(response[i].status));
}
}
} else {
/* All OK, we can do a full cluster unlock */
status = lvm_cluster_request(CLVMD_CMD_UNLOCK,
"",
args, len,
&unlock_response,
&num_unlock_responses);
if (status) {
if (verbosity > 1)
fprintf(stderr, "cluster command failed: %s\n",
strerror(errno));
} else {
for (i = 0; i < num_unlock_responses; i++) {
if (unlock_response[i].status != 0) {
if (verbosity > 1)
fprintf(stderr,
"unlock on node %s failed: %s\n",
response[i].node,
strerror(unlock_response
[0].status));
}
}
}
lvm_cluster_free_request(unlock_response);
}
lvm_cluster_free_request(response);
return 0;
}

View File

@@ -1,36 +0,0 @@
/*
* Copyright (C) 1997-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
*/
#ifndef _LIBCLVM_H
#define _LIBCLVM_H
typedef struct lvm_response {
char node[255];
char *response;
int status;
int len;
} lvm_response_t;
extern int lvm_cluster_request(char cmd, const char *node, void *data, int len,
lvm_response_t ** response, int *num);
extern int lvm_cluster_write(char cmd, char *node, void *data, int len);
extern int lvm_cluster_free_request(lvm_response_t * response);
/* The "high-level" API */
extern int lvm_lock_for_cluster(char scope, char *name, int verbosity);
extern int lvm_unlock_for_cluster(char scope, char *name, int verbosity);
#endif

View File

@@ -31,6 +31,9 @@
#include <syslog.h>
#include <assert.h>
#include "libdevmapper.h"
#include "list.h"
#include "lvm-types.h"
#include "libdlm.h"
#include "clvm.h"
#include "clvmd-comms.h"
@@ -41,25 +44,31 @@
#include "toolcontext.h"
#include "log.h"
#include "activate.h"
#include "hash.h"
#include "locking.h"
#include "defaults.h"
static struct cmd_context *cmd = NULL;
static struct hash_table *lv_hash = NULL;
static struct dm_hash_table *lv_hash = NULL;
static pthread_mutex_t lv_hash_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)
{
struct lv_info *lvi;
pthread_mutex_lock(&lv_hash_lock);
lvi = hash_lookup(lv_hash, resource);
lvi = dm_hash_lookup(lv_hash, resource);
pthread_mutex_unlock(&lv_hash_lock);
if (lvi) {
return lvi->lock_mode;
@@ -71,13 +80,13 @@ static int get_current_lock(char *resource)
/* Called at shutdown to tidy the lockspace */
void unlock_all()
{
struct hash_node *v;
struct dm_hash_node *v;
pthread_mutex_lock(&lv_hash_lock);
hash_iterate(v, lv_hash) {
struct lv_info *lvi = hash_get_data(lv_hash, v);
dm_hash_iterate(v, lv_hash) {
struct lv_info *lvi = dm_hash_get_data(lv_hash, v);
sync_unlock(hash_get_key(lv_hash, v), lvi->lock_id);
sync_unlock(dm_hash_get_key(lv_hash, v), lvi->lock_id);
}
pthread_mutex_unlock(&lv_hash_lock);
}
@@ -92,7 +101,7 @@ int hold_lock(char *resource, int mode, int flags)
flags &= LKF_NOQUEUE; /* Only LKF_NOQUEUE is valid here */
pthread_mutex_lock(&lv_hash_lock);
lvi = hash_lookup(lv_hash, resource);
lvi = dm_hash_lookup(lv_hash, resource);
pthread_mutex_unlock(&lv_hash_lock);
if (lvi) {
/* Already exists - convert it */
@@ -122,7 +131,7 @@ int hold_lock(char *resource, int mode, int flags)
strerror(errno));
} else {
pthread_mutex_lock(&lv_hash_lock);
hash_insert(lv_hash, resource, lvi);
dm_hash_insert(lv_hash, resource, lvi);
pthread_mutex_unlock(&lv_hash_lock);
}
errno = saved_errno;
@@ -138,7 +147,7 @@ int hold_unlock(char *resource)
int saved_errno;
pthread_mutex_lock(&lv_hash_lock);
lvi = hash_lookup(lv_hash, resource);
lvi = dm_hash_lookup(lv_hash, resource);
pthread_mutex_unlock(&lv_hash_lock);
if (!lvi) {
DEBUGLOG("hold_unlock, lock not already held\n");
@@ -149,7 +158,7 @@ int hold_unlock(char *resource)
saved_errno = errno;
if (!status) {
pthread_mutex_lock(&lv_hash_lock);
hash_remove(lv_hash, resource);
dm_hash_remove(lv_hash, resource);
pthread_mutex_unlock(&lv_hash_lock);
free(lvi);
} else {
@@ -168,11 +177,12 @@ int hold_unlock(char *resource)
*/
/* Activate LV exclusive or non-exclusive */
static int do_activate_lv(char *resource, int mode)
static int do_activate_lv(char *resource, unsigned char lock_flags, int mode)
{
int oldmode;
int status;
int activate_lv;
int exclusive = 0;
struct lvinfo lvi;
/* Is it already open ? */
@@ -189,16 +199,29 @@ static int do_activate_lv(char *resource, int mode)
return 0; /* Success, we did nothing! */
/* Do we need to activate exclusively? */
if (activate_lv == 2)
if ((activate_lv == 2) || (mode == LKM_EXMODE)) {
exclusive = 1;
mode = LKM_EXMODE;
}
/* OK, try to get the lock */
status = hold_lock(resource, mode, LKF_NOQUEUE);
if (status)
return errno;
/* 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) {
/* 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 */
if (!lv_info_by_lvid(cmd, resource, &lvi))
if (!lv_info_by_lvid(cmd, resource, &lvi, 0))
return EIO;
if (lvi.suspended)
@@ -206,7 +229,7 @@ static int do_activate_lv(char *resource, int mode)
return EIO;
/* Now activate it */
if (!lv_activate(cmd, resource))
if (!lv_activate(cmd, resource, exclusive))
return EIO;
return 0;
@@ -220,7 +243,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 */
}
@@ -244,7 +267,7 @@ static int do_suspend_lv(char *resource)
}
/* Only suspend it if it exists */
if (!lv_info_by_lvid(cmd, resource, &lvi))
if (!lv_info_by_lvid(cmd, resource, &lvi, 0))
return EIO;
if (lvi.exists) {
@@ -255,14 +278,14 @@ static int do_suspend_lv(char *resource)
return 0;
}
static int do_deactivate_lv(char *resource)
static int do_deactivate_lv(char *resource, unsigned char lock_flags)
{
int oldmode;
int status;
/* Is it open ? */
oldmode = get_current_lock(resource);
if (oldmode == -1) {
if (oldmode == -1 && (lock_flags & LCK_CLUSTER_VG)) {
DEBUGLOG("do_deactivate_lock, lock not already held\n");
return 0; /* We don't need to do anything */
}
@@ -270,9 +293,11 @@ static int do_deactivate_lv(char *resource)
if (!lv_deactivate(cmd, resource))
return EIO;
status = hold_unlock(resource);
if (status)
return errno;
if (lock_flags & LCK_CLUSTER_VG) {
status = hold_unlock(resource);
if (status)
return errno;
}
return 0;
}
@@ -283,7 +308,7 @@ int do_lock_lv(unsigned char command, unsigned char lock_flags, char *resource)
{
int status = 0;
DEBUGLOG("do_lock_lv: resource '%s', cmd = 0x%x, flags = %d\n",
DEBUGLOG("do_lock_lv: resource '%s', cmd = 0x%x, flags = %x\n",
resource, command, lock_flags);
if (!cmd->config_valid || config_files_changed(cmd)) {
@@ -294,9 +319,18 @@ int do_lock_lv(unsigned char command, unsigned char lock_flags, char *resource)
}
}
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, LKM_EXMODE);
status = do_activate_lv(resource, lock_flags, LKM_EXMODE);
break;
case LCK_LV_SUSPEND:
@@ -309,11 +343,11 @@ int do_lock_lv(unsigned char command, unsigned char lock_flags, char *resource)
break;
case LCK_LV_ACTIVATE:
status = do_activate_lv(resource, LKM_CRMODE);
status = do_activate_lv(resource, lock_flags, LKM_CRMODE);
break;
case LCK_LV_DEACTIVATE:
status = do_deactivate_lv(resource);
status = do_deactivate_lv(resource, lock_flags);
break;
default:
@@ -322,8 +356,17 @@ 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 */
pool_empty(cmd->mem);
dm_pool_empty(cmd->mem);
DEBUGLOG("Command return is %d\n", status);
return status;
@@ -363,7 +406,7 @@ 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))
if (!lv_info_by_lvid(cmd, resource, &lvi, 0))
return EIO;
if (lvi.exists) {
@@ -388,6 +431,51 @@ 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
*/
static void drop_vg_locks()
{
char vg[128];
char line[255];
FILE *vgs =
popen
("lvm pvs --nolocking --noheadings -o vg_name", "r");
sync_unlock("P_orphans", LCK_EXCL);
if (!vgs)
return;
while (fgets(line, sizeof(line), vgs)) {
char *vgend;
char *vgstart;
if (line[strlen(line)-1] == '\n')
line[strlen(line)-1] = '\0';
vgstart = line + strspn(line, " ");
vgend = vgstart + strcspn(vgstart, " ");
*vgend = '\0';
if (strncmp(vgstart, "WARNING:", 8) == 0)
continue;
sprintf(vg, "V_%s", vgstart);
sync_unlock(vg, LCK_EXCL);
}
fclose(vgs);
}
/*
* Ideally, clvmd should be started before any LVs are active
* but this may not be the case...
@@ -395,23 +483,24 @@ int do_check_lvm1(char *vgname)
*/
static void *get_initial_state()
{
char lv[64], vg[64], flags[25];
char lv[64], vg[64], flags[25], vg_flags[25];
char uuid[65];
char line[255];
FILE *lvs =
popen
("/sbin/lvm lvs --nolocking --noheadings -o vg_uuid,lv_uuid,lv_attr",
("lvm lvs --nolocking --noheadings -o vg_uuid,lv_uuid,lv_attr,vg_attr",
"r");
if (!lvs)
return NULL;
while (fgets(line, sizeof(line), lvs)) {
if (sscanf(line, "%s %s %s\n", vg, lv, flags) == 3) {
if (sscanf(line, "%s %s %s %s\n", vg, lv, flags, vg_flags) == 4) {
/* States: s:suspended a:active S:dropped snapshot I:invalid snapshot */
if (strlen(vg) == 38 && /* is is a valid UUID ? */
(flags[4] == 'a' || flags[4] == 's')) { /* is it active or suspended? */
(flags[4] == 'a' || flags[4] == 's') && /* is it active or suspended? */
vg_flags[5] == 'c') { /* is it clustered ? */
/* Convert hyphen-separated UUIDs into one */
memcpy(&uuid[0], &vg[0], 6);
memcpy(&uuid[6], &vg[7], 4);
@@ -438,17 +527,55 @@ static void *get_initial_state()
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_tree_int(cmd, "global/locking_type", 1);
if (locking_type == 3) /* compiled-in cluster support */
return;
if (locking_type == 2) { /* External library, check name */
const char *libname;
libname = find_config_tree_str(cmd, "global/locking_library",
"");
if (strstr(libname, "liblvm2clusterlock.so"))
return;
log_error("Incorrect LVM locking library specified in lvm.conf, cluster operations may not work.");
return;
}
log_error("locking_type not set correctly in lvm.conf, cluster operations will not work.");
}
void init_lvhash()
{
/* Create hash table for keeping LV locks & status */
lv_hash = hash_create(100);
lv_hash = dm_hash_create(100);
pthread_mutex_init(&lv_hash_lock, NULL);
}
/* Called to initialise the LVM context of the daemon */
int init_lvm(void)
int init_lvm(int using_gulm)
{
if (!(cmd = create_toolcontext(NULL))) {
if (!(cmd = create_toolcontext(NULL, 0))) {
log_error("Failed to allocate command context");
return 0;
}
@@ -457,7 +584,17 @@ int init_lvm(void)
init_syslog(LOG_DAEMON);
init_debug(_LOG_ERR);
/* Check lvm.conf is setup for cluster-LVM */
check_config();
/* Remove any non-LV locks that may have been left around */
if (using_gulm)
drop_vg_locks();
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 init_lvm(void);
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

@@ -42,7 +42,9 @@
#include "list.h"
#include "locking.h"
#include "system-lv.h"
#include "clvm.h"
#include "clvmd-comms.h"
#include "clvmd.h"
#ifdef HAVE_CCS
#include "ccs.h"
#endif

View File

@@ -2,6 +2,7 @@
*******************************************************************************
**
** Copyright (C) Sistina Software, Inc. 2002-2003 All rights reserved.
** Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
**
*******************************************************************************
******************************************************************************/
@@ -34,17 +35,17 @@
#include <netdb.h>
#include <assert.h>
#include "libdevmapper.h"
#include "clvm.h"
#include "clvmd-comms.h"
#include "clvmd.h"
#include "clvmd-gulm.h"
#include "hash.h"
#define DEFAULT_TCP_PORT 21064
static int listen_fd = -1;
static int tcp_port;
struct hash_table *sock_hash;
struct dm_hash_table *sock_hash;
static int get_our_ip_address(char *addr, int *family);
static int read_from_tcpsock(struct local_client *fd, char *buf, int len, char *csid,
@@ -55,8 +56,8 @@ int init_comms(unsigned short port)
{
struct sockaddr_in6 addr;
sock_hash = hash_create(100);
tcp_port = port ? port : DEFAULT_TCP_PORT;
sock_hash = dm_hash_create(100);
tcp_port = port ? : DEFAULT_TCP_PORT;
listen_fd = socket(AF_INET6, SOCK_STREAM, 0);
@@ -68,6 +69,7 @@ int init_comms(unsigned short port)
{
int one = 1;
setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(int));
setsockopt(listen_fd, SOL_SOCKET, SO_KEEPALIVE, &one, sizeof(int));
}
memset(&addr, 0, sizeof(addr)); // Bind to INADDR_ANY
@@ -84,6 +86,9 @@ int init_comms(unsigned short port)
listen(listen_fd, 5);
/* Set Close-on-exec */
fcntl(listen_fd, F_SETFD, 1);
return 0;
}
@@ -96,19 +101,23 @@ void tcp_remove_client(char *csid)
job of clvmd.c whch will do the job when it notices the
other end has gone. We just need to remove the client(s) from
the hash table so we don't try to use it for sending any more */
client = hash_lookup_binary(sock_hash, csid, MAX_CSID_LEN);
client = dm_hash_lookup_binary(sock_hash, csid, GULM_MAX_CSID_LEN);
if (client)
{
hash_remove_binary(sock_hash, csid, MAX_CSID_LEN);
dm_hash_remove_binary(sock_hash, csid, GULM_MAX_CSID_LEN);
client->removeme = 1;
close(client->fd);
}
/* Look for a mangled one too */
csid[0] ^= 0x80;
client = hash_lookup_binary(sock_hash, csid, MAX_CSID_LEN);
client = dm_hash_lookup_binary(sock_hash, csid, GULM_MAX_CSID_LEN);
if (client)
{
hash_remove_binary(sock_hash, csid, MAX_CSID_LEN);
dm_hash_remove_binary(sock_hash, csid, GULM_MAX_CSID_LEN);
client->removeme = 1;
close(client->fd);
}
/* Put it back as we found it */
@@ -137,7 +146,7 @@ int alloc_client(int fd, char *csid, struct local_client **new_client)
*new_client = client;
/* Add to our list of node sockets */
if (hash_lookup_binary(sock_hash, csid, MAX_CSID_LEN))
if (dm_hash_lookup_binary(sock_hash, csid, GULM_MAX_CSID_LEN))
{
DEBUGLOG("alloc_client mangling CSID for second connection\n");
/* This is a duplicate connection but we can't close it because
@@ -150,7 +159,7 @@ int alloc_client(int fd, char *csid, struct local_client **new_client)
/* If it still exists then kill the connection as we should only
ever have one incoming connection from each node */
if (hash_lookup_binary(sock_hash, csid, MAX_CSID_LEN))
if (dm_hash_lookup_binary(sock_hash, csid, GULM_MAX_CSID_LEN))
{
DEBUGLOG("Multiple incoming connections from node\n");
syslog(LOG_ERR, " Bogus incoming connection from %d.%d.%d.%d\n", csid[0],csid[1],csid[2],csid[3]);
@@ -160,26 +169,26 @@ int alloc_client(int fd, char *csid, struct local_client **new_client)
return -1;
}
}
hash_insert_binary(sock_hash, csid, MAX_CSID_LEN, client);
dm_hash_insert_binary(sock_hash, csid, GULM_MAX_CSID_LEN, client);
return 0;
}
int get_main_cluster_fd()
int get_main_gulm_cluster_fd()
{
return listen_fd;
}
/* Read on main comms (listen) socket, accept it */
int cluster_fd_callback(struct local_client *fd, char *buf, int len, char *csid,
int cluster_fd_gulm_callback(struct local_client *fd, char *buf, int len, char *csid,
struct local_client **new_client)
{
int newfd;
struct sockaddr_in6 addr;
socklen_t addrlen = sizeof(addr);
int status;
char name[MAX_CLUSTER_MEMBER_NAME_LEN];
char name[GULM_MAX_CLUSTER_MEMBER_NAME_LEN];
DEBUGLOG("cluster_fd_callback\n");
*new_client = NULL;
@@ -196,7 +205,7 @@ int cluster_fd_callback(struct local_client *fd, char *buf, int len, char *csid,
/* Check that the client is a member of the cluster
and reject if not.
*/
if (name_from_csid((char *)&addr.sin6_addr, name) < 0)
if (gulm_name_from_csid((char *)&addr.sin6_addr, name) < 0)
{
syslog(LOG_ERR, "Got connect from non-cluster node %s\n",
print_csid((char *)&addr.sin6_addr));
@@ -221,22 +230,62 @@ int cluster_fd_callback(struct local_client *fd, char *buf, int len, char *csid,
return newfd;
}
/* Try to get at least 'len' bytes from the socket */
static int really_read(int fd, char *buf, int len)
{
int got, offset;
got = offset = 0;
do {
got = read(fd, buf+offset, len-offset);
DEBUGLOG("really_read. got %d bytes\n", got);
offset += got;
} while (got > 0 && offset < len);
if (got < 0)
return got;
else
return offset;
}
static int read_from_tcpsock(struct local_client *client, char *buf, int len, char *csid,
struct local_client **new_client)
{
struct sockaddr_in6 addr;
socklen_t slen = sizeof(addr);
struct clvm_header *header = (struct clvm_header *)buf;
int status;
uint32_t arglen;
DEBUGLOG("read_from_tcpsock fd %d\n", client->fd);
*new_client = NULL;
/* Get "csid" */
getpeername(client->fd, (struct sockaddr *)&addr, &slen);
memcpy(csid, &addr.sin6_addr, MAX_CSID_LEN);
memcpy(csid, &addr.sin6_addr, GULM_MAX_CSID_LEN);
status = read(client->fd, buf, len);
/* Read just the header first, then get the rest if there is any.
* Stream sockets, sigh.
*/
status = really_read(client->fd, buf, sizeof(struct clvm_header));
if (status > 0)
{
int status2;
arglen = ntohl(header->arglen);
/* Get the rest */
if (arglen && arglen < GULM_MAX_CLUSTER_MESSAGE)
{
status2 = really_read(client->fd, buf+status, arglen);
if (status2 > 0)
status += status2;
else
status = status2;
}
}
DEBUGLOG("read_from_tcpsock, status = %d(errno = %d)\n", status, errno);
@@ -245,31 +294,33 @@ static int read_from_tcpsock(struct local_client *client, char *buf, int len, ch
if (status == 0 ||
(status < 0 && errno != EAGAIN && errno != EINTR))
{
char remcsid[MAX_CSID_LEN];
char remcsid[GULM_MAX_CSID_LEN];
memcpy(remcsid, csid, MAX_CSID_LEN);
memcpy(remcsid, csid, GULM_MAX_CSID_LEN);
close(client->fd);
/* If the csid was mangled, then make sure we remove the right entry */
if (client->bits.net.flags)
remcsid[0] ^= 0x80;
hash_remove_binary(sock_hash, remcsid, MAX_CSID_LEN);
dm_hash_remove_binary(sock_hash, remcsid, GULM_MAX_CSID_LEN);
/* Tell cluster manager layer */
add_down_node(remcsid);
}
else {
gulm_add_up_node(csid);
/* Send it back to clvmd */
process_message(client, buf, len, csid);
process_message(client, buf, status, csid);
}
return status;
}
static int connect_csid(char *csid, struct local_client **newclient)
int gulm_connect_csid(char *csid, struct local_client **newclient)
{
int fd;
struct sockaddr_in6 addr;
int status;
int one = 1;
DEBUGLOG("Connecting socket\n");
fd = socket(PF_INET6, SOCK_STREAM, 0);
@@ -281,18 +332,28 @@ static int connect_csid(char *csid, struct local_client **newclient)
}
addr.sin6_family = AF_INET6;
memcpy(&addr.sin6_addr, csid, MAX_CSID_LEN);
memcpy(&addr.sin6_addr, csid, GULM_MAX_CSID_LEN);
addr.sin6_port = htons(tcp_port);
DEBUGLOG("Connecting socket %d\n", fd);
if (connect(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in6)) < 0)
{
syslog(LOG_ERR, "Unable to connect to remote node: %m");
/* "Connection refused" is "normal" because clvmd may not yet be running
* on that node.
*/
if (errno != ECONNREFUSED)
{
syslog(LOG_ERR, "Unable to connect to remote node: %m");
}
DEBUGLOG("Unable to connect to remote node: %s\n", strerror(errno));
close(fd);
return -1;
}
/* Set Close-on-exec */
fcntl(fd, F_SETFD, 1);
setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &one, sizeof(int));
status = alloc_client(fd, csid, newclient);
if (status)
close(fd);
@@ -300,7 +361,7 @@ static int connect_csid(char *csid, struct local_client **newclient)
add_client(*newclient);
/* If we can connect to it, it must be running a clvmd */
add_up_node(csid);
gulm_add_up_node(csid);
return status;
}
@@ -309,21 +370,21 @@ static int tcp_send_message(void *buf, int msglen, unsigned char *csid, const ch
{
int status;
struct local_client *client;
char ourcsid[MAX_CSID_LEN];
char ourcsid[GULM_MAX_CSID_LEN];
assert(csid);
DEBUGLOG("tcp_send_message, csid = %s, msglen = %d\n", print_csid(csid), msglen);
/* Don't connect to ourself */
get_our_csid(ourcsid);
if (memcmp(csid, ourcsid, MAX_CSID_LEN) == 0)
get_our_gulm_csid(ourcsid);
if (memcmp(csid, ourcsid, GULM_MAX_CSID_LEN) == 0)
return msglen;
client = hash_lookup_binary(sock_hash, csid, MAX_CSID_LEN);
client = dm_hash_lookup_binary(sock_hash, csid, GULM_MAX_CSID_LEN);
if (!client)
{
status = connect_csid(csid, &client);
status = gulm_connect_csid(csid, &client);
if (status)
return -1;
}
@@ -333,7 +394,7 @@ static int tcp_send_message(void *buf, int msglen, unsigned char *csid, const ch
}
int cluster_send_message(void *buf, int msglen, char *csid, const char *errtext)
int gulm_cluster_send_message(void *buf, int msglen, char *csid, const char *errtext)
{
int status=0;
@@ -343,7 +404,7 @@ int cluster_send_message(void *buf, int msglen, char *csid, const char *errtext)
if (!csid)
{
void *context = NULL;
char loop_csid[MAX_CSID_LEN];
char loop_csid[GULM_MAX_CSID_LEN];
/* Loop round all gulm-known nodes */
while (get_next_node_csid(&context, loop_csid))
@@ -377,9 +438,9 @@ static int get_our_ip_address(char *addr, int *family)
/* Public version of above for those that don't care what protocol
we're using */
void get_our_csid(char *csid)
void get_our_gulm_csid(char *csid)
{
static char our_csid[MAX_CSID_LEN];
static char our_csid[GULM_MAX_CSID_LEN];
static int got_csid = 0;
if (!got_csid)
@@ -392,7 +453,7 @@ void get_our_csid(char *csid)
got_csid = 1;
}
}
memcpy(csid, our_csid, MAX_CSID_LEN);
memcpy(csid, our_csid, GULM_MAX_CSID_LEN);
}
static void map_v4_to_v6(struct in_addr *ip4, struct in6_addr *ip6)
@@ -408,7 +469,7 @@ int get_ip_address(char *node, char *addr)
{
struct hostent *he;
memset(addr, 0, MAX_CSID_LEN);
memset(addr, 0, GULM_MAX_CSID_LEN);
// TODO: what do we do about multi-homed hosts ???
// CCSs ip_interfaces solved this but some bugger removed it.

View File

@@ -1,8 +1,13 @@
#include <netinet/in.h>
#define MAX_CLUSTER_MESSAGE 1600
#define MAX_CSID_LEN sizeof(struct in6_addr)
#define MAX_CLUSTER_MEMBER_NAME_LEN 128
#define GULM_MAX_CLUSTER_MESSAGE 1600
#define GULM_MAX_CSID_LEN sizeof(struct in6_addr)
#define GULM_MAX_CLUSTER_MEMBER_NAME_LEN 128
extern int init_comms(unsigned short);
extern char *print_csid(char *);
int get_main_gulm_cluster_fd(void);
int cluster_fd_gulm_callback(struct local_client *fd, char *buf, int len, char *csid, struct local_client **new_client);
int gulm_cluster_send_message(void *buf, int msglen, char *csid, const char *errtext);
void get_our_gulm_csid(char *csid);
int gulm_connect_csid(char *csid, struct local_client **newclient);

View File

@@ -0,0 +1,19 @@
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

@@ -0,0 +1,83 @@
#
# 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
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
SOURCES = libdevmapper-event.c
LIB_STATIC = libdevmapper-event.a
ifeq ("@LIB_SUFFIX@","dylib")
LIB_SHARED = libdevmapper-event.dylib
else
LIB_SHARED = libdevmapper-event.so
endif
TARGETS = dmeventd
CLEAN_TARGETS = dmeventd.o
include ../make.tmpl
LDFLAGS += -ldl -ldevmapper -lpthread
CLDFLAGS += -ldl -ldevmapper -lpthread
dmeventd: $(LIB_SHARED) dmeventd.o
$(CC) -o $@ dmeventd.o $(CFLAGS) $(LDFLAGS) \
-L. -ldevmapper-event $(LIBS) -rdynamic
.PHONY: install_dynamic install_static install_include \
install_pkgconfig install_dmeventd
INSTALL_TYPE = install_dynamic
ifeq ("@STATIC_LINK@", "yes")
INSTALL_TYPE += install_static
endif
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

1726
daemons/dmeventd/dmeventd.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,51 @@
#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,
};
/* 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,724 @@
/*
* 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 */
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;
}
/*
* 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);
*((uint32_t *)buf) = htonl(msg->cmd);
*((uint32_t *)buf + 1) = htonl(msg->size);
memcpy(buf + 2 * sizeof(uint32_t), msg->data, msg->size);
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 = "%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 ((msg_size = dm_asprintf(&(msg->data), fmt, 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;
return -EIO;
}
if (!_daemon_read(fifos, msg)) {
stack;
return -EIO;
}
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, 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;
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;
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 *p = msg->data;
if ((*dso_name = _fetch_string(&p, ' ')) &&
(*uuid = _fetch_string(&p, ' '))) {
*evmask = atoi(p);
return 0;
}
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;
const char *uuid = NULL;
char *reply_dso = NULL, *reply_uuid = NULL;
enum dm_event_mask reply_mask;
struct dm_task *dmt;
struct dm_event_daemon_message msg;
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);
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);
_dm_event_handler_clear_dev_info(dmevh);
dm_task_destroy(dmt);
return ret;
}
#if 0 /* left out for now */
int dm_event_set_timeout(const char *device_path, uint32_t timeout)
{
struct dm_event_daemon_message msg;
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;
if (!device_exists(device_path))
return -ENODEV;
if (!(ret = _do_event(DM_EVENT_CMD_GET_TIMEOUT, &msg, NULL, device_path,
0, 0)))
*timeout = atoi(msg.data);
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);
int register_device(const char *device_name, const char *uuid, int major, int minor);
int unregister_device(const char *device_name, const char *uuid, int major,
int minor);
#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

@@ -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,278 @@
/*
* 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 "libdevmapper.h"
#include "libdevmapper-event.h"
#include "lvm2cmd.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 --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 *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)
{
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)
{
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,278 @@
/*
* 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 "libdevmapper.h"
#include "libdevmapper-event.h"
#include "lvm2cmd.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 --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 *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)
{
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)
{
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

@@ -33,8 +33,12 @@ devices {
# pattern, the device is accepted; otherwise if any name matches any 'r'
# pattern it is rejected; otherwise it is accepted.
# Remember to run vgscan after you change this parameter to ensure
# that the cache file gets regenerated (see below).
# Don't have more than one filter line active at once: only one gets used.
# Run vgscan after you change this parameter to ensure that
# the cache file gets regenerated (see below).
# If it doesn't do what you expect, check the output of 'vgscan -vvvv'.
# By default we accept every block device:
filter = [ "a/.*/" ]
@@ -203,11 +207,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"
@@ -219,6 +238,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 {
@@ -228,9 +250,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
@@ -247,6 +266,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"
}
@@ -258,11 +325,10 @@ activation {
#
# metadata {
# Default number of copies of metadata to hold on each PV. 0, 1 or 2.
# It's best to leave this at 2.
# You might want to override it from the command line with 0 or 1
# You might want to override it from the command line with 0
# when running pvcreate on new PVs which are to be added to large VGs.
# pvmetadatacopies = 2
# pvmetadatacopies = 1
# Approximate default size of on-disk metadata areas in sectors.
# You should increase this if you have large volume groups or
@@ -286,4 +352,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

@@ -6,9 +6,7 @@
../lib/commands/toolcontext.h
../lib/config/config.h
../lib/config/defaults.h
../lib/datastruct/bitset.h
../lib/datastruct/btree.h
../lib/datastruct/hash.h
../lib/datastruct/list.h
../lib/datastruct/lvm-types.h
../lib/datastruct/str_list.h
@@ -23,6 +21,7 @@
../lib/filters/filter.h
../lib/format1/format1.h
../lib/format_pool/format_pool.h
../lib/format_text/archiver.h
../lib/format_text/format-text.h
../lib/format_text/text_export.h
../lib/format_text/text_import.h
@@ -31,17 +30,18 @@
../lib/log/log.h
../lib/metadata/lv_alloc.h
../lib/metadata/metadata.h
../lib/metadata/pv_alloc.h
../lib/metadata/segtype.h
../lib/mm/dbg_malloc.h
../lib/mm/memlock.h
../lib/mm/pool.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/selinux.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

@@ -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-2005 Red Hat, Inc. All rights reserved.
#
# This file is part of the LVM2.
#
@@ -37,9 +37,8 @@ SOURCES =\
cache/lvmcache.c \
commands/toolcontext.c \
config/config.c \
datastruct/bitset.c \
datastruct/btree.c \
datastruct/hash.c \
datastruct/list.c \
datastruct/str_list.c \
device/dev-cache.c \
device/dev-io.c \
@@ -54,6 +53,7 @@ SOURCES =\
filters/filter-md.c \
filters/filter.c \
format_text/archive.c \
format_text/archiver.c \
format_text/export.c \
format_text/flags.c \
format_text/format-text.c \
@@ -70,15 +70,17 @@ SOURCES =\
metadata/merge.c \
metadata/metadata.c \
metadata/mirror.c \
metadata/pv_manip.c \
metadata/pv_map.c \
metadata/segtype.c \
metadata/snapshot_manip.c \
misc/crc.c \
misc/lvm-exec.c \
misc/lvm-file.c \
misc/lvm-string.c \
mm/dbg_malloc.c \
misc/lvm-wrappers.c \
misc/timestamp.c \
mm/memlock.c \
mm/pool.c \
regex/matcher.c \
regex/parse_rx.c \
regex/ttree.c \
@@ -134,13 +136,22 @@ ifeq ("@HAVE_LIBDL@", "yes")
misc/sharedlib.c
endif
ifeq ("@HAVE_SELINUX@", "yes")
SOURCES += misc/selinux.c
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

@@ -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-2005 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
@@ -19,13 +19,15 @@
#include "memlock.h"
#include "display.h"
#include "fs.h"
#include "lvm-exec.h"
#include "lvm-file.h"
#include "lvm-string.h"
#include "pool.h"
#include "toolcontext.h"
#include "dev_manager.h"
#include "str_list.h"
#include "config.h"
#include "filter.h"
#include "segtype.h"
#include <limits.h>
#include <fcntl.h>
@@ -37,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;
@@ -49,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)
{
@@ -74,25 +136,31 @@ 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 lv_info(const struct logical_volume *lv, struct lvinfo *info)
int target_present(const char *target_name, int use_modprobe)
{
return 0;
}
int lv_info(struct cmd_context *cmd, const struct logical_volume *lv, struct lvinfo *info,
int with_open_count)
{
return 0;
}
int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s,
struct lvinfo *info)
struct lvinfo *info, int with_open_count)
{
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;
}
@@ -129,11 +197,11 @@ int lv_activation_filter(struct cmd_context *cmd, const char *lvid_s,
{
return 1;
}
int lv_activate(struct cmd_context *cmd, const char *lvid_s)
int lv_activate(struct cmd_context *cmd, const char *lvid_s, int exclusive)
{
return 1;
}
int lv_activate_with_filter(struct cmd_context *cmd, const char *lvid_s)
int lv_activate_with_filter(struct cmd_context *cmd, const char *lvid_s, int exclusive)
{
return 1;
}
@@ -143,6 +211,17 @@ int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv)
return 1;
}
int pv_uses_vg(struct physical_volume *pv,
struct volume_group *vg)
{
return 0;
}
void activation_release(void)
{
return;
}
void activation_exit(void)
{
return;
@@ -162,8 +241,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)
@@ -179,7 +258,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;
@@ -238,9 +317,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;
}
@@ -256,53 +335,29 @@ int library_version(char *version, size_t size)
if (!activation())
return 0;
if (!dm_get_library_version(version, size))
return 0;
return 1;
return dm_get_library_version(version, size);
}
int driver_version(char *version, size_t size)
{
int r = 0;
struct dm_task *dmt;
if (!activation())
return 0;
log_very_verbose("Getting driver version");
if (!(dmt = dm_task_create(DM_DEVICE_VERSION))) {
stack;
return 0;
}
if (!dm_task_run(dmt))
log_error("Failed to get driver version");
if (!dm_task_get_driver_version(dmt, version, size))
goto out;
r = 1;
out:
dm_task_destroy(dmt);
return r;
return dm_driver_version(version, size);
}
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;
struct dm_versions *target, *last_target;
if (!activation())
return 0;
log_very_verbose("Getting target version for %s", target_name);
if (!(dmt = dm_task_create(DM_DEVICE_LIST_VERSIONS))) {
stack;
return 0;
}
if (!(dmt = dm_task_create(DM_DEVICE_LIST_VERSIONS)))
return_0;
if (!dm_task_run(dmt)) {
log_debug("Failed to get %s target version", target_name);
@@ -317,6 +372,9 @@ 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;
}
@@ -329,26 +387,57 @@ int target_present(const char *target_name)
return r;
}
/*
* Returns 1 if info structure populated, else 0 on failure.
*/
static int _lv_info(const struct logical_volume *lv, int mknodes,
struct lvinfo *info)
int target_present(const char *target_name, int use_modprobe)
{
int r;
struct dev_manager *dm;
struct dm_info dminfo;
uint32_t maj, min, patchlevel;
#ifdef MODPROBE_CMD
char module[128];
#endif
if (!activation())
return 0;
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name))) {
stack;
return 0;
}
#ifdef MODPROBE_CMD
if (use_modprobe) {
if (target_version(target_name, &maj, &min, &patchlevel))
return 1;
if (!(r = dev_manager_info(dm, lv, mknodes, &dminfo)))
stack;
if (dm_snprintf(module, sizeof(module), "dm-%s", target_name)
< 0) {
log_error("target_present module name too long: %s",
target_name);
return 0;
}
if (!exec_cmd(MODPROBE_CMD, module, "", ""))
return_0;
}
#endif
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 dm_info dminfo;
char *name;
if (!activation())
return 0;
if (!(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);
return_0;
}
info->exists = dminfo.exists;
info->suspended = dminfo.suspended;
@@ -356,31 +445,34 @@ static int _lv_info(const struct logical_volume *lv, int mknodes,
info->major = dminfo.major;
info->minor = dminfo.minor;
info->read_only = dminfo.read_only;
info->live_table = dminfo.live_table;
info->inactive_table = dminfo.inactive_table;
dev_manager_destroy(dm);
return r;
dm_pool_free(cmd->mem, name);
return 1;
}
int lv_info(const struct logical_volume *lv, struct lvinfo *info)
int lv_info(struct cmd_context *cmd, const struct logical_volume *lv, struct lvinfo *info,
int with_open_count)
{
return _lv_info(lv, 0, info);
return _lv_info(cmd, lv, 0, info, with_open_count);
}
int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s,
struct lvinfo *info)
struct lvinfo *info, int with_open_count)
{
struct logical_volume *lv;
if (!(lv = lv_from_lvid(cmd, lvid_s)))
if (!(lv = lv_from_lvid(cmd, lvid_s, 0)))
return 0;
return _lv_info(lv, 0, info);
return _lv_info(cmd, lv, 0, info, with_open_count);
}
/*
* 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;
@@ -388,10 +480,8 @@ int lv_snapshot_percent(struct logical_volume *lv, float *percent)
if (!activation())
return 0;
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name))) {
stack;
return 0;
}
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name)))
return_0;
if (!(r = dev_manager_snapshot_percent(dm, lv, percent)))
stack;
@@ -402,8 +492,8 @@ int lv_snapshot_percent(struct logical_volume *lv, float *percent)
}
/* FIXME Merge with snapshot_percent */
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)
{
int r;
struct dev_manager *dm;
@@ -412,18 +502,14 @@ int lv_mirror_percent(struct logical_volume *lv, int wait, float *percent,
if (!activation())
return 0;
if (!lv_info(lv, &info)) {
stack;
return 0;
}
if (!lv_info(cmd, lv, &info, 0))
return_0;
if (!info.exists)
return 0;
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name))) {
stack;
return 0;
}
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name)))
return_0;
if (!(r = dev_manager_mirror_percent(dm, lv, wait, percent, event_nr)))
stack;
@@ -433,11 +519,11 @@ int lv_mirror_percent(struct logical_volume *lv, int wait, float *percent,
return r;
}
static int _lv_active(struct logical_volume *lv)
static int _lv_active(struct cmd_context *cmd, struct logical_volume *lv)
{
struct lvinfo info;
if (!lv_info(lv, &info)) {
if (!lv_info(cmd, lv, &info, 0)) {
stack;
return -1;
}
@@ -445,11 +531,11 @@ static int _lv_active(struct logical_volume *lv)
return info.exists;
}
static int _lv_open_count(struct logical_volume *lv)
static int _lv_open_count(struct cmd_context *cmd, struct logical_volume *lv)
{
struct lvinfo info;
if (!lv_info(lv, &info)) {
if (!lv_info(cmd, lv, &info, 1)) {
stack;
return -1;
}
@@ -457,16 +543,13 @@ static int _lv_open_count(struct logical_volume *lv)
return info.open_count;
}
/* FIXME Need to detect and handle an lv rename */
static int _lv_activate_lv(struct logical_volume *lv)
{
int r;
struct dev_manager *dm;
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name))) {
stack;
return 0;
}
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name)))
return_0;
if (!(r = dev_manager_activate(dm, lv)))
stack;
@@ -475,15 +558,28 @@ static int _lv_activate_lv(struct logical_volume *lv)
return r;
}
static int _lv_preload(struct logical_volume *lv)
{
int r;
struct dev_manager *dm;
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name)))
return_0;
if (!(r = dev_manager_preload(dm, lv)))
stack;
dev_manager_destroy(dm);
return r;
}
static int _lv_deactivate(struct logical_volume *lv)
{
int r;
struct dev_manager *dm;
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name))) {
stack;
return 0;
}
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name)))
return_0;
if (!(r = dev_manager_deactivate(dm, lv)))
stack;
@@ -492,17 +588,15 @@ 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;
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name))) {
stack;
return 0;
}
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);
@@ -515,17 +609,15 @@ static int _lv_suspend_lv(struct logical_volume *lv)
*/
int lvs_in_vg_activated(struct volume_group *vg)
{
struct list *lvh;
struct logical_volume *lv;
struct lv_list *lvl;
int count = 0;
if (!activation())
return 0;
list_iterate(lvh, &vg->lvs) {
lv = list_item(lvh, struct lv_list)->lv;
if (lv->status & VISIBLE_LV)
count += (_lv_active(lv) == 1);
list_iterate_items(lvl, &vg->lvs) {
if (lvl->lv->status & VISIBLE_LV)
count += (_lv_active(vg->cmd, lvl->lv) == 1);
}
return count;
@@ -533,49 +625,154 @@ int lvs_in_vg_activated(struct volume_group *vg)
int lvs_in_vg_opened(struct volume_group *vg)
{
struct list *lvh;
struct logical_volume *lv;
struct lv_list *lvl;
int count = 0;
if (!activation())
return 0;
list_iterate(lvh, &vg->lvs) {
lv = list_item(lvh, struct lv_list)->lv;
if (lv->status & VISIBLE_LV)
count += (_lv_open_count(lv) > 0);
list_iterate_items(lvl, &vg->lvs) {
if (lvl->lv->status & VISIBLE_LV)
count += (_lv_open_count(vg->cmd, lvl->lv) > 0);
}
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 cmd_context *c, struct lv_segment *s, int e);
/*
* 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(cmd, 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)))
return 0;
if (!(lv = lv_from_lvid(cmd, lvid_s, 0)))
return_0;
/* Use precommitted metadata if present */
if (!(lv_pre = lv_from_lvid(cmd, lvid_s, 1)))
return_0;
if (test_mode()) {
_skip("Suspending '%s'.", lv->name);
return 1;
}
if (!lv_info(lv, &info)) {
stack;
return 0;
}
if (!lv_info(cmd, lv, &info, 0))
return_0;
if (!info.exists || info.suspended)
return error_if_not_suspended ? 0 : 1;
/* If VG was precommitted, preload devices for the 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;
@@ -604,7 +801,7 @@ static int _lv_resume(struct cmd_context *cmd, const char *lvid_s,
if (!activation())
return 1;
if (!(lv = lv_from_lvid(cmd, lvid_s)))
if (!(lv = lv_from_lvid(cmd, lvid_s, 0)))
return 0;
if (test_mode()) {
@@ -612,10 +809,8 @@ static int _lv_resume(struct cmd_context *cmd, const char *lvid_s,
return 1;
}
if (!lv_info(lv, &info)) {
stack;
return 0;
}
if (!lv_info(cmd, lv, &info, 0))
return_0;
if (!info.exists || !info.suspended)
return error_if_not_active ? 0 : 1;
@@ -626,6 +821,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;
}
@@ -649,7 +847,7 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s)
if (!activation())
return 1;
if (!(lv = lv_from_lvid(cmd, lvid_s)))
if (!(lv = lv_from_lvid(cmd, lvid_s, 0)))
return 0;
if (test_mode()) {
@@ -657,20 +855,21 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s)
return 1;
}
if (!lv_info(lv, &info)) {
stack;
return 0;
}
if (!lv_info(cmd, lv, &info, 1))
return_0;
if (!info.exists)
return 1;
if (info.open_count && (lv->status & VISIBLE_LV)) {
log_error("LV %s/%s in use: not removing", lv->vg->name,
log_error("LV %s/%s in use: not deactivating", lv->vg->name,
lv->name);
return 0;
}
if (!monitor_dev_for_events(cmd, lv, 0))
stack;
memlock_inc();
r = _lv_deactivate(lv);
memlock_dec();
@@ -688,7 +887,7 @@ int lv_activation_filter(struct cmd_context *cmd, const char *lvid_s,
if (!activation())
goto activate;
if (!(lv = lv_from_lvid(cmd, lvid_s)))
if (!(lv = lv_from_lvid(cmd, lvid_s, 0)))
return 0;
if (!_passes_activation_filter(cmd, lv)) {
@@ -703,7 +902,8 @@ int lv_activation_filter(struct cmd_context *cmd, const char *lvid_s,
return 1;
}
static int _lv_activate(struct cmd_context *cmd, const char *lvid_s, int filter)
static int _lv_activate(struct cmd_context *cmd, const char *lvid_s,
int exclusive, int filter)
{
struct logical_volume *lv;
struct lvinfo info;
@@ -712,7 +912,7 @@ static int _lv_activate(struct cmd_context *cmd, const char *lvid_s, int filter)
if (!activation())
return 1;
if (!(lv = lv_from_lvid(cmd, lvid_s)))
if (!(lv = lv_from_lvid(cmd, lvid_s, 0)))
return 0;
if (filter && !_passes_activation_filter(cmd, lv)) {
@@ -726,32 +926,36 @@ static int _lv_activate(struct cmd_context *cmd, const char *lvid_s, int filter)
return 1;
}
if (!lv_info(lv, &info)) {
stack;
return 0;
}
if (!lv_info(cmd, lv, &info, 0))
return_0;
if (info.exists && !info.suspended)
if (info.exists && !info.suspended && info.live_table)
return 1;
if (exclusive)
lv->status |= ACTIVATE_EXCL;
memlock_inc();
r = _lv_activate_lv(lv);
memlock_dec();
fs_unlock();
if (!monitor_dev_for_events(cmd, lv, 1))
stack;
return r;
}
/* Activate LV */
int lv_activate(struct cmd_context *cmd, const char *lvid_s)
int lv_activate(struct cmd_context *cmd, const char *lvid_s, int exclusive)
{
return _lv_activate(cmd, lvid_s, 0);
return _lv_activate(cmd, lvid_s, exclusive, 0);
}
/* Activate LV only if it passes filter */
int lv_activate_with_filter(struct cmd_context *cmd, const char *lvid_s)
int lv_activate_with_filter(struct cmd_context *cmd, const char *lvid_s, int exclusive)
{
return _lv_activate(cmd, lvid_s, 1);
return _lv_activate(cmd, lvid_s, exclusive, 1);
}
int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv)
@@ -760,15 +964,13 @@ int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv)
int r = 1;
if (!lv) {
r = dev_manager_mknodes();
r = dm_mknodes(NULL);
fs_unlock();
return r;
}
if (!_lv_info(lv, 1, &info)) {
stack;
return 0;
}
if (!_lv_info(cmd, lv, 1, &info, 0))
return_0;
if (info.exists)
r = dev_manager_lv_mknodes(lv);
@@ -780,6 +982,27 @@ int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv)
return r;
}
/*
* Does PV use VG somewhere in its construction?
* Returns 1 on failure.
*/
int pv_uses_vg(struct physical_volume *pv,
struct volume_group *vg)
{
if (!activation())
return 0;
if (!dm_is_dm_major(MAJOR(pv->dev->dev)))
return 0;
return dev_manager_device_uses_vg(pv->dev, vg);
}
void activation_release(void)
{
dev_manager_release();
}
void activation_exit(void)
{
dev_manager_exit();

View File

@@ -18,10 +18,6 @@
#include "metadata.h"
#ifdef DEVMAPPER_SUPPORT
# include <libdevmapper.h>
#endif
struct lvinfo {
int exists;
int suspended;
@@ -29,6 +25,8 @@ struct lvinfo {
int major;
int minor;
int read_only;
int live_table;
int inactive_table;
};
void set_activation(int activation);
@@ -38,16 +36,24 @@ int driver_version(char *version, size_t size);
int library_version(char *version, size_t size);
int lvm1_present(struct cmd_context *cmd);
int target_present(const char *target_name);
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);
int lv_suspend_if_active(struct cmd_context *cmd, const char *lvid_s);
int lv_resume(struct cmd_context *cmd, const char *lvid_s);
int lv_resume_if_active(struct cmd_context *cmd, const char *lvid_s);
int lv_activate(struct cmd_context *cmd, const char *lvid_s);
int lv_activate_with_filter(struct cmd_context *cmd, const char *lvid_s);
int lv_activate(struct cmd_context *cmd, const char *lvid_s, int exclusive);
int lv_activate_with_filter(struct cmd_context *cmd, const char *lvid_s,
int exclusive);
int lv_deactivate(struct cmd_context *cmd, const char *lvid_s);
int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv);
@@ -55,9 +61,10 @@ int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv);
/*
* Returns 1 if info structure has been populated, else 0.
*/
int lv_info(const struct logical_volume *lv, struct lvinfo *info);
int lv_info(struct cmd_context *cmd, const struct logical_volume *lv, struct lvinfo *info,
int with_open_count);
int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s,
struct lvinfo *info);
struct lvinfo *info, int with_open_count);
/*
* Returns 1 if activate_lv has been set: 1 = activate; 0 = don't.
@@ -68,9 +75,9 @@ 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 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.
@@ -78,6 +85,14 @@ int lv_mirror_percent(struct logical_volume *lv, int wait, float *percent,
int lvs_in_vg_activated(struct volume_group *vg);
int lvs_in_vg_opened(struct volume_group *vg);
int lv_setup_cow_store(struct logical_volume *lv);
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 physical_volume *pv,
struct volume_group *vg);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -17,9 +17,11 @@
#define _LVM_DEV_MANAGER_H
struct logical_volume;
struct volume_group;
struct cmd_context;
struct dev_manager;
struct dm_info;
struct device;
/*
* Constructor and destructor.
@@ -27,6 +29,7 @@ struct dm_info;
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);
/*
@@ -35,24 +38,30 @@ void dev_manager_exit(void);
* (eg, an origin is created before its snapshot, but is not
* unsuspended until the snapshot is also created.)
*/
int dev_manager_info(struct dev_manager *dm, const struct logical_volume *lv,
int mknodes, struct dm_info *info);
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);
int dev_manager_lv_mknodes(const struct logical_volume *lv);
int dev_manager_lv_rmnodes(const struct logical_volume *lv);
int dev_manager_mknodes(void);
/*
* Put the desired changes into effect.
*/
int dev_manager_execute(struct dev_manager *dm);
int dev_manager_device_uses_vg(struct device *dev,
struct volume_group *vg);
#endif

View File

@@ -20,22 +20,17 @@
#include "lvm-file.h"
#include "memlock.h"
#ifdef HAVE_SELINUX
# include "selinux.h"
#endif
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <limits.h>
#include <dirent.h>
#include <libdevmapper.h>
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.");
@@ -58,14 +53,14 @@ 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.");
return 0;
}
if (is_empty_dir(vg_path)) {
if (dir_exists(vg_path) && is_empty_dir(vg_path)) {
log_very_verbose("Removing directory %s", vg_path);
rmdir(vg_path);
}
@@ -92,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;
}
@@ -114,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);
@@ -180,7 +175,7 @@ static int _mk_link(const char *dev_dir, const char *vg_name,
}
#ifdef HAVE_SELINUX
if (!set_selinux_context(lv_path)) {
if (!dm_set_selinux_context(lv_path, S_IFLNK)) {
stack;
return 0;
}
@@ -195,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;
@@ -283,7 +278,7 @@ static int _stack_fs_op(fs_op_t type, const char *dev_dir, const char *vg_name,
strlen(dev) + strlen(old_lv_name) + 5;
char *pos;
if (!(fsp = dbg_malloc(sizeof(*fsp) + len))) {
if (!(fsp = dm_malloc(sizeof(*fsp) + len))) {
log_error("No space to stack fs operation");
return 0;
}
@@ -312,7 +307,7 @@ static void _pop_fs_ops(void)
_do_fs_op(fsp->type, fsp->dev_dir, fsp->vg_name, fsp->lv_name,
fsp->dev, fsp->old_lv_name);
list_del(&fsp->list);
dbg_free(fsp);
dm_free(fsp);
}
}

View File

@@ -19,7 +19,16 @@
struct dev_manager;
struct lv_segment;
int compose_areas_line(struct dev_manager *dm, struct lv_segment *seg, char *params, size_t paramsize, int *pos,
int start_area, int areas);
int compose_areas_line(struct dev_manager *dm, struct lv_segment *seg,
char *params, size_t paramsize, int *pos,
int start_area, int areas);
int add_areas_line(struct dev_manager *dm, struct lv_segment *seg,
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);
char *build_dlid(struct dev_manager *dm, const char *lvid, const char *layer);
#endif

518
lib/cache/lvmcache.c vendored
View File

@@ -16,7 +16,6 @@
#include "lib.h"
#include "lvmcache.h"
#include "hash.h"
#include "toolcontext.h"
#include "dev-cache.h"
#include "metadata.h"
@@ -24,10 +23,10 @@
#include "memlock.h"
#include "str_list.h"
static struct hash_table *_pvid_hash = NULL;
static struct hash_table *_vgid_hash = NULL;
static struct hash_table *_vgname_hash = NULL;
static struct hash_table *_lock_hash = NULL;
static struct dm_hash_table *_pvid_hash = NULL;
static struct dm_hash_table *_vgid_hash = NULL;
static struct dm_hash_table *_vgname_hash = NULL;
static struct dm_hash_table *_lock_hash = NULL;
static struct list _vginfos;
static int _has_scanned = 0;
static int _vgs_locked = 0;
@@ -36,47 +35,46 @@ int lvmcache_init(void)
{
list_init(&_vginfos);
if (!(_vgname_hash = hash_create(128)))
if (!(_vgname_hash = dm_hash_create(128)))
return 0;
if (!(_vgid_hash = hash_create(128)))
if (!(_vgid_hash = dm_hash_create(128)))
return 0;
if (!(_pvid_hash = hash_create(128)))
if (!(_pvid_hash = dm_hash_create(128)))
return 0;
if (!(_lock_hash = hash_create(128)))
if (!(_lock_hash = dm_hash_create(128)))
return 0;
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");
return;
}
if (!hash_insert(_lock_hash, vgname, (void *) 1))
if (!dm_hash_insert(_lock_hash, vgname, (void *) 1))
log_error("Cache locking failure for %s", vgname);
_vgs_locked++;
}
static int _vgname_is_locked(const char *vgname) __attribute__ ((unused));
static int _vgname_is_locked(const char *vgname)
int vgname_is_locked(const char *vgname)
{
if (!_lock_hash)
return 0;
return hash_lookup(_lock_hash, vgname) ? 1 : 0;
return dm_hash_lookup(_lock_hash, vgname) ? 1 : 0;
}
void lvmcache_unlock_vgname(const char *vgname)
{
/* FIXME: Clear all CACHE_LOCKED flags in this vg */
hash_remove(_lock_hash, vgname);
dm_hash_remove(_lock_hash, vgname);
/* FIXME Do this per-VG */
if (!--_vgs_locked)
@@ -88,24 +86,63 @@ 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;
if (!_vgname_hash)
return NULL;
if (!(vginfo = hash_lookup(_vgname_hash, 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;
struct label *label;
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) {
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);
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;
@@ -114,7 +151,7 @@ const struct format_type *fmt_from_vgname(const char *vgname)
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;
@@ -123,16 +160,33 @@ struct lvmcache_vginfo *vginfo_from_vgid(const char *vgid)
strncpy(&id[0], vgid, ID_LEN);
id[ID_LEN] = '\0';
if (!(vginfo = hash_lookup(_vgid_hash, id)))
if (!(vginfo = dm_hash_lookup(_vgid_hash, id)))
return NULL;
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;
@@ -140,7 +194,7 @@ struct lvmcache_info *info_from_pvid(const char *pvid)
strncpy(&id[0], pvid, ID_LEN);
id[ID_LEN] = '\0';
if (!(info = hash_lookup(_pvid_hash, id)))
if (!(info = dm_hash_lookup(_pvid_hash, id)))
return NULL;
return info;
@@ -156,7 +210,7 @@ static void _rescan_entry(struct lvmcache_info *info)
static int _scan_invalid(void)
{
hash_iter(_pvid_hash, (iterate_fn) _rescan_entry);
dm_hash_iter(_pvid_hash, (dm_hash_iterate_fn) _rescan_entry);
return 1;
}
@@ -166,7 +220,6 @@ int lvmcache_label_scan(struct cmd_context *cmd, int full_scan)
struct label *label;
struct dev_iter *iter;
struct device *dev;
struct list *fmth;
struct format_type *fmt;
static int _scanning_in_progress = 0;
@@ -188,7 +241,7 @@ int lvmcache_label_scan(struct cmd_context *cmd, int full_scan)
goto out;
}
if (!(iter = dev_iter_create(cmd->filter))) {
if (!(iter = dev_iter_create(cmd->filter, (full_scan == 2) ? 1 : 0))) {
log_error("dev_iter creation failed");
goto out;
}
@@ -201,8 +254,7 @@ int lvmcache_label_scan(struct cmd_context *cmd, int full_scan)
_has_scanned = 1;
/* Perform any format-specific scanning e.g. text files */
list_iterate(fmth, &cmd->formats) {
fmt = list_item(fmth, struct format_type);
list_iterate_items(fmt, &cmd->formats) {
if (fmt->ops->scan && !fmt->ops->scan(fmt))
goto out;
}
@@ -215,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);
@@ -227,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,
pool_strdup(cmd->mem, vgi->vgname))) {
dm_pool_strdup(cmd->mem, vginfo->vgname))) {
log_error("strlist allocation failed");
return NULL;
}
@@ -238,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;
@@ -266,7 +367,7 @@ struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid)
if (memlock())
return NULL;
lvmcache_label_scan(cmd, 1);
lvmcache_label_scan(cmd, 2);
/* Try again */
if ((info = info_from_pvid((char *) pvid))) {
@@ -280,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);
@@ -288,29 +389,41 @@ static void _drop_vginfo(struct lvmcache_info *info)
}
if (info->vginfo && list_empty(&info->vginfo->infos)) {
hash_remove(_vgname_hash, info->vginfo->vgname);
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)
dbg_free(info->vginfo->vgname);
dm_free(info->vginfo->vgname);
if (info->vginfo->creation_host)
dm_free(info->vginfo->creation_host);
if (*info->vginfo->vgid)
hash_remove(_vgid_hash, info->vginfo->vgid);
dm_hash_remove(_vgid_hash, info->vginfo->vgid);
list_del(&info->vginfo->list);
dbg_free(info->vginfo);
dm_free(info->vginfo);
}
info->vginfo = NULL;
return 1;
}
/* Unused
void lvmcache_del(struct lvmcache_info *info)
{
if (info->dev->pvid[0] && _pvid_hash)
hash_remove(_pvid_hash, info->dev->pvid);
dm_hash_remove(_pvid_hash, info->dev->pvid);
_drop_vginfo(info);
info->label->labeller->ops->destroy_label(info->label->labeller,
info->label);
dbg_free(info);
dm_free(info);
return;
} */
@@ -320,10 +433,10 @@ static int _lvmcache_update_pvid(struct lvmcache_info *info, const char *pvid)
if (!strcmp(info->dev->pvid, pvid))
return 1;
if (*info->dev->pvid) {
hash_remove(_pvid_hash, info->dev->pvid);
dm_hash_remove(_pvid_hash, info->dev->pvid);
}
strncpy(info->dev->pvid, pvid, sizeof(info->dev->pvid));
if (!hash_insert(_pvid_hash, pvid, info)) {
if (!dm_hash_insert(_pvid_hash, pvid, info)) {
log_error("_lvmcache_update: pvid insertion failed: %s", pvid);
return 0;
}
@@ -333,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)
hash_remove(_vgid_hash, info->vginfo->vgid);
if (!vgid)
dm_hash_remove(_vgid_hash, info->vginfo->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';
if (!hash_insert(_vgid_hash, info->vginfo->vgid, info->vginfo)) {
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;
@@ -371,23 +578,59 @@ 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 = dbg_malloc(sizeof(*vginfo)))) {
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;
}
memset(vginfo, 0, sizeof(*vginfo));
if (!(vginfo->vgname = dbg_strdup(vgname))) {
dbg_free(vginfo);
if (!(vginfo->vgname = dm_strdup(vgname))) {
dm_free(vginfo);
log_error("cache vgname alloc failed for %s", vgname);
return 0;
}
list_init(&vginfo->infos);
if (!hash_insert(_vgname_hash, vginfo->vgname, vginfo)) {
log_error("cache_update: vg hash insertion failed: %s",
vginfo->vgname);
dbg_free(vginfo->vgname);
dbg_free(vginfo);
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;
}
/* Ensure orphans appear last on list_iterate */
@@ -395,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;
@@ -403,30 +649,79 @@ 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%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;
}
int lvmcache_update_vg(struct volume_group *vg)
{
struct list *pvh;
struct physical_volume *pv;
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(pvh, &vg->pvs) {
pv = list_item(pvh, struct pv_list)->pv;
strncpy(pvid_s, (char *) &pv->id, sizeof(pvid_s) - 1);
/* FIXME Could 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;
}
}
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_and_id(info, vg->name,
(char *) &vg->id,
vg->status, NULL))
return_0;
}
return 1;
@@ -434,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");
@@ -454,7 +750,7 @@ struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
stack;
return NULL;
}
if (!(info = dbg_malloc(sizeof(*info)))) {
if (!(info = dm_malloc(sizeof(*info)))) {
log_error("lvmcache_info allocation failed");
label_destroy(label);
return NULL;
@@ -475,17 +771,36 @@ struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
pvid, dev_name(dev),
dev_name(existing->dev));
return NULL;
} else if (dm_is_dm_major(MAJOR(existing->dev->dev)) &&
!dm_is_dm_major(MAJOR(dev->dev))) {
log_very_verbose("Ignoring duplicate PV %s on "
"%s - using dm %s",
pvid, dev_name(dev),
dev_name(existing->dev));
return NULL;
} else if (MAJOR(existing->dev->dev) != md_major() &&
MAJOR(dev->dev) == md_major())
log_very_verbose("Duplicate PV %s on %s - "
"using md %s", pvid,
dev_name(existing->dev),
dev_name(dev));
else if (!dm_is_dm_major(MAJOR(existing->dev->dev)) &&
dm_is_dm_major(MAJOR(dev->dev)))
log_very_verbose("Duplicate PV %s on %s - "
"using dm %s", pvid,
dev_name(existing->dev),
dev_name(dev));
/* FIXME If both dm, check dependencies */
//else if (dm_is_dm_major(MAJOR(existing->dev->dev)) &&
//dm_is_dm_major(MAJOR(dev->dev)))
//
else
log_error("Found duplicate PV %s: using %s not "
"%s", pvid, dev_name(dev),
dev_name(existing->dev));
}
/* Switch over to new preferred device */
existing->dev = dev;
info = existing;
/* Has labeller changed? */
if (info->label->labeller != labeller) {
@@ -505,26 +820,22 @@ struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
if (!_lvmcache_update_pvid(info, pvid_s)) {
if (!existing) {
dbg_free(info);
dm_free(info);
label_destroy(label);
}
return NULL;
}
if (!lvmcache_update_vgname(info, vgname)) {
if (!lvmcache_update_vgname_and_id(info, vgname, vgid, vgstatus, NULL)) {
if (!existing) {
hash_remove(_pvid_hash, pvid_s);
dm_hash_remove(_pvid_hash, pvid_s);
strcpy(info->dev->pvid, "");
dbg_free(info);
dm_free(info);
label_destroy(label);
}
return NULL;
}
if (!_lvmcache_update_vgid(info, vgid))
/* Non-critical */
stack;
return info;
}
@@ -534,46 +845,55 @@ static void _lvmcache_destroy_entry(struct lvmcache_info *info)
list_del(&info->list);
strcpy(info->dev->pvid, "");
label_destroy(info->label);
dbg_free(info);
dm_free(info);
}
static void _lvmcache_destroy_vgnamelist(struct lvmcache_vginfo *vginfo)
{
if (vginfo->vgname)
dbg_free(vginfo->vgname);
dbg_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 */
}
void lvmcache_destroy(void)
{
log_verbose("Wiping internal VG cache");
_has_scanned = 0;
if (_vgid_hash) {
hash_destroy(_vgid_hash);
dm_hash_destroy(_vgid_hash);
_vgid_hash = NULL;
}
if (_pvid_hash) {
hash_iter(_pvid_hash, (iterate_fn) _lvmcache_destroy_entry);
hash_destroy(_pvid_hash);
dm_hash_iter(_pvid_hash, (dm_hash_iterate_fn) _lvmcache_destroy_entry);
dm_hash_destroy(_pvid_hash);
_pvid_hash = NULL;
}
if (_vgname_hash) {
hash_iter(_vgname_hash,
(iterate_fn) _lvmcache_destroy_vgnamelist);
hash_destroy(_vgname_hash);
dm_hash_iter(_vgname_hash,
(dm_hash_iterate_fn) _lvmcache_destroy_vgnamelist);
dm_hash_destroy(_vgname_hash);
_vgname_hash = NULL;
}
if (_lock_hash) {
hash_iter(_lock_hash, (iterate_fn) _lvmcache_destroy_lockname);
hash_destroy(_lock_hash);
dm_hash_iter(_lock_hash, (dm_hash_iterate_fn) _lvmcache_destroy_lockname);
dm_hash_destroy(_lock_hash);
_lock_hash = NULL;
}

35
lib/cache/lvmcache.h vendored
View File

@@ -33,14 +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 */
char *vgname; /* "" == orphan */
char vgid[ID_LEN + 1];
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 */
@@ -56,32 +62,47 @@ struct lvmcache_info {
int lvmcache_init(void);
void lvmcache_destroy(void);
/* Set full_scan to 1 to reread every filtered device label */
/* Set full_scan to 1 to reread every filtered device label or
* 2 to rescan /dev for new devices */
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);
/* Returns list of struct str_lists containing pool-allocated copy of vgnames */
/* 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

@@ -16,7 +16,6 @@
#include "lib.h"
#include "toolcontext.h"
#include "pool.h"
#include "metadata.h"
#include "defaults.h"
#include "lvm-string.h"
@@ -35,6 +34,8 @@
#include "str_list.h"
#include "segtype.h"
#include "lvmcache.h"
#include "dev-cache.h"
#include "archiver.h"
#ifdef HAVE_LIBDL
#include "sharedlib.h"
@@ -66,7 +67,7 @@ static int _get_env_vars(struct cmd_context *cmd)
/* 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.");
@@ -83,10 +84,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();
@@ -95,37 +97,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();
@@ -133,15 +135,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
@@ -154,7 +158,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);
@@ -163,8 +167,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;
@@ -174,25 +178,31 @@ 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;
}
if (*cmd->proc_dir && !dir_exists(cmd->proc_dir)) {
log_error("Warning: proc dir %s not found - some checks will be bypassed",
cmd->proc_dir);
cmd->proc_dir[0] = '\0';
}
/* 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))) {
@@ -205,7 +215,7 @@ static int _process_config(struct cmd_context *cmd)
static int _set_tag(struct cmd_context *cmd, const char *tag)
{
log_very_verbose("Setting host tag: %s", pool_strdup(cmd->libmem, tag));
log_very_verbose("Setting host tag: %s", dm_pool_strdup(cmd->libmem, tag));
if (!str_list_add(cmd->libmem, &cmd->tags, tag)) {
log_error("_set_tag: str_list_add %s failed", tag);
@@ -309,18 +319,18 @@ 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;
}
if (!(cfl = pool_alloc(cmd->libmem, sizeof(*cfl)))) {
if (!(cfl = dm_pool_alloc(cmd->libmem, sizeof(*cfl)))) {
log_error("config_tree_list allocation failed");
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;
}
@@ -360,7 +370,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;
}
@@ -398,7 +408,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;
}
@@ -462,7 +472,7 @@ static int _init_dev_cache(struct cmd_context *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");
@@ -487,6 +497,24 @@ static int _init_dev_cache(struct cmd_context *cmd)
}
}
if (!(cn = find_config_tree_node(cmd, "devices/loopfiles")))
return 1;
for (cv = cn->v; cv; cv = cv->next) {
if (cv->type != CFG_STRING) {
log_error("Invalid string in config file: "
"devices/loopfiles");
return 0;
}
if (!dev_cache_add_loopfile(cv->v.str)) {
log_error("Failed to add loopfile %s to internal "
"device cache", cv->v.str);
return 0;
}
}
return 1;
}
@@ -511,14 +539,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");
@@ -528,14 +556,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()))
@@ -559,14 +587,14 @@ static int _init_filters(struct cmd_context *cmd)
if (!(f3 = _init_filter_components(cmd)))
return 0;
if (lvm_snprintf(cache_file, sizeof(cache_file),
if (dm_snprintf(cache_file, sizeof(cache_file),
"%s/.cache", cmd->sys_dir) < 0) {
log_error("Persistent cache filename too long ('%s/.cache').",
cmd->sys_dir);
return 0;
}
dev_cache = find_config_str(cmd->cft->root, "devices/cache",
dev_cache = find_config_tree_str(cmd, "devices/cache",
cache_file);
if (!(f4 = persistent_filter_create(f3, dev_cache))) {
log_error("Failed to create persistent device filter");
@@ -574,15 +602,15 @@ static int _init_filters(struct cmd_context *cmd)
}
/* 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))
(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);
@@ -596,7 +624,6 @@ static int _init_formats(struct cmd_context *cmd)
const char *format;
struct format_type *fmt;
struct list *fmth;
#ifdef HAVE_LIBDL
const struct config_node *cn;
@@ -619,8 +646,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 *);
@@ -632,8 +660,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;
}
@@ -660,11 +688,10 @@ 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(fmth, &cmd->formats) {
fmt = list_item(fmth, struct format_type);
list_iterate_items(fmt, &cmd->formats) {
if (!strcasecmp(fmt->name, format) ||
(fmt->alias && !strcasecmp(fmt->alias, format))) {
cmd->default_settings.fmt = fmt;
@@ -714,8 +741,9 @@ 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 *);
@@ -729,8 +757,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;
}
@@ -776,13 +804,76 @@ static int _init_hostname(struct cmd_context *cmd)
return 0;
}
if (!(cmd->hostname = pool_strdup(cmd->libmem, uts.nodename))) {
log_error("_init_hostname: pool_strdup failed");
if (!(cmd->hostname = dm_pool_strdup(cmd->libmem, uts.nodename))) {
log_error("_init_hostname: dm_pool_strdup failed");
return 0;
}
if (!(cmd->kernel_vsn = pool_strdup(cmd->libmem, uts.release))) {
log_error("_init_hostname: pool_strdup kernel_vsn failed");
if (!(cmd->kernel_vsn = dm_pool_strdup(cmd->libmem, uts.release))) {
log_error("_init_hostname: dm_pool_strdup kernel_vsn failed");
return 0;
}
return 1;
}
static int _init_backup(struct cmd_context *cmd)
{
uint32_t days, min;
char default_dir[PATH_MAX];
const char *dir;
if (!cmd->sys_dir) {
log_warn("WARNING: Metadata changes will NOT be backed up");
backup_init(cmd, "");
archive_init(cmd, "", 0, 0);
return 1;
}
/* set up archiving */
cmd->default_settings.archive =
find_config_tree_bool(cmd, "backup/archive",
DEFAULT_ARCHIVE_ENABLED);
days = (uint32_t) find_config_tree_int(cmd, "backup/retain_days",
DEFAULT_ARCHIVE_DAYS);
min = (uint32_t) find_config_tree_int(cmd, "backup/retain_min",
DEFAULT_ARCHIVE_NUMBER);
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'.",
cmd->sys_dir, DEFAULT_ARCHIVE_SUBDIR);
return 0;
}
dir = find_config_tree_str(cmd, "backup/archive_dir",
default_dir);
if (!archive_init(cmd, dir, days, min)) {
log_debug("backup_init failed.");
return 0;
}
/* set up the backup */
cmd->default_settings.backup =
find_config_tree_bool(cmd, "backup/backup",
DEFAULT_BACKUP_ENABLED);
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'.",
cmd->sys_dir, DEFAULT_BACKUP_SUBDIR);
return 0;
}
dir = find_config_tree_str(cmd, "backup/backup_dir", default_dir);
if (!backup_init(cmd, dir)) {
log_debug("backup_init failed.");
return 0;
}
@@ -790,7 +881,7 @@ static int _init_hostname(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)
{
struct cmd_context *cmd;
@@ -807,12 +898,13 @@ struct cmd_context *create_toolcontext(struct arg *the_args)
init_syslog(DEFAULT_LOG_FACILITY);
if (!(cmd = dbg_malloc(sizeof(*cmd)))) {
if (!(cmd = dm_malloc(sizeof(*cmd)))) {
log_error("Failed to allocate command context");
return NULL;
}
memset(cmd, 0, sizeof(*cmd));
cmd->args = the_args;
cmd->is_static = is_static;
cmd->hosttags = 0;
list_init(&cmd->formats);
list_init(&cmd->segtypes);
@@ -825,12 +917,17 @@ struct cmd_context *create_toolcontext(struct arg *the_args)
goto error;
/* Create system directory if it doesn't already exist */
if (*cmd->sys_dir && !create_dir(cmd->sys_dir))
if (*cmd->sys_dir && !create_dir(cmd->sys_dir)) {
log_error("Failed to create LVM2 system dir for metadata backups, config "
"files and internal cache.");
log_error("Set environment variable LVM_SYSTEM_DIR to alternative location "
"or empty string.");
goto error;
}
if (!(cmd->libmem = pool_create("library", 4 * 1024))) {
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))
@@ -859,9 +956,9 @@ struct cmd_context *create_toolcontext(struct arg *the_args)
if (!_init_filters(cmd))
goto error;
if (!(cmd->mem = pool_create("command", 4 * 1024))) {
if (!(cmd->mem = dm_pool_create("command", 4 * 1024))) {
log_error("Command memory pool creation failed");
return 0;
goto error;
}
memlock_init(cmd);
@@ -872,13 +969,16 @@ struct cmd_context *create_toolcontext(struct arg *the_args)
if (!_init_segtypes(cmd))
goto error;
if (!_init_backup(cmd))
goto error;
cmd->current_settings = cmd->default_settings;
cmd->config_valid = 1;
return cmd;
error:
dbg_free(cmd);
dm_free(cmd);
return NULL;
}
@@ -927,7 +1027,7 @@ int refresh_toolcontext(struct cmd_context *cmd)
persistent_filter_dump(cmd->filter);
}
activation_exit();
activation_release();
lvmcache_destroy();
label_exit();
_destroy_segtypes(&cmd->segtypes);
@@ -982,21 +1082,22 @@ void destroy_toolcontext(struct cmd_context *cmd)
if (cmd->dump_filter)
persistent_filter_dump(cmd->filter);
activation_exit();
archive_exit(cmd);
backup_exit(cmd);
lvmcache_destroy();
label_exit();
_destroy_segtypes(&cmd->segtypes);
_destroy_formats(&cmd->formats);
cmd->filter->destroy(cmd->filter);
pool_destroy(cmd->mem);
dm_pool_destroy(cmd->mem);
dev_cache_exit();
_destroy_tags(cmd);
_destroy_tag_configs(cmd);
pool_destroy(cmd->libmem);
dbg_free(cmd);
dm_pool_destroy(cmd->libmem);
dm_free(cmd);
release_log_memory();
dump_memory();
activation_exit();
fin_log();
fin_syslog();

View File

@@ -17,7 +17,6 @@
#define _LVM_TOOLCONTEXT_H
#include "dev-cache.h"
#include "pool.h"
#include <stdio.h>
#include <limits.h>
@@ -32,26 +31,26 @@ struct config_info {
int syslog;
int activation;
int suffix;
uint64_t unit_factor;
char unit_type;
const char *msg_prefix;
int cmd_name; /* Show command name? */
int archive; /* should we archive ? */
int backup; /* should we backup ? */
const char *msg_prefix;
struct format_type *fmt;
uint64_t unit_factor;
int cmd_name; /* Show command name? */
mode_t umask;
char unit_type;
char _padding[1];
};
struct config_tree;
struct archive_params;
struct backup_params;
/* FIXME Split into tool & library contexts */
/* command-instance-related variables needed by library */
struct cmd_context {
struct pool *libmem; /* For permanent config data */
struct pool *mem; /* Transient: Cleared between each command */
struct dm_pool *libmem; /* For permanent config data */
struct dm_pool *mem; /* Transient: Cleared between each command */
const struct format_type *fmt; /* Current format to use by default */
struct format_type *fmt_backup; /* Format to use for backups */
@@ -65,6 +64,7 @@ struct cmd_context {
struct command *command;
struct arg *args;
char **argv;
unsigned is_static; /* Static binary? */
struct dev_filter *filter;
int dump_filter; /* Dump filter when exiting? */
@@ -72,9 +72,13 @@ 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;
struct archive_params *archive_params;
struct backup_params *backup_params;
/* List of defined tags */
struct list tags;
int hosttags;
@@ -84,7 +88,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);
void destroy_toolcontext(struct cmd_context *cmd);
int refresh_toolcontext(struct cmd_context *cmd);
int config_files_changed(struct cmd_context *cmd);

View File

@@ -16,7 +16,6 @@
#include "lib.h"
#include "config.h"
#include "crc.h"
#include "pool.h"
#include "device.h"
#include "str_list.h"
#include "toolcontext.h"
@@ -42,23 +41,25 @@ 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 */
struct pool *mem;
struct dm_pool *mem;
};
struct cs {
struct config_tree cft;
struct pool *mem;
struct dm_pool *mem;
time_t timestamp;
char *filename;
int exists;
int keep_open;
struct device *dev;
};
static void _get_token(struct parser *p, int tok_prev);
@@ -78,7 +79,7 @@ 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 %d (line %d): unexpected token", p->tb - p->fb + 1, p->line); \
return 0;\
} \
} while(0);
@@ -96,19 +97,19 @@ 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 pool *mem = pool_create("config", 10 * 1024);
struct dm_pool *mem = dm_pool_create("config", 10 * 1024);
if (!mem) {
stack;
log_error("Failed to allocate config pool.");
return 0;
}
if (!(c = pool_zalloc(mem, sizeof(*c)))) {
stack;
pool_destroy(mem);
if (!(c = dm_pool_zalloc(mem, sizeof(*c)))) {
log_error("Failed to allocate config tree.");
dm_pool_destroy(mem);
return 0;
}
@@ -116,14 +117,61 @@ 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 = pool_strdup(c->mem, filename);
c->filename = dm_pool_strdup(c->mem, filename);
return &c->cft;
}
void destroy_config_tree(struct config_tree *cft)
{
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,
@@ -135,8 +183,9 @@ 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 = pool_alloc(c->mem, sizeof(*p)))) {
if (!(p = dm_pool_alloc(c->mem, sizeof(*p)))) {
stack;
return 0;
}
@@ -147,7 +196,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);
@@ -157,22 +206,23 @@ int read_config_fd(struct config_tree *cft, struct device *dev,
}
p->fb = p->fb + mmap_offset;
} else {
if (!(p->fb = dbg_malloc(size + size2))) {
if (!(buf = dm_malloc(size + size2))) {
stack;
return 0;
}
if (!dev_read(dev, (uint64_t) offset, size, p->fb)) {
if (!dev_read(dev, (uint64_t) offset, size, buf)) {
log_error("Read from %s failed", dev_name(dev));
goto out;
}
if (size2) {
if (!dev_read(dev, (uint64_t) offset2, size2,
p->fb + size)) {
buf + size)) {
log_error("Circular read from %s failed",
dev_name(dev));
goto out;
}
}
p->fb = buf;
}
if (checksum_fn && checksum !=
@@ -184,11 +234,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;
}
@@ -197,7 +243,7 @@ int read_config_fd(struct config_tree *cft, struct device *dev,
out:
if (!use_mmap)
dbg_free(p->fb);
dm_free(buf);
else {
/* unmap the file */
if (munmap((char *) (p->fb - mmap_offset), size + mmap_offset)) {
@@ -213,7 +259,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)) {
@@ -235,22 +280,23 @@ int read_config_file(struct config_tree *cft)
return 1;
}
if (!(dev = dev_create_file(c->filename, NULL, NULL))) {
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;
}
@@ -294,7 +340,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:
@@ -327,7 +373,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;
@@ -340,12 +387,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 */
@@ -365,13 +412,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;
@@ -384,9 +433,22 @@ 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 configuration");
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 configuration");
r = 0;
}
} else {
log_error("Configuration node %s not found", *argv);
r = 0;
}
argv++;
}
if (fp != stdout)
@@ -530,7 +592,7 @@ 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 %d (line %d): expected a value", p->tb - p->fb + 1, p->line);
return 0;
}
return v;
@@ -688,22 +750,28 @@ static void _eat_space(struct parser *p)
*/
static struct config_value *_create_value(struct parser *p)
{
struct config_value *v = pool_alloc(p->mem, sizeof(*v));
memset(v, 0, sizeof(*v));
struct config_value *v = dm_pool_alloc(p->mem, sizeof(*v));
if (v)
memset(v, 0, sizeof(*v));
return v;
}
static struct config_node *_create_node(struct parser *p)
{
struct config_node *n = pool_alloc(p->mem, sizeof(*n));
memset(n, 0, sizeof(*n));
struct config_node *n = dm_pool_alloc(p->mem, sizeof(*n));
if (n)
memset(n, 0, sizeof(*n));
return n;
}
static char *_dup_tok(struct parser *p)
{
size_t len = p->te - p->tb;
char *str = pool_alloc(p->mem, len + 1);
char *str = dm_pool_alloc(p->mem, len + 1);
if (!str) {
stack;
return 0;
@@ -716,10 +784,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 */
@@ -730,32 +799,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;
}
@@ -765,9 +864,17 @@ 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);
}
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->type == CFG_INT) {
log_very_verbose("Setting %s to %d", path, n->v->v.i);
@@ -779,10 +886,16 @@ 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);
}
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->type == CFG_FLOAT) {
log_very_verbose("Setting %s to %f", path, n->v->v.r);
@@ -796,6 +909,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;
@@ -822,9 +965,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)
@@ -843,6 +988,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)
{

View File

@@ -16,6 +16,8 @@
#ifndef _LVM_CONFIG_H
#define _LVM_CONFIG_H
#include "lvm-types.h"
struct device;
struct cmd_context;
@@ -51,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,
@@ -69,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);

View File

@@ -32,7 +32,14 @@
#define DEFAULT_MD_COMPONENT_DETECTION 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
@@ -91,19 +98,22 @@
#define DEFAULT_REP_HEADINGS 1
#define DEFAULT_REP_SEPARATOR " "
#define DEFAULT_LVS_COLS "lv_name,vg_name,lv_attr,lv_size,origin,snap_percent,move_pv,copy_percent"
#define DEFAULT_LVS_COLS "lv_name,vg_name,lv_attr,lv_size,origin,snap_percent,move_pv,mirror_log,copy_percent"
#define DEFAULT_VGS_COLS "vg_name,pv_count,lv_count,snap_count,vg_attr,vg_size,vg_free"
#define DEFAULT_PVS_COLS "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free"
#define DEFAULT_SEGS_COLS "lv_name,vg_name,lv_attr,stripes,segtype,seg_size"
#define DEFAULT_PVSEGS_COLS "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free,pvseg_start,pvseg_size"
#define DEFAULT_LVS_COLS_VERB "lv_name,vg_name,seg_count,lv_attr,lv_size,lv_major,lv_minor,lv_kernel_major,lv_kernel_minor,origin,snap_percent,move_pv,copy_percent,lv_uuid"
#define DEFAULT_LVS_COLS_VERB "lv_name,vg_name,seg_count,lv_attr,lv_size,lv_major,lv_minor,lv_kernel_major,lv_kernel_minor,origin,snap_percent,move_pv,copy_percent,mirror_log,lv_uuid"
#define DEFAULT_VGS_COLS_VERB "vg_name,vg_attr,vg_extent_size,pv_count,lv_count,snap_count,vg_size,vg_free,vg_uuid"
#define DEFAULT_PVS_COLS_VERB "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free,dev_size,pv_uuid"
#define DEFAULT_SEGS_COLS_VERB "lv_name,vg_name,lv_attr,seg_start,seg_size,stripes,segtype,stripesize,chunksize"
#define DEFAULT_PVSEGS_COLS_VERB "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free,pvseg_start,pvseg_size"
#define DEFAULT_LVS_SORT "vg_name,lv_name"
#define DEFAULT_VGS_SORT "vg_name"
#define DEFAULT_PVS_SORT "pv_name"
#define DEFAULT_SEGS_SORT "vg_name,lv_name,seg_start"
#define DEFAULT_PVSEGS_SORT "pv_name,pvseg_start"
#endif /* _LVM_DEFAULTS_H */

View File

@@ -24,13 +24,13 @@ struct node {
};
struct btree {
struct pool *mem;
struct dm_pool *mem;
struct node *root;
};
struct btree *btree_create(struct pool *mem)
struct btree *btree_create(struct dm_pool *mem)
{
struct btree *t = pool_alloc(mem, sizeof(*t));
struct btree *t = dm_pool_alloc(mem, sizeof(*t));
if (t) {
t->mem = mem;
@@ -86,7 +86,7 @@ int btree_insert(struct btree *t, uint32_t k, void *data)
struct node *p, **c = _lookup(&t->root, key, &p), *n;
if (!*c) {
if (!(n = pool_alloc(t->mem, sizeof(*n)))) {
if (!(n = dm_pool_alloc(t->mem, sizeof(*n)))) {
stack;
return 0;
}
@@ -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;

View File

@@ -16,11 +16,9 @@
#ifndef _LVM_BTREE_H
#define _LVM_BTREE_H
#include "pool.h"
struct btree;
struct btree *btree_create(struct pool *mem);
struct btree *btree_create(struct dm_pool *mem);
void *btree_lookup(struct btree *t, uint32_t k);
int btree_insert(struct btree *t, uint32_t k, void *data);

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

@@ -18,95 +18,186 @@
#include <assert.h>
/*
* A list consists of a list head plus elements.
* Each element has 'next' and 'previous' pointers.
* The list head's pointers point to the first and the last element.
*/
struct list {
struct list *n, *p;
};
/*
* Initialise a list before use.
* The list head's next and previous pointers point back to itself.
*/
#define LIST_INIT(name) struct list name = { &(name), &(name) }
void list_init(struct list *head);
static inline 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);
static inline void list_add(struct list *head, struct list *elem)
{
assert(head->n);
/*
* 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);
elem->n = head;
elem->p = head->p;
/*
* 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);
head->p->n = elem;
head->p = elem;
}
/*
* Is the list empty?
*/
int list_empty(struct list *head);
static inline void list_add_h(struct list *head, struct list *elem)
{
assert(head->n);
/*
* Is this the first element of the list?
*/
int list_start(struct list *head, struct list *elem);
elem->n = head->n;
elem->p = head;
/*
* Is this the last element of the list?
*/
int list_end(struct list *head, struct list *elem);
head->n->p = elem;
head->n = elem;
}
/*
* Return first element of the list or NULL if empty
*/
struct list *list_first(struct list *head);
static inline void list_del(struct list *elem)
{
elem->n->p = elem->p;
elem->p->n = elem->n;
}
/*
* Return last element of the list or NULL if empty
*/
struct list *list_last(struct list *head);
static inline int list_empty(struct list *head)
{
return head->n == head;
}
/*
* 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);
static inline int list_end(struct list *head, struct list *elem)
{
return elem->n == head;
}
/*
* 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);
static inline struct list *list_next(struct list *head, struct list *elem)
{
return (list_end(head, elem) ? NULL : elem->n);
}
/*
* Given the address v of an instance of 'struct list' called 'head'
* contained in a structure of type t, return the containing structure.
*/
#define list_struct_base(v, t, head) \
((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->head))
#define list_item(v, t) \
((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->list))
/*
* Given the address v of an instance of 'struct list list' contained in
* a structure of type t, return the containing structure.
*/
#define list_item(v, t) list_struct_base((v), t, list)
#define list_struct_base(v, t, h) \
((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->h))
/* Given a known element in a known structure, locate another */
/*
* Given the address v of one known element e in a known structure of type t,
* return another element f.
*/
#define struct_field(v, t, e, f) \
(((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->e))->f)
/* Given a known element in a known structure, locate the list head */
/*
* Given the address v of a known element e in a known structure of type t,
* return the list head 'list'
*/
#define list_head(v, t, e) struct_field(v, t, e, list)
/*
* Set v to each element of a list in turn.
*/
#define list_iterate(v, head) \
for (v = (head)->n; v != head; v = v->n)
/*
* Set v to each element in a list in turn, starting from the element
* in front of 'start'.
* You can use this to 'unwind' a list_iterate and back out actions on
* already-processed elements.
* If 'start' is 'head' it walks the list backwards.
*/
#define list_uniterate(v, head, start) \
for (v = (start)->p; v != head; v = v->p)
/*
* A safe way to walk a list and delete and free some elements along
* the way.
* t must be defined as a temporary variable of the same type as v.
*/
#define list_iterate_safe(v, t, head) \
for (v = (head)->n, t = v->n; v != head; v = t, t = v->n)
#define list_iterate_items(v, head) \
for (v = list_item((head)->n, typeof(*v)); &v->list != (head); \
v = list_item(v->list.n, typeof(*v)))
/*
* Walk a list, setting 'v' in turn to the containing structure of each item.
* The containing structure should be the same type as 'v'.
* The 'struct list' variable within the containing structure is 'field'.
*/
#define list_iterate_items_gen(v, head, field) \
for (v = list_struct_base((head)->n, typeof(*v), field); \
&v->field != (head); \
v = list_struct_base(v->field.n, typeof(*v), field))
static inline unsigned int list_size(const struct list *head)
{
unsigned int s = 0;
const struct list *v;
/*
* Walk a list, setting 'v' in turn to the containing structure of each item.
* The containing structure should be the same type as 'v'.
* The list should be 'struct list list' within the containing structure.
*/
#define list_iterate_items(v, head) list_iterate_items_gen(v, (head), list)
list_iterate(v, head)
s++;
/*
* Walk a list, setting 'v' in turn to the containing structure of each item.
* The containing structure should be the same type as 'v'.
* The 'struct list' variable within the containing structure is 'field'.
* t must be defined as a temporary variable of the same type as v.
*/
#define list_iterate_items_gen_safe(v, t, head, field) \
for (v = list_struct_base((head)->n, typeof(*v), field), \
t = list_struct_base(v->field.n, typeof(*v), field); \
&v->field != (head); \
v = t, t = list_struct_base(v->field.n, typeof(*v), field))
/*
* Walk a list, setting 'v' in turn to the containing structure of each item.
* The containing structure should be the same type as 'v'.
* The list should be 'struct list list' within the containing structure.
* t must be defined as a temporary variable of the same type as v.
*/
#define list_iterate_items_safe(v, t, head) \
list_iterate_items_gen_safe(v, t, (head), list)
return s;
}
/*
* Walk a list backwards, setting 'v' in turn to the containing structure
* of each item.
* The containing structure should be the same type as 'v'.
* The 'struct list' variable within the containing structure is 'field'.
*/
#define list_iterate_back_items_gen(v, head, field) \
for (v = list_struct_base((head)->p, typeof(*v), field); \
&v->field != (head); \
v = list_struct_base(v->field.p, typeof(*v), field))
/*
* Walk a list backwards, setting 'v' in turn to the containing structure
* of each item.
* The containing structure should be the same type as 'v'.
* The list should be 'struct list list' within the containing structure.
*/
#define list_iterate_back_items(v, head) list_iterate_back_items_gen(v, (head), list)
/*
* Return the number of elements in a list by walking it.
*/
unsigned int list_size(const struct list *head);
#endif

View File

@@ -22,7 +22,7 @@
#include <inttypes.h>
/* Define some portable printing types */
#define PRIsize_t "Zu"
#define PRIsize_t "zu"
struct str_list {
struct list list;

View File

@@ -16,11 +16,11 @@
#include "lib.h"
#include "str_list.h"
struct list *str_list_create(struct pool *mem)
struct list *str_list_create(struct dm_pool *mem)
{
struct list *sl;
if (!(sl = pool_alloc(mem, sizeof(struct list)))) {
if (!(sl = dm_pool_alloc(mem, sizeof(struct list)))) {
stack;
return NULL;
}
@@ -30,7 +30,7 @@ struct list *str_list_create(struct pool *mem)
return sl;
}
int str_list_add(struct pool *mem, struct list *sll, const char *str)
int str_list_add(struct dm_pool *mem, struct list *sll, const char *str)
{
struct str_list *sln;
@@ -43,7 +43,7 @@ int str_list_add(struct pool *mem, struct list *sll, const char *str)
if (str_list_match_item(sll, str))
return 1;
if (!(sln = pool_alloc(mem, sizeof(*sln)))) {
if (!(sln = dm_pool_alloc(mem, sizeof(*sln)))) {
stack;
return 0;
}
@@ -66,7 +66,7 @@ int str_list_del(struct list *sll, const char *str)
return 1;
}
int str_list_dup(struct pool *mem, struct list *sllnew, struct list *sllold)
int str_list_dup(struct dm_pool *mem, struct list *sllnew, struct list *sllold)
{
struct str_list *sl;

View File

@@ -16,14 +16,12 @@
#ifndef _LVM_STR_LIST_H
#define _LVM_STR_LIST_H
#include "pool.h"
struct list *str_list_create(struct pool *mem);
int str_list_add(struct pool *mem, struct list *sll, const char *str);
struct list *str_list_create(struct dm_pool *mem);
int str_list_add(struct dm_pool *mem, struct list *sll, const char *str);
int str_list_del(struct list *sll, const char *str);
int str_list_match_item(struct list *sll, const char *str);
int str_list_match_list(struct list *sll, struct list *sll2);
int str_list_lists_equal(struct list *sll, struct list *sll2);
int str_list_dup(struct pool *mem, struct list *sllnew, struct list *sllold);
int str_list_dup(struct dm_pool *mem, struct list *sllnew, struct list *sllold);
#endif

View File

@@ -15,12 +15,10 @@
#include "lib.h"
#include "dev-cache.h"
#include "pool.h"
#include "hash.h"
#include "list.h"
#include "lvm-types.h"
#include "btree.h"
#include "filter.h"
#include "filter-persistent.h"
#include <unistd.h>
#include <sys/param.h>
@@ -37,45 +35,66 @@ struct dir_list {
};
static struct {
struct pool *mem;
struct hash_table *names;
struct dm_pool *mem;
struct dm_hash_table *names;
struct btree *devices;
int has_scanned;
struct list dirs;
struct list files;
} _cache;
#define _alloc(x) pool_alloc(_cache.mem, (x))
#define _free(x) pool_free(_cache.mem, (x))
#define _alloc(x) dm_pool_zalloc(_cache.mem, (x))
#define _free(x) dm_pool_free(_cache.mem, (x))
#define _strdup(x) dm_pool_strdup(_cache.mem, (x))
static int _insert(const char *path, int rec);
struct device *dev_create_file(const char *filename, struct device *dev,
struct str_list *alias)
struct str_list *alias, int use_malloc)
{
int allocate = !dev;
if (allocate && !(dev = dbg_malloc(sizeof(*dev)))) {
log_error("struct device allocation failed");
return NULL;
}
if (allocate && !(alias = dbg_malloc(sizeof(*alias)))) {
log_error("struct str_list allocation failed");
dbg_free(dev);
return NULL;
}
if (!(alias->str = dbg_strdup(filename))) {
log_error("filename strdup failed");
if (allocate) {
dbg_free(dev);
dbg_free(alias);
if (allocate) {
if (use_malloc) {
if (!(dev = dm_malloc(sizeof(*dev)))) {
log_error("struct device allocation failed");
return NULL;
}
if (!(alias = dm_malloc(sizeof(*alias)))) {
log_error("struct str_list allocation failed");
dm_free(dev);
return NULL;
}
if (!(alias->str = dm_strdup(filename))) {
log_error("filename strdup failed");
dm_free(dev);
dm_free(alias);
return NULL;
}
dev->flags = DEV_ALLOCED;
} else {
if (!(dev = _alloc(sizeof(*dev)))) {
log_error("struct device allocation failed");
return NULL;
}
if (!(alias = _alloc(sizeof(*alias)))) {
log_error("struct str_list allocation failed");
_free(dev);
return NULL;
}
if (!(alias->str = _strdup(filename))) {
log_error("filename strdup failed");
return NULL;
}
}
} else if (!(alias->str = dm_strdup(filename))) {
log_error("filename strdup failed");
return NULL;
}
dev->flags = DEV_REGULAR;
if (allocate)
dev->flags |= DEV_ALLOCED;
dev->flags |= DEV_REGULAR;
list_init(&dev->aliases);
list_add(&dev->aliases, &alias->list);
dev->end = UINT64_C(0);
@@ -174,7 +193,7 @@ static int _compare_paths(const char *path0, const char *path1)
static int _add_alias(struct device *dev, const char *path)
{
struct str_list *sl = _alloc(sizeof(*sl));
struct list *ah;
struct str_list *strl;
const char *oldpath;
int prefer_old = 1;
@@ -184,14 +203,14 @@ static int _add_alias(struct device *dev, const char *path)
}
/* Is name already there? */
list_iterate(ah, &dev->aliases) {
if (!strcmp(list_item(ah, struct str_list)->str, path)) {
stack;
list_iterate_items(strl, &dev->aliases) {
if (!strcmp(strl->str, path)) {
log_debug("%s: Already in device cache", path);
return 1;
}
}
if (!(sl->str = pool_strdup(_cache.mem, path))) {
if (!(sl->str = dm_pool_strdup(_cache.mem, path))) {
stack;
return 0;
}
@@ -220,12 +239,27 @@ static int _add_alias(struct device *dev, const char *path)
static int _insert_dev(const char *path, dev_t d)
{
struct device *dev;
static dev_t loopfile_count = 0;
int loopfile = 0;
/* Generate pretend device numbers for loopfiles */
if (!d) {
if (dm_hash_lookup(_cache.names, path))
return 1;
d = ++loopfile_count;
loopfile = 1;
}
/* is this device already registered ? */
if (!(dev = (struct device *) btree_lookup(_cache.devices,
(uint32_t) d))) {
/* create new device */
if (!(dev = _dev_create(d))) {
if (loopfile) {
if (!(dev = dev_create_file(path, NULL, NULL, 0))) {
stack;
return 0;
}
} else if (!(dev = _dev_create(d))) {
stack;
return 0;
}
@@ -237,12 +271,12 @@ static int _insert_dev(const char *path, dev_t d)
}
}
if (!_add_alias(dev, path)) {
if (!loopfile && !_add_alias(dev, path)) {
log_err("Couldn't add alias to dev cache.");
return 0;
}
if (!hash_insert(_cache.names, path, dev)) {
if (!dm_hash_insert(_cache.names, path, dev)) {
log_err("Couldn't add name to hash in dev cache.");
return 0;
}
@@ -253,7 +287,7 @@ static int _insert_dev(const char *path, dev_t d)
static char *_join(const char *dir, const char *name)
{
size_t len = strlen(dir) + strlen(name) + 2;
char *r = dbg_malloc(len);
char *r = dm_malloc(len);
if (r)
snprintf(r, len, "%s/%s", dir, name);
@@ -303,7 +337,7 @@ static int _insert_dir(const char *dir)
_collapse_slashes(path);
r &= _insert(path, 1);
dbg_free(path);
dm_free(path);
free(dirent[n]);
}
@@ -313,6 +347,28 @@ static int _insert_dir(const char *dir)
return r;
}
static int _insert_file(const char *path)
{
struct stat info;
if (stat(path, &info) < 0) {
log_sys_very_verbose("stat", path);
return 0;
}
if (!S_ISREG(info.st_mode)) {
log_debug("%s: Not a regular file", path);
return 0;
}
if (!_insert_dev(path, 0)) {
stack;
return 0;
}
return 1;
}
static int _insert(const char *path, int rec)
{
struct stat info;
@@ -355,19 +411,21 @@ static int _insert(const char *path, int rec)
return r;
}
static void _full_scan(void)
static void _full_scan(int dev_scan)
{
struct list *dh;
struct dir_list *dl;
if (_cache.has_scanned)
if (_cache.has_scanned && !dev_scan)
return;
list_iterate(dh, &_cache.dirs) {
struct dir_list *dl = list_item(dh, struct dir_list);
list_iterate_items(dl, &_cache.dirs)
_insert_dir(dl->dir);
};
list_iterate_items(dl, &_cache.files)
_insert_file(dl->dir);
_cache.has_scanned = 1;
init_full_scan_done(1);
}
int dev_cache_has_scanned(void)
@@ -379,24 +437,23 @@ void dev_cache_scan(int do_scan)
{
if (!do_scan)
_cache.has_scanned = 1;
else {
_cache.has_scanned = 0;
_full_scan();
}
else
_full_scan(1);
}
int dev_cache_init(void)
{
_cache.names = NULL;
_cache.has_scanned = 0;
if (!(_cache.mem = pool_create("dev_cache", 10 * 1024))) {
if (!(_cache.mem = dm_pool_create("dev_cache", 10 * 1024))) {
stack;
return 0;
}
if (!(_cache.names = hash_create(128))) {
if (!(_cache.names = dm_hash_create(128))) {
stack;
pool_destroy(_cache.mem);
dm_pool_destroy(_cache.mem);
_cache.mem = 0;
return 0;
}
@@ -407,6 +464,7 @@ int dev_cache_init(void)
}
list_init(&_cache.dirs);
list_init(&_cache.files);
return 1;
@@ -421,9 +479,9 @@ 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)
{
hash_iter(_cache.names, (iterate_fn) _check_closed);
dm_hash_iter(_cache.names, (dm_hash_iterate_fn) _check_closed);
}
void dev_cache_exit(void)
@@ -432,18 +490,19 @@ void dev_cache_exit(void)
_check_for_open_devices();
if (_cache.mem) {
pool_destroy(_cache.mem);
dm_pool_destroy(_cache.mem);
_cache.mem = NULL;
}
if (_cache.names) {
hash_destroy(_cache.names);
dm_hash_destroy(_cache.names);
_cache.names = NULL;
}
_cache.devices = NULL;
_cache.has_scanned = 0;
list_init(&_cache.dirs);
list_init(&_cache.files);
}
int dev_cache_add_dir(const char *path)
@@ -472,6 +531,32 @@ int dev_cache_add_dir(const char *path)
return 1;
}
int dev_cache_add_loopfile(const char *path)
{
struct dir_list *dl;
struct stat st;
if (stat(path, &st)) {
log_error("Ignoring %s: %s", path, strerror(errno));
/* But don't fail */
return 1;
}
if (!S_ISREG(st.st_mode)) {
log_error("Ignoring %s: Not a regular file", path);
return 1;
}
if (!(dl = _alloc(sizeof(*dl) + strlen(path) + 1))) {
log_error("dir_list allocation failed for file");
return 0;
}
strcpy(dl->dir, path);
list_add(&_cache.files, &dl->list);
return 1;
}
/* Check cached device name is still valid before returning it */
/* This should be a rare occurrence */
/* set quiet if the cache is expected to be out-of-date */
@@ -482,6 +567,9 @@ const char *dev_name_confirmed(struct device *dev, int quiet)
const char *name;
int r;
if ((dev->flags & DEV_REGULAR))
return dev_name(dev);
while ((r = stat(name = list_item(dev->aliases.n,
struct str_list)->str, &buf)) ||
(buf.st_rdev != dev->dev)) {
@@ -501,7 +589,7 @@ const char *dev_name_confirmed(struct device *dev, int quiet)
(int) MINOR(dev->dev));
/* Remove the incorrect hash entry */
hash_remove(_cache.names, name);
dm_hash_remove(_cache.names, name);
/* Leave list alone if there isn't an alternative name */
/* so dev_name will always find something to return. */
@@ -524,32 +612,46 @@ const char *dev_name_confirmed(struct device *dev, int quiet)
struct device *dev_cache_get(const char *name, struct dev_filter *f)
{
struct stat buf;
struct device *d = (struct device *) hash_lookup(_cache.names, name);
struct device *d = (struct device *) dm_hash_lookup(_cache.names, name);
if (d && (d->flags & DEV_REGULAR))
return d;
/* If the entry's wrong, remove it */
if (d && (stat(name, &buf) || (buf.st_rdev != d->dev))) {
hash_remove(_cache.names, name);
dm_hash_remove(_cache.names, name);
d = NULL;
}
if (!d) {
_insert(name, 0);
d = (struct device *) hash_lookup(_cache.names, name);
d = (struct device *) dm_hash_lookup(_cache.names, name);
if (!d) {
_full_scan(0);
d = (struct device *) dm_hash_lookup(_cache.names, name);
}
}
return (d && (!f || f->passes_filter(f, d))) ? d : NULL;
return (d && (!f || (d->flags & DEV_REGULAR) ||
f->passes_filter(f, d))) ? d : NULL;
}
struct dev_iter *dev_iter_create(struct dev_filter *f)
struct dev_iter *dev_iter_create(struct dev_filter *f, int dev_scan)
{
struct dev_iter *di = dbg_malloc(sizeof(*di));
struct dev_iter *di = dm_malloc(sizeof(*di));
if (!di) {
log_error("dev_iter allocation failed");
return NULL;
}
_full_scan();
if (dev_scan && !trust_cache()) {
/* Flag gets reset between each command */
if (!full_scan_done())
persistent_filter_wipe(f); /* Calls _full_scan(1) */
} else
_full_scan(0);
di->current = btree_first(_cache.devices);
di->filter = f;
@@ -558,10 +660,10 @@ struct dev_iter *dev_iter_create(struct dev_filter *f)
void dev_iter_destroy(struct dev_iter *iter)
{
dbg_free(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);
@@ -572,10 +674,21 @@ struct device *dev_iter_get(struct dev_iter *iter)
{
while (iter->current) {
struct device *d = _iter_next(iter);
if (!iter->filter ||
if (!iter->filter || (d->flags & DEV_REGULAR) ||
iter->filter->passes_filter(iter->filter, d))
return d;
}
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

@@ -16,7 +16,6 @@
#ifndef _LVM_DEV_CACHE_H
#define _LVM_DEV_CACHE_H
#include "lvm-types.h"
#include "device.h"
/*
@@ -39,13 +38,14 @@ void dev_cache_scan(int do_scan);
int dev_cache_has_scanned(void);
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);
/*
* Object for iterating through the cache.
*/
struct dev_iter;
struct dev_iter *dev_iter_create(struct dev_filter *f);
struct dev_iter *dev_iter_create(struct dev_filter *f, int dev_scan);
void dev_iter_destroy(struct dev_iter *iter);
struct device *dev_iter_get(struct dev_iter *iter);

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);
@@ -222,11 +222,25 @@ static int _aligned_io(struct device_area *where, void *buffer,
return 1;
}
/*-----------------------------------------------------------------
* Public functions
*---------------------------------------------------------------*/
static int _dev_get_size_file(const struct device *dev, uint64_t *size)
{
const char *name = dev_name(dev);
struct stat info;
int dev_get_size(const struct device *dev, uint64_t *size)
if (stat(name, &info)) {
log_sys_error("stat", name);
return 0;
}
*size = info.st_size;
*size >>= SECTOR_SHIFT; /* Convert to sectors */
log_very_verbose("%s: size is %" PRIu64 " sectors", name, *size);
return 1;
}
static int _dev_get_size_dev(const struct device *dev, uint64_t *size)
{
int fd;
const char *name = dev_name(dev);
@@ -252,6 +266,18 @@ int dev_get_size(const struct device *dev, uint64_t *size)
return 1;
}
/*-----------------------------------------------------------------
* Public functions
*---------------------------------------------------------------*/
int dev_get_size(const struct device *dev, uint64_t *size)
{
if ((dev->flags & DEV_REGULAR))
return _dev_get_size_file(dev, size);
else
return _dev_get_size_dev(dev, size);
}
/* FIXME Unused
int dev_get_sectsize(struct device *dev, uint32_t *size)
{
@@ -294,15 +320,22 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet)
{
struct stat buf;
const char *name;
int need_excl = 0, need_rw = 0;
if ((flags & O_ACCMODE) == O_RDWR)
need_rw = 1;
if ((flags & O_EXCL))
need_excl = 1;
if (dev->fd >= 0) {
if ((dev->flags & DEV_OPENED_RW) ||
((flags & O_ACCMODE) != O_RDWR)) {
if (((dev->flags & DEV_OPENED_RW) || !need_rw) &&
((dev->flags & DEV_OPENED_EXCL) || !need_excl)) {
dev->open_count++;
return 1;
}
if (dev->open_count) {
if (dev->open_count && !need_excl) {
/* FIXME Ensure we never get here */
log_debug("WARNING: %s already opened read-only",
dev_name(dev));
@@ -330,8 +363,13 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet)
}
#ifdef O_DIRECT_SUPPORT
if (direct)
flags |= O_DIRECT;
if (direct) {
if (!(dev->flags & DEV_O_DIRECT_TESTED))
dev->flags |= DEV_O_DIRECT;
if ((dev->flags & DEV_O_DIRECT))
flags |= O_DIRECT;
}
#endif
#ifdef O_NOATIME
@@ -341,22 +379,45 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet)
#endif
if ((dev->fd = open(name, flags, 0777)) < 0) {
log_sys_error("open", name);
#ifdef O_DIRECT_SUPPORT
if (direct && !(dev->flags & DEV_O_DIRECT_TESTED)) {
flags &= ~O_DIRECT;
if ((dev->fd = open(name, flags, 0777)) >= 0) {
dev->flags &= ~DEV_O_DIRECT;
log_debug("%s: Not using O_DIRECT", name);
goto opened;
}
}
#endif
if (quiet)
log_sys_debug("open", name);
else
log_sys_error("open", name);
return 0;
}
#ifdef O_DIRECT_SUPPORT
opened:
if (direct)
dev->flags |= DEV_O_DIRECT_TESTED;
#endif
dev->open_count++;
dev->flags &= ~DEV_ACCESSED_W;
if ((flags & O_ACCMODE) == O_RDWR)
if (need_rw)
dev->flags |= DEV_OPENED_RW;
else
dev->flags &= ~DEV_OPENED_RW;
if (need_excl)
dev->flags |= DEV_OPENED_EXCL;
else
dev->flags &= ~DEV_OPENED_EXCL;
if (!(dev->flags & DEV_REGULAR) &&
((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;
}
@@ -370,8 +431,10 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet)
list_add(&_open_devices, &dev->open_list);
log_debug("Opened %s %s", dev_name(dev),
dev->flags & DEV_OPENED_RW ? "RW" : "RO");
log_debug("Opened %s %s%s%s", dev_name(dev),
dev->flags & DEV_OPENED_RW ? "RW" : "RO",
dev->flags & DEV_OPENED_EXCL ? " O_EXCL" : "",
dev->flags & DEV_O_DIRECT ? " O_DIRECT" : "");
return 1;
}
@@ -394,6 +457,21 @@ int dev_open(struct device *dev)
return dev_open_flags(dev, flags, 1, 0);
}
int dev_test_excl(struct device *dev)
{
int flags;
int r;
flags = vg_write_lock_held() ? O_RDWR : O_RDONLY;
flags |= O_EXCL;
r = dev_open_flags(dev, flags, 1, 1);
if (r)
dev_close_immediate(dev);
return r;
}
static void _close(struct device *dev)
{
if (close(dev->fd))
@@ -405,15 +483,17 @@ static void _close(struct device *dev)
log_debug("Closed %s", dev_name(dev));
if (dev->flags & DEV_ALLOCED) {
dbg_free((void *) list_item(dev->aliases.n, struct str_list)->
dm_free((void *) list_item(dev->aliases.n, struct str_list)->
str);
dbg_free(dev->aliases.n);
dbg_free(dev);
dm_free(dev->aliases.n);
dm_free(dev);
}
}
static int _dev_close(struct device *dev, int immediate)
{
struct lvmcache_info *info;
if (dev->fd < 0) {
log_error("Attempt to close device '%s' "
"which is not open.", dev_name(dev));
@@ -428,8 +508,16 @@ static int _dev_close(struct device *dev, int immediate)
if (dev->open_count > 0)
dev->open_count--;
/* FIXME lookup device in cache to get vgname and see if it's locked? */
if (immediate || (dev->open_count < 1 && !vgs_locked()))
if (immediate && dev->open_count)
log_debug("%s: Immediate close attempt while still referenced",
dev_name(dev));
/* Close unless device is known to belong to a locked VG */
if (immediate ||
(dev->open_count < 1 &&
(!(info = info_from_pvid(dev->pvid)) ||
!info->vginfo ||
!vgname_is_locked(info->vginfo->vgname))))
_close(dev);
return 1;
@@ -514,10 +602,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;
@@ -532,7 +620,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,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)) {
@@ -202,7 +202,7 @@ int _get_partition_type(struct dev_mgr *dm, struct device *d)
return 0;
}
if (!(buffer = dbg_malloc(SECTOR_SIZE))) {
if (!(buffer = dm_malloc(SECTOR_SIZE))) {
log_error("Failed to allocate partition table buffer");
return 0;
}

View File

@@ -17,12 +17,16 @@
#define _LVM_DEVICE_H
#include "uuid.h"
#include <fcntl.h>
#define DEV_ACCESSED_W 0x00000001 /* Device written to? */
#define DEV_REGULAR 0x00000002 /* Regular file? */
#define DEV_ALLOCED 0x00000004 /* dbg_malloc used */
#define DEV_ALLOCED 0x00000004 /* dm_malloc used */
#define DEV_OPENED_RW 0x00000008 /* Opened RW */
#define DEV_OPENED_EXCL 0x00000010 /* Opened EXCL */
#define DEV_O_DIRECT 0x00000020 /* Use O_DIRECT */
#define DEV_O_DIRECT_TESTED 0x00000040 /* DEV_O_DIRECT is reliable */
/*
* All devices in LVM will be represented by one of these.
@@ -41,6 +45,7 @@ struct device {
struct list open_list;
char pvid[ID_LEN + 1];
char _padding[7];
};
struct device_list {
@@ -63,30 +68,23 @@ int dev_get_sectsize(struct device *dev, uint32_t *size);
/* Use quiet version if device number could change e.g. when opening LV */
int dev_open(struct device *dev);
int dev_open_quiet(struct device *dev);
int dev_open_flags(struct device *dev, int flags, int append, int quiet);
int dev_open_flags(struct device *dev, int flags, int direct, int quiet);
int dev_close(struct device *dev);
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_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);
static inline const char *dev_name(const struct device *dev)
{
return (dev) ? list_item(dev->aliases.n, struct str_list)->str :
"unknown device";
}
struct str_list *alias, int use_malloc);
/* 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"},
@@ -151,14 +168,14 @@ const char *display_size(struct cmd_context *cmd, uint64_t size, size_len_t sl)
{" ", " ", " "},
};
if (!(size_buf = pool_alloc(cmd->mem, SIZE_BUF))) {
if (!(size_buf = dm_pool_alloc(cmd->mem, SIZE_BUF))) {
log_error("no memory for size display buffer");
return "";
}
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 -
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;
@@ -317,7 +350,7 @@ void lvdisplay_colons(struct logical_volume *lv)
{
int inkernel;
struct lvinfo info;
inkernel = lv_info(lv, &info) && info.exists;
inkernel = lv_info(lv->vg->cmd, lv, &info, 1) && info.exists;
log_print("%s%s/%s:%s:%d:%d:-1:%d:%" PRIu64 ":%d:-1:%d:%d:%d:%d",
lv->vg->cmd->dev_dir,
@@ -334,13 +367,12 @@ 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;
char uuid[64];
struct snapshot *snap = NULL;
struct list *slh, *snaplist;
int inkernel, snap_active = 0;
char uuid[64] __attribute((aligned(8)));
struct lv_segment *snap_seg = NULL;
float snap_percent; /* fused, fsize; */
if (!id_write_format(&lv->lvid.id[1], uuid, sizeof(uuid))) {
@@ -348,7 +380,7 @@ int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv,
return 0;
}
inkernel = lv_info(lv, &info) && info.exists;
inkernel = lv_info(cmd, lv, &info, 1) && info.exists;
log_print("--- Logical volume ---");
@@ -364,27 +396,30 @@ int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv,
if (lv_is_origin(lv)) {
log_print("LV snapshot status source of");
snaplist = find_snapshots(lv);
list_iterate(slh, snaplist) {
snap = list_item(slh, struct snapshot_list)->snapshot;
snap_active = lv_snapshot_percent(snap->cow,
&snap_percent);
if (!snap_active || snap_percent < 0 ||
snap_percent >= 100) snap_active = 0;
list_iterate_items_gen(snap_seg, &lv->snapshot_segs,
origin_list) {
if (inkernel &&
(snap_active = lv_snapshot_percent(snap_seg->cow,
&snap_percent)))
if (snap_percent < 0 || snap_percent >= 100)
snap_active = 0;
log_print(" %s%s/%s [%s]",
lv->vg->cmd->dev_dir, lv->vg->name,
snap->cow->name,
snap_seg->cow->name,
(snap_active > 0) ? "active" : "INACTIVE");
}
snap = NULL;
} else if ((snap = find_cow(lv))) {
snap_active = lv_snapshot_percent(lv, &snap_percent);
if (!snap_active || snap_percent < 0 || snap_percent >= 100)
snap_active = 0;
snap_seg = NULL;
} else if ((snap_seg = find_cow(lv))) {
if (inkernel &&
(snap_active = lv_snapshot_percent(snap_seg->cow,
&snap_percent)))
if (snap_percent < 0 || snap_percent >= 100)
snap_active = 0;
log_print("LV snapshot status %s destination for %s%s/%s",
(snap_active > 0) ? "active" : "INACTIVE",
lv->vg->cmd->dev_dir, lv->vg->name,
snap->origin->name);
snap_seg->origin->name);
}
if (inkernel && info.suspended)
@@ -402,15 +437,22 @@ int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv,
log_print("LV Size %s",
display_size(cmd,
snap ? snap->origin->size : lv->size,
SIZE_SHORT));
snap_seg ? snap_seg->origin->size : lv->size));
log_print("Current LE %u",
snap ? snap->origin->le_count : lv->le_count);
snap_seg ? snap_seg->origin->le_count : lv->le_count);
/********** FIXME allocation
log_print("Allocated LE %u", lv->allocated_le);
**********/
if (snap_seg) {
log_print("COW-table size %s",
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));
}
log_print("Segments %u", list_size(&lv->segments));
@@ -418,31 +460,6 @@ int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv,
log_print("Stripe size (KByte) %u", lv->stripesize / 2);
***********/
if (snap) {
if (snap_percent == -1)
snap_percent = 100;
log_print("Snapshot chunk size %s",
display_size(cmd, (uint64_t) snap->chunk_size,
SIZE_SHORT));
/*
size = display_size(lv->size, SIZE_SHORT);
sscanf(size, "%f", &fsize);
fused = fsize * snap_percent / 100;
*/
log_print("Allocated to snapshot %.2f%% ", /* [%.2f/%s]", */
snap_percent); /*, fused, size); */
/* dbg_free(size); */
}
/********** FIXME Snapshot
size = ???
log_print("Allocated to COW-table %s", size);
dbg_free(size);
}
******************/
log_print("Allocation %s", get_alloc_string(lv->alloc));
log_print("Read ahead sectors %u", lv->read_ahead);
@@ -463,27 +480,31 @@ int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv,
void display_stripe(const struct lv_segment *seg, uint32_t s, const char *pre)
{
switch (seg->area[s].type) {
switch (seg_type(seg, s)) {
case AREA_PV:
/* FIXME Re-check the conditions for 'Missing' */
log_print("%sPhysical volume\t%s", pre,
seg->area[s].u.pv.pv ?
dev_name(seg->area[s].u.pv.pv->dev) : "Missing");
seg_pv(seg, s) ?
dev_name(seg_dev(seg, s)) :
"Missing");
if (seg->area[s].u.pv.pv)
if (seg_pv(seg, s))
log_print("%sPhysical extents\t%d to %d", pre,
seg->area[s].u.pv.pe,
seg->area[s].u.pv.pe + seg->area_len - 1);
seg_pe(seg, s),
seg_pe(seg, s) + seg->area_len - 1);
break;
case AREA_LV:
log_print("%sLogical volume\t%s", pre,
seg->area[s].u.lv.lv ?
seg->area[s].u.lv.lv->name : "Missing");
seg_lv(seg, s) ?
seg_lv(seg, s)->name : "Missing");
if (seg->area[s].u.lv.lv)
if (seg_lv(seg, s))
log_print("%sLogical extents\t%d to %d", pre,
seg->area[s].u.lv.le,
seg->area[s].u.lv.le + seg->area_len - 1);
seg_le(seg, s),
seg_le(seg, s) + seg->area_len - 1);
break;
case AREA_UNASSIGNED:
log_print("%sUnassigned area", pre);
}
}
@@ -507,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;
}
@@ -516,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);
@@ -550,11 +571,11 @@ void vgdisplay_full(struct volume_group *vg)
vg->status & SHARED ? "yes" : "no");
}
log_print("MAX LV %u", vg->max_lv);
log_print("Cur LV %u", vg->lv_count);
log_print("Cur LV %u", vg->lv_count + vg->snapshot_count);
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);
@@ -563,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);
@@ -576,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;
@@ -598,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);
@@ -651,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

@@ -13,8 +13,6 @@
*/
#include "lib.h"
#include "pool.h"
#include "list.h"
#include "toolcontext.h"
#include "segtype.h"
#include "display.h"
@@ -25,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;
@@ -40,62 +39,72 @@ static int _merge_segments(struct lv_segment *seg1, struct lv_segment *seg2)
}
#ifdef DEVMAPPER_SUPPORT
static int _compose_target_line(struct dev_manager *dm, struct pool *mem,
struct config_tree *cft, void **target_state,
struct lv_segment *seg, char *params,
size_t paramsize, const char **target, int *pos,
uint32_t *pvmove_mirror_count)
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 __attribute((unused)))
{
/* error */
return dm_tree_node_add_error_target(node, len);
}
*target = "error";
*params = '\0';
static int _errseg_target_present(const struct lv_segment *seg __attribute((unused)))
{
static int _errseg_checked = 0;
static int _errseg_present = 0;
/* Reported truncated in older kernels */
if (!_errseg_checked &&
(target_present("error", 0) || target_present("erro", 0)))
_errseg_present = 1;
_errseg_checked = 1;
return _errseg_present;
}
#endif
static int _errseg_modules_needed(struct dm_pool *mem,
const struct lv_segment *seg,
struct list *modules)
{
if (!str_list_add(mem, modules, "error")) {
log_error("error module string list allocation failed");
return 0;
}
return 1;
}
static int _target_present(void)
static void _errseg_destroy(const struct segment_type *segtype)
{
static int checked = 0;
static int present = 0;
if (!checked)
present = target_present("error");
checked = 1;
return present;
}
#endif
static void _destroy(const struct segment_type *segtype)
{
dbg_free((void *) 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
compose_target_line:_compose_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)
{
struct segment_type *segtype = dbg_malloc(sizeof(*segtype));
struct segment_type *segtype = dm_malloc(sizeof(*segtype));
if (!segtype) {
stack;
return NULL;
}
if (!segtype)
return_NULL;
segtype->cmd = cmd;
segtype->ops = &_error_ops;
segtype->name = "error";
segtype->private = NULL;
segtype->flags = SEG_CAN_SPLIT | SEG_VIRTUAL;
segtype->flags = SEG_CAN_SPLIT | SEG_VIRTUAL | SEG_CANNOT_BE_ZEROED;
log_very_verbose("Initialised segtype: %s", segtype->name);

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;
@@ -42,8 +42,8 @@ static void _destroy(struct dev_filter *f)
filters++;
}
dbg_free(f->private);
dbg_free(f);
dm_free(f->private);
dm_free(f);
}
struct dev_filter *composite_filter_create(int n, struct dev_filter **filters)
@@ -55,7 +55,7 @@ struct dev_filter *composite_filter_create(int n, struct dev_filter **filters)
return NULL;
}
if (!(filters_copy = dbg_malloc(sizeof(*filters) * (n + 1)))) {
if (!(filters_copy = dm_malloc(sizeof(*filters) * (n + 1)))) {
log_error("composite filters allocation failed");
return NULL;
}
@@ -63,14 +63,14 @@ struct dev_filter *composite_filter_create(int n, struct dev_filter **filters)
memcpy(filters_copy, filters, sizeof(*filters) * n);
filters_copy[n] = NULL;
if (!(cft = dbg_malloc(sizeof(*cft)))) {
if (!(cft = dm_malloc(sizeof(*cft)))) {
log_error("compsoite filters allocation failed");
dbg_free(filters_copy);
dm_free(filters_copy);
return NULL;
}
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;
@@ -51,14 +43,14 @@ static int _ignore_md(struct dev_filter *f, struct device *dev)
static void _destroy(struct dev_filter *f)
{
dbg_free(f);
dm_free(f);
}
struct dev_filter *md_filter_create(void)
{
struct dev_filter *f;
if (!(f = dbg_malloc(sizeof(*f)))) {
if (!(f = dm_malloc(sizeof(*f)))) {
log_error("md filter allocation failed");
return NULL;
}

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.
*
@@ -16,8 +16,8 @@
#include "lib.h"
#include "config.h"
#include "dev-cache.h"
#include "hash.h"
#include "filter-persistent.h"
#include "lvm-file.h"
#include <sys/stat.h>
#include <fcntl.h>
@@ -25,13 +25,14 @@
struct pfilter {
char *file;
struct hash_table *devices;
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)
@@ -39,9 +40,9 @@ struct pfilter {
static int _init_hash(struct pfilter *pf)
{
if (pf->devices)
hash_destroy(pf->devices);
dm_hash_destroy(pf->devices);
if (!(pf->devices = hash_create(128))) {
if (!(pf->devices = dm_hash_create(128))) {
stack;
return 0;
}
@@ -53,7 +54,9 @@ int persistent_filter_wipe(struct dev_filter *f)
{
struct pfilter *pf = (struct pfilter *) f->private;
hash_wipe(pf->devices);
log_verbose("Wiping cache of LVM-capable devices");
dm_hash_wipe(pf->devices);
/* Trigger complete device scan */
dev_cache_scan(1);
@@ -83,7 +86,7 @@ static int _read_array(struct pfilter *pf, struct config_tree *cft,
continue;
}
if (!hash_insert(pf->devices, cv->v.str, data))
if (!dm_hash_insert(pf->devices, cv->v.str, data))
log_verbose("Couldn't add '%s' to filter ... ignoring",
cv->v.str);
/* Populate dev_cache ourselves */
@@ -92,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);
@@ -116,7 +123,7 @@ int persistent_filter_load(struct dev_filter *f)
PF_BAD_DEVICE); */
/* Did we find anything? */
if (hash_get_num_entries(pf->devices)) {
if (dm_hash_get_num_entries(pf->devices)) {
/* We populated dev_cache ourselves */
dev_cache_scan(0);
r = 1;
@@ -125,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;
}
@@ -134,11 +144,11 @@ static void _write_array(struct pfilter *pf, FILE *fp, const char *path,
{
void *d;
int first = 1;
struct hash_node *n;
struct dm_hash_node *n;
for (n = hash_get_first(pf->devices); n;
n = hash_get_next(pf->devices, n)) {
d = hash_get_data(pf->devices, n);
for (n = dm_hash_get_first(pf->devices); n;
n = dm_hash_get_next(pf->devices, n)) {
d = dm_hash_get_data(pf->devices, n);
if (d != data)
continue;
@@ -150,7 +160,7 @@ static void _write_array(struct pfilter *pf, FILE *fp, const char *path,
first = 0;
}
fprintf(fp, "\t\t\"%s\"", hash_get_key(pf->devices, n));
fprintf(fp, "\t\t\"%s\"", dm_hash_get_key(pf->devices, n));
}
if (!first)
@@ -162,10 +172,14 @@ 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 (!hash_get_num_entries(pf->devices)) {
if (!dm_hash_get_num_entries(pf->devices)) {
log_very_verbose("Internal persistent device cache empty "
"- not writing to %s", pf->file);
return 0;
@@ -178,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,39 +240,50 @@ int persistent_filter_dump(struct dev_filter *f)
fprintf(fp, "}\n");
fclose(fp);
return 1;
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)
{
struct pfilter *pf = (struct pfilter *) f->private;
void *l = hash_lookup(pf->devices, dev_name(dev));
void *l = dm_hash_lookup(pf->devices, dev_name(dev));
struct str_list *sl;
struct list *ah;
if (!l) {
l = pf->real->passes_filter(pf->real, dev) ?
PF_GOOD_DEVICE : PF_BAD_DEVICE;
list_iterate(ah, &dev->aliases) {
sl = list_item(ah, struct str_list);
hash_insert(pf->devices, sl->str, l);
}
list_iterate_items(sl, &dev->aliases)
dm_hash_insert(pf->devices, sl->str, l);
} else if (l == PF_BAD_DEVICE)
log_debug("%s: Skipping (cached)", dev_name(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;
hash_destroy(pf->devices);
dbg_free(pf->file);
dm_hash_destroy(pf->devices);
dm_free(pf->file);
pf->real->destroy(pf->real);
dbg_free(pf);
dbg_free(f);
dm_free(pf);
dm_free(f);
}
struct dev_filter *persistent_filter_create(struct dev_filter *real,
@@ -235,13 +292,13 @@ struct dev_filter *persistent_filter_create(struct dev_filter *real,
struct pfilter *pf;
struct dev_filter *f = NULL;
if (!(pf = dbg_malloc(sizeof(*pf)))) {
if (!(pf = dm_malloc(sizeof(*pf)))) {
stack;
return NULL;
}
memset(pf, 0, sizeof(*pf));
if (!(pf->file = dbg_malloc(strlen(file) + 1))) {
if (!(pf->file = dm_malloc(strlen(file) + 1))) {
stack;
goto bad;
}
@@ -253,22 +310,22 @@ struct dev_filter *persistent_filter_create(struct dev_filter *real,
goto bad;
}
if (!(f = dbg_malloc(sizeof(*f)))) {
if (!(f = dm_malloc(sizeof(*f)))) {
stack;
goto bad;
}
f->passes_filter = _lookup_p;
f->destroy = _destroy;
f->destroy = _persistent_destroy;
f->private = pf;
return f;
bad:
dbg_free(pf->file);
dm_free(pf->file);
if (pf->devices)
hash_destroy(pf->devices);
dbg_free(pf);
dbg_free(f);
dm_hash_destroy(pf->devices);
dm_free(pf);
dm_free(f);
return NULL;
}

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

@@ -14,21 +14,18 @@
*/
#include "lib.h"
#include "pool.h"
#include "filter-regex.h"
#include "matcher.h"
#include "device.h"
#include "bitset.h"
#include "list.h"
struct rfilter {
struct pool *mem;
bitset_t accept;
struct dm_pool *mem;
dm_bitset_t accept;
struct matcher *engine;
};
static int _extract_pattern(struct pool *mem, const char *pat,
char **regex, bitset_t accept, int ix)
static int _extract_pattern(struct dm_pool *mem, const char *pat,
char **regex, dm_bitset_t accept, int ix)
{
char sep, *r, *ptr;
@@ -37,11 +34,11 @@ static int _extract_pattern(struct pool *mem, const char *pat,
*/
switch (*pat) {
case 'a':
bit_set(accept, ix);
dm_bit_set(accept, ix);
break;
case 'r':
bit_clear(accept, ix);
dm_bit_clear(accept, ix);
break;
default:
@@ -74,7 +71,7 @@ static int _extract_pattern(struct pool *mem, const char *pat,
/*
* copy the regex
*/
if (!(r = pool_strdup(mem, pat))) {
if (!(r = dm_pool_strdup(mem, pat))) {
stack;
return 0;
}
@@ -95,13 +92,13 @@ static int _extract_pattern(struct pool *mem, const char *pat,
static int _build_matcher(struct rfilter *rf, struct config_value *val)
{
struct pool *scratch;
struct dm_pool *scratch;
struct config_value *v;
char **regex;
unsigned count = 0;
int i, r = 0;
if (!(scratch = pool_create("filter matcher", 1024))) {
if (!(scratch = dm_pool_create("filter matcher", 1024))) {
stack;
return 0;
}
@@ -122,7 +119,7 @@ static int _build_matcher(struct rfilter *rf, struct config_value *val)
/*
* allocate space for them
*/
if (!(regex = pool_alloc(scratch, sizeof(*regex) * count))) {
if (!(regex = dm_pool_alloc(scratch, sizeof(*regex) * count))) {
stack;
goto out;
}
@@ -130,7 +127,7 @@ static int _build_matcher(struct rfilter *rf, struct config_value *val)
/*
* create the accept/reject bitset
*/
rf->accept = bitset_create(rf->mem, count);
rf->accept = dm_bitset_create(rf->mem, count);
/*
* fill the array back to front because we
@@ -152,23 +149,21 @@ static int _build_matcher(struct rfilter *rf, struct config_value *val)
r = 1;
out:
pool_destroy(scratch);
dm_pool_destroy(scratch);
return r;
}
static int _accept_p(struct dev_filter *f, struct device *dev)
{
struct list *ah;
int m, first = 1, rejected = 0;
struct rfilter *rf = (struct rfilter *) f->private;
struct str_list *sl;
list_iterate(ah, &dev->aliases) {
sl = list_item(ah, struct str_list);
list_iterate_items(sl, &dev->aliases) {
m = matcher_run(rf->engine, sl->str);
if (m >= 0) {
if (bit(rf->accept, m)) {
if (dm_bit(rf->accept, m)) {
if (!first) {
log_debug("%s: New preferred name",
@@ -196,15 +191,15 @@ 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;
pool_destroy(rf->mem);
dm_pool_destroy(rf->mem);
}
struct dev_filter *regex_filter_create(struct config_value *patterns)
{
struct pool *mem = pool_create("filter regex", 10 * 1024);
struct dm_pool *mem = dm_pool_create("filter regex", 10 * 1024);
struct rfilter *rf;
struct dev_filter *f;
@@ -213,7 +208,7 @@ struct dev_filter *regex_filter_create(struct config_value *patterns)
return NULL;
}
if (!(rf = pool_alloc(mem, sizeof(*rf)))) {
if (!(rf = dm_pool_alloc(mem, sizeof(*rf)))) {
stack;
goto bad;
}
@@ -225,17 +220,17 @@ struct dev_filter *regex_filter_create(struct config_value *patterns)
goto bad;
}
if (!(f = pool_zalloc(mem, sizeof(*f)))) {
if (!(f = dm_pool_zalloc(mem, sizeof(*f)))) {
stack;
goto bad;
}
f->passes_filter = _accept_p;
f->destroy = _destroy;
f->destroy = _regex_destroy;
f->private = rf;
return f;
bad:
pool_destroy(mem);
dm_pool_destroy(mem);
return NULL;
}

View File

@@ -15,7 +15,6 @@
#include "lib.h"
#include "filter-sysfs.h"
#include "lvm-string.h"
#include "pool.h"
#ifdef linux
@@ -33,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;
@@ -45,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;
}
@@ -69,27 +68,27 @@ struct entry {
#define SET_BUCKETS 64
struct dev_set {
struct pool *mem;
struct dm_pool *mem;
const char *sys_block;
int initialised;
struct entry *slots[SET_BUCKETS];
};
static struct dev_set *_dev_set_create(struct pool *mem, const char *sys_block)
static struct dev_set *_dev_set_create(struct dm_pool *mem, const char *sys_block)
{
struct dev_set *ds;
if (!(ds = pool_zalloc(mem, sizeof(*ds))))
if (!(ds = dm_pool_zalloc(mem, sizeof(*ds))))
return NULL;
ds->mem = mem;
ds->sys_block = pool_strdup(mem, sys_block);
ds->sys_block = dm_pool_strdup(mem, sys_block);
ds->initialised = 0;
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);
}
@@ -102,7 +101,7 @@ static int _set_insert(struct dev_set *ds, dev_t dev)
struct entry *e;
unsigned h = _hash_dev(dev);
if (!(e = pool_alloc(ds->mem, sizeof(*e))))
if (!(e = dm_pool_alloc(ds->mem, sizeof(*e))))
return 0;
e->next = ds->slots[h];
@@ -172,7 +171,7 @@ static int _read_devs(struct dev_set *ds, const char *dir)
unsigned char dtype;
struct stat info;
char path[PATH_MAX];
dev_t dev;
dev_t dev = { 0 };
int r = 1;
if (!(dr = opendir(dir))) {
@@ -184,7 +183,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);
@@ -258,20 +257,20 @@ static int _accept_p(struct dev_filter *f, struct device *dev)
static void _destroy(struct dev_filter *f)
{
struct dev_set *ds = (struct dev_set *) f->private;
pool_destroy(ds->mem);
dm_pool_destroy(ds->mem);
}
struct dev_filter *sysfs_filter_create(const char *proc)
{
char sys_block[PATH_MAX];
struct pool *mem;
struct dm_pool *mem;
struct dev_set *ds;
struct dev_filter *f;
if (!_locate_sysfs_blocks(proc, sys_block, sizeof(sys_block)))
return NULL;
if (!(mem = pool_create("sysfs", 256))) {
if (!(mem = dm_pool_create("sysfs", 256))) {
log_error("sysfs pool creation failed");
return NULL;
}
@@ -281,7 +280,7 @@ struct dev_filter *sysfs_filter_create(const char *proc)
goto bad;
}
if (!(f = pool_zalloc(mem, sizeof(*f)))) {
if (!(f = dm_pool_zalloc(mem, sizeof(*f)))) {
stack;
goto bad;
}
@@ -292,7 +291,7 @@ struct dev_filter *sysfs_filter_create(const char *proc)
return f;
bad:
pool_destroy(mem);
dm_pool_destroy(mem);
return NULL;
}

View File

@@ -28,7 +28,6 @@
#define NUMBER_OF_MAJORS 4096
/* FIXME Make this sparse */
/* 0 means LVM won't use this major number. */
static int _max_partitions_by_major[NUMBER_OF_MAJORS];
@@ -69,6 +68,11 @@ static const device_info_t device_info[] = {
{"power2", 16}, /* EMC Powerpath */
{"i2o_block", 16}, /* i2o Block Disk */
{"iseries/vd", 8}, /* iSeries disks */
{"gnbd", 1}, /* Network block device */
{"ramdisk", 1}, /* RAM disk */
{"aoe", 16}, /* ATA over Ethernet */
{"device-mapper", 1}, /* Other mapped devices */
{"xvd", 16}, /* Xen virtual block device */
{NULL, 0}
};
@@ -87,7 +91,7 @@ static int _passes_lvm_type_device_filter(struct dev_filter *f,
}
/* Check it's accessible */
if (!dev_open_flags(dev, O_RDONLY, 0, 0)) {
if (!dev_open_flags(dev, O_RDONLY, 0, 1)) {
log_debug("%s: Skipping: open failed", name);
return 0;
}
@@ -141,7 +145,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;
@@ -200,6 +204,7 @@ 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");
fclose(pd);
return 0;
}
dev_len = strlen(cv->v.str);
@@ -209,12 +214,14 @@ 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);
fclose(pd);
return 0;
}
if (!cv->v.i) {
log_error("Zero partition count invalid for "
"%s in devices/types in config file",
name);
fclose(pd);
return 0;
}
if (dev_len <= strlen(line + i) &&
@@ -239,7 +246,7 @@ struct dev_filter *lvm_type_filter_create(const char *proc,
{
struct dev_filter *f;
if (!(f = dbg_malloc(sizeof(struct dev_filter)))) {
if (!(f = dm_malloc(sizeof(struct dev_filter)))) {
log_error("LVM type filter allocation failed");
return NULL;
}
@@ -250,6 +257,7 @@ struct dev_filter *lvm_type_filter_create(const char *proc,
if (!_scan_proc_dev(proc, cn)) {
stack;
dm_free(f);
return NULL;
}
@@ -258,6 +266,6 @@ struct dev_filter *lvm_type_filter_create(const char *proc,
void lvm_type_filter_destroy(struct dev_filter *f)
{
dbg_free(f);
dm_free(f);
return;
}

View File

@@ -36,7 +36,6 @@ struct dev_filter *lvm_type_filter_create(const char *proc,
void lvm_type_filter_destroy(struct dev_filter *f);
int md_major(void);
int max_partitions(int major);
#endif

View File

@@ -15,7 +15,6 @@
#include "lib.h"
#include "disk-rep.h"
#include "pool.h"
#include "xlate.h"
#include "filter.h"
#include "lvmcache.h"
@@ -103,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);
@@ -117,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:
@@ -154,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;
}
@@ -173,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;
}
@@ -224,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);
@@ -238,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;
@@ -255,7 +256,7 @@ static int _read_uuids(struct disk_list *data)
if (!dev_read(data->dev, pos, sizeof(buffer), buffer))
fail;
if (!(ul = pool_alloc(data->mem, sizeof(*ul))))
if (!(ul = dm_pool_alloc(data->mem, sizeof(*ul))))
fail;
memcpy(ul->uuid, buffer, NAME_LEN);
@@ -270,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');
}
@@ -284,7 +285,7 @@ static int _read_lvs(struct disk_list *data)
for (i = 0; (i < vgd->lv_max) && (read < vgd->lv_cur); i++) {
pos = data->pvd.lv_on_disk.base + (i * sizeof(struct lv_disk));
ll = pool_alloc(data->mem, sizeof(*ll));
ll = dm_pool_alloc(data->mem, sizeof(*ll));
if (!ll)
fail;
@@ -305,7 +306,7 @@ static int _read_lvs(struct disk_list *data)
static int _read_extents(struct disk_list *data)
{
size_t len = sizeof(struct pe_disk) * data->pvd.pe_total;
struct pe_disk *extents = pool_alloc(data->mem, len);
struct pe_disk *extents = dm_pool_alloc(data->mem, len);
uint64_t pos = data->pvd.pe_on_disk.base;
if (!extents)
@@ -320,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 pool *mem,
struct device *dev, struct dm_pool *mem,
const char *vg_name)
{
struct disk_list *dl = 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;
@@ -343,41 +362,32 @@ static struct disk_list *__read_disk(const struct format_type *fmt,
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;
}
/*
* is it an orphan ?
*/
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;
@@ -400,12 +410,12 @@ static struct disk_list *__read_disk(const struct format_type *fmt,
return dl;
bad:
pool_free(dl->mem, dl);
dm_pool_free(dl->mem, dl);
return NULL;
}
struct disk_list *read_disk(const struct format_type *fmt, struct device *dev,
struct pool *mem, const char *vg_name)
struct dm_pool *mem, const char *vg_name)
{
struct disk_list *r;
@@ -424,12 +434,12 @@ struct disk_list *read_disk(const struct format_type *fmt, struct device *dev,
static void _add_pv_to_list(struct list *head, struct disk_list *data)
{
struct list *pvdh;
struct pv_disk *pvd;
struct disk_list *diskl;
list_iterate(pvdh, head) {
pvd = &list_item(pvdh, struct disk_list)->pvd;
if (!strncmp(data->pvd.pv_uuid, pvd->pv_uuid,
list_iterate_items(diskl, head) {
pvd = &diskl->pvd;
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 "
@@ -439,7 +449,7 @@ static void _add_pv_to_list(struct list *head, struct disk_list *data)
}
log_very_verbose("Duplicate PV %s - using md %s",
pvd->pv_uuid, dev_name(data->dev));
list_del(pvdh);
list_del(&diskl->list);
break;
}
}
@@ -448,24 +458,24 @@ 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,
struct dev_filter *filter, struct pool *mem,
struct dev_filter *filter, struct dm_pool *mem,
struct list *head)
{
struct dev_iter *iter;
struct device *dev;
struct disk_list *data = NULL;
struct list *vgih;
struct lvmcache_vginfo *vginfo;
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(vgih, &vginfo->infos) {
dev = list_item(vgih, struct lvmcache_info)->dev;
list_iterate_items(info, &vginfo->infos) {
dev = info->dev;
if (dev && !(data = read_disk(fmt, dev, mem, vg_name)))
break;
_add_pv_to_list(head, data);
@@ -482,7 +492,7 @@ int read_pvs_in_vg(const struct format_type *fmt, const char *vg_name,
/* vgcache_del(vg_name); */
}
if (!(iter = dev_iter_create(filter))) {
if (!(iter = dev_iter_create(filter, 1))) {
log_error("read_pvs_in_vg: dev_iter_create failed");
return 0;
}
@@ -506,6 +516,9 @@ static int _write_vgd(struct disk_list *data)
struct vg_disk *vgd = &data->vgd;
uint64_t pos = data->pvd.vg_on_disk.base;
log_debug("Writing %s VG metadata to %s at %" PRIu64 " len %" PRIsize_t,
data->pvd.vg_name, dev_name(data->dev), pos, sizeof(*vgd));
_xlate_vgd(vgd);
if (!dev_write(data->dev, pos, sizeof(*vgd), vgd))
fail;
@@ -518,18 +531,20 @@ static int _write_vgd(struct disk_list *data)
static int _write_uuids(struct disk_list *data)
{
struct uuid_list *ul;
struct list *uh;
uint64_t pos = data->pvd.pv_uuidlist_on_disk.base;
uint64_t end = pos + data->pvd.pv_uuidlist_on_disk.size;
list_iterate(uh, &data->uuids) {
list_iterate_items(ul, &data->uuids) {
if (pos >= end) {
log_error("Too many uuids to fit on %s",
dev_name(data->dev));
return 0;
}
ul = list_item(uh, struct uuid_list);
log_debug("Writing %s uuidlist to %s at %" PRIu64 " len %d",
data->pvd.vg_name, dev_name(data->dev),
pos, NAME_LEN);
if (!dev_write(data->dev, pos, NAME_LEN, ul->uuid))
fail;
@@ -541,6 +556,10 @@ static int _write_uuids(struct disk_list *data)
static int _write_lvd(struct device *dev, uint64_t pos, struct lv_disk *disk)
{
log_debug("Writing %s LV %s metadata to %s at %" PRIu64 " len %"
PRIsize_t, disk->vg_name, disk->lv_name, dev_name(dev),
pos, sizeof(*disk));
_xlate_lvd(disk);
if (!dev_write(dev, pos, sizeof(*disk), disk))
fail;
@@ -552,20 +571,18 @@ static int _write_lvd(struct device *dev, uint64_t pos, struct lv_disk *disk)
static int _write_lvs(struct disk_list *data)
{
struct list *lvh;
struct lvd_list *ll;
uint64_t pos, offset;
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;
}
list_iterate(lvh, &data->lvds) {
struct lvd_list *ll = list_item(lvh, struct lvd_list);
list_iterate_items(ll, &data->lvds) {
offset = sizeof(struct lv_disk) * ll->lvd.lv_number;
if (offset + sizeof(struct lv_disk) > data->pvd.lv_on_disk.size) {
log_error("lv_number %d too large", ll->lvd.lv_number);
@@ -585,6 +602,10 @@ static int _write_extents(struct disk_list *data)
struct pe_disk *extents = data->extents;
uint64_t pos = data->pvd.pe_on_disk.base;
log_debug("Writing %s extents metadata to %s at %" PRIu64 " len %"
PRIsize_t, data->pvd.vg_name, dev_name(data->dev),
pos, len);
_xlate_extents(extents, data->pvd.pe_total);
if (!dev_write(data->dev, pos, len, extents))
fail;
@@ -608,7 +629,7 @@ static int _write_pvd(struct disk_list *data)
/* Make sure that the gap between the PV structure and
the next one is zeroed in order to make non LVM tools
happy (idea from AED) */
buf = dbg_malloc(size);
buf = dm_malloc(size);
if (!buf) {
log_err("Couldn't allocate temporary PV buffer.");
return 0;
@@ -617,13 +638,17 @@ static int _write_pvd(struct disk_list *data)
memset(buf, 0, size);
memcpy(buf, &data->pvd, sizeof(struct pv_disk));
log_debug("Writing %s PV metadata to %s at %" PRIu64 " len %"
PRIsize_t, data->pvd.vg_name, dev_name(data->dev),
pos, size);
_xlate_pvd((struct pv_disk *) buf);
if (!dev_write(data->dev, pos, size, buf)) {
dbg_free(buf);
dm_free(buf);
fail;
}
dbg_free(buf);
dm_free(buf);
return 1;
}
@@ -704,11 +729,9 @@ static int _write_all_pvd(const struct format_type *fmt, struct disk_list *data)
*/
int write_disks(const struct format_type *fmt, struct list *pvs)
{
struct list *pvh;
struct disk_list *dl;
list_iterate(pvh, pvs) {
dl = list_item(pvh, struct disk_list);
list_iterate_items(dl, pvs) {
if (!(_write_all_pvd(fmt, dl)))
fail;

View File

@@ -18,7 +18,6 @@
#include "lvm-types.h"
#include "metadata.h"
#include "pool.h"
#include "toolcontext.h"
#define MAX_PV 256
@@ -74,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;
@@ -99,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;
@@ -123,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 */
@@ -149,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 {
@@ -159,20 +158,21 @@ struct lvd_list {
struct disk_list {
struct list list;
struct pool *mem;
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
@@ -191,11 +191,11 @@ int calculate_extent_count(struct physical_volume *pv, uint32_t extent_size,
*/
struct disk_list *read_disk(const struct format_type *fmt, struct device *dev,
struct pool *mem, const char *vg_name);
struct dm_pool *mem, const char *vg_name);
int read_pvs_in_vg(const struct format_type *fmt, const char *vg_name,
struct dev_filter *filter,
struct pool *mem, struct list *results);
struct dm_pool *mem, struct list *results);
int write_disks(const struct format_type *fmt, struct list *pvds);
@@ -203,33 +203,34 @@ 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 pool *mem, struct device *dev,
struct volume_group *vg,
struct physical_volume *pv, struct pv_disk *pvd);
int export_pv(struct cmd_context *cmd, struct pool *mem,
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);
int import_vg(struct pool *mem,
int import_vg(struct dm_pool *mem,
struct volume_group *vg, struct disk_list *dl, int partial);
int export_vg(struct vg_disk *vgd, struct volume_group *vg);
int import_lv(struct pool *mem, struct logical_volume *lv, struct lv_disk *lvd);
int import_lv(struct dm_pool *mem, struct logical_volume *lv, struct lv_disk *lvd);
int import_extents(struct cmd_context *cmd, struct volume_group *vg,
struct list *pvds);
int export_extents(struct disk_list *dl, uint32_t lv_num,
struct logical_volume *lv, struct physical_volume *pv);
int import_pvs(const struct format_type *fmt, struct pool *mem,
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 pool *mem, struct volume_group *vg, struct list *pvds);
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,
struct physical_volume *pv, const char *dev_dir);
int import_snapshots(struct pool *mem, struct volume_group *vg,
int import_snapshots(struct dm_pool *mem, struct volume_group *vg,
struct list *pvds);
int export_uuids(struct disk_list *dl, struct volume_group *vg);
@@ -238,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

@@ -15,10 +15,7 @@
#include "lib.h"
#include "disk-rep.h"
#include "pool.h"
#include "hash.h"
#include "limits.h"
#include "list.h"
#include "display.h"
#include "toolcontext.h"
#include "lvmcache.h"
@@ -46,9 +43,7 @@ static int _check_vgs(struct list *pvs, int *partial)
* This means an active VG won't be affected if disks are inserted
* bearing an exported VG with the same name.
*/
list_iterate(pvh, pvs) {
dl = list_item(pvh, struct disk_list);
list_iterate_items(dl, pvs) {
if (first_time) {
exported = dl->pvd.pv_status & VG_EXPORTED;
first_time = 0;
@@ -130,8 +125,8 @@ static int _check_vgs(struct list *pvs, int *partial)
static struct volume_group *_build_vg(struct format_instance *fid,
struct list *pvs)
{
struct pool *mem = fid->fmt->cmd->mem;
struct volume_group *vg = pool_alloc(mem, sizeof(*vg));
struct dm_pool *mem = fid->fmt->cmd->mem;
struct volume_group *vg = dm_pool_alloc(mem, sizeof(*vg));
struct disk_list *dl;
int partial;
@@ -148,7 +143,6 @@ static struct volume_group *_build_vg(struct format_instance *fid,
vg->seqno = 0;
list_init(&vg->pvs);
list_init(&vg->lvs);
list_init(&vg->snapshots);
list_init(&vg->tags);
if (!_check_vgs(pvs, &partial))
@@ -175,15 +169,15 @@ static struct volume_group *_build_vg(struct format_instance *fid,
bad:
stack;
pool_free(mem, vg);
dm_pool_free(mem, vg);
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)
{
struct pool *mem = pool_create("lvm1 vg_read", 1024 * 10);
struct dm_pool *mem = dm_pool_create("lvm1 vg_read", 1024 * 10);
struct list pvs;
struct volume_group *vg = NULL;
list_init(&pvs);
@@ -208,16 +202,16 @@ static struct volume_group *_vg_read(struct format_instance *fid,
}
bad:
pool_destroy(mem);
dm_pool_destroy(mem);
return vg;
}
static struct disk_list *_flatten_pv(struct format_instance *fid,
struct pool *mem, struct volume_group *vg,
struct dm_pool *mem, struct volume_group *vg,
struct physical_volume *pv,
const char *dev_dir)
{
struct disk_list *dl = pool_alloc(mem, sizeof(*dl));
struct disk_list *dl = dm_pool_alloc(mem, sizeof(*dl));
if (!dl) {
stack;
@@ -235,25 +229,22 @@ static struct disk_list *_flatten_pv(struct format_instance *fid,
!export_uuids(dl, vg) ||
!export_lvs(dl, vg, pv, dev_dir) || !calculate_layout(dl)) {
stack;
pool_free(mem, dl);
dm_pool_free(mem, dl);
return NULL;
}
return dl;
}
static int _flatten_vg(struct format_instance *fid, struct pool *mem,
static int _flatten_vg(struct format_instance *fid, struct dm_pool *mem,
struct volume_group *vg,
struct list *pvds, const char *dev_dir,
struct dev_filter *filter)
{
struct list *pvh;
struct pv_list *pvl;
struct disk_list *data;
list_iterate(pvh, &vg->pvs) {
pvl = list_item(pvh, struct pv_list);
list_iterate_items(pvl, &vg->pvs) {
if (!(data = _flatten_pv(fid, mem, vg, pvl->pv, dev_dir))) {
stack;
return 0;
@@ -273,10 +264,10 @@ static int _flatten_vg(struct format_instance *fid, struct 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 pool *mem = pool_create("lvm1 vg_write", 1024 * 10);
struct dm_pool *mem = dm_pool_create("lvm1 vg_write", 1024 * 10);
struct list pvds;
int r = 0;
@@ -292,14 +283,14 @@ static int _vg_write(struct format_instance *fid, struct volume_group *vg,
write_disks(fid->fmt, &pvds));
lvmcache_update_vg(vg);
pool_destroy(mem);
dm_pool_destroy(mem);
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 pool *mem = pool_create("lvm1 pv_read", 1024);
struct dm_pool *mem = dm_pool_create("lvm1 pv_read", 1024);
struct disk_list *dl;
struct device *dev;
int r = 0;
@@ -321,7 +312,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;
}
@@ -331,11 +322,11 @@ static int _pv_read(const struct format_type *fmt, const char *pv_name,
r = 1;
out:
pool_destroy(mem);
dm_pool_destroy(mem);
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,
@@ -346,8 +337,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;
}
@@ -373,7 +363,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;
@@ -387,25 +377,24 @@ 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 pool *mem;
struct dm_pool *mem;
struct disk_list *dl;
struct list pvs;
struct label *label;
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;
}
@@ -419,14 +408,14 @@ 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 = pool_create("lvm1 pv_write", 1024))) {
if (!(mem = dm_pool_create("lvm1 pv_write", 1024))) {
stack;
return 0;
}
if (!(dl = pool_alloc(mem, sizeof(*dl)))) {
if (!(dl = dm_pool_alloc(mem, sizeof(*dl)))) {
stack;
goto bad;
}
@@ -442,7 +431,7 @@ static int _pv_write(const struct format_type *fmt, struct physical_volume *pv,
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)) {
@@ -450,15 +439,15 @@ static int _pv_write(const struct format_type *fmt, struct physical_volume *pv,
goto bad;
}
pool_destroy(mem);
dm_pool_destroy(mem);
return 1;
bad:
pool_destroy(mem);
dm_pool_destroy(mem);
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)
@@ -469,18 +458,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;
}
@@ -493,8 +479,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;
@@ -505,18 +491,19 @@ 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;
struct metadata_area *mda;
if (!(fid = pool_alloc(fmt->cmd->mem, sizeof(*fid)))) {
if (!(fid = dm_pool_alloc(fmt->cmd->mem, sizeof(*fid)))) {
stack;
return NULL;
}
@@ -525,9 +512,9 @@ static struct format_instance *_create_instance(const struct format_type *fmt,
list_init(&fid->metadata_areas);
/* Define a NULL metadata area */
if (!(mda = pool_alloc(fmt->cmd->mem, sizeof(*mda)))) {
if (!(mda = dm_pool_alloc(fmt->cmd->mem, sizeof(*mda)))) {
stack;
pool_free(fmt->cmd->mem, fid);
dm_pool_free(fmt->cmd->mem, fid);
return NULL;
}
@@ -538,26 +525,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)
{
dbg_free((void *) 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
@@ -567,7 +554,7 @@ struct format_type *init_format(struct cmd_context *cmd);
struct format_type *init_format(struct cmd_context *cmd)
#endif
{
struct format_type *fmt = dbg_malloc(sizeof(*fmt));
struct format_type *fmt = dm_malloc(sizeof(*fmt));
if (!fmt) {
stack;

View File

@@ -19,13 +19,12 @@
#include "lib.h"
#include "disk-rep.h"
#include "pool.h"
#include "hash.h"
#include "list.h"
#include "lvm-string.h"
#include "filter.h"
#include "toolcontext.h"
#include "segtype.h"
#include "pv_alloc.h"
#include "display.h"
#include <time.h>
@@ -37,7 +36,7 @@ static int _check_vg_name(const char *name)
/*
* Extracts the last part of a path.
*/
static char *_create_lv_name(struct pool *mem, const char *full_name)
static char *_create_lv_name(struct dm_pool *mem, const char *full_name)
{
const char *ptr = strrchr(full_name, '/');
@@ -46,28 +45,33 @@ static char *_create_lv_name(struct pool *mem, const char *full_name)
else
ptr++;
return pool_strdup(mem, ptr);
return dm_pool_strdup(mem, ptr);
}
int import_pv(struct 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 = 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,9 +90,34 @@ int import_pv(struct pool *mem, struct device *dev,
pv->pe_size = pvd->pe_size;
pv->pe_start = pvd->pe_start;
pv->pe_count = pvd->pe_total;
pv->pe_alloc_count = pvd->pe_allocated;
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);
if (!alloc_pv_segment_whole_pv(mem, pv)) {
stack;
return 0;
}
return 1;
}
@@ -96,7 +125,7 @@ int import_pv(struct 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;
@@ -105,7 +134,7 @@ static int _system_id(struct cmd_context *cmd, char *s, const char *prefix)
return 1;
}
int export_pv(struct cmd_context *cmd, struct pool *mem,
int export_pv(struct cmd_context *cmd, struct dm_pool *mem,
struct volume_group *vg,
struct pv_disk *pvd, struct physical_volume *pv)
{
@@ -117,19 +146,17 @@ int export_pv(struct cmd_context *cmd, struct 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)) {
@@ -137,24 +164,24 @@ int export_pv(struct cmd_context *cmd, struct 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;
}
@@ -162,7 +189,7 @@ int export_pv(struct cmd_context *cmd, struct 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;
}
@@ -170,8 +197,8 @@ int export_pv(struct cmd_context *cmd, struct 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);
@@ -191,23 +218,23 @@ int export_pv(struct cmd_context *cmd, struct pool *mem,
return 1;
}
int import_vg(struct pool *mem,
int import_vg(struct dm_pool *mem,
struct volume_group *vg, struct disk_list *dl, int partial)
{
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 = pool_strdup(mem, dl->pvd.vg_name))) {
if (!(vg->name = dm_pool_strdup(mem, (char *)dl->pvd.vg_name))) {
stack;
return 0;
}
if (!(vg->system_id = pool_alloc(mem, NAME_LEN))) {
if (!(vg->system_id = dm_pool_alloc(mem, NAME_LEN))) {
stack;
return 0;
}
@@ -234,7 +261,7 @@ int import_vg(struct pool *mem,
vg->extent_size = vgd->pe_size;
vg->extent_count = vgd->pe_total;
vg->free_count = vgd->pe_total - vgd->pe_allocated;
vg->free_count = vgd->pe_total;
vg->max_lv = vgd->lv_max;
vg->max_pv = vgd->pv_max;
vg->alloc = ALLOC_NORMAL;
@@ -281,11 +308,11 @@ int export_vg(struct vg_disk *vgd, struct volume_group *vg)
return 1;
}
int import_lv(struct pool *mem, struct logical_volume *lv, struct lv_disk *lvd)
int import_lv(struct dm_pool *mem, struct logical_volume *lv, struct lv_disk *lvd)
{
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;
}
@@ -323,6 +350,8 @@ int import_lv(struct pool *mem, struct logical_volume *lv, struct lv_disk *lvd)
lv->size = lvd->lv_size;
lv->le_count = lvd->lv_allocated_le;
lv->snapshot = NULL;
list_init(&lv->snapshot_segs);
list_init(&lv->segments);
list_init(&lv->tags);
@@ -333,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;
@@ -373,14 +402,11 @@ static void _export_lv(struct lv_disk *lvd, struct volume_group *vg,
int export_extents(struct disk_list *dl, uint32_t lv_num,
struct logical_volume *lv, struct physical_volume *pv)
{
struct list *segh;
struct pe_disk *ped;
struct lv_segment *seg;
uint32_t pe, s;
list_iterate(segh, &lv->segments) {
seg = list_item(segh, struct lv_segment);
list_iterate_items(seg, &lv->segments) {
for (s = 0; s < seg->area_count; s++) {
if (!(seg->segtype->flags & SEG_FORMAT1_SUPPORT)) {
log_error("Segment type %s in LV %s: "
@@ -388,16 +414,16 @@ int export_extents(struct disk_list *dl, uint32_t lv_num,
seg->segtype->name, lv->name);
return 0;
}
if (seg->area[s].type != AREA_PV) {
log_error("LV stripe found in LV %s: "
if (seg_type(seg, s) != AREA_PV) {
log_error("Non-PV stripe found in LV %s: "
"unsupported by format1", lv->name);
return 0;
}
if (seg->area[s].u.pv.pv != pv)
if (seg_pv(seg, s) != pv)
continue; /* not our pv */
for (pe = 0; pe < (seg->len / seg->area_count); pe++) {
ped = &dl->extents[pe + seg->area[s].u.pv.pe];
ped = &dl->extents[pe + seg_pe(seg, s)];
ped->lv_num = lv_num;
ped->le_num = (seg->le / seg->area_count) + pe +
s * (lv->le_count / seg->area_count);
@@ -408,26 +434,22 @@ int export_extents(struct disk_list *dl, uint32_t lv_num,
return 1;
}
int import_pvs(const struct format_type *fmt, struct pool *mem,
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 list *pvdh;
struct disk_list *dl;
struct pv_list *pvl;
*count = 0;
list_iterate(pvdh, pvds) {
dl = list_item(pvdh, struct disk_list);
if (!(pvl = pool_zalloc(mem, sizeof(*pvl))) ||
!(pvl->pv = pool_alloc(mem, sizeof(*pvl->pv)))) {
list_iterate_items(dl, pvds) {
if (!(pvl = dm_pool_zalloc(mem, sizeof(*pvl))) ||
!(pvl->pv = dm_pool_alloc(mem, sizeof(*pvl->pv)))) {
stack;
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;
}
@@ -440,15 +462,15 @@ int import_pvs(const struct format_type *fmt, struct pool *mem,
return 1;
}
static struct logical_volume *_add_lv(struct pool *mem,
static struct logical_volume *_add_lv(struct dm_pool *mem,
struct volume_group *vg,
struct lv_disk *lvd)
{
struct lv_list *ll;
struct logical_volume *lv;
if (!(ll = pool_zalloc(mem, sizeof(*ll))) ||
!(ll->lv = pool_zalloc(mem, sizeof(*ll->lv)))) {
if (!(ll = dm_pool_zalloc(mem, sizeof(*ll))) ||
!(ll->lv = dm_pool_zalloc(mem, sizeof(*ll->lv)))) {
stack;
return NULL;
}
@@ -466,20 +488,17 @@ static struct logical_volume *_add_lv(struct pool *mem,
return lv;
}
int import_lvs(struct pool *mem, struct volume_group *vg, struct list *pvds)
int import_lvs(struct dm_pool *mem, struct volume_group *vg, struct list *pvds)
{
struct disk_list *dl;
struct lvd_list *ll;
struct lv_disk *lvd;
struct list *pvdh, *lvdh;
list_iterate(pvdh, pvds) {
dl = list_item(pvdh, struct disk_list);
list_iterate(lvdh, &dl->lvds) {
ll = list_item(lvdh, struct lvd_list);
list_iterate_items(dl, 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;
@@ -495,19 +514,18 @@ int export_lvs(struct disk_list *dl, struct volume_group *vg,
struct physical_volume *pv, const char *dev_dir)
{
int r = 0;
struct list *lvh, *sh;
struct lv_list *ll;
struct lvd_list *lvdl;
size_t len;
uint32_t lv_num;
struct hash_table *lvd_hash;
struct dm_hash_table *lvd_hash;
if (!_check_vg_name(vg->name)) {
stack;
return 0;
}
if (!(lvd_hash = hash_create(32))) {
if (!(lvd_hash = dm_hash_create(32))) {
stack;
return 0;
}
@@ -516,15 +534,17 @@ int export_lvs(struct disk_list *dl, struct volume_group *vg,
* setup the pv's extents array
*/
len = sizeof(struct pe_disk) * dl->pvd.pe_total;
if (!(dl->extents = pool_alloc(dl->mem, len))) {
if (!(dl->extents = dm_pool_alloc(dl->mem, len))) {
stack;
goto out;
}
memset(dl->extents, 0, len);
list_iterate(lvh, &vg->lvs) {
ll = list_item(lvh, struct lv_list);
if (!(lvdl = pool_alloc(dl->mem, sizeof(*lvdl)))) {
list_iterate_items(ll, &vg->lvs) {
if (ll->lv->status & SNAPSHOT)
continue;
if (!(lvdl = dm_pool_alloc(dl->mem, sizeof(*lvdl)))) {
stack;
goto out;
}
@@ -532,10 +552,9 @@ int export_lvs(struct disk_list *dl, struct volume_group *vg,
_export_lv(&lvdl->lvd, vg, ll->lv, dev_dir);
lv_num = lvnum_from_lvid(&ll->lv->lvid);
lvdl->lvd.lv_number = lv_num;
if (!hash_insert(lvd_hash, ll->lv->name, &lvdl->lvd)) {
if (!dm_hash_insert(lvd_hash, ll->lv->name, &lvdl->lvd)) {
stack;
goto out;
}
@@ -545,75 +564,56 @@ int export_lvs(struct disk_list *dl, struct volume_group *vg,
goto out;
}
if (lv_is_origin(ll->lv))
lvdl->lvd.lv_access |= LV_SNAPSHOT_ORG;
if (lv_is_cow(ll->lv)) {
lvdl->lvd.lv_access |= LV_SNAPSHOT;
lvdl->lvd.lv_chunk_size = ll->lv->snapshot->chunk_size;
lvdl->lvd.lv_snapshot_minor =
lvnum_from_lvid(&ll->lv->snapshot->origin->lvid);
}
list_add(&dl->lvds, &lvdl->list);
dl->pvd.lv_cur++;
}
/*
* Now we need to run through the snapshots, exporting
* the SNAPSHOT_ORG flags etc.
*/
list_iterate(sh, &vg->snapshots) {
struct lv_disk *org, *cow;
struct snapshot *s = list_item(sh,
struct snapshot_list)->snapshot;
if (!(org = hash_lookup(lvd_hash, s->origin->name))) {
log_err("Couldn't find snapshot origin '%s'.",
s->origin->name);
goto out;
}
if (!(cow = hash_lookup(lvd_hash, s->cow->name))) {
log_err("Couldn't find snapshot cow store '%s'.",
s->cow->name);
goto out;
}
org->lv_access |= LV_SNAPSHOT_ORG;
cow->lv_access |= LV_SNAPSHOT;
cow->lv_snapshot_minor = org->lv_number;
cow->lv_chunk_size = s->chunk_size;
}
r = 1;
out:
hash_destroy(lvd_hash);
dm_hash_destroy(lvd_hash);
return r;
}
/*
* FIXME: More inefficient code.
*/
int import_snapshots(struct pool *mem, struct volume_group *vg,
int import_snapshots(struct dm_pool *mem, struct volume_group *vg,
struct list *pvds)
{
struct logical_volume *lvs[MAX_LV];
struct list *pvdh, *lvdh;
struct disk_list *dl;
struct lvd_list *ll;
struct lv_disk *lvd;
int lvnum;
struct logical_volume *org, *cow;
/* build an index of lv numbers */
memset(lvs, 0, sizeof(lvs));
list_iterate(pvdh, pvds) {
dl = list_item(pvdh, struct disk_list);
list_iterate(lvdh, &dl->lvds) {
lvd = &(list_item(lvdh, struct lvd_list)->lvd);
list_iterate_items(dl, pvds) {
list_iterate_items(ll, &dl->lvds) {
lvd = &ll->lvd;
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;
@@ -624,11 +624,9 @@ int import_snapshots(struct pool *mem, struct volume_group *vg,
/*
* Now iterate through yet again adding the snapshots.
*/
list_iterate(pvdh, pvds) {
dl = list_item(pvdh, struct disk_list);
list_iterate(lvdh, &dl->lvds) {
lvd = &(list_item(lvdh, struct lvd_list)->lvd);
list_iterate_items(dl, pvds) {
list_iterate_items(ll, &dl->lvds) {
lvd = &ll->lvd;
if (!(lvd->lv_access & LV_SNAPSHOT))
continue;
@@ -646,7 +644,8 @@ int import_snapshots(struct pool *mem, struct volume_group *vg,
continue;
/* insert the snapshot */
if (!vg_add_snapshot(org, cow, 1, NULL,
if (!vg_add_snapshot(vg->fid, NULL, org, cow, NULL,
org->le_count,
lvd->lv_chunk_size)) {
log_err("Couldn't add snapshot.");
return 0;
@@ -661,11 +660,9 @@ int export_uuids(struct disk_list *dl, struct volume_group *vg)
{
struct uuid_list *ul;
struct pv_list *pvl;
struct list *pvh;
list_iterate(pvh, &vg->pvs) {
pvl = list_item(pvh, struct pv_list);
if (!(ul = pool_alloc(dl->mem, sizeof(*ul)))) {
list_iterate_items(pvl, &vg->pvs) {
if (!(ul = dm_pool_alloc(dl->mem, sizeof(*ul)))) {
stack;
return 0;
}
@@ -684,14 +681,11 @@ int export_uuids(struct disk_list *dl, struct volume_group *vg)
*/
void export_numbers(struct list *pvds, struct volume_group *vg)
{
struct list *pvdh;
struct disk_list *dl;
int pv_num = 1;
list_iterate(pvdh, pvds) {
dl = list_item(pvdh, struct disk_list);
list_iterate_items(dl, pvds)
dl->pvd.pv_number = pv_num++;
}
}
/*
@@ -699,26 +693,20 @@ void export_numbers(struct list *pvds, struct volume_group *vg)
*/
void export_pv_act(struct list *pvds)
{
struct list *pvdh;
struct disk_list *dl;
int act = 0;
list_iterate(pvdh, pvds) {
dl = list_item(pvdh, struct disk_list);
list_iterate_items(dl, pvds)
if (dl->pvd.pv_status & PV_ACTIVE)
act++;
}
list_iterate(pvdh, pvds) {
dl = list_item(pvdh, struct disk_list);
list_iterate_items(dl, pvds)
dl->vgd.pv_act = act;
}
}
int export_vg_number(struct format_instance *fid, struct list *pvds,
const char *vg_name, struct dev_filter *filter)
{
struct list *pvdh;
struct disk_list *dl;
int vg_num;
@@ -727,10 +715,8 @@ int export_vg_number(struct format_instance *fid, struct list *pvds,
return 0;
}
list_iterate(pvdh, pvds) {
dl = list_item(pvdh, struct disk_list);
list_iterate_items(dl, pvds)
dl->vgd.vg_number = vg_num;
}
return 1;
}

View File

@@ -15,8 +15,6 @@
#include "lib.h"
#include "metadata.h"
#include "hash.h"
#include "pool.h"
#include "disk-rep.h"
#include "lv_alloc.h"
#include "display.h"
@@ -44,11 +42,10 @@ struct lv_map {
struct pe_specifier *map;
};
static struct hash_table *_create_lv_maps(struct pool *mem,
static struct dm_hash_table *_create_lv_maps(struct dm_pool *mem,
struct volume_group *vg)
{
struct hash_table *maps = hash_create(32);
struct list *llh;
struct dm_hash_table *maps = dm_hash_create(32);
struct lv_list *ll;
struct lv_map *lvm;
@@ -58,22 +55,23 @@ static struct hash_table *_create_lv_maps(struct pool *mem,
return NULL;
}
list_iterate(llh, &vg->lvs) {
ll = list_item(llh, struct lv_list);
list_iterate_items(ll, &vg->lvs) {
if (ll->lv->status & SNAPSHOT)
continue;
if (!(lvm = pool_alloc(mem, sizeof(*lvm)))) {
if (!(lvm = dm_pool_alloc(mem, sizeof(*lvm)))) {
stack;
goto bad;
}
lvm->lv = ll->lv;
if (!(lvm->map = pool_zalloc(mem, sizeof(*lvm->map)
if (!(lvm->map = dm_pool_zalloc(mem, sizeof(*lvm->map)
* ll->lv->le_count))) {
stack;
goto bad;
}
if (!hash_insert(maps, ll->lv->name, lvm)) {
if (!dm_hash_insert(maps, ll->lv->name, lvm)) {
stack;
goto bad;
}
@@ -82,21 +80,20 @@ static struct hash_table *_create_lv_maps(struct pool *mem,
return maps;
bad:
hash_destroy(maps);
dm_hash_destroy(maps);
return NULL;
}
static int _fill_lv_array(struct lv_map **lvs,
struct hash_table *maps, struct disk_list *dl)
struct dm_hash_table *maps, struct disk_list *dl)
{
struct list *lvh;
struct lvd_list *ll;
struct lv_map *lvm;
memset(lvs, 0, sizeof(*lvs) * MAX_LV);
list_iterate(lvh, &dl->lvds) {
struct lvd_list *ll = list_item(lvh, struct lvd_list);
if (!(lvm = hash_lookup(maps, strrchr(ll->lvd.lv_name, '/')
list_iterate_items(ll, &dl->lvds) {
if (!(lvm = dm_hash_lookup(maps, strrchr((char *)ll->lvd.lv_name, '/')
+ 1))) {
log_err("Physical volume (%s) contains an "
"unknown logical volume (%s).",
@@ -113,18 +110,16 @@ static int _fill_lv_array(struct lv_map **lvs,
return 1;
}
static int _fill_maps(struct hash_table *maps, struct volume_group *vg,
static int _fill_maps(struct dm_hash_table *maps, struct volume_group *vg,
struct list *pvds)
{
struct list *pvdh;
struct disk_list *dl;
struct physical_volume *pv;
struct lv_map *lvms[MAX_LV], *lvm;
struct pe_disk *e;
uint32_t i, lv_num, le;
list_iterate(pvdh, pvds) {
dl = list_item(pvdh, struct disk_list);
list_iterate_items(dl, pvds) {
pv = find_pv(vg, dl->dev);
e = dl->extents;
@@ -145,7 +140,12 @@ static int _fill_maps(struct 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;
}
@@ -187,13 +187,13 @@ static int _check_single_map(struct lv_map *lvm)
return 1;
}
static int _check_maps_are_complete(struct hash_table *maps)
static int _check_maps_are_complete(struct dm_hash_table *maps)
{
struct hash_node *n;
struct dm_hash_node *n;
struct lv_map *lvm;
for (n = hash_get_first(maps); n; n = hash_get_next(maps, n)) {
lvm = (struct lv_map *) hash_get_data(maps, n);
for (n = dm_hash_get_first(maps); n; n = dm_hash_get_next(maps, n)) {
lvm = (struct lv_map *) dm_hash_get_data(maps, n);
if (!_check_single_map(lvm)) {
stack;
@@ -205,58 +205,59 @@ static int _check_maps_are_complete(struct hash_table *maps)
static int _read_linear(struct cmd_context *cmd, struct lv_map *lvm)
{
uint32_t le = 0;
uint32_t le = 0, len;
struct lv_segment *seg;
struct segment_type *segtype;
if (!(segtype = get_segtype_from_string(cmd, "striped"))) {
stack;
return 0;
}
while (le < lvm->lv->le_count) {
seg = alloc_lv_segment(cmd->mem, 1);
len = 0;
seg->lv = lvm->lv;
if (!(seg->segtype = get_segtype_from_string(cmd, "striped"))) {
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));
if (!(seg = alloc_lv_segment(cmd->mem, segtype, lvm->lv, le,
len, 0, 0, NULL, 1, len, 0, 0, 0))) {
log_error("Failed to allocate linear segment.");
return 0;
}
if (!set_lv_segment_area_pv(seg, 0, lvm->map[le].pv,
lvm->map[le].pe)) {
stack;
return 0;
}
seg->le = le;
seg->len = 0;
seg->area_len = 0;
seg->stripe_size = 0;
seg->area[0].type = AREA_PV;
seg->area[0].u.pv.pv = lvm->map[le].pv;
seg->area[0].u.pv.pe = lvm->map[le].pe;
do {
seg->len++;
seg->area_len++;
} while ((lvm->map[le + seg->len].pv == seg->area[0].u.pv.pv) &&
(seg->area[0].u.pv.pv &&
lvm->map[le + seg->len].pe == seg->area[0].u.pv.pe +
seg->len));
list_add(&lvm->lv->segments, &seg->list);
le += seg->len;
list_add(&lvm->lv->segments, &seg->list);
}
return 1;
}
static int _check_stripe(struct lv_map *lvm, struct lv_segment *seg,
uint32_t base_le, uint32_t len)
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 le, st;
le = base_le + seg->len;
uint32_t st;
/*
* Is the next physical extent in every stripe adjacent to the last?
*/
for (st = 0; st < seg->area_count; st++)
if ((lvm->map[le + st * len].pv != seg->area[st].u.pv.pv) ||
(seg->area[st].u.pv.pv &&
lvm->map[le + st * len].pe !=
seg->area[st].u.pv.pe + seg->len)) return 0;
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))
return 0;
return 1;
}
@@ -264,7 +265,9 @@ static int _check_stripe(struct lv_map *lvm, struct lv_segment *seg,
static int _read_stripes(struct cmd_context *cmd, struct lv_map *lvm)
{
uint32_t st, le = 0, len;
uint32_t area_len;
struct lv_segment *seg;
struct segment_type *segtype;
/*
* Work out overall striped length
@@ -276,43 +279,46 @@ static int _read_stripes(struct cmd_context *cmd, struct lv_map *lvm)
}
len = lvm->lv->le_count / lvm->stripes;
if (!(segtype = get_segtype_from_string(cmd, "striped"))) {
stack;
return 0;
}
while (le < len) {
if (!(seg = alloc_lv_segment(cmd->mem, lvm->stripes))) {
stack;
return 0;
}
seg->lv = lvm->lv;
if (!(seg->segtype = get_segtype_from_string(cmd, "striped"))) {
stack;
return 0;
}
seg->stripe_size = lvm->stripe_size;
seg->le = seg->area_count * le;
seg->len = 1;
seg->area_len = 1;
/*
* Set up start positions of each stripe in this segment
*/
for (st = 0; st < seg->area_count; st++) {
seg->area[st].u.pv.pv = lvm->map[le + st * len].pv;
seg->area[st].u.pv.pe = lvm->map[le + st * len].pe;
}
area_len = 1;
/*
* Find how many blocks are contiguous in all stripes
* and so can form part of this segment
*/
while (_check_stripe(lvm, seg, le, len)) {
seg->len++;
seg->area_len++;
while (_check_stripe(lvm, lvm->stripes,
area_len * lvm->stripes, le, len))
area_len++;
if (!(seg = alloc_lv_segment(cmd->mem, segtype, lvm->lv,
lvm->stripes * le,
lvm->stripes * area_len,
0, lvm->stripe_size, NULL,
lvm->stripes,
area_len, 0, 0, 0))) {
log_error("Failed to allocate striped segment.");
return 0;
}
le += seg->len;
seg->len *= seg->area_count;
/*
* Set up start positions of each stripe in this segment
*/
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;
}
list_add(&lvm->lv->segments, &seg->list);
le += seg->len;
}
return 1;
@@ -324,13 +330,13 @@ static int _build_segments(struct cmd_context *cmd, struct lv_map *lvm)
_read_linear(cmd, lvm));
}
static int _build_all_segments(struct cmd_context *cmd, struct hash_table *maps)
static int _build_all_segments(struct cmd_context *cmd, struct dm_hash_table *maps)
{
struct hash_node *n;
struct dm_hash_node *n;
struct lv_map *lvm;
for (n = hash_get_first(maps); n; n = hash_get_next(maps, n)) {
lvm = (struct lv_map *) hash_get_data(maps, n);
for (n = dm_hash_get_first(maps); n; n = dm_hash_get_next(maps, n)) {
lvm = (struct lv_map *) dm_hash_get_data(maps, n);
if (!_build_segments(cmd, lvm)) {
stack;
return 0;
@@ -344,8 +350,8 @@ int import_extents(struct cmd_context *cmd, struct volume_group *vg,
struct list *pvds)
{
int r = 0;
struct pool *scratch = pool_create("lvm1 import_extents", 10 * 1024);
struct hash_table *maps;
struct dm_pool *scratch = dm_pool_create("lvm1 import_extents", 10 * 1024);
struct dm_hash_table *maps;
if (!scratch) {
stack;
@@ -375,7 +381,7 @@ int import_extents(struct cmd_context *cmd, struct volume_group *vg,
out:
if (maps)
hash_destroy(maps);
pool_destroy(scratch);
dm_hash_destroy(maps);
dm_pool_destroy(scratch);
return r;
}

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
@@ -117,7 +119,7 @@ int calculate_layout(struct disk_list *dl)
int calculate_extent_count(struct physical_volume *pv, uint32_t extent_size,
uint32_t max_extent_count, uint64_t pe_start)
{
struct pv_disk *pvd = dbg_malloc(sizeof(*pvd));
struct pv_disk *pvd = dm_malloc(sizeof(*pvd));
uint32_t end;
if (!pvd) {
@@ -138,7 +140,7 @@ int calculate_extent_count(struct physical_volume *pv, uint32_t extent_size,
if (pvd->pe_total < PE_SIZE_PV_SIZE_REL) {
log_error("Too few extents on %s. Try smaller extent size.",
dev_name(pv->dev));
dbg_free(pvd);
dm_free(pvd);
return 0;
}
@@ -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);
@@ -160,13 +162,13 @@ int calculate_extent_count(struct physical_volume *pv, uint32_t extent_size,
log_error("Metadata extent limit (%u) exceeded for %s - "
"%u required", MAX_PE_TOTAL, dev_name(pv->dev),
pvd->pe_total);
dbg_free(pvd);
dm_free(pvd);
return 0;
}
pv->pe_count = pvd->pe_total;
pv->pe_start = pvd->pe_start;
/* We can't set pe_size here without breaking LVM1 compatibility */
dbg_free(pvd);
dm_free(pvd);
return 1;
}

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,38 +85,38 @@ 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)
{
dbg_free(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)
{
struct labeller *l;
if (!(l = dbg_malloc(sizeof(*l)))) {
if (!(l = dm_malloc(sizeof(*l)))) {
log_err("Couldn't allocate labeller object.");
return NULL;
}

View File

@@ -14,7 +14,6 @@
*/
#include "lib.h"
#include "pool.h"
#include "disk-rep.h"
/*
@@ -27,10 +26,9 @@
int get_free_vg_number(struct format_instance *fid, struct dev_filter *filter,
const char *candidate_vg, int *result)
{
struct list *pvh;
struct list all_pvs;
struct disk_list *dl;
struct pool *mem = pool_create("lvm1 vg_number", 10 * 1024);
struct dm_pool *mem = dm_pool_create("lvm1 vg_number", 10 * 1024);
int numbers[MAX_VG], i, r = 0;
list_init(&all_pvs);
@@ -47,9 +45,8 @@ int get_free_vg_number(struct format_instance *fid, struct dev_filter *filter,
memset(numbers, 0, sizeof(numbers));
list_iterate(pvh, &all_pvs) {
dl = list_item(pvh, struct disk_list);
if (!*dl->pvd.vg_name || !strcmp(dl->pvd.vg_name, candidate_vg))
list_iterate_items(dl, &all_pvs) {
if (!*dl->pvd.vg_name || !strcmp((char *)dl->pvd.vg_name, candidate_vg))
continue;
numbers[dl->vgd.vg_number] = 1;
@@ -64,6 +61,6 @@ int get_free_vg_number(struct format_instance *fid, struct dev_filter *filter,
}
out:
pool_destroy(mem);
dm_pool_destroy(mem);
return r;
}

View File

@@ -14,12 +14,10 @@
*/
#include "lib.h"
#include "pool.h"
#include "label.h"
#include "metadata.h"
#include "lvmcache.h"
#include "filter.h"
#include "list.h"
#include "xlate.h"
#include "disk_rep.h"
@@ -35,10 +33,10 @@
#define CPOUT_64(x, y) {(y) = xlate64_be((x));}
static int __read_pool_disk(const struct format_type *fmt, struct device *dev,
struct pool *mem, struct pool_list *pl,
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)) {
@@ -57,14 +55,11 @@ static int __read_pool_disk(const struct format_type *fmt, struct device *dev,
static void _add_pl_to_list(struct list *head, struct pool_list *data)
{
struct list *pvdh;
struct pool_list *pl;
list_iterate(pvdh, head) {
pl = list_item(pvdh, struct pool_list);
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);
@@ -76,7 +71,7 @@ static void _add_pl_to_list(struct list *head, struct pool_list *data)
}
log_very_verbose("Duplicate PV %s - using md %s",
uuid, dev_name(data->dev));
list_del(pvdh);
list_del(&pl->list);
break;
}
}
@@ -89,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);
@@ -103,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;
}
@@ -133,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;
@@ -168,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;
@@ -243,44 +238,42 @@ void get_pool_uuid(char *uuid, uint64_t poolid, uint32_t spid, uint32_t devid)
}
static int _read_vg_pds(const struct format_type *fmt, struct pool *mem,
static int _read_vg_pds(const struct format_type *fmt, struct dm_pool *mem,
struct lvmcache_vginfo *vginfo, struct list *head,
uint32_t *devcount)
{
struct list *vgih = NULL;
struct device *dev;
struct lvmcache_info *info;
struct pool_list *pl = NULL;
struct pool *tmpmem = NULL;
struct dm_pool *tmpmem;
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 */
if (!(tmpmem = pool_create("pool read_vg", 512))) {
if (!(tmpmem = dm_pool_create("pool read_vg", 512))) {
stack;
return 0;
}
list_iterate(vgih, &vginfo->infos) {
dev = list_item(vgih, struct lvmcache_info)->dev;
if (dev &&
!(pl = read_pool_disk(fmt, dev, mem, vginfo->vgname)))
list_iterate_items(info, &vginfo->infos) {
if (info->dev &&
!(pl = read_pool_disk(fmt, info->dev, mem, vginfo->vgname)))
break;
/*
* We need to keep track of the total expected number
* of devices per subpool
*/
if (!sp_count) {
/* FIXME pl left uninitialised if !info->dev */
sp_count = pl->pd.pl_subpools;
if (!(sp_devs =
pool_zalloc(tmpmem,
dm_pool_zalloc(tmpmem,
sizeof(uint32_t) * sp_count))) {
log_error("Unable to allocate %d 32-bit uints",
sp_count);
pool_destroy(tmpmem);
dm_pool_destroy(tmpmem);
return 0;
}
}
@@ -298,11 +291,10 @@ static int _read_vg_pds(const struct format_type *fmt, struct pool *mem,
}
*devcount = 0;
for (i = 0; i < sp_count; i++) {
for (i = 0; i < sp_count; i++)
*devcount += sp_devs[i];
}
pool_destroy(tmpmem);
dm_pool_destroy(tmpmem);
if (pl && *pl->pd.pl_pool_name)
return 1;
@@ -312,7 +304,7 @@ static int _read_vg_pds(const struct format_type *fmt, struct pool *mem,
}
int read_pool_pds(const struct format_type *fmt, const char *vg_name,
struct pool *mem, struct list *pdhead)
struct dm_pool *mem, struct list *pdhead)
{
struct lvmcache_vginfo *vginfo;
uint32_t totaldevs;
@@ -322,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)) {
@@ -357,7 +349,7 @@ int read_pool_pds(const struct format_type *fmt, const char *vg_name,
}
struct pool_list *read_pool_disk(const struct format_type *fmt,
struct device *dev, struct pool *mem,
struct device *dev, struct dm_pool *mem,
const char *vg_name)
{
struct pool_list *pl;
@@ -367,7 +359,7 @@ struct pool_list *read_pool_disk(const struct format_type *fmt,
return NULL;
}
if (!(pl = pool_zalloc(mem, sizeof(*pl)))) {
if (!(pl = dm_pool_zalloc(mem, sizeof(*pl)))) {
log_error("Unable to allocate pool list structure");
return 0;
}

View File

@@ -18,7 +18,8 @@
#include "label.h"
#include "metadata.h"
#include "pool.h"
#define MINOR_OFFSET 65536
/* From NSP.cf */
#define NSPMajorVersion 4
@@ -66,29 +67,6 @@ struct pool_list;
struct user_subpool;
struct user_device;
/* This must be kept up to date with sistina/pool/module/pool_sptypes.h */
/* Generic Labels */
#define SPTYPE_DATA (0x00000000)
/* GFS specific labels */
#define SPTYPE_GFS_DATA (0x68011670)
#define SPTYPE_GFS_JOURNAL (0x69011670)
struct sptype_name {
const char *name;
uint32_t label;
};
static const struct sptype_name sptype_names[] = {
{"data", SPTYPE_DATA},
{"gfs_data", SPTYPE_GFS_DATA},
{"gfs_journal", SPTYPE_GFS_JOURNAL},
{"", 0x0} /* This must be the last flag. */
};
struct pool_disk {
uint64_t pl_magic; /* Pool magic number */
uint64_t pl_pool_id; /* Unique pool identifier */
@@ -156,23 +134,23 @@ 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 pool *mem, struct list *pls);
int import_pool_lvs(struct volume_group *vg, struct pool *mem,
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,
struct list *pls);
int import_pool_pvs(const struct format_type *fmt, struct volume_group *vg,
struct list *pvs, struct pool *mem, struct list *pls);
int import_pool_pv(const struct format_type *fmt, struct pool *mem,
struct list *pvs, struct dm_pool *mem, struct list *pls);
int import_pool_pv(const struct format_type *fmt, struct dm_pool *mem,
struct volume_group *vg, struct physical_volume *pv,
struct pool_list *pl);
int import_pool_segments(struct list *lvs, struct pool *mem,
int import_pool_segments(struct list *lvs, struct dm_pool *mem,
struct user_subpool *usp, int sp_count);
int read_pool_pds(const struct format_type *fmt, const char *vgname,
struct pool *mem, struct list *head);
struct dm_pool *mem, struct list *head);
struct pool_list *read_pool_disk(const struct format_type *fmt,
struct device *dev, struct pool *mem,
struct device *dev, struct dm_pool *mem,
const char *vg_name);
#endif /* DISK_REP_POOL_FORMAT_H */

View File

@@ -14,12 +14,9 @@
*/
#include "lib.h"
#include "pool.h"
#include "label.h"
#include "metadata.h"
#include "hash.h"
#include "limits.h"
#include "list.h"
#include "display.h"
#include "toolcontext.h"
#include "lvmcache.h"
@@ -30,11 +27,9 @@
#define FMT_POOL_NAME "pool"
/* Must be called after pvs are imported */
static struct user_subpool *_build_usp(struct list *pls, struct pool *mem,
static struct user_subpool *_build_usp(struct list *pls, struct dm_pool *mem,
int *sps)
{
struct list *plhs;
struct pool_list *pl;
struct user_subpool *usp = NULL, *cur_sp = NULL;
struct user_device *cur_dev = NULL;
@@ -43,11 +38,9 @@ static struct user_subpool *_build_usp(struct list *pls, struct pool *mem,
* FIXME: Need to do some checks here - I'm tempted to add a
* user_pool structure and build the entire thing to check against.
*/
list_iterate(plhs, pls) {
pl = list_item(plhs, struct pool_list);
list_iterate_items(pl, pls) {
*sps = pl->pd.pl_subpools;
if (!usp && (!(usp = pool_zalloc(mem, sizeof(*usp) * (*sps))))) {
if (!usp && (!(usp = dm_pool_zalloc(mem, sizeof(*usp) * (*sps))))) {
log_error("Unable to allocate %d subpool structures",
*sps);
return 0;
@@ -65,20 +58,20 @@ static struct user_subpool *_build_usp(struct list *pls, struct pool *mem,
if (!cur_sp->devs &&
(!(cur_sp->devs =
pool_zalloc(mem,
dm_pool_zalloc(mem,
sizeof(*usp->devs) * pl->pd.pl_sp_devs)))) {
log_error("Unable to allocate %d pool_device "
"structures", pl->pd.pl_sp_devs);
return 0;
}
cur_dev = &cur_sp->devs[pl->pd.pl_sp_devid];
cur_dev->sp_id = cur_sp->id;
cur_dev->devid = pl->pd.pl_sp_id;
cur_dev->blocks = pl->pd.pl_blocks;
cur_dev->pv = pl->pv;
cur_dev->initialized = 1;
}
return usp;
@@ -86,7 +79,8 @@ static struct user_subpool *_build_usp(struct list *pls, struct 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) {
@@ -95,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;
}
@@ -107,15 +101,15 @@ static int _check_usp(char *vgname, struct user_subpool *usp, int sp_count)
}
static struct volume_group *_build_vg_from_pds(struct format_instance
*fid, struct pool *mem,
*fid, struct dm_pool *mem,
struct list *pds)
{
struct pool *smem = fid->fmt->cmd->mem;
struct dm_pool *smem = fid->fmt->cmd->mem;
struct volume_group *vg = NULL;
struct user_subpool *usp = NULL;
int sp_count;
if (!(vg = pool_zalloc(smem, sizeof(*vg)))) {
if (!(vg = dm_pool_zalloc(smem, sizeof(*vg)))) {
log_error("Unable to allocate volume group structure");
return NULL;
}
@@ -132,7 +126,6 @@ static struct volume_group *_build_vg_from_pds(struct format_instance
vg->system_id = NULL;
list_init(&vg->pvs);
list_init(&vg->lvs);
list_init(&vg->snapshots);
list_init(&vg->tags);
if (!import_pool_vg(vg, smem, pds)) {
@@ -177,11 +170,11 @@ 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)
{
struct pool *mem = pool_create("pool vg_read", 1024);
struct dm_pool *mem = dm_pool_create("pool vg_read", 1024);
struct list pds;
struct volume_group *vg = NULL;
@@ -210,11 +203,11 @@ static struct volume_group *_vg_read(struct format_instance *fid,
}
out:
pool_destroy(mem);
dm_pool_destroy(mem);
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,
@@ -224,10 +217,10 @@ 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 pool *mem = pool_create("pool pv_read", 1024);
struct dm_pool *mem = dm_pool_create("pool pv_read", 1024);
struct pool_list *pl;
struct device *dev;
int r = 0;
@@ -264,24 +257,25 @@ static int _pv_read(const struct format_type *fmt, const char *pv_name,
r = 1;
out:
pool_destroy(mem);
dm_pool_destroy(mem);
return r;
}
/* *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;
struct metadata_area *mda;
if (!(fid = pool_zalloc(fmt->cmd->mem, sizeof(*fid)))) {
if (!(fid = dm_pool_zalloc(fmt->cmd->mem, sizeof(*fid)))) {
log_error("Unable to allocate format instance structure for "
"pool format");
return NULL;
@@ -291,10 +285,10 @@ static struct format_instance *_create_instance(const struct format_type *fmt,
list_init(&fid->metadata_areas);
/* Define a NULL metadata area */
if (!(mda = pool_zalloc(fmt->cmd->mem, sizeof(*mda)))) {
if (!(mda = dm_pool_zalloc(fmt->cmd->mem, sizeof(*mda)))) {
log_error("Unable to allocate metadata area structure "
"for pool format");
pool_free(fmt->cmd->mem, fid);
dm_pool_free(fmt->cmd->mem, fid);
return NULL;
}
@@ -305,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)
{
dbg_free((void *) 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 */
@@ -332,7 +326,7 @@ struct format_type *init_format(struct cmd_context *cmd);
struct format_type *init_format(struct cmd_context *cmd)
#endif
{
struct format_type *fmt = dbg_malloc(sizeof(*fmt));
struct format_type *fmt = dm_malloc(sizeof(*fmt));
if (!fmt) {
log_error("Unable to allocate format type structure for pool "

View File

@@ -14,26 +14,24 @@
*/
#include "lib.h"
#include "pool.h"
#include "label.h"
#include "metadata.h"
#include "lvmcache.h"
#include "disk_rep.h"
#include "sptype_names.h"
#include "lv_alloc.h"
#include "pv_alloc.h"
#include "str_list.h"
#include "display.h"
#include "segtype.h"
/* This file contains only imports at the moment... */
int import_pool_vg(struct volume_group *vg, struct pool *mem, struct list *pls)
int import_pool_vg(struct volume_group *vg, struct dm_pool *mem, struct list *pls)
{
struct list *plhs;
struct pool_list *pl;
list_iterate(plhs, pls) {
pl = list_item(plhs, struct pool_list);
list_iterate_items(pl, pls) {
vg->extent_count +=
((pl->pd.pl_blocks) / POOL_PE_SIZE);
@@ -42,11 +40,11 @@ int import_pool_vg(struct volume_group *vg, struct pool *mem, struct list *pls)
if (vg->name)
continue;
vg->name = pool_strdup(mem, pl->pd.pl_pool_name);
vg->name = dm_pool_strdup(mem, pl->pd.pl_pool_name);
get_pool_vg_uuid(&vg->id, &pl->pd);
vg->extent_size = POOL_PE_SIZE;
vg->status |= LVM_READ | LVM_WRITE | CLUSTERED | SHARED;
vg->free_count = 0;
vg->free_count = vg->extent_count;
vg->max_lv = 1;
vg->max_pv = POOL_MAX_DEVICES;
vg->alloc = ALLOC_NORMAL;
@@ -56,11 +54,10 @@ int import_pool_vg(struct volume_group *vg, struct pool *mem, struct list *pls)
return 1;
}
int import_pool_lvs(struct volume_group *vg, struct pool *mem, struct list *pls)
int import_pool_lvs(struct volume_group *vg, struct dm_pool *mem, struct list *pls)
{
struct pool_list *pl;
struct list *plhs;
struct lv_list *lvl = pool_zalloc(mem, sizeof(*lvl));
struct lv_list *lvl = dm_pool_zalloc(mem, sizeof(*lvl));
struct logical_volume *lv;
if (!lvl) {
@@ -68,7 +65,7 @@ int import_pool_lvs(struct volume_group *vg, struct pool *mem, struct list *pls)
return 0;
}
if (!(lvl->lv = pool_zalloc(mem, sizeof(*lvl->lv)))) {
if (!(lvl->lv = dm_pool_zalloc(mem, sizeof(*lvl->lv)))) {
log_error("Unable to allocate logical volume structure");
return 0;
}
@@ -81,18 +78,18 @@ int import_pool_lvs(struct volume_group *vg, struct pool *mem, struct list *pls)
lv->name = NULL;
lv->le_count = 0;
lv->read_ahead = 0;
lv->snapshot = NULL;
list_init(&lv->snapshot_segs);
list_init(&lv->segments);
list_init(&lv->tags);
list_iterate(plhs, pls) {
pl = list_item(plhs, struct pool_list);
list_iterate_items(pl, pls) {
lv->size += pl->pd.pl_blocks;
if (lv->name)
continue;
if (!(lv->name = pool_strdup(mem, pl->pd.pl_pool_name))) {
if (!(lv->name = dm_pool_strdup(mem, pl->pd.pl_pool_name))) {
stack;
return 0;
}
@@ -107,10 +104,12 @@ int import_pool_lvs(struct volume_group *vg, struct pool *mem, struct list *pls)
/* for pool a minor of 0 is dynamic */
if (pl->pd.pl_minor) {
lv->status |= FIXED_MINOR;
lv->minor = pl->pd.pl_minor;
lv->minor = pl->pd.pl_minor + MINOR_OFFSET;
} else {
lv->minor = -1;
}
lv->snapshot = NULL;
list_init(&lv->snapshot_segs);
list_init(&lv->segments);
list_init(&lv->tags);
}
@@ -124,20 +123,17 @@ int import_pool_lvs(struct volume_group *vg, struct pool *mem, struct list *pls)
}
int import_pool_pvs(const struct format_type *fmt, struct volume_group *vg,
struct list *pvs, struct pool *mem, struct list *pls)
struct list *pvs, struct dm_pool *mem, struct list *pls)
{
struct pv_list *pvl;
struct pool_list *pl;
struct list *plhs;
list_iterate(plhs, pls) {
pl = list_item(plhs, struct pool_list);
if (!(pvl = pool_zalloc(mem, sizeof(*pvl)))) {
list_iterate_items(pl, pls) {
if (!(pvl = dm_pool_zalloc(mem, sizeof(*pvl)))) {
log_error("Unable to allocate pv list structure");
return 0;
}
if (!(pvl->pv = pool_zalloc(mem, sizeof(*pvl->pv)))) {
if (!(pvl->pv = dm_pool_zalloc(mem, sizeof(*pvl->pv)))) {
log_error("Unable to allocate pv structure");
return 0;
}
@@ -153,7 +149,7 @@ int import_pool_pvs(const struct format_type *fmt, struct volume_group *vg,
return 1;
}
int import_pool_pv(const struct format_type *fmt, struct pool *mem,
int import_pool_pv(const struct format_type *fmt, struct dm_pool *mem,
struct volume_group *vg, struct physical_volume *pv,
struct pool_list *pl)
{
@@ -165,18 +161,25 @@ int import_pool_pv(const struct format_type *fmt, struct pool *mem,
pv->fmt = fmt;
pv->dev = pl->dev;
if (!(pv->vg_name = pool_strdup(mem, pd->pl_pool_name))) {
if (!(pv->vg_name = dm_pool_strdup(mem, pd->pl_pool_name))) {
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;
pv->pe_start = POOL_PE_START;
pv->pe_count = pv->size / POOL_PE_SIZE;
pv->pe_alloc_count = pv->pe_count;
pv->pe_alloc_count = 0;
list_init(&pv->tags);
list_init(&pv->segments);
if (!alloc_pv_segment_whole_pv(mem, pv)) {
stack;
return 0;
}
return 1;
}
@@ -194,101 +197,107 @@ static const char *_cvt_sptype(uint32_t sptype)
return sptype_names[i].name;
}
static int _add_stripe_seg(struct pool *mem,
static int _add_stripe_seg(struct dm_pool *mem,
struct user_subpool *usp, struct logical_volume *lv,
uint32_t *le_cur)
{
struct lv_segment *seg;
int j;
struct segment_type *segtype;
unsigned j;
uint32_t area_len;
if (!(seg = alloc_lv_segment(mem, usp->num_devs))) {
log_error("Unable to allocate striped lv_segment structure");
return 0;
}
if(usp->striping & (usp->striping - 1)) {
if (usp->striping & (usp->striping - 1)) {
log_error("Stripe size must be a power of 2");
return 0;
}
seg->stripe_size = usp->striping;
seg->status |= 0;
seg->le += *le_cur;
area_len = (usp->devs[0].blocks) / POOL_PE_SIZE;
if (!(segtype = get_segtype_from_string(lv->vg->cmd,
"striped"))) {
stack;
return 0;
}
if (!(seg = alloc_lv_segment(mem, segtype, lv, *le_cur,
area_len * usp->num_devs, 0,
usp->striping, NULL, usp->num_devs,
area_len, 0, 0, 0))) {
log_error("Unable to allocate striped lv_segment structure");
return 0;
}
for (j = 0; j < usp->num_devs; j++)
if (!set_lv_segment_area_pv(seg, j, usp->devs[j].pv, 0)) {
stack;
return 0;
}
/* add the subpool type to the segment tag list */
str_list_add(mem, &seg->tags, _cvt_sptype(usp->type));
for (j = 0; j < usp->num_devs; j++) {
if (!(seg->segtype = get_segtype_from_string(lv->vg->cmd,
"striped"))) {
stack;
return 0;
}
seg->area_len = (usp->devs[j].blocks) / POOL_PE_SIZE;
seg->len += seg->area_len;
*le_cur += seg->area_len;
seg->lv = lv;
seg->area[j].type = AREA_PV;
seg->area[j].u.pv.pv = usp->devs[j].pv;
seg->area[j].u.pv.pe = 0;
}
list_add(&lv->segments, &seg->list);
*le_cur += seg->len;
return 1;
}
static int _add_linear_seg(struct pool *mem,
static int _add_linear_seg(struct dm_pool *mem,
struct user_subpool *usp, struct logical_volume *lv,
uint32_t *le_cur)
{
struct lv_segment *seg;
int j;
struct segment_type *segtype;
unsigned j;
uint32_t area_len;
if (!(segtype = get_segtype_from_string(lv->vg->cmd, "striped"))) {
stack;
return 0;
}
for (j = 0; j < usp->num_devs; j++) {
/* linear segments only have 1 data area */
if (!(seg = alloc_lv_segment(mem, 1))) {
area_len = (usp->devs[j].blocks) / POOL_PE_SIZE;
if (!(seg = alloc_lv_segment(mem, segtype, lv, *le_cur,
area_len, 0, usp->striping,
NULL, 1, area_len,
POOL_PE_SIZE, 0, 0))) {
log_error("Unable to allocate linear lv_segment "
"structure");
return 0;
}
seg->stripe_size = usp->striping;
seg->le += *le_cur;
seg->chunk_size = POOL_PE_SIZE;
seg->status |= 0;
if (!(seg->segtype = get_segtype_from_string(lv->vg->cmd,
"striped"))) {
stack;
return 0;
}
/* add the subpool type to the segment tag list */
str_list_add(mem, &seg->tags, _cvt_sptype(usp->type));
seg->lv = lv;
seg->area_len = (usp->devs[j].blocks) / POOL_PE_SIZE;
seg->len = seg->area_len;
*le_cur += seg->len;
seg->area[0].type = AREA_PV;
seg->area[0].u.pv.pv = usp->devs[j].pv;
seg->area[0].u.pv.pe = 0;
if (!set_lv_segment_area_pv(seg, 0, usp->devs[j].pv, 0)) {
stack;
return 0;
}
list_add(&lv->segments, &seg->list);
*le_cur += seg->len;
}
return 1;
}
int import_pool_segments(struct list *lvs, struct pool *mem,
int import_pool_segments(struct list *lvs, struct dm_pool *mem,
struct user_subpool *usp, int subpools)
{
struct list *lvhs;
struct lv_list *lvl;
struct logical_volume *lv;
uint32_t le_cur = 0;
int i;
list_iterate(lvhs, lvs) {
lvl = list_item(lvhs, struct lv_list);
list_iterate_items(lvl, lvs) {
lv = lvl->lv;
if (lv->status & SNAPSHOT)
continue;
for (i = 0; i < subpools; i++) {
if (usp[i].striping) {
if (!_add_stripe_seg(mem, &usp[i], lv, &le_cur)) {
@@ -305,5 +314,4 @@ int import_pool_segments(struct list *lvs, struct pool *mem,
}
return 1;
}

View File

@@ -14,7 +14,6 @@
*/
#include "lib.h"
#include "pool.h"
#include "label.h"
#include "metadata.h"
#include "xlate.h"
@@ -24,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;
@@ -51,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;
@@ -65,38 +64,38 @@ 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)
{
dbg_free(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)
{
struct labeller *l;
if (!(l = dbg_malloc(sizeof(*l)))) {
if (!(l = dm_malloc(sizeof(*l)))) {
log_error("Couldn't allocate labeller object.");
return NULL;
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright (C) 1997-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004-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 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
*/
#ifndef SPTYPE_NAMES_H
#define SPTYPE_NAMES_H
/* This must be kept up to date with sistina/pool/module/pool_sptypes.h */
/* Generic Labels */
#define SPTYPE_DATA (0x00000000)
/* GFS specific labels */
#define SPTYPE_GFS_DATA (0x68011670)
#define SPTYPE_GFS_JOURNAL (0x69011670)
struct sptype_name {
const char *name;
uint32_t label;
};
static const struct sptype_name sptype_names[] = {
{"data", SPTYPE_DATA},
{"gfs_data", SPTYPE_GFS_DATA},
{"gfs_journal", SPTYPE_GFS_JOURNAL},
{"", 0x0} /* This must be the last flag. */
};
#endif

View File

@@ -16,9 +16,7 @@
#include "lib.h"
#include "format-text.h"
#include "pool.h"
#include "config.h"
#include "hash.h"
#include "import-export.h"
#include "lvm-string.h"
#include "lvm-file.h"
@@ -53,7 +51,7 @@ struct archive_file {
struct list list;
char *path;
int index;
uint32_t index;
};
/*
@@ -89,9 +87,8 @@ 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 list *bh;
struct archive_file *bf = NULL;
if (list_empty(head)) {
@@ -99,11 +96,9 @@ static void _insert_file(struct list *head, struct archive_file *b)
return;
}
/* index increases through list */
list_iterate(bh, head) {
bf = list_item(bh, struct archive_file);
if (bf->index > b->index) {
/* index reduces through list */
list_iterate_items(bf, head) {
if (b->index > bf->index) {
list_add(&bf->list, &b->list);
return;
}
@@ -112,33 +107,34 @@ static void _insert_file(struct list *head, struct archive_file *b)
list_add_h(&bf->list, &b->list);
}
static char *_join(struct 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 (!pool_begin_object(mem, 32) ||
!pool_grow_object(mem, dir, strlen(dir)) ||
!pool_grow_object(mem, "/", 1) ||
!pool_grow_object(mem, name, strlen(name)) ||
!pool_grow_object(mem, "\0", 1)) {
if (!dm_pool_begin_object(mem, 32) ||
!dm_pool_grow_object(mem, dir, strlen(dir)) ||
!dm_pool_grow_object(mem, "/", 1) ||
!dm_pool_grow_object(mem, name, strlen(name)) ||
!dm_pool_grow_object(mem, "\0", 1)) {
stack;
return NULL;
}
return pool_end_object(mem);
return dm_pool_end_object(mem);
}
/*
* Returns a list of archive_files.
*/
static struct list *_scan_archive(struct pool *mem,
static struct list *_scan_archive(struct dm_pool *mem,
const char *vgname, const char *dir)
{
int i, count, ix;
int i, count;
uint32_t ix;
char vgname_found[64], *path;
struct dirent **dirent;
struct archive_file *af;
struct list *results;
if (!(results = pool_alloc(mem, sizeof(*results)))) {
if (!(results = dm_pool_alloc(mem, sizeof(*results)))) {
stack;
return NULL;
}
@@ -147,13 +143,13 @@ static struct list *_scan_archive(struct pool *mem,
/* Sort fails beyond 5-digit indexes */
if ((count = scandir(dir, &dirent, NULL, alphasort)) < 0) {
log_err("Couldn't scan archive directory.");
log_err("Couldn't scan the archive directory (%s).", dir);
return 0;
}
for (i = 0; i < count; i++) {
/* ignore dot files */
if (dirent[i]->d_name[0] == '.')
if (!strcmp(dirent[i]->d_name, ".") ||
!strcmp(dirent[i]->d_name, ".."))
continue;
/* check the name is the correct format */
@@ -165,7 +161,7 @@ static struct list *_scan_archive(struct 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;
}
@@ -173,7 +169,7 @@ static struct list *_scan_archive(struct pool *mem,
/*
* Create a new archive_file.
*/
if (!(af = pool_alloc(mem, sizeof(*af)))) {
if (!(af = dm_pool_alloc(mem, sizeof(*af)))) {
log_err("Couldn't create new archive file.");
results = NULL;
goto out;
@@ -185,7 +181,7 @@ static struct list *_scan_archive(struct pool *mem,
/*
* Insert it to the correct part of the list.
*/
_insert_file(results, af);
_insert_archive_file(results, af);
}
out:
@@ -199,7 +195,6 @@ static struct list *_scan_archive(struct pool *mem,
static void _remove_expired(struct list *archives, uint32_t archives_size,
uint32_t retain_days, uint32_t min_archive)
{
struct list *bh;
struct archive_file *bf;
struct stat sb;
time_t retain_time;
@@ -212,10 +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(bh, archives) {
bf = list_item(bh, struct archive_file);
/* 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);
@@ -240,7 +233,7 @@ int archive_vg(struct volume_group *vg,
uint32_t retain_days, uint32_t min_archive)
{
int i, fd, renamed = 0;
unsigned int ix = 0;
uint32_t ix = 0;
struct archive_file *last;
FILE *fp = NULL;
char temp_file[PATH_MAX], archive_name[PATH_MAX];
@@ -272,20 +265,20 @@ int archive_vg(struct volume_group *vg,
* Now we want to rename this file to <vg>_index.vg.
*/
if (!(archives = _scan_archive(vg->cmd->mem, vg->name, dir))) {
log_err("Couldn't scan the archive directory (%s).", dir);
stack;
return 0;
}
if (list_empty(archives))
ix = 0;
else {
last = list_item(archives->p, struct archive_file);
last = list_item(list_first(archives), struct archive_file);
ix = last->index + 1;
}
for (i = 0; i < 10; i++) {
if (lvm_snprintf(archive_name, sizeof(archive_name),
"%s/%s_%05d.vg", dir, vg->name, ix) < 0) {
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;
}
@@ -318,7 +311,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;
}
@@ -335,33 +328,30 @@ 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));
pool_free(cmd->mem, vg);
dm_pool_free(cmd->mem, vg);
tf->fmt->ops->destroy_instance(tf);
}
int archive_list(struct cmd_context *cmd, const char *dir, const char *vgname)
{
struct list *archives, *ah;
struct list *archives;
struct archive_file *af;
if (!(archives = _scan_archive(cmd->mem, vgname, dir))) {
log_err("Couldn't scan the archive directory (%s).", dir);
stack;
return 0;
}
if (list_empty(archives))
log_print("No archives found in %s.", dir);
list_iterate(ah, archives) {
af = list_item(ah, struct archive_file);
list_iterate_back_items(af, archives)
_display_archive(cmd, af);
}
pool_free(cmd->mem, archives);
dm_pool_free(cmd->mem, archives);
return 1;
}
@@ -370,7 +360,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

@@ -13,61 +13,72 @@
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "tools.h"
#include "lib.h"
#include "archiver.h"
#include "format-text.h"
#include "lvm-file.h"
#include "lvm-string.h"
#include "lvmcache.h"
#include "toolcontext.h"
static struct {
#include <unistd.h>
struct archive_params {
int enabled;
char *dir;
unsigned int keep_days;
unsigned int keep_number;
};
} _archive_params;
static struct {
struct backup_params {
int enabled;
char *dir;
};
} _backup_params;
int archive_init(const char *dir, unsigned int keep_days, unsigned int keep_min)
int archive_init(struct cmd_context *cmd, const char *dir,
unsigned int keep_days, unsigned int keep_min)
{
_archive_params.dir = NULL;
if (!(cmd->archive_params = dm_pool_zalloc(cmd->libmem,
sizeof(*cmd->archive_params)))) {
log_error("archive_params alloc failed");
return 0;
}
cmd->archive_params->dir = NULL;
if (!*dir)
return 1;
if (!create_dir(dir))
return 0;
if (!(_archive_params.dir = dbg_strdup(dir))) {
if (!(cmd->archive_params->dir = dm_strdup(dir))) {
log_error("Couldn't copy archive directory name.");
return 0;
}
_archive_params.keep_days = keep_days;
_archive_params.keep_number = keep_min;
_archive_params.enabled = 1;
cmd->archive_params->keep_days = keep_days;
cmd->archive_params->keep_number = keep_min;
cmd->archive_params->enabled = 1;
return 1;
}
void archive_exit(void)
void archive_exit(struct cmd_context *cmd)
{
if (_archive_params.dir)
dbg_free(_archive_params.dir);
memset(&_archive_params, 0, sizeof(_archive_params));
if (cmd->archive_params->dir)
dm_free(cmd->archive_params->dir);
memset(cmd->archive_params, 0, sizeof(*cmd->archive_params));
}
void archive_enable(int flag)
void archive_enable(struct cmd_context *cmd, int flag)
{
_archive_params.enabled = flag;
cmd->archive_params->enabled = flag;
}
static char *_build_desc(struct pool *mem, const char *line, int before)
static char *_build_desc(struct dm_pool *mem, const char *line, int before)
{
size_t len = strlen(line) + 32;
char *buffer;
if (!(buffer = pool_zalloc(mem, strlen(line) + 32))) {
if (!(buffer = dm_pool_zalloc(mem, strlen(line) + 32))) {
stack;
return NULL;
}
@@ -91,14 +102,14 @@ static int __archive(struct volume_group *vg)
return 0;
}
return archive_vg(vg, _archive_params.dir, desc,
_archive_params.keep_days,
_archive_params.keep_number);
return archive_vg(vg, vg->cmd->archive_params->dir, desc,
vg->cmd->archive_params->keep_days,
vg->cmd->archive_params->keep_number);
}
int archive(struct volume_group *vg)
{
if (!_archive_params.enabled || !_archive_params.dir)
if (!vg->cmd->archive_params->enabled || !vg->cmd->archive_params->dir)
return 1;
if (test_mode()) {
@@ -106,7 +117,16 @@ int archive(struct volume_group *vg)
return 1;
}
log_verbose("Archiving volume group \"%s\" metadata.", vg->name);
if (!create_dir(vg->cmd->archive_params->dir))
return 0;
/* Trap a read-only file system */
if ((access(vg->cmd->archive_params->dir, R_OK | W_OK | X_OK) == -1) &&
(errno == EROFS))
return 0;
log_verbose("Archiving volume group \"%s\" metadata (seqno %u).", vg->name,
vg->seqno);
if (!__archive(vg)) {
log_error("Volume group \"%s\" metadata archive failed.",
vg->name);
@@ -121,23 +141,26 @@ int archive_display(struct cmd_context *cmd, const char *vg_name)
int r1, r2;
init_partial(1);
r1 = archive_list(cmd, _archive_params.dir, vg_name);
r2 = backup_list(cmd, _backup_params.dir, vg_name);
r1 = archive_list(cmd, cmd->archive_params->dir, vg_name);
r2 = backup_list(cmd, cmd->backup_params->dir, vg_name);
init_partial(0);
return r1 && r2;
}
int backup_init(const char *dir)
int backup_init(struct cmd_context *cmd, const char *dir)
{
_backup_params.dir = NULL;
if (!(cmd->backup_params = dm_pool_zalloc(cmd->libmem,
sizeof(*cmd->archive_params)))) {
log_error("archive_params alloc failed");
return 0;
}
cmd->backup_params->dir = NULL;
if (!*dir)
return 1;
if (!create_dir(dir))
return 0;
if (!(_backup_params.dir = dbg_strdup(dir))) {
if (!(cmd->backup_params->dir = dm_strdup(dir))) {
log_error("Couldn't copy backup directory name.");
return 0;
}
@@ -145,16 +168,16 @@ int backup_init(const char *dir)
return 1;
}
void backup_exit(void)
void backup_exit(struct cmd_context *cmd)
{
if (_backup_params.dir)
dbg_free(_backup_params.dir);
memset(&_backup_params, 0, sizeof(_backup_params));
if (cmd->backup_params->dir)
dm_free(cmd->backup_params->dir);
memset(cmd->backup_params, 0, sizeof(*cmd->backup_params));
}
void backup_enable(int flag)
void backup_enable(struct cmd_context *cmd, int flag)
{
_backup_params.enabled = flag;
cmd->backup_params->enabled = flag;
}
static int __backup(struct volume_group *vg)
@@ -167,8 +190,8 @@ static int __backup(struct volume_group *vg)
return 0;
}
if (lvm_snprintf(name, sizeof(name), "%s/%s",
_backup_params.dir, vg->name) < 0) {
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.");
return 0;
@@ -179,7 +202,7 @@ static int __backup(struct volume_group *vg)
int backup(struct volume_group *vg)
{
if (!_backup_params.enabled || !_backup_params.dir) {
if (!vg->cmd->backup_params->enabled || !vg->cmd->backup_params->dir) {
log_print("WARNING: This metadata update is NOT backed up");
return 1;
}
@@ -189,6 +212,14 @@ int backup(struct volume_group *vg)
return 1;
}
if (!create_dir(vg->cmd->backup_params->dir))
return 0;
/* Trap a read-only file system */
if ((access(vg->cmd->backup_params->dir, R_OK | W_OK | X_OK) == -1) &&
(errno == EROFS))
return 0;
if (!__backup(vg)) {
log_error("Backup of volume group %s metadata failed.",
vg->name);
@@ -198,12 +229,12 @@ int backup(struct volume_group *vg)
return 1;
}
int backup_remove(const char *vg_name)
int backup_remove(struct cmd_context *cmd, const char *vg_name)
{
char path[PATH_MAX];
if (lvm_snprintf(path, sizeof(path), "%s/%s",
_backup_params.dir, vg_name) < 0) {
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;
}
@@ -226,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;
}
@@ -255,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;
}
@@ -269,7 +300,7 @@ int backup_restore_vg(struct cmd_context *cmd, struct volume_group *vg)
return 0;
}
if (cmd->fmt != info->fmt) {
log_error("PV %s is a different format (%s)",
log_error("PV %s is a different format (seqno %s)",
dev_name(pv->dev), info->fmt->name);
return 0;
}
@@ -311,8 +342,8 @@ int backup_restore(struct cmd_context *cmd, const char *vg_name)
{
char path[PATH_MAX];
if (lvm_snprintf(path, sizeof(path), "%s/%s",
_backup_params.dir, vg_name) < 0) {
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;
}
@@ -330,11 +361,11 @@ int backup_to_file(const char *file, const char *desc, struct volume_group *vg)
cmd = vg->cmd;
log_verbose("Creating volume group backup \"%s\"", file);
log_verbose("Creating volume group backup \"%s\" (seqno %u).", file, vg->seqno);
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;
}
@@ -354,3 +385,34 @@ int backup_to_file(const char *file, const char *desc, struct volume_group *vg)
tf->fmt->ops->destroy_instance(tf);
return r;
}
/*
* Update backup (and archive) if they're out-of-date or don't exist.
*/
void check_current_backup(struct volume_group *vg)
{
char path[PATH_MAX];
struct volume_group *vg_backup;
if ((vg->status & PARTIAL_VG) || (vg->status & EXPORTED_VG))
return;
if (dm_snprintf(path, sizeof(path), "%s/%s",
vg->cmd->backup_params->dir, vg->name) < 0) {
log_debug("Failed to generate backup filename.");
return;
}
log_suppress(1);
/* Up-to-date backup exists? */
if ((vg_backup = backup_read_vg(vg->cmd, vg->name, path)) &&
(vg->seqno == vg_backup->seqno) &&
(id_equal(&vg->id, &vg_backup->id)))
return;
log_suppress(0);
if (vg_backup)
archive(vg_backup);
archive(vg);
backup(vg);
}

View File

@@ -18,11 +18,6 @@
#include "metadata.h"
/*
* FIXME: This file is going to merge with the archiving code in
* lib/format_text at some point.
*/
/*
* There are two operations that come under the general area of
* backups. 'Archiving' occurs just before a volume group
@@ -36,20 +31,20 @@
* Typically backups will be stored in /etc/lvm/backups.
*/
int archive_init(const char *dir,
int archive_init(struct cmd_context *cmd, const char *dir,
unsigned int keep_days, unsigned int keep_min);
void archive_exit(void);
void archive_exit(struct cmd_context *cmd);
void archive_enable(int flag);
void archive_enable(struct cmd_context *cmd, int flag);
int archive(struct volume_group *vg);
int archive_display(struct cmd_context *cmd, const char *vg_name);
int backup_init(const char *dir);
void backup_exit(void);
int backup_init(struct cmd_context *cmd, const char *dir);
void backup_exit(struct cmd_context *cmd);
void backup_enable(int flag);
void backup_enable(struct cmd_context *cmd, int flag);
int backup(struct volume_group *vg);
int backup_remove(const char *vg_name);
int backup_remove(struct cmd_context *cmd, const char *vg_name);
struct volume_group *backup_read_vg(struct cmd_context *cmd,
const char *vg_name, const char *file);
@@ -60,4 +55,6 @@ int backup_restore(struct cmd_context *cmd, const char *vg_name);
int backup_to_file(const char *file, const char *desc, struct volume_group *vg);
void check_current_backup(struct volume_group *vg);
#endif

View File

@@ -16,8 +16,6 @@
#include "lib.h"
#include "import-export.h"
#include "metadata.h"
#include "hash.h"
#include "pool.h"
#include "display.h"
#include "lvm-string.h"
#include "segtype.h"
@@ -30,19 +28,32 @@
struct formatter;
typedef int (*out_with_comment_fn) (struct formatter * f, const char *comment,
const char *fmt, va_list ap);
typedef void (*nl_fn) (struct formatter * f);
typedef int (*nl_fn) (struct formatter * f);
/*
* Macro for formatted output.
* out_with_comment_fn returns -1 if data didn't fit and buffer was expanded.
* Then argument list is reset and out_with_comment_fn is called again.
*/
#define _out_with_comment(f, buffer, fmt, ap) \
do { \
va_start(ap, fmt); \
r = f->out_with_comment(f, buffer, fmt, ap); \
va_end(ap); \
} while (r == -1)
/*
* The first half of this file deals with
* exporting the vg, ie. writing it to a file.
*/
struct formatter {
struct pool *mem; /* pv names allocated from here */
struct hash_table *pv_names; /* dev_name -> pv_name (eg, pv1) */
struct dm_pool *mem; /* pv names allocated from here */
struct dm_hash_table *pv_names; /* dev_name -> pv_name (eg, pv1) */
union {
FILE *fp; /* where we're writing to */
struct {
char *buf;
char *start;
uint32_t size;
uint32_t used;
} buf;
@@ -95,22 +106,45 @@ static void _dec_indent(struct formatter *f)
/*
* Newline function for prettier layout.
*/
static void _nl_file(struct formatter *f)
static int _nl_file(struct formatter *f)
{
fprintf(f->data.fp, "\n");
return 1;
}
static void _nl_raw(struct formatter *f)
static int _extend_buffer(struct formatter *f)
{
if (f->data.buf.used >= f->data.buf.size - 1)
return;
char *newbuf;
*f->data.buf.buf = '\n';
f->data.buf.buf += 1;
log_debug("Doubling metadata output buffer to %" PRIu32,
f->data.buf.size * 2);
if (!(newbuf = dm_realloc(f->data.buf.start,
f->data.buf.size * 2))) {
log_error("Buffer reallocation failed.");
return 0;
}
f->data.buf.start = newbuf;
f->data.buf.size *= 2;
return 1;
}
static int _nl_raw(struct formatter *f)
{
/* If metadata doesn't fit, extend buffer */
if ((f->data.buf.used + 2 > f->data.buf.size) &&
(!_extend_buffer(f))) {
stack;
return 0;
}
*(f->data.buf.start + f->data.buf.used) = '\n';
f->data.buf.used += 1;
*f->data.buf.buf = '\0';
return;
*(f->data.buf.start + f->data.buf.used) = '\0';
return 1;
}
#define COMMENT_TAB 6
@@ -149,21 +183,27 @@ 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;
n = vsnprintf(f->data.buf.buf, f->data.buf.size - f->data.buf.used,
fmt, ap);
n = vsnprintf(f->data.buf.start + f->data.buf.used,
f->data.buf.size - f->data.buf.used, fmt, ap);
if (n < 0 || (n > f->data.buf.size - f->data.buf.used - 1))
return 0;
/* If metadata doesn't fit, extend buffer */
if (n < 0 || (n + f->data.buf.used + 2 > f->data.buf.size)) {
if (!_extend_buffer(f)) {
stack;
return 0;
}
return -1; /* Retry */
}
f->data.buf.buf += n;
f->data.buf.used += n;
f->nl(f);
outnl(f);
return 1;
}
@@ -181,6 +221,8 @@ static int _sectors_to_units(uint64_t sectors, char *buffer, size_t s)
"Megabytes",
"Gigabytes",
"Terabytes",
"Petabytes",
"Exabytes",
NULL
};
@@ -193,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;
}
/*
@@ -209,9 +251,7 @@ int out_size(struct formatter *f, uint64_t size, const char *fmt, ...)
if (!_sectors_to_units(size, buffer, sizeof(buffer)))
return 0;
va_start(ap, fmt);
r = f->out_with_comment(f, buffer, fmt, ap);
va_end(ap);
_out_with_comment(f, buffer, fmt, ap);
return r;
}
@@ -225,9 +265,7 @@ int out_hint(struct formatter *f, const char *fmt, ...)
va_list ap;
int r;
va_start(ap, fmt);
r = f->out_with_comment(f, "# Hint only", fmt, ap);
va_end(ap);
_out_with_comment(f, "# Hint only", fmt, ap);
return r;
}
@@ -240,15 +278,13 @@ int out_text(struct formatter *f, const char *fmt, ...)
va_list ap;
int r;
va_start(ap, fmt);
r = f->out_with_comment(f, NULL, fmt, ap);
va_end(ap);
_out_with_comment(f, NULL, fmt, ap);
return r;
}
static int _print_header(struct formatter *f,
struct volume_group *vg, const char *desc)
const char *desc)
{
time_t t;
@@ -257,10 +293,10 @@ static int _print_header(struct formatter *f,
outf(f, "# Generated by LVM2: %s", ctime(&t));
outf(f, CONTENTS_FIELD " = \"" CONTENTS_VALUE "\"");
outf(f, FORMAT_VERSION_FIELD " = %d", FORMAT_VERSION_VALUE);
f->nl(f);
outnl(f);
outf(f, "description = \"%s\"", desc);
f->nl(f);
outnl(f);
outf(f, "creation_host = \"%s\"\t# %s %s %s %s %s", _utsname.nodename,
_utsname.sysname, _utsname.nodename, _utsname.release,
_utsname.version, _utsname.machine);
@@ -309,7 +345,7 @@ static int _print_vg(struct formatter *f, struct volume_group *vg)
/* Default policy is NORMAL; INHERIT is meaningless */
if (vg->alloc != ALLOC_NORMAL && vg->alloc != ALLOC_INHERIT) {
f->nl(f);
outnl(f);
outf(f, "allocation_policy = \"%s\"",
get_alloc_string(vg->alloc));
}
@@ -321,16 +357,15 @@ 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 *)
hash_lookup(f->pv_names, dev_name(pv->dev)) : "Missing";
dm_hash_lookup(f->pv_names, dev_name(pv->dev)) : "Missing";
}
static int _print_pvs(struct formatter *f, struct volume_group *vg)
{
struct list *pvh;
struct pv_list *pvl;
struct physical_volume *pv;
char buffer[4096];
const char *name;
@@ -338,15 +373,15 @@ static int _print_pvs(struct formatter *f, struct volume_group *vg)
outf(f, "physical_volumes {");
_inc_indent(f);
list_iterate(pvh, &vg->pvs) {
pv = list_item(pvh, struct pv_list)->pv;
list_iterate_items(pvl, &vg->pvs) {
pv = pvl->pv;
if (!(name = _get_pv_name(f, pv))) {
stack;
return 0;
}
f->nl(f);
outnl(f);
outf(f, "%s {", name);
_inc_indent(f);
@@ -360,7 +395,7 @@ static int _print_pvs(struct formatter *f, struct volume_group *vg)
stack;
return 0;
}
f->nl(f);
outnl(f);
if (!print_flags(pv->status, PV_FLAGS, buffer, sizeof(buffer))) {
stack;
@@ -376,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)) {
@@ -407,7 +447,7 @@ static int _print_segment(struct formatter *f, struct volume_group *vg,
return 0;
}
f->nl(f);
outnl(f);
outf(f, "type = \"%s\"", seg->segtype->name);
if (!list_empty(&seg->tags)) {
@@ -436,28 +476,31 @@ int out_areas(struct formatter *f, const struct lv_segment *seg,
const char *name;
unsigned int s;
f->nl(f);
outnl(f);
outf(f, "%ss = [", type);
_inc_indent(f);
for (s = 0; s < seg->area_count; s++) {
switch (seg->area[s].type) {
switch (seg_type(seg, s)) {
case AREA_PV:
if (!(name = _get_pv_name(f, seg->area[s].u.pv.pv))) {
if (!(name = _get_pv_name(f, seg_pv(seg, s)))) {
stack;
return 0;
}
outf(f, "\"%s\", %u%s", name,
seg->area[s].u.pv.pe,
seg_pe(seg, s),
(s == seg->area_count - 1) ? "" : ",");
break;
case AREA_LV:
outf(f, "\"%s\", %u%s",
seg->area[s].u.lv.lv->name,
seg->area[s].u.lv.le,
seg_lv(seg, s)->name,
seg_le(seg, s),
(s == seg->area_count - 1) ? "" : ",");
break;
case AREA_UNASSIGNED:
return 0;
}
}
@@ -466,72 +509,57 @@ int out_areas(struct formatter *f, const struct lv_segment *seg,
return 1;
}
static int _count_segments(struct logical_volume *lv)
static int _print_lv(struct formatter *f, struct logical_volume *lv)
{
int r = 0;
struct list *segh;
struct lv_segment *seg;
char buffer[4096];
int seg_count;
list_iterate(segh, &lv->segments)
r++;
return r;
}
static int _print_snapshot(struct formatter *f, struct snapshot *snap,
unsigned int count)
{
char buffer[256];
struct lv_segment seg;
f->nl(f);
outf(f, "snapshot%u {", count);
outnl(f);
outf(f, "%s {", lv->name);
_inc_indent(f);
if (!id_write_format(&snap->id, buffer, sizeof(buffer))) {
/* FIXME: Write full lvid */
if (!id_write_format(&lv->lvid.id[1], buffer, sizeof(buffer))) {
stack;
return 0;
}
outf(f, "id = \"%s\"", buffer);
seg.status = LVM_READ | LVM_WRITE | VISIBLE_LV;
if (!print_flags(seg.status, LV_FLAGS, buffer, sizeof(buffer))) {
if (!print_flags(lv->status, LV_FLAGS, buffer, sizeof(buffer))) {
stack;
return 0;
}
outf(f, "status = %s", buffer);
outf(f, "segment_count = 1");
f->nl(f);
if (!(seg.segtype = get_segtype_from_string(snap->origin->vg->cmd,
"snapshot"))) {
stack;
return 0;
if (!list_empty(&lv->tags)) {
if (!print_tags(&lv->tags, buffer, sizeof(buffer))) {
stack;
return 0;
}
outf(f, "tags = %s", buffer);
}
seg.le = 0;
seg.len = snap->origin->le_count;
seg.origin = snap->origin;
seg.cow = snap->cow;
seg.chunk_size = snap->chunk_size;
if (lv->alloc != ALLOC_INHERIT)
outf(f, "allocation_policy = \"%s\"",
get_alloc_string(lv->alloc));
/* FIXME Dummy values */
list_init(&seg.list);
seg.lv = snap->cow;
seg.stripe_size = 0;
seg.area_count = 0;
seg.area_len = 0;
seg.extents_copied = 0;
if (lv->read_ahead)
outf(f, "read_ahead = %u", lv->read_ahead);
if (lv->major >= 0)
outf(f, "major = %d", lv->major);
if (lv->minor >= 0)
outf(f, "minor = %d", lv->minor);
outf(f, "segment_count = %u", list_size(&lv->segments));
outnl(f);
/* Can't tag a snapshot independently of its origin */
list_init(&seg.tags);
if (!_print_segment(f, snap->origin->vg, 1, &seg)) {
stack;
return 0;
seg_count = 1;
list_iterate_items(seg, &lv->segments) {
if (!_print_segment(f, lv->vg, seg_count++, seg)) {
stack;
return 0;
}
}
_dec_indent(f);
@@ -540,31 +568,9 @@ static int _print_snapshot(struct formatter *f, struct snapshot *snap,
return 1;
}
static int _print_snapshots(struct formatter *f, struct volume_group *vg)
{
struct list *sh;
struct snapshot *s;
unsigned int count = 0;
list_iterate(sh, &vg->snapshots) {
s = list_item(sh, struct snapshot_list)->snapshot;
if (!_print_snapshot(f, s, count++)) {
stack;
return 0;
}
}
return 1;
}
static int _print_lvs(struct formatter *f, struct volume_group *vg)
{
struct list *lvh;
struct logical_volume *lv;
struct lv_segment *seg;
char buffer[4096];
int seg_count;
struct lv_list *lvl;
/*
* Don't bother with an lv section if there are no lvs.
@@ -575,63 +581,25 @@ static int _print_lvs(struct formatter *f, struct volume_group *vg)
outf(f, "logical_volumes {");
_inc_indent(f);
list_iterate(lvh, &vg->lvs) {
lv = list_item(lvh, struct lv_list)->lv;
f->nl(f);
outf(f, "%s {", lv->name);
_inc_indent(f);
/* FIXME: Write full lvid */
if (!id_write_format(&lv->lvid.id[1], buffer, sizeof(buffer))) {
/*
* Write visible LVs first
*/
list_iterate_items(lvl, &vg->lvs) {
if (!(lvl->lv->status & VISIBLE_LV))
continue;
if (!_print_lv(f, lvl->lv)) {
stack;
return 0;
}
outf(f, "id = \"%s\"", buffer);
if (!print_flags(lv->status, LV_FLAGS, buffer, sizeof(buffer))) {
stack;
return 0;
}
outf(f, "status = %s", buffer);
if (!list_empty(&lv->tags)) {
if (!print_tags(&lv->tags, buffer, sizeof(buffer))) {
stack;
return 0;
}
outf(f, "tags = %s", buffer);
}
if (lv->alloc != ALLOC_INHERIT)
outf(f, "allocation_policy = \"%s\"",
get_alloc_string(lv->alloc));
if (lv->read_ahead)
outf(f, "read_ahead = %u", lv->read_ahead);
if (lv->major >= 0)
outf(f, "major = %d", lv->major);
if (lv->minor >= 0)
outf(f, "minor = %d", lv->minor);
outf(f, "segment_count = %u", _count_segments(lv));
f->nl(f);
seg_count = 1;
list_iterate_items(seg, &lv->segments) {
if (!_print_segment(f, vg, seg_count++, seg)) {
stack;
return 0;
}
}
_dec_indent(f);
outf(f, "}");
}
if (!_print_snapshots(f, vg)) {
stack;
return 0;
list_iterate_items(lvl, &vg->lvs) {
if ((lvl->lv->status & VISIBLE_LV))
continue;
if (!_print_lv(f, lvl->lv)) {
stack;
return 0;
}
}
_dec_indent(f);
@@ -648,50 +616,31 @@ static int _print_lvs(struct formatter *f, struct volume_group *vg)
static int _build_pv_names(struct formatter *f, struct volume_group *vg)
{
int count = 0;
struct list *pvh;
struct pv_list *pvl;
struct physical_volume *pv;
char buffer[32], *name;
if (!(f->mem = 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 = hash_create(128))) {
stack;
goto bad;
}
if (!(f->pv_names = dm_hash_create(128)))
return_0;
list_iterate(pvh, &vg->pvs) {
pv = list_item(pvh, struct pv_list)->pv;
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 = pool_strdup(f->mem, buffer))) {
stack;
goto bad;
}
if (!(name = dm_pool_strdup(f->mem, buffer)))
return_0;
if (!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)
pool_destroy(f->mem);
if (f->pv_names)
hash_destroy(f->pv_names);
return 0;
}
static int _text_vg_export(struct formatter *f,
@@ -703,43 +652,41 @@ 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;
f->nl(f);
outnl(f);
if (!_print_pvs(f, vg))
fail;
goto_out;
f->nl(f);
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:
if (f->mem)
pool_destroy(f->mem);
dm_pool_destroy(f->mem);
if (f->pv_names)
hash_destroy(f->pv_names);
dm_hash_destroy(f->pv_names);
return r;
}
@@ -751,7 +698,7 @@ int text_vg_export_file(struct volume_group *vg, const char *desc, FILE *fp)
_init();
if (!(f = dbg_malloc(sizeof(*f)))) {
if (!(f = dm_malloc(sizeof(*f)))) {
stack;
return 0;
}
@@ -766,27 +713,31 @@ int text_vg_export_file(struct volume_group *vg, const char *desc, FILE *fp)
r = _text_vg_export(f, vg, desc);
if (r)
r = !ferror(f->data.fp);
dbg_free(f);
dm_free(f);
return r;
}
/* Returns amount of buffer used incl. terminating NUL */
int text_vg_export_raw(struct volume_group *vg, const char *desc, char *buf,
uint32_t size)
int text_vg_export_raw(struct volume_group *vg, const char *desc, char **buf)
{
struct formatter *f;
int r;
int r = 0;
_init();
if (!(f = dbg_malloc(sizeof(*f)))) {
if (!(f = dm_malloc(sizeof(*f)))) {
stack;
return 0;
}
memset(f, 0, sizeof(*f));
f->data.buf.buf = buf;
f->data.buf.size = size;
f->data.buf.size = 65536; /* Initial metadata limit */
if (!(f->data.buf.start = dm_malloc(f->data.buf.size))) {
log_error("text_export buffer allocation failed");
goto out;
}
f->indent = 0;
f->header = 0;
f->out_with_comment = &_out_with_comment_raw;
@@ -794,15 +745,17 @@ int text_vg_export_raw(struct volume_group *vg, const char *desc, char *buf,
if (!_text_vg_export(f, vg, desc)) {
stack;
r = 0;
dm_free(f->data.buf.start);
goto out;
}
r = f->data.buf.used + 1;
*buf = f->data.buf.start;
out:
dbg_free(f);
dm_free(f);
return r;
}
#undef outf
#undef outnl

View File

@@ -36,6 +36,7 @@ static struct flag _vg_flags[] = {
{LVM_WRITE, "WRITE"},
{CLUSTERED, "CLUSTERED"},
{SHARED, "SHARED"},
{PRECOMMITTED, NULL},
{0, NULL}
};
@@ -52,8 +53,13 @@ static struct flag _lv_flags[] = {
{VISIBLE_LV, "VISIBLE"},
{PVMOVE, "PVMOVE"},
{LOCKED, "LOCKED"},
{MIRROR_NOTSYNCED, "NOTSYNCED"},
{MIRROR_IMAGE, NULL},
{MIRROR_LOG, NULL},
{MIRRORED, NULL},
{VIRTUAL, NULL},
{SNAPSHOT, NULL},
{ACTIVATE_EXCL, NULL},
{0, NULL}
};

File diff suppressed because it is too large Load Diff

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