1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-12-24 16:23:50 +03:00

Compare commits

...

152 Commits

Author SHA1 Message Date
Alasdair Kergon
5571ff35d8 pre-release 2007-07-13 16:07:30 +00:00
Dave Wysochanski
2a4819f3c8 Change pv_read_path to pv_by_path 2007-07-12 15:38:53 +00:00
Dave Wysochanski
7121866b13 Turn _add_pv_to_vg() into external library function add_pv_to_vg() 2007-07-12 05:04:42 +00:00
Dave Wysochanski
d6e05ad9e2 Refactor vg_extend error path. 2007-07-12 04:12:04 +00:00
Dave Wysochanski
993e30a7de Add pv_read_path, a proposed external LVM library function to take a device path and return a PV handle 2007-07-11 23:33:12 +00:00
Patrick Caulfield
49cae61254 Tidy bits of clvmd-openais and improve an error report. 2007-07-11 12:07:39 +00:00
Alasdair Kergon
1ea4b2ea91 Cope with find_seg_by_le() failure in check_lv_segments(). 2007-07-10 18:50:03 +00:00
Alasdair Kergon
bc1d6e1f90 tidy 2007-07-10 18:20:00 +00:00
Alasdair Kergon
9ec6e68d0c Fix pv_mda_count to cope with missing PV.
[vgcreate vg1 pv1 pv2; pvremove -ff pv1; pvs -P -o+pv_mda_count =>segfault]
2007-07-10 18:18:33 +00:00
Alasdair Kergon
341bdc93e2 Call dev_iter_destroy() if _process_all_devs() is interrupted by sigint. 2007-07-10 17:51:26 +00:00
Alasdair Kergon
6fb3e1aa15 Add vg_mda_count and pv_mda_count columns to reports. 2007-07-09 15:40:43 +00:00
Alasdair Kergon
f1f92eb2e2 Fix dumpconfig to use log_print instead of stdout directly. 2007-07-08 22:51:20 +00:00
Dave Wysochanski
8c2369d40f Fix WHATS_NEW for last checkin until further patches for LVM library are ready. 2007-07-03 13:10:14 +00:00
Dave Wysochanski
a6d9fc58eb Convert _add_pv_to_vg to usable LVM library function. 2007-07-02 21:48:30 +00:00
Milan Broz
f7cd471548 Add kernel and device-mapper targets versions report to lvmdump. 2007-07-02 20:18:38 +00:00
Dave Wysochanski
5f951faf32 Don't use index and rindex functions marked by SUSv3 as legacy - Jakub Bogusz <qboosh@pld-linux.org> 2007-07-02 11:17:21 +00:00
Milan Broz
b228dfaf2c Fix vgsplit if splitting all PVs from VG. 2007-06-28 17:59:34 +00:00
Petr Rockai
764858fa12 Make warnings go to stderr. Change log_warn to that effect, log_print
continues to send messages to stdout.
2007-06-28 17:33:44 +00:00
Petr Rockai
5ee976d276 Make warnings go to stderr. Adds log_warn macro for that purpose,
log_print continues to print to stdout.
2007-06-28 17:27:02 +00:00
Bryn M. Reeves
8b28b6f2d3 Fix lvmdiskscan volume reporting when run in the lvm shell 2007-06-25 13:19:37 +00:00
Patrick Caulfield
fe16df2e6f Use cpg_local_get() rather then Clm to get the local nodeid. 2007-06-25 09:02:37 +00:00
Alasdair Kergon
779047f8c9 revert accidental change 2007-06-19 16:50:38 +00:00
Alasdair Kergon
094e9fb45d Fix dmsetup -o devno string termination. (1.02.20) 2007-06-19 15:47:20 +00:00
Milan Broz
1458bd0e74 Fix missing lvm_shell symbol in lvm2cmd library. (2.02.23) 2007-06-19 10:51:51 +00:00
Dave Wysochanski
d2cb05988d Convert vg->status checks to use vg_check_status function.\nRename status_flags to status in vg_check_status. 2007-06-19 04:36:12 +00:00
Dave Wysochanski
6e056767b4 Add vg_status function and clean up vg->status in tools directory 2007-06-19 04:23:32 +00:00
Dave Wysochanski
a10afb1b98 Make vg_extend() format_instance * parameter internal to vg_extend() 2007-06-19 00:33:43 +00:00
Alasdair Kergon
bb6d3b6cfd Add --ignoremonitoring to disable all dmeventd interaction. 2007-06-18 14:14:33 +00:00
Dave Wysochanski
c75d4af4bc Remove get_ prefix from get_pv_* functions 2007-06-15 22:16:55 +00:00
Alasdair Kergon
972dc39d00 post-release 2007-06-15 20:49:30 +00:00
Alasdair Kergon
9daac5c178 pre-release 2007-06-15 20:46:04 +00:00
Alasdair Kergon
dd2a3f40e1 pre-release 2007-06-15 19:05:02 +00:00
Alasdair Kergon
78f76c1690 Fix default dmsetup report buffering and add --unbuffered.
Add tree-based and dependency fields to dmsetup reports.
2007-06-15 18:20:28 +00:00
Dave Wysochanski
4788066a5f Update vgcfgrestore man pg 2007-06-15 16:05:57 +00:00
Petr Rockai
10e4254e7d Allow keyboard interrupts in yes_no_prompt(). Add code to toollib.c
loops and to pvcreate.c, lvchange.c and lvresize.c to handle
interrupted prompts.
2007-06-15 10:11:14 +00:00
Dave Wysochanski
0106e4df9d Fix inverted logic on last checkin for pvremove 2007-06-14 15:51:36 +00:00
Dave Wysochanski
8ac718a3a2 convert pv->vg_name[0] to \!is_orphan(pv) 2007-06-14 15:48:05 +00:00
Dave Wysochanski
46d45273a1 Convert pv->vg_name to get_pv_vg_name 2007-06-14 15:25:36 +00:00
Patrick Caulfield
8da9ec3599 Remove system-lv.[ch] 2007-06-14 10:17:12 +00:00
Patrick Caulfield
01fdf84d69 Remove system LV code from clvmd. It's never been used and never should be
used! It's removal tidies a number of code paths inside clvmd.
2007-06-14 10:16:35 +00:00
Dave Wysochanski
cc78386e75 Update WHATS_NEW for get_pv* conversions 2007-06-13 23:57:15 +00:00
Dave Wysochanski
3755157c61 Convert pv->vg_name to get_pv_vg_name 2007-06-13 23:53:38 +00:00
Dave Wysochanski
80f8436f0a Convert pv->status to get_pv_status 2007-06-13 23:33:45 +00:00
Dave Wysochanski
f88a4b7760 Convert pv->dev to get_pv_dev 2007-06-13 23:29:33 +00:00
Dave Wysochanski
de229b8ab0 Convert pv->size to get_pv_size 2007-06-13 23:02:51 +00:00
Dave Wysochanski
a3ba37e45e Convert existing_pv dereferences to get_pv_* 2007-06-13 22:58:32 +00:00
Dave Wysochanski
50c779b3c6 Convert pv->pe_size to get_pv_pe_size 2007-06-13 22:30:26 +00:00
Dave Wysochanski
192372e1c3 Convert pv->pe_start to get_pv_pe_start 2007-06-13 22:16:27 +00:00
Dave Wysochanski
f88fd88c38 Convert pv->pe_count to get_pv_pe_count 2007-06-13 22:11:29 +00:00
Dave Wysochanski
6e15145af1 Convert pv->pe_alloc_count to get_pv_pe_alloc_count 2007-06-13 22:04:45 +00:00
Dave Wysochanski
4b5fad4e48 Remove casts in pv_create and find_pv_in_vg_by_uuid 2007-06-13 21:14:07 +00:00
Dave Wysochanski
7a13e71c80 Convert pv_handle_t to pv_t * and tidy up whitespace 2007-06-13 20:55:56 +00:00
Dave Wysochanski
3c10943900 Add typedef pv_handle_t 2007-06-13 19:52:48 +00:00
Dave Wysochanski
696b8811c2 Fix a couple benign warnings by adding variable initializations. 2007-06-13 15:11:19 +00:00
Dave Wysochanski
9fd2c8602a Convert find_pv_in_vg_by_uuid and pv_create to use PV handles 2007-06-12 22:41:27 +00:00
Dave Wysochanski
a3636a5af4 Change PV_HANDLE_DEREF to pv_field and add paren's 2007-06-12 21:39:49 +00:00
Dave Wysochanski
f2e5f07718 Add get_pv_* functions to return PV fields in prep for external LVM library 2007-06-12 21:20:20 +00:00
Dave Wysochanski
16c6fdde60 Add wrappers to functions related to pv commands in preparation for exported LVM lib 2007-06-11 18:29:30 +00:00
Alasdair Kergon
2155c93426 Add capability for tree-based fields to dmsetup reports. 2007-06-11 13:20:29 +00:00
Bryn M. Reeves
c394631e4c Allow vgcfgrestore to list metadata backup files using -f 2007-06-08 22:38:48 +00:00
Dave Wysochanski
8b370b7cc1 Add vg_check_status to consolidate vg status flags checks and error messages. 2007-06-06 19:40:28 +00:00
Dave Wysochanski
607db9971c make code consistent with pvresize code - good candidate for common code cleanup 2007-06-05 18:23:17 +00:00
Dave Wysochanski
6768f64e2f Fix pvdisplay --maps to not display segment header for orphan PVs. 2007-05-31 20:26:11 +00:00
Dave Wysochanski
f1813b1cc6 Fix redundant segment display when PV is given to 'pvdisplay --maps' cmdline. 2007-05-31 20:10:25 +00:00
Dave Wysochanski
fb665bd0dd Remove 'Type' from pvdisplay --maps as there is no 'Type' of a physical segment, only logical segments 2007-05-31 15:18:44 +00:00
Dave Wysochanski
65dda2ef3d Small fixes to pvdisplay --maps: 1) rename struct pv_segment vars from 'seg' to 'pvseg', 2) Change heading 2007-05-31 14:19:57 +00:00
Dave Wysochanski
b162b992af Add --maps to pvdisplay.
Modified original patch from David Robinson <zxvdr.au@gmail.com>.
2007-05-30 20:43:09 +00:00
Dave Wysochanski
67a3a3d130 Fix vgcfgrestore man pg to show mandatory VG name and remove LVM1 options. 2007-05-22 02:52:57 +00:00
Dave Wysochanski
92cd9bf7d2 Fix vgrename man page to include UUID and be more consistent with lvrename. 2007-05-22 02:51:33 +00:00
Patrick Caulfield
bf97034485 Add *Experimental* OpenAIS support to clvmd. 2007-05-21 10:52:01 +00:00
Milan Broz
1ded1fc509 Remove symlinks if parent volume is deactivated. 2007-05-15 14:42:01 +00:00
Milan Broz
e0592c58b3 Fix and clarify vgsplit error messages. 2007-05-15 13:01:41 +00:00
Milan Broz
5ead2706b4 Fix a segfault if a device has no target (no table) 2007-05-14 11:27:34 +00:00
Patrick Caulfield
52ada4853c Misc clvmd cleanups from Jim Meyering 2007-05-02 12:22:40 +00:00
Patrick Caulfield
c2b27a8298 Add some more debuglogs to clvmd startup. 2007-05-02 08:23:36 +00:00
Alasdair Kergon
3934c1d437 post-release 2007-04-27 20:58:45 +00:00
Alasdair Kergon
e366b68ad3 pre-release 2007-04-27 20:47:14 +00:00
Alasdair Kergon
fb94fb980a Fix get_config_uint64() to read a 64-bit value not a 32-bit one. 2007-04-27 20:41:50 +00:00
Alasdair Kergon
b10cc18f53 Add -Wformat-security and change one fprintf() to fputs(). 2007-04-27 19:26:57 +00:00
Alasdair Kergon
a249de3b72 Standardise protective include file #defines. 2007-04-27 19:07:43 +00:00
Alasdair Kergon
d04e972d65 Move regex functions into libdevmapper. 2007-04-27 18:52:05 +00:00
Alasdair Kergon
b9f5a18a76 Add regex functions to library. 2007-04-27 18:40:23 +00:00
Alasdair Kergon
d3f157f08a configure.h isn't a system header 2007-04-27 18:01:45 +00:00
Alasdair Kergon
2294fdb496 Change some #include lines to search only standard system directories. 2007-04-27 17:46:16 +00:00
Alasdair Kergon
d7ba0e01a5 Avoid trailing separator in reports when there are hidden sort fields. 2007-04-27 15:22:27 +00:00
Alasdair Kergon
b6172b53fd Fix segfault in 'dmsetup status' without --showkeys against crypt target. [nec] 2007-04-27 15:12:26 +00:00
Alasdair Kergon
477ec611d5 Deal with some more compiler warnings. Hope this doesn't break anything... 2007-04-27 14:52:41 +00:00
Alasdair Kergon
b6194edd67 add preferred_names to man page. 2007-04-26 17:14:57 +00:00
Alasdair Kergon
dcdbbb3ecb Add devices/preferred_names config regex list for displayed device names.
Free a temporary dir string in fcntl_lock_file() after use.
Fix a dm_pool_destroy() in matcher_create().
Introduce goto_bad macro.
2007-04-26 16:44:59 +00:00
Dave Wysochanski
7ef99ee4e6 Fix warnings on x86_64 involving ptrdiff_t:
config/config.c:493: warning: format '%d' expects type 'int', but argument 5 has type 'long int'

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

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

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

--
2007-04-25 18:24:19 +00:00
Bryn M. Reeves
9d67bbb104 Make lvm_dump.sh capture a listing of /sys/block entries. 2007-04-25 14:49:27 +00:00
Patrick Caulfield
d6c8e1df61 Fix thread race in clvmd. 2007-04-24 15:13:13 +00:00
Petr Rockai
5ec7c8fece Fix the regression introduced by dmeventd leak fixes. 2007-04-24 13:29:02 +00:00
Dave Wysochanski
86b21eaf83 Add 'scan_sector' parameter to label_read and _find_labeller to add
flexibility in searching for disk labels.
2007-04-23 18:21:01 +00:00
Petr Rockai
228486a971 Fix some memory leaks in dmeventd. 2007-04-23 15:06:03 +00:00
Patrick Caulfield
88c0caab26 Make clvmd cope with quorum devices in RHEL5
bz#237386
2007-04-23 14:55:28 +00:00
Bryn M. Reeves
5cd4679419 re-commit lvm_dump.sh change 2007-04-19 23:06:05 +00:00
Bryn M. Reeves
eeed5e0d19 Make lvm_dump.sh list /dev recursively to aid identifying devices. 2007-04-19 22:56:16 +00:00
Alasdair Kergon
369ab1e0b2 Introduce _add_field() and _is_same_field() to libdm-report.c. 2007-04-19 20:24:00 +00:00
Milan Broz
2e21519a10 Fix libdevmapper-event memory leaks 2007-04-19 19:10:19 +00:00
Dave Wysochanski
ecc001ed08 Add dev_read_circular, read 2 regions on same device. 2007-04-19 02:10:42 +00:00
Dave Wysochanski
cd96852696 Add stub for pvck, a command to check physical volume consistency. 2007-03-30 21:00:26 +00:00
Patrick Caulfield
b9f7f30158 Add some extra error checking & robustness.
Thanks to the Crosswalk engineering team:
    Leonard Maiorani
    Henry Harris
    Scott Cannata
2007-03-29 13:59:33 +00:00
Alasdair Kergon
ca5e423331 Update lists of attribute characters in man pages.
Change cling alloc policy attribute character from 'C' to l'.
2007-03-27 13:35:33 +00:00
Milan Broz
fa9407089c Fix creation and conversion of mirrors with tags. 2007-03-26 16:10:10 +00:00
Milan Broz
66f28e193a Fix vgsplit for lvm1 format (set and validate VG name in PVs metadata).
Split metadata areas in vgsplit properly.
2007-03-23 12:43:17 +00:00
Alasdair Kergon
0d93f89f5c post-release 2007-03-19 21:16:49 +00:00
Alasdair Kergon
154e9a2c47 pre-release 2007-03-19 21:12:54 +00:00
Milan Broz
84574a1257 Fix processing of exit status in init scripts 2007-03-16 17:15:36 +00:00
Alasdair Kergon
bf83527b64 Remove unnecessary memset() return value checks. [Jim Meyering] 2007-03-16 14:36:14 +00:00
Milan Broz
12c53622a0 Fix vgremove to require at least one vg argument. 2007-03-15 14:00:30 +00:00
Alasdair Kergon
d8f54cf891 Try to fix reading in of lvm1 striped LVs.
There are two fixes other than improving variable names and updating code
layout etc.
The loop counter is incremented by area_len instead of area_len * stripes;
the 3rd _check_stripe parameter is no longer multiplied by number of stripes.
2007-03-15 13:38:28 +00:00
Patrick Caulfield
625a671189 Flag nolocking as a clustered locking module as we need to be able
to look at clustered LVs at clvmd startup
2007-03-13 14:59:21 +00:00
Alasdair Kergon
6ebdad3102 Add a few missing pieces of vgname command line validation. 2007-03-09 21:25:33 +00:00
Alasdair Kergon
9a8f21aa03 Support the /dev/mapper prefix on most command lines. 2007-03-09 20:47:41 +00:00
Alasdair Kergon
291dd8edc2 post-release 2007-03-08 21:37:48 +00:00
Alasdair Kergon
de4c1daf29 pre-release 2007-03-08 21:28:13 +00:00
Alasdair Kergon
0b55d7d0d8 Fix vgrename active LV check to ignore differing vgids. 2007-03-08 21:08:25 +00:00
Alasdair Kergon
5d86fd8fdb Remove no-longer-used uuid_out parameter from activation info functions. 2007-03-08 19:58:04 +00:00
Alasdair Kergon
1b76eb1f59 Fix two more segfaults if an empty config file section encountered. 2007-03-08 19:22:52 +00:00
Alasdair Kergon
b05678d8bf Move .cache file into a new /etc/lvm/cache directory by default.
Add devices/cache_dir & devices/cache_file_prefix, deprecating devices/cache.
Create directory in fcntl_lock_file() if required.
2007-02-28 18:27:13 +00:00
Alasdair Kergon
781f4971c6 Exclude readline support from lvm.static 2007-02-14 16:51:48 +00:00
Alasdair Kergon
d02ac7b99a Fix a leak in a reporting error path. 2007-02-14 15:18:31 +00:00
Alasdair Kergon
b1b6c97f7c Fix a few leaks in reporting error paths. 2007-02-14 15:12:16 +00:00
Alasdair Kergon
baee28ab5c post-release 2007-02-13 16:16:15 +00:00
Alasdair Kergon
83edf68ff9 pre-release 2007-02-13 16:12:24 +00:00
Alasdair Kergon
c7588f91dd Correct -b and -P on a couple of man pages.
Add global/units to example.conf.
2007-02-13 16:04:01 +00:00
Alasdair Kergon
30b432adc5 Fix loading of segment_libraries. [gentoo] 2007-02-08 17:31:02 +00:00
Alasdair Kergon
7c9733eb5d If a PV reappears after it was removed from its VG, make it an orphan. 2007-02-07 13:29:52 +00:00
Alasdair Kergon
a223c3fea3 Improve dmeventd messaging protocol: drain pipe and tag messages. 2007-02-02 17:08:51 +00:00
Alasdair Kergon
d5250f4901 Fix some &->&& vgreduce cmdline validation. [Andre Noll] 2007-01-31 16:26:23 +00:00
Alasdair Kergon
25f29f4712 post-release 2007-01-30 21:37:18 +00:00
Alasdair Kergon
382af5563d pre-release 2007-01-30 18:08:17 +00:00
Alasdair Kergon
8cf3d165d3 Add warning to lvm2_monitoring_init_rhel4 if attempting to stop monitoring. 2007-01-30 18:02:15 +00:00
Alasdair Kergon
0fd6ce546f Fix vgsplit to handle mirrors.
Reorder fields in reporting field definitions.
2007-01-29 23:01:18 +00:00
Alasdair Kergon
b881c372bc post-release 2007-01-29 20:25:19 +00:00
Alasdair Kergon
94c5e7deb0 pre-release 2007-01-29 19:57:24 +00:00
Alasdair Kergon
c344766f3c Add recent reporting options to dmsetup man page.
Revise some report fields names.
2007-01-29 19:35:24 +00:00
Alasdair Kergon
67895de0bc help on help 2007-01-29 18:45:08 +00:00
Alasdair Kergon
ff00cb6990 help unused attr 2007-01-29 18:43:27 +00:00
Alasdair Kergon
2cc75c11ed add help -c for field list 2007-01-29 18:37:57 +00:00
Alasdair Kergon
cd79e58eda Add dmsetup 'help' command and update usage text. 2007-01-29 18:18:41 +00:00
Alasdair Kergon
6fa801f3d8 reorder report field definitions 2007-01-29 17:45:32 +00:00
Alasdair Kergon
684eecba1d Use fixed-size fields in report interface. 2007-01-29 17:23:54 +00:00
Alasdair Kergon
da9cf7e5de fix pvsegs report too 2007-01-27 02:32:31 +00:00
Alasdair Kergon
f57e7445fd Fix vgs to treat args as VGs even when PV fields are displayed. 2007-01-27 02:09:06 +00:00
Alasdair Kergon
fba1388719 Fix md signature check to handle both endiannesses. 2007-01-26 17:15:16 +00:00
Alasdair Kergon
80ed029c17 post-release 2007-01-25 23:40:33 +00:00
152 changed files with 7751 additions and 4638 deletions

View File

@@ -1 +1 @@
2.02.20-cvs (2007-01-25)
2.02.27-cvs (2007-06-15)

109
WHATS_NEW
View File

@@ -1,3 +1,112 @@
Version 2.02.27 -
================================
Turn _add_pv_to_vg() into external library function add_pv_to_vg().
Add pv_by_path() external library function.
Tidy clvmd-openais of redundant bits, and improve an error report.
Cope with find_seg_by_le() failure in check_lv_segments().
Call dev_iter_destroy() if _process_all_devs() is interrupted by sigint.
Add vg_mda_count and pv_mda_count columns to reports.
Fix dumpconfig to use log_print instead of stdout directly.
Remove unused parameter 'fid' from _add_pv_to_vg.
Add kernel and device-mapper targets versions to lvmdump.
Replace BSD (r)index with C89 str(r)chr.
Handle vgsplit of an entire VG as a vgrename.
Reinitialise internal lvmdiskscan variables when called repeatedly.
Fix missing lvm_shell symbol in lvm2cmd library. (2.02.23)
Add vg_status function and clean up vg->status in tools directory.
Add --ignoremonitoring to disable all dmeventd interaction.
Remove get_ prefix from get_pv_* functions.
clvmd-openais now uses cpg_local_get() to get nodeid, rather than Clm.
Print warnings to stderr instead of stdout.
Version 2.02.26 - 15th June 2007
================================
Update vgcfgrestore man page.
Allow keyboard interrupt during user prompts when appropriate.
Remove unused clvmd system-lv code.
Replace many physical_volume struct dereferences with new get_pv_* functions.
Suppress a benign compile-time warning.
Convert find_pv_in_vg_by_uuid and pv_create to use PV handles.
Add wrappers to some functions in preparation for external LVM library.
Add -f to vgcfgrestore to list metadata backup files.
Add vg_check_status to consolidate vg status checks and error messages.
Add pvdisplay --maps implementation.
Remove unsupported LVM1 options from vgcfgrestore man page.
Update vgcfgrestore man page to show mandatory VG name.
Update vgrename man page to include UUID and be consistent with lvrename.
Add (experimental) OpenAIS support to clvmd.
Fix deactivation code to follow dependencies and remove symlinks.
Fix and clarify vgsplit error messages.
Fix a segfault in device_is_usable() if a device has no table.
Add some more debug messages to clvmd startup.
Misc clvmd cleanups.
Version 2.02.25 - 27th April 2007
=================================
Fix get_config_uint64() to read a 64-bit value not a 32-bit one.
Add -Wformat-security and change one fprintf() to fputs().
Move regex functions into libdevmapper.
Change some #include lines to search only standard system directories.
Add devices/preferred_names config regex list for displayed device names.
Free a temporary dir string in fcntl_lock_file() after use.
Fix a dm_pool_destroy() in matcher_create().
Introduce goto_bad macro.
Fix warnings on x86_64 involving ptrdiff_t in log_error messages.
Update pvck to include text metadata area and record detection.
Add support functions for token counting in config file extracts.
Update pvck to read labels on disk, with --labelsector parameter.
Add count_chars and count_chars_len functions.
Add /sys/block listings to lvm_dump.sh.
Make lvm_dump.sh list /dev recursively.
Fix thread race in clvmd.
Add scan_sector param to label_read and _find_labeller.
Make clvmd cope with quorum devices.
Add extra internal error checking to clvmd.
Add dev_read_circular.
Add pvck command stub.
Update lists of attribute characters in man pages.
Change cling alloc policy attribute character from 'C' to l'.
Fix creation and conversion of mirrors with tags.
Fix vgsplit for lvm1 format (set and validate VG name in PVs metadata).
Split metadata areas in vgsplit properly.
Version 2.02.24 - 19th March 2007
=================================
Fix processing of exit status in init scripts
Fix vgremove to require at least one vg argument.
Fix reading of striped LVs in LVM1 format.
Flag nolocking as clustered so clvmd startup sees clustered LVs. (2.02.10)
Add a few missing pieces of vgname command line validation.
Support the /dev/mapper prefix on most command lines.
Version 2.02.23 - 8th March 2007
================================
Fix vgrename active LV check to ignore differing vgids.
Remove no-longer-used uuid_out parameter from activation info functions.
Fix two more segfaults if an empty config file section encountered.
Move .cache file into a new /etc/lvm/cache directory by default.
Add devices/cache_dir & devices/cache_file_prefix, deprecating devices/cache.
Create directory in fcntl_lock_file() if required.
Exclude readline support from lvm.static.
Fix a leak in a reporting error path (2.02.19).
Version 2.02.22 - 13th February 2007
====================================
Correct -b and -P on a couple of man pages.
Add global/units to example.conf.
Fix loading of segment_libraries.
If a PV reappears after it was removed from its VG, make it an orphan.
Don't update metadata automatically if VGIDs don't match.
Fix some vgreduce --removemissing command line validation.
Version 2.02.21 - 30th January 2007
===================================
Add warning to lvm2_monitoring_init_rhel4 if attempting to stop monitoring.
Fix vgsplit to handle mirrors.
Reorder fields in reporting field definitions.
Fix vgs to treat args as VGs even when PV fields are displayed.
Fix md signature check to handle both endiannesses.
Version 2.02.20 - 25th January 2007
===================================
dmeventd mirror sets ignore_suspended_devices and avoids scanning mirrors.

View File

@@ -1,3 +1,36 @@
Version 1.02.21 - 13th July 2007
================================
Introduce _LOG_STDERR to send log_warn() messages to stderr not stdout.
Fix dmsetup -o devno string termination. (1.02.20)
Version 1.02.20 - 15th June 2007
================================
Fix default dmsetup report buffering and add --unbuffered.
Add tree-based and dependency fields to dmsetup reports.
Version 1.02.19 - 27th April 2007
=================================
Standardise protective include file #defines.
Add regex functions to library.
Avoid trailing separator in reports when there are hidden sort fields.
Fix segfault in 'dmsetup status' without --showkeys against crypt target.
Deal with some more compiler warnings.
Introduce _add_field() and _is_same_field() to libdm-report.c.
Fix some libdevmapper-event and dmeventd memory leaks.
Remove unnecessary memset() return value checks.
Fix a few leaks in reporting error paths. [1.02.15+]
Version 1.02.18 - 13th February 2007
====================================
Improve dmeventd messaging protocol: drain pipe and tag messages.
Version 1.02.17 - 29th January 2007
===================================
Add recent reporting options to dmsetup man page.
Revise some report fields names.
Add dmsetup 'help' command and update usage text.
Use fixed-size fields in report interface and reorder.
Version 1.02.16 - 25th January 2007
===================================
Add some missing close() and fclose() return value checks.

View File

@@ -19,8 +19,7 @@ SOURCES = \
clvmd-command.c \
clvmd.c \
lvm-functions.c \
refresh_clvmd.c \
system-lv.c
refresh_clvmd.c
ifeq ("@CLVMD@", "gulm")
GULM = yes
@@ -30,9 +29,16 @@ ifeq ("@CLVMD@", "cman")
CMAN = yes
endif
ifeq ("@CLVMD@", "openais")
OPENAIS = yes
GULM = no
CMAN = no
endif
ifeq ("@CLVMD@", "all")
GULM = yes
CMAN = yes
OPENAIS = no
endif
ifeq ("@DEBUG@", "yes")
@@ -51,6 +57,12 @@ ifeq ("$(CMAN)", "yes")
DEFS += -DUSE_CMAN
endif
ifeq ("$(OPENAIS)", "yes")
SOURCES += clvmd-openais.c
LMLIBS += -lSaLck -lcpg
DEFS += -DUSE_OPENAIS
endif
TARGETS = \
clvmd

View File

@@ -36,10 +36,10 @@
#include <fcntl.h>
#include <getopt.h>
#include <errno.h>
#include <libdlm.h>
#include "clvmd-comms.h"
#include "clvm.h"
#include "libdlm.h"
#include "log.h"
#include "clvmd.h"
#include "lvm-functions.h"
@@ -58,7 +58,7 @@ 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 nodeid_from_csid(const 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,
@@ -78,6 +78,7 @@ static int _init_cluster(void)
syslog(LOG_ERR, "Can't open cluster manager socket: %m");
return -1;
}
DEBUGLOG("Connected to CMAN\n");
if (cman_start_recv_data(c_handle, data_callback, CLUSTER_PORT_CLVMD)) {
syslog(LOG_ERR, "Can't bind cluster socket: %m");
@@ -93,6 +94,8 @@ static int _init_cluster(void)
get_members();
count_clvmds_running();
DEBUGLOG("CMAN initialisation complete\n");
/* Create a lockspace for LV & VG locks to live in */
lockspace = dlm_create_lockspace(LOCKSPACE_NAME, 0600);
if (!lockspace) {
@@ -100,7 +103,7 @@ static int _init_cluster(void)
return -1;
}
dlm_ls_pthread_init(lockspace);
DEBUGLOG("DLM initialisation complete\n");
return 0;
}
@@ -121,14 +124,15 @@ static int _get_num_nodes()
/* return number of ACTIVE nodes */
for (i=0; i<num_nodes; i++) {
if (nodes[i].cn_member)
if (nodes[i].cn_member && nodes[i].cn_nodeid)
nnodes++;
}
return nnodes;
}
/* send_message with the fd check removed */
static int _cluster_send_message(void *buf, int msglen, char *csid, const char *errtext)
static int _cluster_send_message(const void *buf, int msglen, const char *csid,
const char *errtext)
{
int nodeid = 0;
@@ -137,7 +141,7 @@ static int _cluster_send_message(void *buf, int msglen, char *csid, const char *
if (cman_send_data(c_handle, buf, msglen, 0, CLUSTER_PORT_CLVMD, nodeid) <= 0)
{
log_error(errtext);
log_error("%s", errtext);
}
return msglen;
}
@@ -152,14 +156,15 @@ static void _get_our_csid(char *csid)
/* 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 *,
void (*callback) (struct local_client *,
const char *,
int))
{
int i;
int somedown = 0;
for (i = 0; i < _get_num_nodes(); i++) {
if (nodes[i].cn_member) {
if (nodes[i].cn_member && nodes[i].cn_nodeid) {
callback(client, (char *)&nodes[i].cn_nodeid, node_updown[nodes[i].cn_nodeid]);
if (!node_updown[nodes[i].cn_nodeid])
somedown = -1;
@@ -168,8 +173,7 @@ static int _cluster_do_node_callback(struct local_client *client,
return somedown;
}
/* Process OOB message from the cluster socket,
this currently just means that a node has stopped listening on our port */
/* Process OOB messages from the cluster socket */
static void event_callback(cman_handle_t handle, void *private, int reason, int arg)
{
char namebuf[MAX_CLUSTER_MEMBER_NAME_LEN];
@@ -206,7 +210,8 @@ static void event_callback(cman_handle_t handle, void *private, int reason, int
}
static struct local_client *cman_client;
static int _cluster_fd_callback(struct local_client *fd, char *buf, int len, char *csid,
static int _cluster_fd_callback(struct local_client *fd, char *buf, int len,
const char *csid,
struct local_client **new_client)
{
@@ -229,7 +234,7 @@ static void data_callback(cman_handle_t handle, void *private,
process_message(cman_client, buf, len, (char *)&nodeid);
}
static void _add_up_node(char *csid)
static void _add_up_node(const char *csid)
{
/* It's up ! */
int nodeid = nodeid_from_csid(csid);
@@ -321,17 +326,16 @@ static void get_members()
}
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));
size_t buf_len = sizeof(int) * max(num_nodes, max_updown_nodes);
node_updown = malloc(buf_len);
if (node_updown)
memset(node_updown, 0, buf_len);
}
}
/* Convert a node name to a CSID */
static int _csid_from_name(char *csid, char *name)
static int _csid_from_name(char *csid, const char *name)
{
int i;
@@ -345,7 +349,7 @@ static int _csid_from_name(char *csid, char *name)
}
/* Convert a CSID to a node name */
static int _name_from_csid(char *csid, char *name)
static int _name_from_csid(const char *csid, char *name)
{
int i;
@@ -377,7 +381,7 @@ static int name_from_nodeid(int nodeid, char *name)
}
/* Convert a CSID to a node ID */
static int nodeid_from_csid(char *csid)
static int nodeid_from_csid(const char *csid)
{
int nodeid;

View File

@@ -64,8 +64,9 @@
#include <stddef.h>
#include <unistd.h>
#include <errno.h>
#include <libdevmapper.h>
#include <libdlm.h>
#include "libdevmapper.h"
#include "list.h"
#include "locking.h"
#include "log.h"
@@ -73,7 +74,6 @@
#include "clvmd-comms.h"
#include "clvm.h"
#include "clvmd.h"
#include "libdlm.h"
extern struct cluster_ops *clops;
@@ -95,13 +95,22 @@ int do_command(struct local_client *client, struct clvm_header *msg, int msglen,
/* Just a test message */
case CLVMD_CMD_TEST:
if (arglen > buflen) {
char *new_buf;
buflen = arglen + 200;
*buf = realloc(*buf, buflen);
new_buf = realloc(*buf, buflen);
if (new_buf == NULL) {
status = errno;
free (*buf);
}
*buf = new_buf;
}
if (*buf) {
uname(&nodeinfo);
*retlen = 1 + snprintf(*buf, buflen,
"TEST from %s: %s v%s",
nodeinfo.nodename, args,
nodeinfo.release);
}
uname(&nodeinfo);
*retlen = 1 + snprintf(*buf, buflen, "TEST from %s: %s v%s",
nodeinfo.nodename, args,
nodeinfo.release);
break;
case CLVMD_CMD_LOCK_VG:
@@ -118,7 +127,7 @@ int do_command(struct local_client *client, struct clvm_header *msg, int msglen,
/* Replace EIO with something less scary */
if (status == EIO) {
*retlen =
1 + snprintf(*buf, buflen,
1 + snprintf(*buf, buflen, "%s",
get_last_lvm_error());
return EIO;
}
@@ -131,7 +140,7 @@ int do_command(struct local_client *client, struct clvm_header *msg, int msglen,
case CLVMD_CMD_GET_CLUSTERNAME:
status = clops->get_cluster_name(*buf, buflen);
if (!status)
*retlen = strlen(*buf);
*retlen = strlen(*buf)+1;
break;
default:
@@ -141,7 +150,7 @@ int do_command(struct local_client *client, struct clvm_header *msg, int msglen,
/* Check the status of the command and return the error text */
if (status) {
*retlen = 1 + snprintf(*buf, buflen, strerror(status));
*retlen = 1 + snprintf(*buf, buflen, "%s", strerror(status));
}
return status;

View File

@@ -25,27 +25,31 @@ struct local_client;
struct cluster_ops {
void (*cluster_init_completed) (void);
int (*cluster_send_message) (void *buf, int msglen, char *csid,
const char *errtext);
int (*name_from_csid) (char *csid, char *name);
int (*csid_from_name) (char *csid, char *name);
int (*cluster_send_message) (const void *buf, int msglen,
const char *csid,
const char *errtext);
int (*name_from_csid) (const char *csid, char *name);
int (*csid_from_name) (char *csid, const 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);
const char *csid,
struct local_client **new_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));
void (*callback) (struct local_client *,
const char *csid,
int node_up));
int (*is_quorate) (void);
void (*get_our_csid) (char *csid);
void (*add_up_node) (char *csid);
void (*add_up_node) (const char *csid);
void (*reread_config) (void);
void (*cluster_closedown) (void);
int (*get_cluster_name)(char *buf, int buflen);
int (*sync_lock) (const char *resource, int mode, int flags, int *lockid);
int (*sync_lock) (const char *resource, int mode,
int flags, int *lockid);
int (*sync_unlock) (const char *resource, int lockid);
};
@@ -71,6 +75,23 @@ struct cluster_ops *init_gulm_cluster(void);
struct cluster_ops *init_cman_cluster(void);
#endif
#ifdef USE_OPENAIS
# include <openais/saAis.h>
# include <openais/totem/totem.h>
# define OPENAIS_CSID_LEN (sizeof(int))
# define OPENAIS_MAX_CLUSTER_MESSAGE MESSAGE_SIZE_MAX
# define OPENAIS_MAX_CLUSTER_MEMBER_NAME_LEN SA_MAX_NAME_LENGTH
# ifndef MAX_CLUSTER_MEMBER_NAME_LEN
# define MAX_CLUSTER_MEMBER_NAME_LEN SA_MAX_NAME_LENGTH
# endif
# ifndef CMAN_MAX_CLUSTER_MESSAGE
# define CMAN_MAX_CLUSTER_MESSAGE MESSAGE_SIZE_MAX
# endif
# ifndef MAX_CSID_LEN
# define MAX_CSID_LEN sizeof(int)
# endif
struct cluster_ops *init_openais_cluster(void);
#endif
#endif

View File

@@ -40,9 +40,10 @@
#include <utmpx.h>
#include <syslog.h>
#include <assert.h>
#include <libdevmapper.h>
#include <ccs.h>
#include <libgulm.h>
#include "libdevmapper.h"
#include "ccs.h"
#include "list.h"
#include "locking.h"
#include "log.h"
@@ -51,7 +52,6 @@
#include "lvm-functions.h"
#include "clvmd.h"
#include "clvmd-gulm.h"
#include "libgulm.h"
/* Hash list of nodes in the cluster */
static struct dm_hash_table *node_hash;

View File

@@ -0,0 +1,737 @@
/******************************************************************************
*******************************************************************************
**
** Copyright (C) 2007 Red Hat, Inc. All rights reserved.
**
*******************************************************************************
******************************************************************************/
/* This provides the interface between clvmd and OpenAIS as the cluster
* and lock manager.
*
*/
#include <pthread.h>
#include <sys/types.h>
#include <sys/utsname.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/file.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <signal.h>
#include <fcntl.h>
#include <string.h>
#include <stddef.h>
#include <stdint.h>
#include <unistd.h>
#include <errno.h>
#include <utmpx.h>
#include <syslog.h>
#include <assert.h>
#include <libdevmapper.h>
#include <openais/saAis.h>
#include <openais/saLck.h>
#include <openais/cpg.h>
#include "list.h"
#include "locking.h"
#include "log.h"
#include "clvm.h"
#include "clvmd-comms.h"
#include "lvm-functions.h"
#include "clvmd.h"
/* Timeout value for several openais calls */
#define TIMEOUT 10
static void lck_lock_callback(SaInvocationT invocation,
SaLckLockStatusT lockStatus,
SaAisErrorT error);
static void lck_unlock_callback(SaInvocationT invocation,
SaAisErrorT error);
static void cpg_deliver_callback (cpg_handle_t handle,
struct cpg_name *groupName,
uint32_t nodeid,
uint32_t pid,
void *msg,
int msg_len);
static void cpg_confchg_callback(cpg_handle_t handle,
struct cpg_name *groupName,
struct cpg_address *member_list, int member_list_entries,
struct cpg_address *left_list, int left_list_entries,
struct cpg_address *joined_list, int joined_list_entries);
static void _cluster_closedown(void);
/* Hash list of nodes in the cluster */
static struct dm_hash_table *node_hash;
/* For associating lock IDs & resource handles */
static struct dm_hash_table *lock_hash;
/* Number of active nodes */
static int num_nodes;
static unsigned int our_nodeid;
static struct local_client *cluster_client;
/* OpenAIS handles */
static cpg_handle_t cpg_handle;
static SaLckHandleT lck_handle;
static struct cpg_name cpg_group_name;
/* Openais callback structs */
cpg_callbacks_t cpg_callbacks = {
.cpg_deliver_fn = cpg_deliver_callback,
.cpg_confchg_fn = cpg_confchg_callback,
};
SaLckCallbacksT lck_callbacks = {
.saLckLockGrantCallback = lck_lock_callback,
.saLckResourceUnlockCallback = lck_unlock_callback
};
struct node_info
{
enum {NODE_UNKNOWN, NODE_DOWN, NODE_UP, NODE_CLVMD} state;
int nodeid;
};
struct lock_info
{
SaLckResourceHandleT res_handle;
SaLckLockIdT lock_id;
SaNameT lock_name;
};
struct lock_wait
{
pthread_cond_t cond;
pthread_mutex_t mutex;
int status;
};
/* Set errno to something approximating the right value and return 0 or -1 */
static int ais_to_errno(SaAisErrorT err)
{
switch(err)
{
case SA_AIS_OK:
return 0;
case SA_AIS_ERR_LIBRARY:
errno = EINVAL;
break;
case SA_AIS_ERR_VERSION:
errno = EINVAL;
break;
case SA_AIS_ERR_INIT:
errno = EINVAL;
break;
case SA_AIS_ERR_TIMEOUT:
errno = ETIME;
break;
case SA_AIS_ERR_TRY_AGAIN:
errno = EAGAIN;
break;
case SA_AIS_ERR_INVALID_PARAM:
errno = EINVAL;
break;
case SA_AIS_ERR_NO_MEMORY:
errno = ENOMEM;
break;
case SA_AIS_ERR_BAD_HANDLE:
errno = EINVAL;
break;
case SA_AIS_ERR_BUSY:
errno = EBUSY;
break;
case SA_AIS_ERR_ACCESS:
errno = EPERM;
break;
case SA_AIS_ERR_NOT_EXIST:
errno = ENOENT;
break;
case SA_AIS_ERR_NAME_TOO_LONG:
errno = ENAMETOOLONG;
break;
case SA_AIS_ERR_EXIST:
errno = EEXIST;
break;
case SA_AIS_ERR_NO_SPACE:
errno = ENOSPC;
break;
case SA_AIS_ERR_INTERRUPT:
errno = EINTR;
break;
case SA_AIS_ERR_NAME_NOT_FOUND:
errno = ENOENT;
break;
case SA_AIS_ERR_NO_RESOURCES:
errno = ENOMEM;
break;
case SA_AIS_ERR_NOT_SUPPORTED:
errno = EOPNOTSUPP;
break;
case SA_AIS_ERR_BAD_OPERATION:
errno = EINVAL;
break;
case SA_AIS_ERR_FAILED_OPERATION:
errno = EIO;
break;
case SA_AIS_ERR_MESSAGE_ERROR:
errno = EIO;
break;
case SA_AIS_ERR_QUEUE_FULL:
errno = EXFULL;
break;
case SA_AIS_ERR_QUEUE_NOT_AVAILABLE:
errno = EINVAL;
break;
case SA_AIS_ERR_BAD_FLAGS:
errno = EINVAL;
break;
case SA_AIS_ERR_TOO_BIG:
errno = E2BIG;
break;
case SA_AIS_ERR_NO_SECTIONS:
errno = ENOMEM;
break;
default:
errno = EINVAL;
break;
}
return -1;
}
static char *print_csid(const char *csid)
{
static char buf[128];
int id;
memcpy(&id, csid, sizeof(int));
sprintf(buf, "%d", id);
return buf;
}
static int add_internal_client(int fd, fd_callback_t callback)
{
struct local_client *client;
DEBUGLOG("Add_internal_client, fd = %d\n", fd);
client = malloc(sizeof(struct local_client));
if (!client)
{
DEBUGLOG("malloc failed\n");
return -1;
}
memset(client, 0, sizeof(struct local_client));
client->fd = fd;
client->type = CLUSTER_INTERNAL;
client->callback = callback;
add_client(client);
/* Set Close-on-exec */
fcntl(fd, F_SETFD, 1);
return 0;
}
static void cpg_deliver_callback (cpg_handle_t handle,
struct cpg_name *groupName,
uint32_t nodeid,
uint32_t pid,
void *msg,
int msg_len)
{
int target_nodeid;
memcpy(&target_nodeid, msg, OPENAIS_CSID_LEN);
DEBUGLOG("Got message from nodeid %d for %d. len %d\n",
nodeid, target_nodeid, msg_len-4);
if (target_nodeid == our_nodeid)
process_message(cluster_client, (char *)msg+OPENAIS_CSID_LEN,
msg_len-OPENAIS_CSID_LEN, (char*)&nodeid);
}
static void cpg_confchg_callback(cpg_handle_t handle,
struct cpg_name *groupName,
struct cpg_address *member_list, int member_list_entries,
struct cpg_address *left_list, int left_list_entries,
struct cpg_address *joined_list, int joined_list_entries)
{
int i;
struct node_info *ninfo;
DEBUGLOG("confchg callback. %d joined, %d left, %d members\n",
joined_list_entries, left_list_entries, member_list_entries);
for (i=0; i<joined_list_entries; i++) {
ninfo = dm_hash_lookup_binary(node_hash,
(char *)&joined_list[i].nodeid,
OPENAIS_CSID_LEN);
if (!ninfo) {
ninfo = malloc(sizeof(struct node_info));
if (!ninfo) {
break;
}
else {
ninfo->nodeid = joined_list[i].nodeid;
dm_hash_insert_binary(node_hash,
(char *)&ninfo->nodeid,
OPENAIS_CSID_LEN, ninfo);
}
}
ninfo->state = NODE_CLVMD;
}
for (i=0; i<left_list_entries; i++) {
ninfo = dm_hash_lookup_binary(node_hash,
(char *)&left_list[i].nodeid,
OPENAIS_CSID_LEN);
if (ninfo)
ninfo->state = NODE_DOWN;
}
num_nodes = joined_list_entries;
}
static void lck_lock_callback(SaInvocationT invocation,
SaLckLockStatusT lockStatus,
SaAisErrorT error)
{
struct lock_wait *lwait = (struct lock_wait *)(long)invocation;
DEBUGLOG("lck_lock_callback, error = %d\n", error);
lwait->status = error;
pthread_mutex_lock(&lwait->mutex);
pthread_cond_signal(&lwait->cond);
pthread_mutex_unlock(&lwait->mutex);
}
static void lck_unlock_callback(SaInvocationT invocation,
SaAisErrorT error)
{
struct lock_wait *lwait = (struct lock_wait *)(long)invocation;
DEBUGLOG("lck_unlock_callback\n");
lwait->status = SA_AIS_OK;
pthread_mutex_lock(&lwait->mutex);
pthread_cond_signal(&lwait->cond);
pthread_mutex_unlock(&lwait->mutex);
}
static int lck_dispatch(struct local_client *client, char *buf, int len,
const char *csid, struct local_client **new_client)
{
*new_client = NULL;
saLckDispatch(lck_handle, SA_DISPATCH_ONE);
return 1;
}
static int _init_cluster(void)
{
SaAisErrorT err;
SaVersionT ver = { 'B', 1, 1 };
int select_fd;
node_hash = dm_hash_create(100);
lock_hash = dm_hash_create(10);
err = cpg_initialize(&cpg_handle,
&cpg_callbacks);
if (err != SA_AIS_OK) {
syslog(LOG_ERR, "Cannot initialise OpenAIS CPG service: %d",
err);
DEBUGLOG("Cannot initialise OpenAIS CPG service: %d", err);
return ais_to_errno(err);
}
err = saLckInitialize(&lck_handle,
&lck_callbacks,
&ver);
if (err != SA_AIS_OK) {
cpg_initialize(&cpg_handle, &cpg_callbacks);
syslog(LOG_ERR, "Cannot initialise OpenAIS lock service: %d",
err);
DEBUGLOG("Cannot initialise OpenAIS lock service: %d\n\n", err);
return ais_to_errno(err);
}
/* Connect to the clvmd group */
strcpy((char *)cpg_group_name.value, "clvmd");
cpg_group_name.length = strlen((char *)cpg_group_name.value);
err = cpg_join(cpg_handle, &cpg_group_name);
if (err != SA_AIS_OK) {
cpg_finalize(cpg_handle);
saLckFinalize(lck_handle);
syslog(LOG_ERR, "Cannot join clvmd process group");
DEBUGLOG("Cannot join clvmd process group: %d\n", err);
return ais_to_errno(err);
}
err = cpg_local_get(cpg_handle,
&our_nodeid);
if (err != SA_AIS_OK) {
cpg_finalize(cpg_handle);
saLckFinalize(lck_handle);
syslog(LOG_ERR, "Cannot get local node id\n");
return ais_to_errno(err);
}
DEBUGLOG("Our local node id is %d\n", our_nodeid);
saLckSelectionObjectGet(lck_handle, (SaSelectionObjectT *)&select_fd);
add_internal_client(select_fd, lck_dispatch);
DEBUGLOG("Connected to OpenAIS\n");
return 0;
}
static void _cluster_closedown(void)
{
DEBUGLOG("cluster_closedown\n");
unlock_all();
saLckFinalize(lck_handle);
cpg_finalize(cpg_handle);
}
static void _get_our_csid(char *csid)
{
memcpy(csid, &our_nodeid, sizeof(int));
}
/* OpenAIS doesn't really have nmode names so we
just use the node ID in hex instead */
static int _csid_from_name(char *csid, const char *name)
{
int nodeid;
struct node_info *ninfo;
if (sscanf(name, "%x", &nodeid) == 1) {
ninfo = dm_hash_lookup_binary(node_hash, csid, OPENAIS_CSID_LEN);
if (ninfo)
return nodeid;
}
return -1;
}
static int _name_from_csid(const char *csid, char *name)
{
struct node_info *ninfo;
ninfo = dm_hash_lookup_binary(node_hash, csid, OPENAIS_CSID_LEN);
if (!ninfo)
{
sprintf(name, "UNKNOWN %s", print_csid(csid));
return -1;
}
sprintf(name, "%x", ninfo->nodeid);
return 0;
}
static int _get_num_nodes()
{
DEBUGLOG("num_nodes = %d\n", num_nodes);
return num_nodes;
}
/* Node is now known to be running a clvmd */
static void _add_up_node(const char *csid)
{
struct node_info *ninfo;
ninfo = dm_hash_lookup_binary(node_hash, csid, OPENAIS_CSID_LEN);
if (!ninfo) {
DEBUGLOG("openais_add_up_node no node_hash entry for csid %s\n",
print_csid(csid));
return;
}
DEBUGLOG("openais_add_up_node %d\n", ninfo->nodeid);
ninfo->state = NODE_CLVMD;
return;
}
/* Call a callback for each node, so the caller knows whether it's up or down */
static int _cluster_do_node_callback(struct local_client *master_client,
void (*callback)(struct local_client *,
const char *csid, int node_up))
{
struct dm_hash_node *hn;
struct node_info *ninfo;
dm_hash_iterate(hn, node_hash)
{
char csid[OPENAIS_CSID_LEN];
ninfo = dm_hash_get_data(node_hash, hn);
memcpy(csid, dm_hash_get_key(node_hash, hn), OPENAIS_CSID_LEN);
DEBUGLOG("down_callback. node %d, state = %d\n", ninfo->nodeid,
ninfo->state);
if (ninfo->state != NODE_DOWN)
callback(master_client, csid, ninfo->state == NODE_CLVMD);
}
return 0;
}
/* Real locking */
static int _lock_resource(char *resource, int mode, int flags, int *lockid)
{
struct lock_wait lwait;
struct lock_info *linfo;
SaLckResourceHandleT res_handle;
SaAisErrorT err;
SaLckLockIdT lock_id;
pthread_cond_init(&lwait.cond, NULL);
pthread_mutex_init(&lwait.mutex, NULL);
pthread_mutex_lock(&lwait.mutex);
/* This needs to be converted from DLM/LVM2 value for OpenAIS LCK */
if (flags & LCK_NONBLOCK) flags = SA_LCK_LOCK_NO_QUEUE;
linfo = malloc(sizeof(struct lock_info));
if (!linfo)
return -1;
DEBUGLOG("lock_resource '%s', flags=%d, mode=%d\n", resource, flags, mode);
linfo->lock_name.length = strlen(resource)+1;
strcpy((char *)linfo->lock_name.value, resource);
err = saLckResourceOpen(lck_handle, &linfo->lock_name,
SA_LCK_RESOURCE_CREATE, TIMEOUT, &res_handle);
if (err != SA_AIS_OK)
{
DEBUGLOG("ResourceOpen returned %d\n", err);
free(linfo);
return ais_to_errno(err);
}
err = saLckResourceLockAsync(res_handle,
(SaInvocationT)(long)&lwait,
&lock_id,
mode,
flags,
0);
if (err != SA_AIS_OK)
{
free(linfo);
saLckResourceClose(res_handle);
return ais_to_errno(err);
}
/* Wait for it to complete */
pthread_cond_wait(&lwait.cond, &lwait.mutex);
pthread_mutex_unlock(&lwait.mutex);
DEBUGLOG("lock_resource returning %d, lock_id=%llx\n", lwait.status,
lock_id);
linfo->lock_id = lock_id;
linfo->res_handle = res_handle;
dm_hash_insert(lock_hash, resource, linfo);
return ais_to_errno(lwait.status);
}
static int _unlock_resource(char *resource, int lockid)
{
struct lock_wait lwait;
SaAisErrorT err;
struct lock_info *linfo;
pthread_cond_init(&lwait.cond, NULL);
pthread_mutex_init(&lwait.mutex, NULL);
pthread_mutex_lock(&lwait.mutex);
DEBUGLOG("unlock_resource %s\n", resource);
linfo = dm_hash_lookup(lock_hash, resource);
if (!linfo)
return 0;
DEBUGLOG("unlock_resource: lockid: %llx\n", linfo->lock_id);
err = saLckResourceUnlockAsync((SaInvocationT)(long)&lwait, linfo->lock_id);
if (err != SA_AIS_OK)
{
DEBUGLOG("Unlock returned %d\n", err);
return ais_to_errno(err);
}
/* Wait for it to complete */
pthread_cond_wait(&lwait.cond, &lwait.mutex);
pthread_mutex_unlock(&lwait.mutex);
/* Release the resource */
dm_hash_remove(lock_hash, resource);
saLckResourceClose(linfo->res_handle);
free(linfo);
return ais_to_errno(lwait.status);
}
static int _sync_lock(const char *resource, int mode, int flags, int *lockid)
{
int status;
char lock1[strlen(resource)+3];
char lock2[strlen(resource)+3];
snprintf(lock1, sizeof(lock1), "%s-1", resource);
snprintf(lock2, sizeof(lock2), "%s-2", resource);
switch (mode)
{
case LCK_EXCL:
status = _lock_resource(lock1, SA_LCK_EX_LOCK_MODE, flags, lockid);
if (status)
goto out;
/* If we can't get this lock too then bail out */
status = _lock_resource(lock2, SA_LCK_EX_LOCK_MODE, LCK_NONBLOCK,
lockid);
if (status == SA_LCK_LOCK_NOT_QUEUED)
{
_unlock_resource(lock1, *lockid);
status = -1;
errno = EAGAIN;
}
break;
case LCK_PREAD:
case LCK_READ:
status = _lock_resource(lock1, SA_LCK_PR_LOCK_MODE, flags, lockid);
if (status)
goto out;
_unlock_resource(lock2, *lockid);
break;
case LCK_WRITE:
status = _lock_resource(lock2, SA_LCK_EX_LOCK_MODE, flags, lockid);
if (status)
goto out;
_unlock_resource(lock1, *lockid);
break;
default:
status = -1;
errno = EINVAL;
break;
}
out:
*lockid = mode;
return status;
}
static int _sync_unlock(const char *resource, int lockid)
{
int status = 0;
char lock1[strlen(resource)+3];
char lock2[strlen(resource)+3];
snprintf(lock1, sizeof(lock1), "%s-1", resource);
snprintf(lock2, sizeof(lock2), "%s-2", resource);
_unlock_resource(lock1, lockid);
_unlock_resource(lock2, lockid);
return status;
}
/* We are always quorate ! */
static int _is_quorate()
{
return 1;
}
static int _get_main_cluster_fd(void)
{
int select_fd;
cpg_fd_get(cpg_handle, &select_fd);
return select_fd;
}
static int _cluster_fd_callback(struct local_client *fd, char *buf, int len,
const char *csid,
struct local_client **new_client)
{
cluster_client = fd;
*new_client = NULL;
cpg_dispatch(cpg_handle, SA_DISPATCH_ONE);
return 1;
}
static int _cluster_send_message(const void *buf, int msglen, const char *csid,
const char *errtext)
{
struct iovec iov[2];
SaAisErrorT err;
int target_node;
if (csid)
memcpy(&target_node, csid, OPENAIS_CSID_LEN);
else
target_node = 0;
iov[0].iov_base = &target_node;
iov[0].iov_len = sizeof(int);
iov[1].iov_base = (char *)buf;
iov[1].iov_len = msglen;
err = cpg_mcast_joined(cpg_handle, CPG_TYPE_AGREED, iov, 2);
return ais_to_errno(err);
}
/* We don't have a cluster name to report here */
static int _get_cluster_name(char *buf, int buflen)
{
strncpy(buf, "OpenAIS", buflen);
return 0;
}
static struct cluster_ops _cluster_openais_ops = {
.cluster_init_completed = NULL,
.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,
.reread_config = NULL,
.cluster_closedown = _cluster_closedown,
.get_cluster_name = _get_cluster_name,
.sync_lock = _sync_lock,
.sync_unlock = _sync_unlock,
};
struct cluster_ops *init_openais_cluster(void)
{
if (!_init_cluster())
return &_cluster_openais_ops;
else
return NULL;
}

View File

@@ -37,6 +37,7 @@
#include <getopt.h>
#include <syslog.h>
#include <errno.h>
#include <libdlm.h>
#include "clvmd-comms.h"
#include "lvm-functions.h"
@@ -44,8 +45,6 @@
#include "version.h"
#include "clvmd.h"
#include "refresh_clvmd.h"
#include "libdlm.h"
#include "system-lv.h"
#include "list.h"
#include "log.h"
@@ -56,9 +55,7 @@
#define FALSE 0
#endif
/* 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_RETRIES 4
#define ISLOCAL_CSID(c) (memcmp(c, our_csid, max_csid_len) == 0)
@@ -113,31 +110,32 @@ static void send_local_reply(struct local_client *client, int status,
static void free_reply(struct local_client *client);
static void send_version_message(void);
static void *pre_and_post_thread(void *arg);
static int send_message(void *buf, int msglen, char *csid, int fd,
static int send_message(void *buf, int msglen, const char *csid, int fd,
const char *errtext);
static int read_from_local_sock(struct local_client *thisfd);
static int process_local_command(struct clvm_header *msg, int msglen,
struct local_client *client,
unsigned short xid);
static void process_remote_command(struct clvm_header *msg, int msglen, int fd,
char *csid);
static int process_reply(struct clvm_header *msg, int msglen, char *csid);
const char *csid);
static int process_reply(const struct clvm_header *msg, int msglen,
const 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(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,
int len, const char *csid,
struct local_client **new_client);
static void *lvm_thread_fn(void *);
static int add_to_lvmqueue(struct local_client *client, struct clvm_header *msg,
int msglen, char *csid);
int msglen, const char *csid);
static int distribute_command(struct local_client *thisfd);
static void hton_clvm(struct clvm_header *hdr);
static void ntoh_clvm(struct clvm_header *hdr);
static void add_reply_to_list(struct local_client *client, int status,
char *csid, const char *buf, int len);
const char *csid, const char *buf, int len);
static void usage(char *prog, FILE *file)
{
@@ -293,6 +291,15 @@ int main(int argc, char *argv[])
syslog(LOG_NOTICE, "Cluster LVM daemon started - connected to GULM");
}
#endif
#ifdef USE_OPENAIS
if (!clops)
if ((clops = init_openais_cluster())) {
max_csid_len = OPENAIS_CSID_LEN;
max_cluster_message = OPENAIS_MAX_CLUSTER_MESSAGE;
max_cluster_member_name_len = OPENAIS_MAX_CLUSTER_MEMBER_NAME_LEN;
syslog(LOG_NOTICE, "Cluster LVM daemon started - connected to OpenAIS");
}
#endif
if (!clops) {
DEBUGLOG("Can't initialise cluster interface\n");
@@ -325,7 +332,7 @@ 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,
pthread_create(&lvm_thread, NULL, lvm_thread_fn,
(void *)(long)using_gulm);
/* Tell the rest of the cluster our version number */
@@ -357,7 +364,8 @@ void clvmd_cluster_init_completed()
/* Data on a connected socket */
static int local_sock_callback(struct local_client *thisfd, char *buf, int len,
char *csid, struct local_client **new_client)
const char *csid,
struct local_client **new_client)
{
*new_client = NULL;
return read_from_local_sock(thisfd);
@@ -365,7 +373,7 @@ static int local_sock_callback(struct local_client *thisfd, char *buf, int len,
/* Data on a connected socket */
static int local_rendezvous_callback(struct local_client *thisfd, char *buf,
int len, char *csid,
int len, const char *csid,
struct local_client **new_client)
{
/* Someone connected to our local socket, accept it. */
@@ -375,6 +383,9 @@ static int local_rendezvous_callback(struct local_client *thisfd, char *buf,
socklen_t sl = sizeof(socka);
int client_fd = accept(thisfd->fd, (struct sockaddr *) &socka, &sl);
if (client_fd == -1 && errno == EINTR)
return 1;
if (client_fd >= 0) {
newfd = malloc(sizeof(struct local_client));
if (!newfd) {
@@ -403,7 +414,7 @@ static int local_rendezvous_callback(struct local_client *thisfd, char *buf,
}
static int local_pipe_callback(struct local_client *thisfd, char *buf,
int maxlen, char *csid,
int maxlen, const char *csid,
struct local_client **new_client)
{
int len;
@@ -412,6 +423,8 @@ static int local_pipe_callback(struct local_client *thisfd, char *buf,
int status = -1; /* in error by default */
len = read(thisfd->fd, buffer, sizeof(int));
if (len == -1 && errno == EINTR)
return 1;
if (len == sizeof(int)) {
memcpy(&status, buffer, sizeof(int));
@@ -477,7 +490,7 @@ static int local_pipe_callback(struct local_client *thisfd, char *buf,
add one with "ETIMEDOUT".
NOTE: This won't race with real replies because they happen in the same thread.
*/
static void timedout_callback(struct local_client *client, char *csid,
static void timedout_callback(struct local_client *client, const char *csid,
int node_up)
{
if (node_up) {
@@ -786,6 +799,8 @@ static int read_from_local_sock(struct local_client *thisfd)
char buffer[PIPE_BUF];
len = read(thisfd->fd, buffer, sizeof(buffer));
if (len == -1 && errno == EINTR)
return 1;
DEBUGLOG("Read on local socket %d, len = %d\n", thisfd->fd, len);
@@ -901,8 +916,12 @@ static int read_from_local_sock(struct local_client *thisfd)
len - strlen(inheader->node) - sizeof(struct clvm_header);
missing_len = inheader->arglen - argslen;
if (missing_len < 0)
missing_len = 0;
/* Save the message */
thisfd->bits.localsock.cmd = malloc(len + missing_len);
if (!thisfd->bits.localsock.cmd) {
struct clvm_header reply;
reply.cmd = CLVMD_CMD_REPLY;
@@ -927,9 +946,8 @@ static int read_from_local_sock(struct local_client *thisfd)
DEBUGLOG
("got %d bytes, need another %d (total %d)\n",
argslen, missing_len, inheader->arglen);
len =
read(thisfd->fd, argptr + argslen,
missing_len);
len = read(thisfd->fd, argptr + argslen,
missing_len);
if (len >= 0) {
missing_len -= len;
argslen += len;
@@ -1039,31 +1057,6 @@ int add_client(struct local_client *new_client)
return 0;
}
/*
* Send a long message using the System LV
*/
static int send_long_message(struct local_client *thisfd, struct clvm_header *inheader, int len)
{
struct clvm_header new_header;
int status;
DEBUGLOG("Long message: being sent via system LV:\n");
/* Use System LV */
status = system_lv_write_data((char *)inheader, len);
if (status < 0)
return errno;
/* Send message indicating System-LV is being used */
memcpy(&new_header, inheader, sizeof(new_header));
new_header.flags |= CLVMD_FLAG_SYSTEMLV;
new_header.xid = thisfd->xid;
return send_message(&new_header, sizeof(new_header), NULL, -1,
"Error forwarding long message to cluster");
}
/* Called when the pre-command has completed successfully - we
now execute the real command on all the requested nodes */
static int distribute_command(struct local_client *thisfd)
@@ -1090,13 +1083,9 @@ static int distribute_command(struct local_client *thisfd)
add_to_lvmqueue(thisfd, inheader, len, NULL);
DEBUGLOG("Sending message to all cluster nodes\n");
if (len > MAX_INLINE_MESSAGE) {
send_long_message(thisfd, inheader, len );
} else {
inheader->xid = thisfd->xid;
send_message(inheader, len, NULL, -1,
"Error forwarding message to cluster");
}
inheader->xid = thisfd->xid;
send_message(inheader, len, NULL, -1,
"Error forwarding message to cluster");
} else {
/* Do it on a single node */
char csid[MAX_CSID_LEN];
@@ -1117,14 +1106,10 @@ static int distribute_command(struct local_client *thisfd)
} else {
DEBUGLOG("Sending message to single node: %s\n",
inheader->node);
if (len > MAX_INLINE_MESSAGE) {
send_long_message(thisfd, inheader, len );
} else {
inheader->xid = thisfd->xid;
send_message(inheader, len,
csid, -1,
"Error forwarding message to cluster node");
}
inheader->xid = thisfd->xid;
send_message(inheader, len,
csid, -1,
"Error forwarding message to cluster node");
}
}
}
@@ -1140,7 +1125,7 @@ static int distribute_command(struct local_client *thisfd)
/* Process a command from a remote node and return the result */
static void process_remote_command(struct clvm_header *msg, int msglen, int fd,
char *csid)
const char *csid)
{
char *replyargs;
char nodename[max_cluster_member_name_len];
@@ -1155,55 +1140,6 @@ static void process_remote_command(struct clvm_header *msg, int msglen, int fd,
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) {
struct clvm_header *newmsg;
DEBUGLOG("Reading message from system LV\n");
newmsg =
(struct clvm_header *) malloc(msg->arglen +
sizeof(struct clvm_header));
if (newmsg) {
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.flags = 0;
head.clientid = msg->clientid;
head.arglen = 0;
head.node[0] = '\0';
send_message(&head, sizeof(struct clvm_header),
csid, fd,
"Error sending ENOMEM command reply");
return;
}
} else {
struct clvm_header head;
DEBUGLOG
("Error attempting to malloc %d bytes for system LV read\n",
msg->arglen);
/* Return a failure response */
head.cmd = CLVMD_CMD_REPLY;
head.status = ENOMEM;
head.flags = 0;
head.clientid = msg->clientid;
head.arglen = 0;
head.node[0] = '\0';
send_message(&head, sizeof(struct clvm_header), csid,
fd, "Error sending ENOMEM command reply");
return;
}
}
/* Check for GOAWAY and sulk */
if (msg->cmd == CLVMD_CMD_GOAWAY) {
@@ -1215,7 +1151,7 @@ static 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[3];
int version_nums[3];
char node[256];
memcpy(version_nums, msg->args, sizeof(version_nums));
@@ -1278,40 +1214,16 @@ static void process_remote_command(struct clvm_header *msg, int msglen, int fd,
replyargs, replylen);
agghead->xid = msg->xid;
/* Use the system LV ? */
if (replylen > MAX_INLINE_MESSAGE) {
agghead->cmd = CLVMD_CMD_REPLY;
agghead->status = status;
agghead->flags = CLVMD_FLAG_SYSTEMLV;
agghead->clientid = msg->clientid;
agghead->arglen = replylen;
agghead->node[0] = '\0';
/* 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
&& replylen > 0)
agghead->status = EFBIG;
send_message(agghead,
sizeof(struct clvm_header), csid,
fd,
"Error sending long command reply");
} else {
agghead->cmd = CLVMD_CMD_REPLY;
agghead->status = status;
agghead->flags = 0;
agghead->clientid = msg->clientid;
agghead->arglen = replylen;
agghead->node[0] = '\0';
send_message(aggreply,
sizeof(struct clvm_header) +
replylen, csid, fd,
"Error sending command reply");
}
agghead->cmd = CLVMD_CMD_REPLY;
agghead->status = status;
agghead->flags = 0;
agghead->clientid = msg->clientid;
agghead->arglen = replylen;
agghead->node[0] = '\0';
send_message(aggreply,
sizeof(struct clvm_header) +
replylen, csid, fd,
"Error sending command reply");
} else {
struct clvm_header head;
@@ -1340,7 +1252,7 @@ static void process_remote_command(struct clvm_header *msg, int msglen, int fd,
If we have got a full set then send them to the waiting client down the local
socket */
static void add_reply_to_list(struct local_client *client, int status,
char *csid, const char *buf, int len)
const char *csid, const char *buf, int len)
{
struct node_reply *reply;
@@ -1395,6 +1307,7 @@ static __attribute__ ((noreturn)) void *pre_and_post_thread(void *arg)
{
struct local_client *client = (struct local_client *) arg;
int status;
int write_status;
sigset_t ss;
int pipe_fd = client->bits.localsock.pipe;
@@ -1424,8 +1337,19 @@ static __attribute__ ((noreturn)) void *pre_and_post_thread(void *arg)
client->bits.localsock.all_success = 0;
DEBUGLOG("Writing status %d down pipe %d\n", status, pipe_fd);
/* Tell the parent process we have finished this bit */
write(pipe_fd, &status, sizeof(int));
do {
write_status = write(pipe_fd, &status, sizeof(int));
if (write_status == sizeof(int))
break;
if (write_status < 0 &&
(errno == EINTR || errno == EAGAIN))
continue;
log_error("Error sending to pipe: %m\n");
break;
} while(1);
if (status)
continue; /* Wait for another PRE command */
@@ -1446,7 +1370,16 @@ static __attribute__ ((noreturn)) void *pre_and_post_thread(void *arg)
status = 0;
do_post_command(client);
write(pipe_fd, &status, sizeof(int));
do {
write_status = write(pipe_fd, &status, sizeof(int));
if (write_status == sizeof(int))
break;
if (write_status < 0 &&
(errno == EINTR || errno == EAGAIN))
continue;
log_error("Error sending to pipe: %m\n");
break;
} while(1);
DEBUGLOG("Waiting for next pre command\n");
@@ -1496,7 +1429,7 @@ static int process_local_command(struct clvm_header *msg, int msglen,
return status;
}
static int process_reply(struct clvm_header *msg, int msglen, char *csid)
static int process_reply(const struct clvm_header *msg, int msglen, const char *csid)
{
struct local_client *client = NULL;
@@ -1646,10 +1579,15 @@ static void send_version_message()
}
/* Send a message to either a local client or another server */
static int send_message(void *buf, int msglen, char *csid, int fd,
static int send_message(void *buf, int msglen, const char *csid, int fd,
const char *errtext)
{
int len;
int saved_errno = 0;
struct timespec delay;
struct timespec remtime;
int retry_cnt = 0;
/* Send remote messages down the cluster socket */
if (csid == NULL || !ISLOCAL_CSID(csid)) {
@@ -1660,14 +1598,38 @@ static int send_message(void *buf, int msglen, char *csid, int fd,
/* Make sure it all goes */
do {
if (retry_cnt > MAX_RETRIES)
{
errno = saved_errno;
log_error("%s", errtext);
errno = saved_errno;
break;
}
len = write(fd, buf + ptr, msglen - ptr);
if (len <= 0) {
log_error(errtext);
if (errno == EINTR)
continue;
if (errno == EAGAIN ||
errno == EIO ||
errno == ENOSPC) {
saved_errno = errno;
retry_cnt++;
delay.tv_sec = 0;
delay.tv_nsec = 100000;
remtime.tv_sec = 0;
remtime.tv_nsec = 0;
(void) nanosleep (&delay, &remtime);
continue;
}
log_error("%s", errtext);
break;
}
ptr += len;
} while (len < msglen);
} while (ptr < msglen);
}
return len;
}
@@ -1749,7 +1711,7 @@ static __attribute__ ((noreturn)) void *lvm_thread_fn(void *arg)
/* Pass down some work to the LVM thread */
static int add_to_lvmqueue(struct local_client *client, struct clvm_header *msg,
int msglen, char *csid)
int msglen, const char *csid)
{
struct lvm_thread_cmd *cmd;
@@ -1827,7 +1789,8 @@ static int open_local_sock()
return local_socket;
}
void process_message(struct local_client *client, char *buf, int len, char *csid)
void process_message(struct local_client *client, const char *buf, int len,
const char *csid)
{
struct clvm_header *inheader;
@@ -1840,7 +1803,7 @@ void process_message(struct local_client *client, char *buf, int len, char *csid
}
static void check_all_callback(struct local_client *client, char *csid,
static void check_all_callback(struct local_client *client, const char *csid,
int node_up)
{
if (!node_up)

View File

@@ -76,7 +76,8 @@ struct netsock_bits {
};
typedef int (*fd_callback_t) (struct local_client * fd, char *buf, int len,
char *csid, struct local_client ** new_client);
const char *csid,
struct local_client ** new_client);
/* One of these for each fd we are listening on */
struct local_client {
@@ -112,7 +113,8 @@ extern void cmd_client_cleanup(struct local_client *client);
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 process_message(struct local_client *client, const char *buf,
int len, const char *csid);
extern void debuglog(const char *fmt, ... );
int sync_lock(const char *resource, int mode, int flags, int *lockid);

View File

@@ -30,11 +30,11 @@
#include <errno.h>
#include <syslog.h>
#include <assert.h>
#include <libdevmapper.h>
#include <libdlm.h>
#include "libdevmapper.h"
#include "list.h"
#include "lvm-types.h"
#include "libdlm.h"
#include "clvm.h"
#include "clvmd-comms.h"
#include "clvmd.h"
@@ -50,6 +50,7 @@
static struct cmd_context *cmd = NULL;
static struct dm_hash_table *lv_hash = NULL;
static pthread_mutex_t lv_hash_lock;
static pthread_mutex_t lvm_lock;
static char last_error[1024];
struct lv_info {
@@ -311,10 +312,12 @@ int do_lock_lv(unsigned char command, unsigned char lock_flags, char *resource)
DEBUGLOG("do_lock_lv: resource '%s', cmd = 0x%x, flags = %x\n",
resource, command, lock_flags);
pthread_mutex_lock(&lvm_lock);
if (!cmd->config_valid || config_files_changed(cmd)) {
/* Reinitialise various settings inc. logging, filters */
if (!refresh_toolcontext(cmd)) {
log_error("Updated config file invalid. Aborting.");
pthread_mutex_unlock(&lvm_lock);
return EINVAL;
}
}
@@ -367,6 +370,7 @@ int do_lock_lv(unsigned char command, unsigned char lock_flags, char *resource)
/* clean the pool for another command */
dm_pool_empty(cmd->mem);
pthread_mutex_unlock(&lvm_lock);
DEBUGLOG("Command return is %d\n", status);
return status;
@@ -393,6 +397,8 @@ int pre_lock_lv(unsigned char command, unsigned char lock_flags, char *resource)
int post_lock_lv(unsigned char command, unsigned char lock_flags,
char *resource)
{
int status;
/* Opposite of above, done on resume after a metadata update */
if (command == LCK_LV_RESUME) {
int oldmode;
@@ -406,7 +412,10 @@ int post_lock_lv(unsigned char command, unsigned char lock_flags,
if (oldmode == LKM_PWMODE) {
struct lvinfo lvi;
if (!lv_info_by_lvid(cmd, resource, &lvi, 0))
pthread_mutex_lock(&lvm_lock);
status = lv_info_by_lvid(cmd, resource, &lvi, 0);
pthread_mutex_unlock(&lvm_lock);
if (!status)
return EIO;
if (lvi.exists) {
@@ -533,7 +542,7 @@ 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
* Ignore non-error messages, but store the latest one for returning
* to the user.
*/
if (level != _LOG_ERR && level != _LOG_FATAL)
@@ -572,6 +581,7 @@ void init_lvhash()
/* Create hash table for keeping LV locks & status */
lv_hash = dm_hash_create(100);
pthread_mutex_init(&lv_hash_lock, NULL);
pthread_mutex_init(&lvm_lock, NULL);
}
/* Called to initialise the LVM context of the daemon */

View File

@@ -1,371 +0,0 @@
/*
* Copyright (C) 2002-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
*/
/* Routines dealing with the System LV */
#include <pthread.h>
#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/mount.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 <dirent.h>
#include <errno.h>
#include <mntent.h>
#include "libdlm.h"
#include "log.h"
#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
#define SYSTEM_LV_FILESYSTEM "ext2"
#define SYSTEM_LV_MOUNTPOINT "/tmp/.clvmd-XXXXXX"
extern char *config_filename(void);
static char system_lv_name[PATH_MAX] = { '\0' };
static char mount_point[PATH_MAX] = { '\0' };
static int mounted = 0;
static int mounted_rw = 0;
static int lockid;
static const char *lock_name = "CLVM_SYSTEM_LV";
/* Look in /proc/mounts or (as a last resort) /etc/mtab to
see if the system-lv is mounted. If it is mounted and we
think it's not then abort because we don't have the right
lock status and we don't know what other processes are doing with it.
Returns 1 for mounted, 0 for not mounted so it matches the condition
of the "mounted" static variable above.
*/
static int is_really_mounted(void)
{
FILE *mountfile;
struct mntent *ment;
mountfile = setmntent("/proc/mounts", "r");
if (!mountfile) {
mountfile = setmntent("/etc/mtab", "r");
if (!mountfile) {
log_error("Unable to open /proc/mounts or /etc/mtab");
return -1;
}
}
/* Look for system LV name in the file */
do {
ment = getmntent(mountfile);
if (ment) {
if (strcmp(ment->mnt_fsname, system_lv_name) == 0) {
endmntent(mountfile);
return 1;
}
}
}
while (ment);
endmntent(mountfile);
return 0;
}
/* Get the system LV name from the config file */
static int find_system_lv(void)
{
if (system_lv_name[0] == '\0') {
#ifdef HAVE_CCS
int error;
ccs_node_t *ctree;
/* Read the cluster config file */
/* Open the config file */
error = open_ccs_file(&ctree, "clvm.ccs");
if (error) {
perror("reading config file");
return -1;
}
strcpy(system_lv_name, find_ccs_str(ctree,
"cluster/systemlv", '/',
"/dev/vg/system_lv"));
/* Finished with config file */
close_ccs_file(ctree);
#else
if (getenv("CLVMD_SYSTEM_LV"))
strcpy(system_lv_name, getenv("CLVMD_SYSTEM_LV"));
else
return -1;
#endif
}
/* See if it has been mounted outside our control */
if (is_really_mounted() != mounted) {
log_error
("The system LV state has been mounted/umounted outside the control of clvmd\n"
"it cannot not be used for cluster communications until this is fixed.\n");
return -1;
}
return 0;
}
/* No prizes */
int system_lv_umount(void)
{
if (!mounted)
return 0;
if (umount(mount_point) < 0) {
log_error("umount of system LV (%s) failed: %m\n",
system_lv_name);
return -1;
}
sync_unlock(lock_name, lockid);
mounted = 0;
/* Remove the mount point */
rmdir(mount_point);
return 0;
}
int system_lv_mount(int readwrite)
{
int status;
int saved_errno;
int fd;
if (find_system_lv()) {
errno = EBUSY;
return -1;
}
/* Is it already mounted suitably? */
if (mounted) {
if (!readwrite || (readwrite && mounted_rw)) {
return 0;
} else {
/* Mounted RO and we need RW */
if (system_lv_umount() < 0)
return -1;
}
}
/* Randomize the mount point */
strcpy(mount_point, SYSTEM_LV_MOUNTPOINT);
fd = mkstemp(mount_point);
if (fd < 0) {
log_error("mkstemp for system LV mount point failed: %m\n");
return -1;
}
/* Race condition here but there's no mkstemp for directories */
close(fd);
unlink(mount_point);
mkdir(mount_point, 0600);
/* Make sure we have a system-lv lock */
status =
sync_lock(lock_name, (readwrite) ? LKM_EXMODE : LKM_CRMODE, 0,
&lockid);
if (status < 0)
return -1;
/* Mount it */
if (mount(system_lv_name, mount_point, SYSTEM_LV_FILESYSTEM,
MS_MGC_VAL | MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_SYNCHRONOUS
| (readwrite ? 0 : MS_RDONLY), NULL) < 0) {
/* mount(2) returns EINVAL if the volume has no FS on it. So, if we want to
write to it we try to make a filesystem in it and retry the mount */
if (errno == EINVAL && readwrite) {
char cmd[256];
log_error("Attempting mkfs on system LV device %s\n",
system_lv_name);
snprintf(cmd, sizeof(cmd), "/sbin/mkfs -t %s %s",
SYSTEM_LV_FILESYSTEM, system_lv_name);
system(cmd);
if (mount
(system_lv_name, mount_point, SYSTEM_LV_FILESYSTEM,
MS_MGC_VAL | MS_NOSUID | MS_NODEV | MS_NOEXEC |
MS_SYNCHRONOUS | (readwrite ? 0 : MS_RDONLY),
NULL) == 0)
goto mounted;
}
saved_errno = errno;
log_error("mount of system LV (%s, %s, %s) failed: %m\n",
system_lv_name, mount_point, SYSTEM_LV_FILESYSTEM);
sync_unlock(lock_name, lockid);
errno = saved_errno;
return -1;
}
mounted:
/* Set the internal flags */
mounted = 1;
mounted_rw = readwrite;
return 0;
}
/* Erase *all* files in the root directory of the system LV.
This *MUST* be called with an appropriate lock held!
The LV is left mounted RW because it is assumed that the
caller wants to write something here after clearing some space */
int system_lv_eraseall(void)
{
DIR *dir;
struct dirent *ent;
char fname[PATH_MAX];
/* Must be mounted R/W */
system_lv_mount(1);
dir = opendir(mount_point);
if (!dir)
return -1;
while ((ent = readdir(dir))) {
struct stat st;
snprintf(fname, sizeof(fname), "%s/%s", mount_point,
ent->d_name);
if (stat(fname, &st)) {
if (S_ISREG(st.st_mode))
unlink(fname);
}
}
closedir(dir);
return 0;
}
/* This is a "high-level" routine - it mounts the system LV, writes
the data into a file named after this node and then umounts the LV
again */
int system_lv_write_data(char *data, ssize_t len)
{
struct utsname nodeinfo;
char fname[PATH_MAX];
int outfile;
ssize_t thiswrite;
ssize_t written;
if (system_lv_mount(1))
return -1;
/* Build the file name we are goingto use. */
uname(&nodeinfo);
snprintf(fname, sizeof(fname), "%s/%s", mount_point, nodeinfo.nodename);
/* Open the file for output */
outfile = open(fname, O_RDWR | O_CREAT | O_TRUNC, 0600);
if (outfile < 0) {
int saved_errno = errno;
system_lv_umount();
errno = saved_errno;
return -1;
}
written = 0;
do {
thiswrite = write(outfile, data + written, len - written);
if (thiswrite > 0)
written += thiswrite;
} while (written < len && thiswrite > 0);
close(outfile);
system_lv_umount();
return (thiswrite < 0) ? -1 : 0;
}
/* This is a "high-level" routine - it mounts the system LV, reads
the data from a named file and then umounts the LV
again */
int system_lv_read_data(char *fname_base, char *data, ssize_t *len)
{
char fname[PATH_MAX];
int outfile;
struct stat st;
ssize_t filesize;
ssize_t thisread;
ssize_t readbytes;
if (system_lv_mount(0))
return -1;
/* Build the file name we are going to use. */
snprintf(fname, sizeof(fname), "%s/%s", mount_point, fname_base);
/* Get the file size and stuff. Actually we only need the file size but
this will also check that the file exists */
if (stat(fname, &st) < 0) {
int saved_errno = errno;
log_error("stat of file %s on system LV failed: %m\n", fname);
system_lv_umount();
errno = saved_errno;
return -1;
}
filesize = st.st_size;
outfile = open(fname, O_RDONLY);
if (outfile < 0) {
int saved_errno = errno;
log_error("open of file %s on system LV failed: %m\n", fname);
system_lv_umount();
errno = saved_errno;
return -1;
}
readbytes = 0;
do {
thisread =
read(outfile, data + readbytes, filesize - readbytes);
if (thisread > 0)
readbytes += thisread;
} while (readbytes < filesize && thisread > 0);
close(outfile);
system_lv_umount();
*len = readbytes;
return (thisread < 0) ? -1 : 0;
}

View File

@@ -1,30 +0,0 @@
/*
* Copyright (C) 2002-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 _CLVM_SYSTEM_LV_H
#define _CLVM_SYSTEM_LV_H
/* Prototypes for System-LV functions */
/* "low-level" functions */
extern int system_lv_umount(void);
extern int system_lv_mount(int readwrite);
extern int system_lv_eraseall(void);
/* "high-level" functions */
extern int system_lv_write_data(char *data, ssize_t len);
extern int system_lv_read_data(char *fname_base, char *data, ssize_t *len);
#endif

View File

@@ -34,8 +34,8 @@
#include <syslog.h>
#include <netdb.h>
#include <assert.h>
#include <libdevmapper.h>
#include "libdevmapper.h"
#include "clvm.h"
#include "clvmd-comms.h"
#include "clvmd.h"
@@ -92,41 +92,37 @@ int init_comms(unsigned short port)
return 0;
}
void tcp_remove_client(char *csid)
{
void tcp_remove_client(const char *c_csid)
{
struct local_client *client;
char csid[GULM_MAX_CSID_LEN];
unsigned int i;
memcpy(csid, c_csid, sizeof csid);
DEBUGLOG("tcp_remove_client\n");
/* Don't actually close the socket here - that's the
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 = dm_hash_lookup_binary(sock_hash, csid, GULM_MAX_CSID_LEN);
if (client)
for (i = 0; i < 2; i++)
{
dm_hash_remove_binary(sock_hash, csid, GULM_MAX_CSID_LEN);
client->removeme = 1;
close(client->fd);
client = dm_hash_lookup_binary(sock_hash, csid, GULM_MAX_CSID_LEN);
if (client)
{
dm_hash_remove_binary(sock_hash, csid, GULM_MAX_CSID_LEN);
client->removeme = 1;
close(client->fd);
}
/* Look for a mangled one too, on the 2nd iteration. */
csid[0] ^= 0x80;
}
/* Look for a mangled one too */
csid[0] ^= 0x80;
client = dm_hash_lookup_binary(sock_hash, csid, GULM_MAX_CSID_LEN);
if (client)
{
dm_hash_remove_binary(sock_hash, csid, GULM_MAX_CSID_LEN);
client->removeme = 1;
close(client->fd);
}
/* Put it back as we found it */
csid[0] ^= 0x80;
}
int alloc_client(int fd, char *csid, struct local_client **new_client)
int alloc_client(int fd, const char *c_csid, struct local_client **new_client)
{
struct local_client *client;
char csid[GULM_MAX_CSID_LEN];
memcpy(csid, c_csid, sizeof csid);
DEBUGLOG("alloc_client %d csid = %s\n", fd, print_csid(csid));
@@ -315,7 +311,7 @@ static int read_from_tcpsock(struct local_client *client, char *buf, int len, ch
return status;
}
int gulm_connect_csid(char *csid, struct local_client **newclient)
int gulm_connect_csid(const char *csid, struct local_client **newclient)
{
int fd;
struct sockaddr_in6 addr;
@@ -366,7 +362,7 @@ int gulm_connect_csid(char *csid, struct local_client **newclient)
}
/* Send a message to a known CSID */
static int tcp_send_message(void *buf, int msglen, unsigned char *csid, const char *errtext)
static int tcp_send_message(void *buf, int msglen, const char *csid, const char *errtext)
{
int status;
struct local_client *client;
@@ -465,7 +461,7 @@ static void map_v4_to_v6(struct in_addr *ip4, struct in6_addr *ip6)
}
/* Get someone else's IP address from DNS */
int get_ip_address(char *node, char *addr)
int get_ip_address(const char *node, char *addr)
{
struct hostent *he;
@@ -493,7 +489,7 @@ int get_ip_address(char *node, char *addr)
return 0;
}
char *print_csid(char *csid)
char *print_csid(const char *csid)
{
static char buf[128];
int *icsid = (int *)csid;

View File

@@ -5,9 +5,9 @@
#define GULM_MAX_CLUSTER_MEMBER_NAME_LEN 128
extern int init_comms(unsigned short);
extern char *print_csid(char *);
extern char *print_csid(const 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);
int gulm_connect_csid(const char *csid, struct local_client **newclient);

View File

@@ -146,6 +146,7 @@ static LIST_INIT(_dso_registry);
/* Structure to keep parsed register variables from client message. */
struct message_data {
char *id;
char *dso_name; /* Name of DSO. */
char *device_uuid; /* Mapped device path. */
union {
@@ -225,8 +226,8 @@ static struct thread_status *_alloc_thread_status(struct message_data *data,
if (!ret)
return NULL;
if (!memset(ret, 0, sizeof(*ret)) ||
!(ret->device.uuid = dm_strdup(data->device_uuid))) {
memset(ret, 0, sizeof(*ret));
if (!(ret->device.uuid = dm_strdup(data->device_uuid))) {
dm_free(ret);
return NULL;
}
@@ -244,6 +245,8 @@ static struct thread_status *_alloc_thread_status(struct message_data *data,
static void _free_thread_status(struct thread_status *thread)
{
if (thread->current_task)
dm_task_destroy(thread->current_task);
dm_free(thread->device.uuid);
dm_free(thread->device.name);
dm_free(thread);
@@ -257,8 +260,8 @@ static struct dso_data *_alloc_dso_data(struct message_data *data)
if (!ret)
return NULL;
if (!memset(ret, 0, sizeof(*ret)) ||
!(ret->dso_name = dm_strdup(data->dso_name))) {
memset(ret, 0, sizeof(*ret));
if (!(ret->dso_name = dm_strdup(data->dso_name))) {
dm_free(ret);
return NULL;
}
@@ -320,6 +323,8 @@ static int _fetch_string(char **ptr, char **src, const int delimiter)
/* Free message memory. */
static void _free_message(struct message_data *message_data)
{
if (message_data->id)
dm_free(message_data->id);
if (message_data->dso_name)
dm_free(message_data->dso_name);
@@ -342,7 +347,8 @@ static int _parse_message(struct message_data *message_data)
* Retrieve application identifier, mapped device
* path and events # string from message.
*/
if (_fetch_string(&message_data->dso_name, &p, ' ') &&
if (_fetch_string(&message_data->id, &p, ' ') &&
_fetch_string(&message_data->dso_name, &p, ' ') &&
_fetch_string(&message_data->device_uuid, &p, ' ') &&
_fetch_string(&message_data->events.str, &p, ' ') &&
_fetch_string(&message_data->timeout.str, &p, ' ')) {
@@ -617,6 +623,8 @@ static int _event_wait(struct thread_status *thread, struct dm_task **task)
} else if (thread->events & DM_EVENT_TIMEOUT && errno == EINTR) {
thread->current_events |= DM_EVENT_TIMEOUT;
ret = DM_WAIT_INTR;
} else if (thread->status == DM_THREAD_SHUTDOWN && errno == EINTR) {
ret = DM_WAIT_FATAL;
} else {
syslog(LOG_NOTICE, "dm_task_run failed, errno = %d, %s",
errno, strerror(errno));
@@ -807,11 +815,6 @@ static int _create_thread(struct thread_status *thread)
static int _terminate_thread(struct thread_status *thread)
{
int ret;
if ((ret = pthread_cancel(thread->thread)))
return ret;
return pthread_kill(thread->thread, SIGALRM);
}
@@ -875,8 +878,8 @@ static struct dso_data *_load_dso(struct message_data *data)
syslog(LOG_ERR, "dmeventd %s dlopen failed: %s", data->dso_name,
dlerr);
data->msg->size =
dm_asprintf(&(data->msg->data), "%s dlopen failed: %s",
data->dso_name, dlerr);
dm_asprintf(&(data->msg->data), "%s %s dlopen failed: %s",
data->id, data->dso_name, dlerr);
return NULL;
}
@@ -1056,7 +1059,8 @@ static int _registered_device(struct message_data *message_data,
{
struct dm_event_daemon_message *msg = message_data->msg;
const char *fmt = "%s %s %u";
const char *fmt = "%s %s %s %u";
const char *id = message_data->id;
const char *dso = thread->dso_data->dso_name;
const char *dev = thread->device.uuid;
unsigned events = ((thread->status == DM_THREAD_RUNNING)
@@ -1066,7 +1070,7 @@ static int _registered_device(struct message_data *message_data,
if (msg->data)
dm_free(msg->data);
msg->size = dm_asprintf(&(msg->data), fmt, dso, dev, events);
msg->size = dm_asprintf(&(msg->data), fmt, id, dso, dev, events);
_unlock_mutex();
@@ -1180,7 +1184,8 @@ static int _get_timeout(struct message_data *message_data)
_lock_mutex();
if ((thread = _lookup_thread_status(message_data))) {
msg->size =
dm_asprintf(&(msg->data), "%" PRIu32, thread->timeout);
dm_asprintf(&(msg->data), "%s %" PRIu32, message_data->id,
thread->timeout);
} else {
msg->data = NULL;
msg->size = 0;
@@ -1375,17 +1380,32 @@ static int _handle_request(struct dm_event_daemon_message *msg,
static int _do_process_request(struct dm_event_daemon_message *msg)
{
int ret;
char *answer;
static struct message_data message_data;
/* Parse the message. */
memset(&message_data, 0, sizeof(message_data));
message_data.msg = msg;
if (msg->cmd != DM_EVENT_CMD_ACTIVE && !_parse_message(&message_data)) {
if (msg->cmd == DM_EVENT_CMD_HELLO) {
ret = 0;
answer = msg->data;
if (answer) {
msg->size = dm_asprintf(&(msg->data), "%s HELLO", answer);
dm_free(answer);
} else {
msg->size = 0;
msg->data = NULL;
}
} else if (msg->cmd != DM_EVENT_CMD_ACTIVE && !_parse_message(&message_data)) {
stack;
ret = -EINVAL;
} else
ret = _handle_request(msg, &message_data);
msg->cmd = ret;
if (!msg->data)
msg->size = dm_asprintf(&(msg->data), "%s %s", message_data.id, strerror(-ret));
_free_message(&message_data);
return ret;
@@ -1405,16 +1425,9 @@ static void _process_request(struct dm_event_fifos *fifos)
if (!_client_read(fifos, &msg))
return;
msg.cmd = _do_process_request(&msg);
if (!msg.data) {
msg.data = dm_strdup(strerror(-msg.cmd));
if (msg.data)
msg.size = strlen(msg.data) + 1;
else {
msg.size = 0;
stack;
}
}
/* _do_process_request fills in msg (if memory allows for
data, otherwise just cmd and size = 0) */
_do_process_request(&msg);
if (!_client_write(fifos, &msg))
stack;

View File

@@ -20,6 +20,7 @@ enum dm_event_command {
DM_EVENT_CMD_GET_NEXT_REGISTERED_DEVICE,
DM_EVENT_CMD_SET_TIMEOUT,
DM_EVENT_CMD_GET_TIMEOUT,
DM_EVENT_CMD_HELLO,
};
/* Message passed between client and daemon. */

View File

@@ -30,6 +30,8 @@
#include <sys/wait.h>
#include <arpa/inet.h> /* for htonl, ntohl */
static int _sequence_nr = 0;
struct dm_event_handler {
char *dso;
@@ -182,6 +184,21 @@ enum dm_event_mask dm_event_handler_get_event_mask(const struct dm_event_handler
return dmevh->mask;
}
static int _check_message_id(struct dm_event_daemon_message *msg)
{
int pid, seq_nr;
if ((sscanf(msg->data, "%d:%d", &pid, &seq_nr) != 2) ||
(pid != getpid()) || (seq_nr != _sequence_nr)) {
log_error("Ignoring out-of-sequence reply from dmeventd. "
"Expected %d:%d but received %s", getpid(),
_sequence_nr, msg->data);
return 0;
}
return 1;
}
/*
* daemon_read
* @fifos
@@ -260,11 +277,28 @@ static int _daemon_write(struct dm_event_fifos *fifos,
size_t size = 2 * sizeof(uint32_t) + msg->size;
char *buf = alloca(size);
char drainbuf[128];
struct timeval tval = { 0, 0 };
*((uint32_t *)buf) = htonl(msg->cmd);
*((uint32_t *)buf + 1) = htonl(msg->size);
memcpy(buf + 2 * sizeof(uint32_t), msg->data, msg->size);
/* drain the answer fifo */
while (1) {
FD_ZERO(&fds);
FD_SET(fifos->server, &fds);
tval.tv_usec = 100;
ret = select(fifos->server + 1, &fds, NULL, NULL, &tval);
if ((ret < 0) && (errno != EINTR)) {
log_error("Unable to talk to event daemon");
return 0;
}
if (ret == 0)
break;
read(fifos->server, drainbuf, 127);
}
while (bytes < size) {
do {
/* Watch daemon write FIFO to be ready for output. */
@@ -301,7 +335,7 @@ static int _daemon_talk(struct dm_event_fifos *fifos,
{
const char *dso = dso_name ? dso_name : "";
const char *dev = dev_name ? dev_name : "";
const char *fmt = "%s %s %u %" PRIu32;
const char *fmt = "%d:%d %s %s %u %" PRIu32;
int msg_size;
memset(msg, 0, sizeof(*msg));
@@ -310,8 +344,10 @@ static int _daemon_talk(struct dm_event_fifos *fifos,
* into ASCII message string.
*/
msg->cmd = cmd;
if ((msg_size = dm_asprintf(&(msg->data), fmt, dso, dev, evmask,
timeout)) < 0) {
if (cmd == DM_EVENT_CMD_HELLO)
fmt = "%d:%d HELLO";
if ((msg_size = dm_asprintf(&(msg->data), fmt, getpid(), _sequence_nr,
dso, dev, evmask, timeout)) < 0) {
log_error("_daemon_talk: message allocation failed");
return -ENOMEM;
}
@@ -323,13 +359,24 @@ static int _daemon_talk(struct dm_event_fifos *fifos,
*/
if (!_daemon_write(fifos, msg)) {
stack;
dm_free(msg->data);
msg->data = 0;
return -EIO;
}
if (!_daemon_read(fifos, msg)) {
stack;
return -EIO;
}
do {
if (msg->data)
dm_free(msg->data);
msg->data = 0;
if (!_daemon_read(fifos, msg)) {
stack;
return -EIO;
}
} while (!_check_message_id(msg));
_sequence_nr++;
return (int32_t) msg->cmd;
}
@@ -507,7 +554,14 @@ static int _do_event(int cmd, struct dm_event_daemon_message *msg,
return -ESRCH;
}
ret = _daemon_talk(&fifos, msg, cmd, dso_name, dev_name, evmask, timeout);
ret = _daemon_talk(&fifos, msg, DM_EVENT_CMD_HELLO, 0, 0, 0, 0);
if (msg->data)
dm_free(msg->data);
msg->data = 0;
if (!ret)
ret = _daemon_talk(&fifos, msg, cmd, dso_name, dev_name, evmask, timeout);
/* what is the opposite of init? */
_dtr_client(&fifos);
@@ -521,7 +575,7 @@ 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;
struct dm_event_daemon_message msg = { 0, 0, NULL };
if (!(dmt = _get_device_info(dmevh))) {
stack;
@@ -551,7 +605,7 @@ 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;
struct dm_event_daemon_message msg = { 0, 0, NULL };
if (!(dmt = _get_device_info(dmevh))) {
stack;
@@ -598,15 +652,20 @@ static char *_fetch_string(char **src, const int delimiter)
static int _parse_message(struct dm_event_daemon_message *msg, char **dso_name,
char **uuid, enum dm_event_mask *evmask)
{
char *id = NULL;
char *p = msg->data;
if ((*dso_name = _fetch_string(&p, ' ')) &&
if ((id = _fetch_string(&p, ' ')) &&
(*dso_name = _fetch_string(&p, ' ')) &&
(*uuid = _fetch_string(&p, ' '))) {
*evmask = atoi(p);
dm_free(id);
return 0;
}
if (id)
dm_free(id);
return -ENOMEM;
}
@@ -621,12 +680,12 @@ static int _parse_message(struct dm_event_daemon_message *msg, char **dso_name,
*/
int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next)
{
int ret;
int ret = 0;
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;
enum dm_event_mask reply_mask = 0;
struct dm_task *dmt = NULL;
struct dm_event_daemon_message msg = { 0, 0, NULL };
if (!(dmt = _get_device_info(dmevh))) {
stack;
@@ -667,6 +726,12 @@ int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next)
dm_event_handler_set_dso(dmevh, reply_dso);
dm_event_handler_set_event_mask(dmevh, reply_mask);
if (reply_dso)
dm_free(reply_dso);
if (reply_uuid)
dm_free(reply_uuid);
dmevh->dev_name = dm_strdup(dm_task_get_name(dmt));
if (!dmevh->dev_name) {
ret = -ENOMEM;
@@ -689,6 +754,10 @@ int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next)
fail:
if (msg.data)
dm_free(msg.data);
if (reply_dso)
dm_free(reply_dso);
if (reply_uuid)
dm_free(reply_uuid);
_dm_event_handler_clear_dev_info(dmevh);
dm_task_destroy(dmt);
return ret;
@@ -696,9 +765,17 @@ int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next)
#if 0 /* left out for now */
static char *_skip_string(char *src, const int delimiter)
{
src = srtchr(src, delimiter);
if (src && *(src + 1))
return src + 1;
return NULL;
}
int dm_event_set_timeout(const char *device_path, uint32_t timeout)
{
struct dm_event_daemon_message msg;
struct dm_event_daemon_message msg = { 0, 0, NULL };
if (!device_exists(device_path))
return -ENODEV;
@@ -710,13 +787,20 @@ int dm_event_set_timeout(const char *device_path, uint32_t timeout)
int dm_event_get_timeout(const char *device_path, uint32_t *timeout)
{
int ret;
struct dm_event_daemon_message msg;
struct dm_event_daemon_message msg = { 0, 0, NULL };
if (!device_exists(device_path))
return -ENODEV;
if (!(ret = _do_event(DM_EVENT_CMD_GET_TIMEOUT, &msg, NULL, device_path,
0, 0)))
*timeout = atoi(msg.data);
0, 0))) {
char *p = _skip_string(msg.data, ' ');
if (!p) {
log_error("malformed reply from dmeventd '%s'\n",
msg.data);
return -EIO;
}
*timeout = atoi(p);
}
if (msg.data)
dm_free(msg.data);
return ret;

View File

@@ -12,10 +12,10 @@
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "libdevmapper.h"
#include "libdevmapper-event.h"
#include "lvm2cmd.h"
#include <libdevmapper.h>
#include <libdevmapper-event.h>
#include <errno.h>
#include <signal.h>
#include <string.h>

View File

@@ -12,10 +12,10 @@
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "libdevmapper.h"
#include "libdevmapper-event.h"
#include "lvm2cmd.h"
#include <libdevmapper.h>
#include <libdevmapper-event.h>
#include <errno.h>
#include <signal.h>
#include <string.h>

View File

@@ -19,6 +19,14 @@ devices {
# to use with LVM2.
scan = [ "/dev" ]
# If several entries in the scanned directories correspond to the
# same block device and the tools need to display a name for device,
# all the pathnames are matched against each item in the following
# list of regular expressions in turn and the first match is used.
preferred_names = [ ]
# preferred_names = [ "^/dev/mpath/", "^/dev/[hs]d" ]
# A filter that tells LVM2 to only use a restricted set of devices.
# The filter consists of an array of regular expressions. These
# expressions can be delimited by a character of your choice, and
@@ -56,10 +64,14 @@ devices {
# filter = [ "a|^/dev/hda8$|", "r/.*/" ]
# The results of the filtering are cached on disk to avoid
# rescanning dud devices (which can take a very long time). By
# default this cache file is hidden in the /etc/lvm directory.
# It is safe to delete this file: the tools regenerate it.
cache = "/etc/lvm/.cache"
# rescanning dud devices (which can take a very long time).
# By default this cache is stored in the /etc/lvm/cache directory
# in a file called '.cache'.
# It is safe to delete the contents: the tools regenerate it.
# (The old setting 'cache' is still respected if neither of
# these new ones is present.)
cache_dir = "/etc/lvm/cache"
cache_file_prefix = ""
# You can turn off writing this cache file by setting this to 0.
write_cache_state = 1
@@ -188,6 +200,9 @@ global {
# command. Defaults to off.
test = 0
# Default value for --units argument
units = "h"
# Whether or not to communicate with the kernel device-mapper.
# Set to 0 if you want to use the tools to manipulate LVM metadata
# without activating any logical volumes.

View File

@@ -43,7 +43,6 @@
../lib/misc/lvm-string.h
../lib/misc/lvm-wrappers.h
../lib/misc/sharedlib.h
../lib/regex/matcher.h
../lib/report/report.h
../lib/uuid/uuid.h
../po/pogen.h

View File

@@ -81,9 +81,6 @@ SOURCES =\
misc/lvm-wrappers.c \
misc/timestamp.c \
mm/memlock.c \
regex/matcher.c \
regex/parse_rx.c \
regex/ttree.c \
report/report.c \
striped/striped.c \
uuid/uuid.c \

View File

@@ -168,6 +168,10 @@ int lvs_in_vg_activated(struct volume_group *vg)
{
return 0;
}
int lvs_in_vg_activated_by_uuid_only(struct volume_group *vg)
{
return 0;
}
int lvs_in_vg_opened(struct volume_group *vg)
{
return 0;
@@ -241,7 +245,7 @@ void set_activation(int act)
log_verbose("Activation enabled. Device-mapper kernel "
"driver will be used.");
else
log_print("WARNING: Activation disabled. No device-mapper "
log_warn("WARNING: Activation disabled. No device-mapper "
"interaction will be attempted.");
}
@@ -309,7 +313,7 @@ static int _passes_activation_filter(struct cmd_context *cmd,
else
continue;
}
if (!index(str, '/')) {
if (!strchr(str, '/')) {
/* vgname supplied */
if (!strcmp(str, lv->vg->name))
return 1;
@@ -421,21 +425,23 @@ int target_present(const char *target_name, int use_modprobe)
* Returns 1 if info structure populated, else 0 on failure.
*/
static int _lv_info(struct cmd_context *cmd, const struct logical_volume *lv, int with_mknodes,
struct lvinfo *info, int with_open_count)
struct lvinfo *info, int with_open_count, unsigned by_uuid_only)
{
struct dm_info dminfo;
char *name;
char *name = NULL;
if (!activation())
return 0;
if (!(name = build_dm_name(cmd->mem, lv->vg->name, lv->name, NULL)))
if (!by_uuid_only &&
!(name = build_dm_name(cmd->mem, lv->vg->name, lv->name, NULL)))
return_0;
log_debug("Getting device info for %s", name);
if (!dev_manager_info(lv->vg->cmd->mem, name, lv, with_mknodes,
with_open_count, &dminfo)) {
dm_pool_free(cmd->mem, name);
if (name)
dm_pool_free(cmd->mem, name);
return_0;
}
@@ -448,14 +454,16 @@ static int _lv_info(struct cmd_context *cmd, const struct logical_volume *lv, in
info->live_table = dminfo.live_table;
info->inactive_table = dminfo.inactive_table;
dm_pool_free(cmd->mem, name);
if (name)
dm_pool_free(cmd->mem, name);
return 1;
}
int lv_info(struct cmd_context *cmd, const struct logical_volume *lv, struct lvinfo *info,
int with_open_count)
{
return _lv_info(cmd, lv, 0, info, with_open_count);
return _lv_info(cmd, lv, 0, info, with_open_count, 0);
}
int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s,
@@ -466,7 +474,7 @@ int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s,
if (!(lv = lv_from_lvid(cmd, lvid_s, 0)))
return 0;
return _lv_info(cmd, lv, 0, info, with_open_count);
return _lv_info(cmd, lv, 0, info, with_open_count, 0);
}
/*
@@ -519,11 +527,12 @@ int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv,
return r;
}
static int _lv_active(struct cmd_context *cmd, struct logical_volume *lv)
static int _lv_active(struct cmd_context *cmd, struct logical_volume *lv,
unsigned by_uuid_only)
{
struct lvinfo info;
if (!lv_info(cmd, lv, &info, 0)) {
if (!_lv_info(cmd, lv, 0, &info, 0, by_uuid_only)) {
stack;
return -1;
}
@@ -607,7 +616,7 @@ static int _lv_suspend_lv(struct logical_volume *lv, int lockfs)
* These two functions return the number of visible LVs in the state,
* or -1 on error.
*/
int lvs_in_vg_activated(struct volume_group *vg)
static int _lvs_in_vg_activated(struct volume_group *vg, unsigned by_uuid_only)
{
struct lv_list *lvl;
int count = 0;
@@ -617,12 +626,22 @@ int lvs_in_vg_activated(struct volume_group *vg)
list_iterate_items(lvl, &vg->lvs) {
if (lvl->lv->status & VISIBLE_LV)
count += (_lv_active(vg->cmd, lvl->lv) == 1);
count += (_lv_active(vg->cmd, lvl->lv, by_uuid_only) == 1);
}
return count;
}
int lvs_in_vg_activated_by_uuid_only(struct volume_group *vg)
{
return _lvs_in_vg_activated(vg, 1);
}
int lvs_in_vg_activated(struct volume_group *vg)
{
return _lvs_in_vg_activated(vg, 0);
}
int lvs_in_vg_opened(struct volume_group *vg)
{
struct lv_list *lvl;
@@ -973,7 +992,7 @@ int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv)
return r;
}
if (!_lv_info(cmd, lv, 1, &info, 0))
if (!_lv_info(cmd, lv, 1, &info, 0, 0))
return_0;
if (info.exists)

View File

@@ -83,6 +83,7 @@ int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv,
* Return number of LVs in the VG that are active.
*/
int lvs_in_vg_activated(struct volume_group *vg);
int lvs_in_vg_activated_by_uuid_only(struct volume_group *vg);
int lvs_in_vg_opened(struct volume_group *vg);

View File

@@ -118,12 +118,10 @@ static struct dm_task *_setup_task(const char *name, const char *uuid,
}
static int _info_run(const char *name, const char *dlid, struct dm_info *info,
int mknodes, int with_open_count, struct dm_pool *mem,
char **uuid_out)
int mknodes, int with_open_count)
{
int r = 0;
struct dm_task *dmt;
const char *u;
int dmtask;
dmtask = mknodes ? DM_DEVICE_MKNODES : DM_DEVICE_INFO;
@@ -143,11 +141,6 @@ static int _info_run(const char *name, const char *dlid, struct dm_info *info,
if (!dm_task_get_info(dmt, info))
goto_out;
if (info->exists && uuid_out) {
if (!(u = dm_task_get_uuid(dmt)))
goto_out;
*uuid_out = dm_pool_strdup(mem, u);
}
r = 1;
out:
@@ -194,7 +187,7 @@ int device_is_usable(dev_t dev)
next = dm_get_next_target(dmt, next, &start, &length,
&target_type, &params);
/* Skip if target type doesn't match */
if (!strcmp(target_type, "mirror"))
if (target_type && !strcmp(target_type, "mirror"))
goto out;
} while (next);
@@ -208,23 +201,20 @@ int device_is_usable(dev_t dev)
}
static int _info(const char *name, const char *dlid, int mknodes,
int with_open_count, struct dm_info *info,
struct dm_pool *mem, char **uuid_out)
int with_open_count, struct dm_info *info)
{
if (!mknodes && dlid && *dlid) {
if (_info_run(NULL, dlid, info, 0, with_open_count, mem,
uuid_out) &&
if (_info_run(NULL, dlid, info, 0, with_open_count) &&
info->exists)
return 1;
else if (_info_run(NULL, dlid + sizeof(UUID_PREFIX) - 1, info,
0, with_open_count, mem, uuid_out) &&
0, with_open_count) &&
info->exists)
return 1;
}
if (name)
return _info_run(name, NULL, info, mknodes, with_open_count,
mem, uuid_out);
return _info_run(name, NULL, info, mknodes, with_open_count);
return 0;
}
@@ -240,8 +230,7 @@ int dev_manager_info(struct dm_pool *mem, const char *name,
return 0;
}
return _info(name, dlid, with_mknodes, with_open_count, info,
NULL, NULL);
return _info(name, dlid, with_mknodes, with_open_count, info);
}
/* FIXME Interface must cope with multiple targets */
@@ -446,10 +435,8 @@ struct dev_manager *dev_manager_create(struct cmd_context *cmd,
return NULL;
}
if (!(dm = dm_pool_alloc(mem, sizeof(*dm)))) {
stack;
goto bad;
}
if (!(dm = dm_pool_alloc(mem, sizeof(*dm))))
goto_bad;
dm->cmd = cmd;
dm->mem = mem;
@@ -461,10 +448,8 @@ struct dev_manager *dev_manager_create(struct cmd_context *cmd,
}
dm->stripe_filler = stripe_filler;
if (!(dm->vg_name = dm_pool_strdup(dm->mem, vg_name))) {
stack;
goto bad;
}
if (!(dm->vg_name = dm_pool_strdup(dm->mem, vg_name)))
goto_bad;
dm->target_state = NULL;
@@ -576,7 +561,7 @@ int dev_manager_mirror_percent(struct dev_manager *dm,
log_debug("Getting device info for %s", dl->name);
/* Rename? */
if ((suffix = rindex(dl->dlid + sizeof(UUID_PREFIX) - 1, '-')))
if ((suffix = strrchr(dl->dlid + sizeof(UUID_PREFIX) - 1, '-')))
suffix++;
newname = build_dm_name(dm->mem, dm->vg_name, dl->lv->name,
suffix);
@@ -646,7 +631,7 @@ static int _add_dev_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
return_0;
log_debug("Getting device info for %s [%s]", name, dlid);
if (!_info(name, dlid, 0, 1, &info, dm->mem, NULL)) {
if (!_info(name, dlid, 0, 1, &info)) {
log_error("Failed to get info for %s [%s].", name, dlid);
return 0;
}
@@ -952,6 +937,10 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
return 1;
}
/* FIXME: symlinks should be created/destroyed at the same time
* as the kernel devices but we can't do that from within libdevmapper
* at present so we must walk the tree twice instead. */
/*
* Create LV symlinks for children of supplied root node.
*/
@@ -984,6 +973,32 @@ static int _create_lv_symlinks(struct dev_manager *dm, struct dm_tree_node *root
return r;
}
/*
* Remove LV symlinks for children of supplied root node.
*/
static int _remove_lv_symlinks(struct dev_manager *dm, struct dm_tree_node *root)
{
void *handle = NULL;
struct dm_tree_node *child;
char *vgname, *lvname, *layer;
int r = 1;
while ((child = dm_tree_next_child(&handle, root, 0))) {
if (!dm_split_lvm_name(dm->mem, dm_tree_node_get_name(child), &vgname, &lvname, &layer)) {
r = 0;
continue;
}
/* only top level layer has symlinks */
if (*layer)
continue;
fs_del_lv_byname(dm->cmd->dev_dir, vgname, lvname);
}
return r;
}
static int _clean_tree(struct dev_manager *dm, struct dm_tree_node *root)
{
void *handle = NULL;
@@ -1043,6 +1058,8 @@ static int _tree_action(struct dev_manager *dm, struct logical_volume *lv, actio
/* Deactivate LV and all devices it references that nothing else has open. */
if (!dm_tree_deactivate_children(root, dlid, ID_LEN + sizeof(UUID_PREFIX) - 1))
goto_out;
if (!_remove_lv_symlinks(dm, root))
log_error("Failed to remove all device symlinks associated with %s.", lv->name);
break;
case SUSPEND:
dm_tree_skip_lockfs(root);

View File

@@ -338,6 +338,11 @@ int fs_del_lv(const struct logical_volume *lv)
"", "");
}
int fs_del_lv_byname(const char *dev_dir, const char *vg_name, const char *lv_name)
{
return _fs_op(FS_DEL, dev_dir, vg_name, lv_name, "", "");
}
int fs_rename_lv(struct logical_volume *lv,
const char *dev, const char *old_name)
{

View File

@@ -25,6 +25,7 @@
*/
int fs_add_lv(const struct logical_volume *lv, const char *dev);
int fs_del_lv(const struct logical_volume *lv);
int fs_del_lv_byname(const char *dev_dir, const char *vg_name, const char *lv_name);
int fs_rename_lv(struct logical_volume *lv,
const char *dev, const char *old_name);
void fs_unlock(void);

12
lib/cache/lvmcache.c vendored
View File

@@ -135,7 +135,7 @@ const struct format_type *fmt_from_vgname(const char *vgname, const char *vgid)
list_iterate_safe(devh, tmp, &devs) {
devl = list_item(devh, struct device_list);
label_read(devl->dev, &label);
label_read(devl->dev, &label, UINT64_C(0));
list_del(&devl->list);
dm_free(devl);
}
@@ -205,7 +205,7 @@ static void _rescan_entry(struct lvmcache_info *info)
struct label *label;
if (info->status & CACHE_INVALID)
label_read(info->dev, &label);
label_read(info->dev, &label, UINT64_C(0));
}
static int _scan_invalid(void)
@@ -247,7 +247,7 @@ int lvmcache_label_scan(struct cmd_context *cmd, int full_scan)
}
while ((dev = dev_iter_get(iter)))
label_read(dev, &label);
label_read(dev, &label, UINT64_C(0));
dev_iter_destroy(iter);
@@ -346,7 +346,7 @@ struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid)
/* Already cached ? */
if ((info = info_from_pvid((char *) pvid))) {
if (label_read(info->dev, &label)) {
if (label_read(info->dev, &label, UINT64_C(0))) {
info = (struct lvmcache_info *) label->info;
if (id_equal(pvid, (struct id *) &info->dev->pvid))
return info->dev;
@@ -357,7 +357,7 @@ struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid)
/* Try again */
if ((info = info_from_pvid((char *) pvid))) {
if (label_read(info->dev, &label)) {
if (label_read(info->dev, &label, UINT64_C(0))) {
info = (struct lvmcache_info *) label->info;
if (id_equal(pvid, (struct id *) &info->dev->pvid))
return info->dev;
@@ -371,7 +371,7 @@ struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid)
/* Try again */
if ((info = info_from_pvid((char *) pvid))) {
if (label_read(info->dev, &label)) {
if (label_read(info->dev, &label, UINT64_C(0))) {
info = (struct lvmcache_info *) label->info;
if (id_equal(pvid, (struct id *) &info->dev->pvid))
return info->dev;

View File

@@ -184,7 +184,7 @@ static int _process_config(struct cmd_context *cmd)
}
if (*cmd->proc_dir && !dir_exists(cmd->proc_dir)) {
log_error("Warning: proc dir %s not found - some checks will be bypassed",
log_error("WARNING: proc dir %s not found - some checks will be bypassed",
cmd->proc_dir);
cmd->proc_dir[0] = '\0';
}
@@ -465,10 +465,8 @@ static int _init_dev_cache(struct cmd_context *cmd)
const struct config_node *cn;
struct config_value *cv;
if (!dev_cache_init()) {
stack;
return 0;
}
if (!dev_cache_init(cmd))
return_0;
if (!(cn = find_config_tree_node(cmd, "devices/scan"))) {
if (!dev_cache_add_dir("/dev")) {
@@ -575,7 +573,7 @@ static struct dev_filter *_init_filter_components(struct cmd_context *cmd)
static int _init_filters(struct cmd_context *cmd, unsigned load_persistent_cache)
{
const char *dev_cache;
const char *dev_cache = NULL, *cache_dir, *cache_file_prefix;
struct dev_filter *f3, *f4;
struct stat st;
char cache_file[PATH_MAX];
@@ -585,19 +583,35 @@ static int _init_filters(struct cmd_context *cmd, unsigned load_persistent_cache
if (!(f3 = _init_filter_components(cmd)))
return 0;
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;
}
init_ignore_suspended_devices(find_config_tree_int(cmd,
"devices/ignore_suspended_devices", DEFAULT_IGNORE_SUSPENDED_DEVICES));
dev_cache = find_config_tree_str(cmd, "devices/cache",
cache_file);
if (!(f4 = persistent_filter_create(f3, dev_cache))) {
/*
* If 'cache_dir' or 'cache_file_prefix' is set, ignore 'cache'.
*/
cache_dir = find_config_tree_str(cmd, "devices/cache_dir", NULL);
cache_file_prefix = find_config_tree_str(cmd, "devices/cache_file_prefix", NULL);
if (cache_dir || cache_file_prefix) {
if (dm_snprintf(cache_file, sizeof(cache_file),
"%s%s%s/%s.cache",
cache_dir ? "" : cmd->sys_dir,
cache_dir ? "" : "/",
cache_dir ? : DEFAULT_CACHE_SUBDIR,
cache_file_prefix ? : DEFAULT_CACHE_FILE_PREFIX) < 0) {
log_error("Persistent cache filename too long.");
return 0;
}
} else if (!(dev_cache = find_config_tree_str(cmd, "devices/cache", NULL)) &&
(dm_snprintf(cache_file, sizeof(cache_file),
"%s/%s/%s.cache",
cmd->sys_dir, DEFAULT_CACHE_SUBDIR,
DEFAULT_CACHE_FILE_PREFIX) < 0)) {
log_error("Persistent cache filename too long.");
return 0;
}
if (!(f4 = persistent_filter_create(f3, dev_cache ? : cache_file))) {
log_error("Failed to create persistent device filter");
return 0;
}
@@ -754,7 +768,6 @@ static int _init_segtypes(struct cmd_context *cmd)
struct config_value *cv;
struct segment_type *(*init_segtype_fn) (struct cmd_context *);
void *lib;
struct list *sgtl, *tmp;
struct segment_type *segtype2;
for (cv = cn->v; cv; cv = cv->next) {
@@ -781,18 +794,16 @@ static int _init_segtypes(struct cmd_context *cmd)
segtype->library = lib;
list_add(&cmd->segtypes, &segtype->list);
list_iterate_safe(sgtl, tmp, &cmd->segtypes) {
segtype2 = list_item(sgtl, struct segment_type);
if (!strcmp(segtype2->name, segtype->name)) {
log_error("Duplicate segment type %s: "
"unloading shared library %s",
segtype->name, cv->v.str);
list_del(&segtype->list);
segtype->ops->destroy(segtype);
dlclose(lib);
break;
}
list_iterate_items(segtype2, &cmd->segtypes) {
if ((segtype == segtype2) ||
strcmp(segtype2->name, segtype->name))
continue;
log_error("Duplicate segment type %s: "
"unloading shared library %s",
segtype->name, cv->v.str);
list_del(&segtype->list);
segtype->ops->destroy(segtype);
dlclose(lib);
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* 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.
@@ -19,6 +19,7 @@
#include "device.h"
#include "str_list.h"
#include "toolcontext.h"
#include "lvm-string.h"
#include <sys/stat.h>
#include <sys/mman.h>
@@ -26,6 +27,9 @@
#include <fcntl.h>
#include <ctype.h>
#define SECTION_B_CHAR '{'
#define SECTION_E_CHAR '}'
enum {
TOK_INT,
TOK_FLOAT,
@@ -62,6 +66,11 @@ struct cs {
struct device *dev;
};
struct output_line {
FILE *fp;
struct dm_pool *mem;
};
static void _get_token(struct parser *p, int tok_prev);
static void _eat_space(struct parser *p);
static struct config_node *_file(struct parser *p);
@@ -79,7 +88,8 @@ static const int sep = '/';
#define match(t) do {\
if (!_match_aux(p, (t))) {\
log_error("Parse error at byte %d (line %d): unexpected token", p->tb - p->fb + 1, p->line); \
log_error("Parse error at byte %" PRIptrdiff_t " (line %d): unexpected token", \
p->tb - p->fb + 1, p->line); \
return 0;\
} \
} while(0);
@@ -183,7 +193,7 @@ int read_config_fd(struct config_tree *cft, struct device *dev,
int r = 0;
int use_mmap = 1;
off_t mmap_offset = 0;
char *buf;
char *buf = NULL;
if (!(p = dm_pool_alloc(c->mem, sizeof(*p)))) {
stack;
@@ -210,18 +220,10 @@ int read_config_fd(struct config_tree *cft, struct device *dev,
stack;
return 0;
}
if (!dev_read(dev, (uint64_t) offset, size, buf)) {
log_error("Read from %s failed", dev_name(dev));
if (!dev_read_circular(dev, (uint64_t) offset, size,
(uint64_t) offset2, size2, buf)) {
goto out;
}
if (size2) {
if (!dev_read(dev, (uint64_t) offset2, size2,
buf + size)) {
log_error("Circular read from %s failed",
dev_name(dev));
goto out;
}
}
p->fb = buf;
}
@@ -348,33 +350,87 @@ int config_file_changed(struct config_tree *cft)
return 1;
}
static void _write_value(FILE *fp, struct config_value *v)
static int _line_start(struct output_line *outline)
{
if (!dm_pool_begin_object(outline->mem, 128)) {
log_error("dm_pool_begin_object failed for config line");
return 0;
}
return 1;
}
static int _line_append(struct output_line *outline, const char *fmt, ...)
{
char buf[4096];
va_list ap;
int n;
va_start(ap, fmt);
n = vsnprintf(&buf[0], 4095, fmt, ap);
if (n < 0 || n > 4095) {
log_error("vsnprintf failed for config line");
return 0;
}
va_end(ap);
if (!dm_pool_grow_object(outline->mem, &buf[0], strlen(buf))) {
log_error("dm_pool_grew_object failed for config line");
return 0;
}
return 1;
}
#define line_append(args...) do {if (!_line_append(outline, args)) {return_0;}} while (0)
static int _line_end(struct output_line *outline)
{
const char *line;
if (!dm_pool_grow_object(outline->mem, "\0", 1)) {
log_error("dm_pool_grow_object failed for config line");
return 0;
}
line = dm_pool_end_object(outline->mem);
if (!outline->fp)
log_print("%s", line);
else
fprintf(outline->fp, "%s\n", line);
return 1;
}
static int _write_value(struct output_line *outline, struct config_value *v)
{
switch (v->type) {
case CFG_STRING:
fprintf(fp, "\"%s\"", v->v.str);
line_append("\"%s\"", v->v.str);
break;
case CFG_FLOAT:
fprintf(fp, "%f", v->v.r);
line_append("%f", v->v.r);
break;
case CFG_INT:
fprintf(fp, "%d", v->v.i);
line_append("%" PRId64, v->v.i);
break;
case CFG_EMPTY_ARRAY:
fprintf(fp, "[]");
line_append("[]");
break;
default:
log_error("_write_value: Unknown value type: %d", v->type);
}
return 1;
}
static int _write_config(struct config_node *n, int only_one, FILE *fp,
int level)
static int _write_config(struct config_node *n, int only_one,
struct output_line *outline, int level)
{
char space[MAX_INDENT + 1];
int l = (level < MAX_INDENT) ? level : MAX_INDENT;
@@ -388,29 +444,38 @@ static int _write_config(struct config_node *n, int only_one, FILE *fp,
space[i] = '\0';
do {
fprintf(fp, "%s%s", space, n->key);
if (!_line_start(outline))
return_0;
line_append("%s%s", space, n->key);
if (!n->v) {
/* it's a sub section */
fprintf(fp, " {\n");
_write_config(n->child, 0, fp, level + 1);
fprintf(fp, "%s}", space);
line_append(" {");
if (!_line_end(outline))
return_0;
if (!_line_start(outline))
return_0;
_write_config(n->child, 0, outline, level + 1);
line_append("%s}", space);
} else {
/* it's a value */
struct config_value *v = n->v;
fprintf(fp, "=");
line_append("=");
if (v->next) {
fprintf(fp, "[");
line_append("[");
while (v) {
_write_value(fp, v);
if (!_write_value(outline, v))
return_0;
v = v->next;
if (v)
fprintf(fp, ", ");
line_append(", ");
}
fprintf(fp, "]");
line_append("]");
} else
_write_value(fp, v);
if (!_write_value(outline, v))
return_0;
}
fprintf(fp, "\n");
if (!_line_end(outline))
return_0;
n = n->sib;
} while (n && !only_one);
/* FIXME: add error checking */
@@ -422,25 +487,27 @@ int write_config_file(struct config_tree *cft, const char *file,
{
struct config_node *cn;
int r = 1;
FILE *fp;
struct output_line outline;
outline.fp = NULL;
if (!file) {
fp = stdout;
if (!file)
file = "stdout";
} else if (!(fp = fopen(file, "w"))) {
else if (!(outline.fp = fopen(file, "w"))) {
log_sys_error("open", file);
return 0;
}
outline.mem = dm_pool_create("config_line", 1024);
log_verbose("Dumping configuration to %s", file);
if (!argc) {
if (!_write_config(cft->root, 0, fp, 0)) {
if (!_write_config(cft->root, 0, &outline, 0)) {
log_error("Failure while writing to %s", file);
r = 0;
}
} else while (argc--) {
if ((cn = find_config_node(cft->root, *argv))) {
if (!_write_config(cn, 1, fp, 0)) {
if (!_write_config(cn, 1, &outline, 0)) {
log_error("Failure while writing to %s", file);
r = 0;
}
@@ -451,11 +518,12 @@ int write_config_file(struct config_tree *cft, const char *file,
argv++;
}
if ((fp != stdout) && fclose(fp)) {
if (outline.fp && fclose(outline.fp)) {
log_sys_error("fclose", file);
r = 0;
}
dm_pool_destroy(outline.mem);
return r;
}
@@ -482,7 +550,7 @@ static struct config_node *_file(struct parser *p)
static struct config_node *_section(struct parser *p)
{
/* IDENTIFIER '{' VALUE* '}' */
/* IDENTIFIER SECTION_B_CHAR VALUE* SECTION_E_CHAR */
struct config_node *root, *n, *l = NULL;
if (!(root = _create_node(p))) {
stack;
@@ -571,7 +639,7 @@ static struct config_value *_type(struct parser *p)
switch (p->t) {
case TOK_INT:
v->type = CFG_INT;
v->v.i = strtol(p->tb, NULL, 0); /* FIXME: check error */
v->v.i = strtoll(p->tb, NULL, 0); /* FIXME: check error */
match(TOK_INT);
break;
@@ -594,7 +662,8 @@ static struct config_value *_type(struct parser *p)
break;
default:
log_error("Parse error at byte %d (line %d): expected a value", p->tb - p->fb + 1, p->line);
log_error("Parse error at byte %" PRIptrdiff_t " (line %d): expected a value",
p->tb - p->fb + 1, p->line);
return 0;
}
return v;
@@ -631,12 +700,12 @@ static void _get_token(struct parser *p, int tok_prev)
p->t = TOK_INT; /* fudge so the fall through for
floats works */
switch (*p->te) {
case '{':
case SECTION_B_CHAR:
p->t = TOK_SECTION_B;
p->te++;
break;
case '}':
case SECTION_E_CHAR:
p->t = TOK_SECTION_E;
p->te++;
break;
@@ -716,8 +785,9 @@ static void _get_token(struct parser *p, int tok_prev)
default:
p->t = TOK_IDENTIFIER;
while ((p->te != p->fe) && (*p->te) && !isspace(*p->te) &&
(*p->te != '#') && (*p->te != '=') && (*p->te != '{') &&
(*p->te != '}'))
(*p->te != '#') && (*p->te != '=') &&
(*p->te != SECTION_B_CHAR) &&
(*p->te != SECTION_E_CHAR))
p->te++;
break;
}
@@ -872,25 +942,26 @@ const char *find_config_str(const struct config_node *cn,
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)
static int64_t _find_config_int64(const struct config_node *cn1,
const struct config_node *cn2,
const char *path, int64_t 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);
if (n && n->v && n->v->type == CFG_INT) {
log_very_verbose("Setting %s to %" PRId64, path, n->v->v.i);
return n->v->v.i;
}
log_very_verbose("%s not found in config: defaulting to %d",
log_very_verbose("%s not found in config: defaulting to %" PRId64,
path, fail);
return fail;
}
int find_config_int(const struct config_node *cn, const char *path, int fail)
{
return _find_config_int(cn, NULL, path, fail);
/* FIXME Add log_error message on overflow */
return (int) _find_config_int64(cn, NULL, path, (int64_t) fail);
}
static float _find_config_float(const struct config_node *cn1,
@@ -899,7 +970,7 @@ static float _find_config_float(const struct config_node *cn1,
{
const struct config_node *n = _find_first_config_node(cn1, cn2, path);
if (n && n->v->type == CFG_FLOAT) {
if (n && n->v && n->v->type == CFG_FLOAT) {
log_very_verbose("Setting %s to %f", path, n->v->v.r);
return n->v->v.r;
}
@@ -918,25 +989,26 @@ float find_config_float(const struct config_node *cn, const char *path,
}
struct config_node *find_config_tree_node(struct cmd_context *cmd,
const char *path)
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)
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)
int fail)
{
return _find_config_int(cmd->cft_override ? cmd->cft_override->root : NULL, cmd->cft->root, path, fail);
/* FIXME Add log_error message on overflow */
return (int) _find_config_int64(cmd->cft_override ? cmd->cft_override->root : NULL, cmd->cft->root, path, (int64_t) fail);
}
float find_config_tree_float(struct cmd_context *cmd, const char *path,
float fail)
float fail)
{
return _find_config_float(cmd->cft_override ? cmd->cft_override->root : NULL, cmd->cft->root, path, fail);
}
@@ -1024,7 +1096,6 @@ int get_config_uint64(const struct config_node *cn, const char *path,
if (!n || !n->v || n->v->type != CFG_INT)
return 0;
/* FIXME Support 64-bit value! */
*result = (uint64_t) n->v->v.i;
return 1;
}
@@ -1154,3 +1225,61 @@ int merge_config_tree(struct cmd_context *cmd, struct config_tree *cft,
return 1;
}
/*
* Convert a token type to the char it represents.
*/
static char _token_type_to_char(int type)
{
switch (type) {
case TOK_SECTION_B:
return SECTION_B_CHAR;
case TOK_SECTION_E:
return SECTION_E_CHAR;
default:
return 0;
}
}
/*
* Returns:
* # of 'type' tokens in 'str'.
*/
static unsigned _count_tokens (const char *str, unsigned len, int type)
{
char c;
c = _token_type_to_char(type);
return(count_chars_len(str, len, c));
}
/*
* Heuristic function to make a quick guess as to whether a text
* region probably contains a valid config "section". (Useful for
* scanning areas of the disk for old metadata.)
* Config sections contain various tokens, may contain other sections
* and strings, and are delimited by begin (type 'TOK_SECTION_B') and
* end (type 'TOK_SECTION_E') tokens. As a quick heuristic, we just
* count the number of begin and end tokens, and see if they are
* non-zero and the counts match.
* Full validation of the section should be done with another function
* (for example, read_config_fd).
*
* Returns:
* 0 - probably is not a valid config section
* 1 - probably _is_ a valid config section
*/
unsigned maybe_config_section(const char *str, unsigned len)
{
int begin_count;
int end_count;
begin_count = _count_tokens(str, len, TOK_SECTION_B);
end_count = _count_tokens(str, len, TOK_SECTION_E);
if (begin_count && end_count && (begin_count - end_count == 0))
return 1;
else
return 0;
}

View File

@@ -31,7 +31,7 @@ enum {
struct config_value {
int type;
union {
int i;
int64_t i;
float r;
char *str;
} v;
@@ -108,4 +108,6 @@ int get_config_uint64(const struct config_node *cn, const char *path,
int get_config_str(const struct config_node *cn, const char *path,
char **result);
unsigned maybe_config_section(const char *str, unsigned len);
#endif

View File

@@ -21,6 +21,8 @@
#define DEFAULT_ARCHIVE_SUBDIR "archive"
#define DEFAULT_BACKUP_SUBDIR "backup"
#define DEFAULT_CACHE_SUBDIR "cache"
#define DEFAULT_CACHE_FILE_PREFIX ""
#define DEFAULT_ARCHIVE_DAYS 30
#define DEFAULT_ARCHIVE_NUMBER 10

View File

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

View File

@@ -19,6 +19,7 @@
#include "btree.h"
#include "filter.h"
#include "filter-persistent.h"
#include "toolcontext.h"
#include <unistd.h>
#include <sys/param.h>
@@ -38,6 +39,7 @@ static struct {
struct dm_pool *mem;
struct dm_hash_table *names;
struct btree *devices;
struct dm_regex *preferred_names_matcher;
int has_scanned;
struct list dirs;
@@ -129,15 +131,52 @@ static struct device *_dev_create(dev_t d)
return dev;
}
void dev_set_preferred_name(struct str_list *sl, struct device *dev)
{
/*
* Don't interfere with ordering specified in config file.
*/
if (_cache.preferred_names_matcher)
return;
log_debug("%s: New preferred name", sl->str);
list_del(&sl->list);
list_add_h(&dev->aliases, &sl->list);
}
/* Return 1 if we prefer path1 else return 0 */
static int _compare_paths(const char *path0, const char *path1)
{
int slash0 = 0, slash1 = 0;
int m0, m1;
const char *p;
char p0[PATH_MAX], p1[PATH_MAX];
char *s0, *s1;
struct stat stat0, stat1;
/*
* FIXME Better to compare patterns one-at-a-time against all names.
*/
if (_cache.preferred_names_matcher) {
m0 = dm_regex_match(_cache.preferred_names_matcher, path0);
m1 = dm_regex_match(_cache.preferred_names_matcher, path1);
if (m0 != m1) {
if (m0 < 0)
return 1;
if (m1 < 0)
return 0;
if (m0 < m1)
return 1;
if (m1 < m0)
return 0;
}
}
/*
* Built-in rules.
*/
/* Return the path with fewer slashes */
for (p = path0; p++; p = (const char *) strchr(p, '/'))
slash0++;
@@ -441,7 +480,65 @@ void dev_cache_scan(int do_scan)
_full_scan(1);
}
int dev_cache_init(void)
static int _init_preferred_names(struct cmd_context *cmd)
{
const struct config_node *cn;
struct config_value *v;
struct dm_pool *scratch = NULL;
char **regex;
unsigned count = 0;
int i, r = 0;
_cache.preferred_names_matcher = NULL;
if (!(cn = find_config_tree_node(cmd, "devices/preferred_names")) ||
cn->v->type == CFG_EMPTY_ARRAY) {
log_very_verbose("devices/preferred_names not found in config file: "
"using built-in preferences");
return 1;
}
for (v = cn->v; v; v = v->next) {
if (v->type != CFG_STRING) {
log_error("preferred_names patterns must be enclosed in quotes");
return 0;
}
count++;
}
if (!(scratch = dm_pool_create("preferred device name matcher", 1024)))
return_0;
if (!(regex = dm_pool_alloc(scratch, sizeof(*regex) * count))) {
log_error("Failed to allocate preferred device name "
"pattern list.");
goto out;
}
for (v = cn->v, i = count - 1; v; v = v->next, i--) {
if (!(regex[i] = dm_pool_strdup(scratch, v->v.str))) {
log_error("Failed to allocate a preferred device name "
"pattern.");
goto out;
}
}
if (!(_cache.preferred_names_matcher =
dm_regex_create(_cache.mem,(const char **) regex, count))) {
log_error("Preferred device name pattern matcher creation failed.");
goto out;
}
r = 1;
out:
dm_pool_destroy(scratch);
return r;
}
int dev_cache_init(struct cmd_context *cmd)
{
_cache.names = NULL;
_cache.has_scanned = 0;
@@ -466,6 +563,9 @@ int dev_cache_init(void)
list_init(&_cache.dirs);
list_init(&_cache.files);
if (!_init_preferred_names(cmd))
goto_bad;
return 1;
bad:
@@ -489,6 +589,9 @@ void dev_cache_exit(void)
if (_cache.names)
_check_for_open_devices();
if (_cache.preferred_names_matcher)
_cache.preferred_names_matcher = NULL;
if (_cache.mem) {
dm_pool_destroy(_cache.mem);
_cache.mem = NULL;

View File

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

View File

@@ -564,6 +564,35 @@ int dev_read(struct device *dev, uint64_t offset, size_t len, void *buffer)
return _aligned_io(&where, buffer, 0);
}
/*
* Read from 'dev' into 'buf', possibly in 2 distinct regions, denoted
* by (offset,len) and (offset2,len2). Thus, the total size of
* 'buf' should be len+len2.
*/
int dev_read_circular(struct device *dev, uint64_t offset, size_t len,
uint64_t offset2, size_t len2, void *buf)
{
if (!dev_read(dev, offset, len, buf)) {
log_error("Read from %s failed", dev_name(dev));
return 0;
}
/*
* The second region is optional, and allows for
* a circular buffer on the device.
*/
if (!len2)
return 1;
if (!dev_read(dev, offset2, len2, buf + len)) {
log_error("Circular read from %s failed",
dev_name(dev));
return 0;
}
return 1;
}
/* FIXME If O_DIRECT can't extend file, dev_extend first; dev_truncate after.
* But fails if concurrent processes writing
*/

View File

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

View File

@@ -78,6 +78,8 @@ int dev_fd(struct device *dev);
const char *dev_name(const struct device *dev);
int dev_read(struct device *dev, uint64_t offset, size_t len, void *buffer);
int dev_read_circular(struct device *dev, uint64_t offset, size_t len,
uint64_t offset2, size_t len2, void *buf);
int dev_write(struct device *dev, uint64_t offset, size_t len, void *buffer);
int dev_append(struct device *dev, size_t len, void *buffer);
int dev_set(struct device *dev, uint64_t offset, size_t len, int value);

View File

@@ -258,6 +258,33 @@ void pvdisplay_colons(struct physical_volume *pv)
return;
}
void pvdisplay_segments(struct physical_volume *pv)
{
struct pv_segment *pvseg;
if (pv->pe_size)
log_print("--- Physical Segments ---");
list_iterate_items(pvseg, &pv->segments) {
log_print("Physical extent %u to %u:",
pvseg->pe, pvseg->pe + pvseg->len - 1);
if (pvseg->lvseg) {
log_print(" Logical volume\t%s%s/%s",
pvseg->lvseg->lv->vg->cmd->dev_dir,
pvseg->lvseg->lv->vg->name,
pvseg->lvseg->lv->name);
log_print(" Logical extents\t%d to %d",
pvseg->lvseg->le, pvseg->lvseg->le +
pvseg->lvseg->len - 1);
} else
log_print(" FREE");
}
log_print(" ");
return;
}
/* FIXME Include label fields */
void pvdisplay_full(struct cmd_context *cmd, struct physical_volume *pv,
void *handle __attribute((unused)))

View File

@@ -31,6 +31,7 @@ char *display_uuid(char *uuidstr);
void display_stripe(const struct lv_segment *seg, uint32_t s, const char *pre);
void pvdisplay_colons(struct physical_volume *pv);
void pvdisplay_segments(struct physical_volume *pv);
void pvdisplay_full(struct cmd_context *cmd, struct physical_volume *pv,
void *handle);
int pvdisplay_short(struct cmd_context *cmd, struct volume_group *vg,

View File

@@ -301,10 +301,9 @@ struct dev_filter *persistent_filter_create(struct dev_filter *real,
}
memset(pf, 0, sizeof(*pf));
if (!(pf->file = dm_malloc(strlen(file) + 1))) {
stack;
goto bad;
}
if (!(pf->file = dm_malloc(strlen(file) + 1)))
goto_bad;
strcpy(pf->file, file);
pf->real = real;
@@ -313,10 +312,8 @@ struct dev_filter *persistent_filter_create(struct dev_filter *real,
goto bad;
}
if (!(f = dm_malloc(sizeof(*f)))) {
stack;
goto bad;
}
if (!(f = dm_malloc(sizeof(*f))))
goto_bad;
f->passes_filter = _lookup_p;
f->destroy = _persistent_destroy;

View File

@@ -15,13 +15,12 @@
#include "lib.h"
#include "filter-regex.h"
#include "matcher.h"
#include "device.h"
struct rfilter {
struct dm_pool *mem;
dm_bitset_t accept;
struct matcher *engine;
struct dm_regex *engine;
};
static int _extract_pattern(struct dm_pool *mem, const char *pat,
@@ -98,18 +97,15 @@ static int _build_matcher(struct rfilter *rf, struct config_value *val)
unsigned count = 0;
int i, r = 0;
if (!(scratch = dm_pool_create("filter matcher", 1024))) {
stack;
return 0;
}
if (!(scratch = dm_pool_create("filter dm_regex", 1024)))
return_0;
/*
* count how many patterns we have.
*/
for (v = val; v; v = v->next) {
if (v->type != CFG_STRING) {
log_info("filter patterns must be enclosed in quotes");
log_error("filter patterns must be enclosed in quotes");
goto out;
}
@@ -119,10 +115,8 @@ static int _build_matcher(struct rfilter *rf, struct config_value *val)
/*
* allocate space for them
*/
if (!(regex = dm_pool_alloc(scratch, sizeof(*regex) * count))) {
stack;
goto out;
}
if (!(regex = dm_pool_alloc(scratch, sizeof(*regex) * count)))
goto_out;
/*
* create the accept/reject bitset
@@ -136,15 +130,15 @@ static int _build_matcher(struct rfilter *rf, struct config_value *val)
*/
for (v = val, i = count - 1; v; v = v->next, i--)
if (!_extract_pattern(scratch, v->v.str, regex, rf->accept, i)) {
log_info("invalid filter pattern");
log_error("invalid filter pattern");
goto out;
}
/*
* build the matcher.
*/
if (!(rf->engine = matcher_create(rf->mem, (const char **) regex,
count)))
if (!(rf->engine = dm_regex_create(rf->mem, (const char **) regex,
count)))
stack;
r = 1;
@@ -160,17 +154,12 @@ static int _accept_p(struct dev_filter *f, struct device *dev)
struct str_list *sl;
list_iterate_items(sl, &dev->aliases) {
m = matcher_run(rf->engine, sl->str);
m = dm_regex_match(rf->engine, sl->str);
if (m >= 0) {
if (dm_bit(rf->accept, m)) {
if (!first) {
log_debug("%s: New preferred name",
sl->str);
list_del(&sl->list);
list_add_h(&dev->aliases, &sl->list);
}
if (!first)
dev_set_preferred_name(sl, dev);
return 1;
}
@@ -208,22 +197,16 @@ struct dev_filter *regex_filter_create(struct config_value *patterns)
return NULL;
}
if (!(rf = dm_pool_alloc(mem, sizeof(*rf)))) {
stack;
goto bad;
}
if (!(rf = dm_pool_alloc(mem, sizeof(*rf))))
goto_bad;
rf->mem = mem;
if (!_build_matcher(rf, patterns)) {
stack;
goto bad;
}
if (!_build_matcher(rf, patterns))
goto_bad;
if (!(f = dm_pool_zalloc(mem, sizeof(*f)))) {
stack;
goto bad;
}
if (!(f = dm_pool_zalloc(mem, sizeof(*f))))
goto_bad;
f->passes_filter = _accept_p;
f->destroy = _regex_destroy;

View File

@@ -284,10 +284,8 @@ struct dev_filter *sysfs_filter_create(const char *proc)
goto bad;
}
if (!(f = dm_pool_zalloc(mem, sizeof(*f)))) {
stack;
goto bad;
}
if (!(f = dm_pool_zalloc(mem, sizeof(*f))))
goto_bad;
f->passes_filter = _accept_p;
f->destroy = _destroy;

View File

@@ -357,10 +357,8 @@ static struct disk_list *__read_disk(const struct format_type *fmt,
list_init(&dl->uuids);
list_init(&dl->lvds);
if (!_read_pvd(dev, &dl->pvd)) {
stack;
goto bad;
}
if (!_read_pvd(dev, &dl->pvd))
goto_bad;
/*
* is it an orphan ?

View File

@@ -131,10 +131,10 @@ static struct volume_group *_build_vg(struct format_instance *fid,
int partial;
if (!vg)
goto bad;
goto_bad;
if (list_empty(pvs))
goto bad;
goto_bad;
memset(vg, 0, sizeof(*vg));
@@ -146,24 +146,24 @@ static struct volume_group *_build_vg(struct format_instance *fid,
list_init(&vg->tags);
if (!_check_vgs(pvs, &partial))
goto bad;
goto_bad;
dl = list_item(pvs->n, struct disk_list);
if (!import_vg(mem, vg, dl, partial))
goto bad;
goto_bad;
if (!import_pvs(fid->fmt, mem, vg, pvs, &vg->pvs, &vg->pv_count))
goto bad;
goto_bad;
if (!import_lvs(mem, vg, pvs))
goto bad;
goto_bad;
if (!import_extents(fid->fmt->cmd, vg, pvs))
goto bad;
goto_bad;
if (!import_snapshots(mem, vg, pvs))
goto bad;
goto_bad;
return vg;
@@ -191,15 +191,11 @@ static struct volume_group *_format1_vg_read(struct format_instance *fid,
vg_name = strip_dir(vg_name, fid->fmt->cmd->dev_dir);
if (!read_pvs_in_vg
(fid->fmt, vg_name, fid->fmt->cmd->filter, mem, &pvs)) {
stack;
goto bad;
}
(fid->fmt, vg_name, fid->fmt->cmd->filter, mem, &pvs))
goto_bad;
if (!(vg = _build_vg(fid, &pvs))) {
stack;
goto bad;
}
if (!(vg = _build_vg(fid, &pvs)))
goto_bad;
bad:
dm_pool_destroy(mem);
@@ -415,17 +411,14 @@ static int _format1_pv_write(const struct format_type *fmt, struct physical_volu
return 0;
}
if (!(dl = dm_pool_alloc(mem, sizeof(*dl)))) {
stack;
goto bad;
}
if (!(dl = dm_pool_alloc(mem, sizeof(*dl))))
goto_bad;
dl->mem = mem;
dl->dev = pv->dev;
if (!export_pv(fmt->cmd, mem, NULL, &dl->pvd, pv)) {
stack;
goto bad;
}
if (!export_pv(fmt->cmd, mem, NULL, &dl->pvd, pv))
goto_bad;
/* must be set to be able to zero gap after PV structure in
dev_write in order to make other disk tools happy */
@@ -434,10 +427,8 @@ static int _format1_pv_write(const struct format_type *fmt, struct physical_volu
dl->pvd.pe_on_disk.base = LVM1_PE_ALIGN << SECTOR_SHIFT;
list_add(&pvs, &dl->list);
if (!write_disks(fmt, &pvs)) {
stack;
goto bad;
}
if (!write_disks(fmt, &pvs))
goto_bad;
dm_pool_destroy(mem);
return 1;

View File

@@ -59,22 +59,16 @@ static struct dm_hash_table *_create_lv_maps(struct dm_pool *mem,
if (ll->lv->status & SNAPSHOT)
continue;
if (!(lvm = dm_pool_alloc(mem, sizeof(*lvm)))) {
stack;
goto bad;
}
if (!(lvm = dm_pool_alloc(mem, sizeof(*lvm))))
goto_bad;
lvm->lv = ll->lv;
if (!(lvm->map = dm_pool_zalloc(mem, sizeof(*lvm->map)
* ll->lv->le_count))) {
stack;
goto bad;
}
* ll->lv->le_count)))
goto_bad;
if (!dm_hash_insert(maps, ll->lv->name, lvm)) {
stack;
goto bad;
}
if (!dm_hash_insert(maps, ll->lv->name, lvm))
goto_bad;
}
return maps;
@@ -203,6 +197,19 @@ static int _check_maps_are_complete(struct dm_hash_table *maps)
return 1;
}
static uint32_t _area_length(struct lv_map *lvm, uint32_t le)
{
uint32_t len = 0;
do
len++;
while ((lvm->map[le + len].pv == lvm->map[le].pv) &&
(lvm->map[le].pv &&
lvm->map[le + len].pe == lvm->map[le].pe + len));
return len;
}
static int _read_linear(struct cmd_context *cmd, struct lv_map *lvm)
{
uint32_t le = 0, len;
@@ -215,13 +222,7 @@ static int _read_linear(struct cmd_context *cmd, struct lv_map *lvm)
}
while (le < lvm->lv->le_count) {
len = 0;
do
len++;
while ((lvm->map[le + len].pv == lvm->map[le].pv) &&
(lvm->map[le].pv &&
lvm->map[le + len].pe == lvm->map[le].pe + len));
len = _area_length(lvm, le);
if (!(seg = alloc_lv_segment(cmd->mem, segtype, lvm->lv, le,
len, 0, 0, NULL, 1, len, 0, 0, 0))) {
@@ -230,10 +231,8 @@ static int _read_linear(struct cmd_context *cmd, struct lv_map *lvm)
}
if (!set_lv_segment_area_pv(seg, 0, lvm->map[le].pv,
lvm->map[le].pe)) {
stack;
return 0;
}
lvm->map[le].pe))
return_0;
list_add(&lvm->lv->segments, &seg->list);
@@ -244,7 +243,8 @@ static int _read_linear(struct cmd_context *cmd, struct lv_map *lvm)
}
static int _check_stripe(struct lv_map *lvm, uint32_t area_count,
uint32_t seg_len, uint32_t base_le, uint32_t len)
uint32_t area_len, uint32_t base_le,
uint32_t total_area_len)
{
uint32_t st;
@@ -252,11 +252,11 @@ static int _check_stripe(struct lv_map *lvm, uint32_t area_count,
* Is the next physical extent in every stripe adjacent to the last?
*/
for (st = 0; st < area_count; st++)
if ((lvm->map[base_le + st * len + seg_len].pv !=
lvm->map[base_le + st * len].pv) ||
(lvm->map[base_le + st * len].pv &&
lvm->map[base_le + st * len + seg_len].pe !=
lvm->map[base_le + st * len].pe + seg_len))
if ((lvm->map[base_le + st * total_area_len + area_len].pv !=
lvm->map[base_le + st * total_area_len].pv) ||
(lvm->map[base_le + st * total_area_len].pv &&
lvm->map[base_le + st * total_area_len + area_len].pe !=
lvm->map[base_le + st * total_area_len].pe + area_len))
return 0;
return 1;
@@ -264,7 +264,7 @@ static int _check_stripe(struct lv_map *lvm, uint32_t area_count,
static int _read_stripes(struct cmd_context *cmd, struct lv_map *lvm)
{
uint32_t st, le = 0, len;
uint32_t st, first_area_le = 0, total_area_len;
uint32_t area_len;
struct lv_segment *seg;
struct segment_type *segtype;
@@ -277,26 +277,25 @@ static int _read_stripes(struct cmd_context *cmd, struct lv_map *lvm)
"with logical extent count (%u) for %s",
lvm->stripes, lvm->lv->le_count, lvm->lv->name);
}
len = lvm->lv->le_count / lvm->stripes;
if (!(segtype = get_segtype_from_string(cmd, "striped"))) {
stack;
return 0;
}
total_area_len = lvm->lv->le_count / lvm->stripes;
while (le < len) {
if (!(segtype = get_segtype_from_string(cmd, "striped")))
return_0;
while (first_area_le < total_area_len) {
area_len = 1;
/*
* Find how many blocks are contiguous in all stripes
* Find how many extents are contiguous in all stripes
* and so can form part of this segment
*/
while (_check_stripe(lvm, lvm->stripes,
area_len * lvm->stripes, le, len))
area_len, first_area_le, total_area_len))
area_len++;
if (!(seg = alloc_lv_segment(cmd->mem, segtype, lvm->lv,
lvm->stripes * le,
lvm->stripes * first_area_le,
lvm->stripes * area_len,
0, lvm->stripe_size, NULL,
lvm->stripes,
@@ -310,15 +309,13 @@ static int _read_stripes(struct cmd_context *cmd, struct lv_map *lvm)
*/
for (st = 0; st < seg->area_count; st++)
if (!set_lv_segment_area_pv(seg, st,
lvm->map[le + st * len].pv,
lvm->map[le + st * len].pe)) {
stack;
return 0;
}
lvm->map[first_area_le + st * total_area_len].pv,
lvm->map[first_area_le + st * total_area_len].pe))
return_0;
list_add(&lvm->lv->segments, &seg->list);
le += seg->len;
first_area_le += area_len;
}
return 1;

View File

@@ -71,7 +71,7 @@ static int _split_vg(const char *filename, char *vgname, size_t vg_size,
if (strcmp(".vg", dot))
return 0;
if (!(underscore = rindex(filename, '_')))
if (!(underscore = strrchr(filename, '_')))
return 0;
if (sscanf(underscore + 1, "%u", ix) != 1)
@@ -362,6 +362,22 @@ int archive_list(struct cmd_context *cmd, const char *dir, const char *vgname)
return 1;
}
int archive_list_file(struct cmd_context *cmd, const char *file)
{
struct archive_file af;
af.path = (char *)file;
if (!path_exists(af.path)) {
log_err("Archive file %s not found.", af.path);
return 0;
}
_display_archive(cmd, &af);
return 1;
}
int backup_list(struct cmd_context *cmd, const char *dir, const char *vgname)
{
struct archive_file af;

View File

@@ -148,6 +148,17 @@ int archive_display(struct cmd_context *cmd, const char *vg_name)
return r1 && r2;
}
int archive_display_file(struct cmd_context *cmd, const char *file)
{
int r;
init_partial(1);
r = archive_list_file(cmd, file);
init_partial(0);
return r;
}
int backup_init(struct cmd_context *cmd, const char *dir)
{
if (!(cmd->backup_params = dm_pool_zalloc(cmd->libmem,
@@ -203,7 +214,7 @@ static int __backup(struct volume_group *vg)
int backup(struct volume_group *vg)
{
if (!vg->cmd->backup_params->enabled || !vg->cmd->backup_params->dir) {
log_print("WARNING: This metadata update is NOT backed up");
log_warn("WARNING: This metadata update is NOT backed up");
return 1;
}

View File

@@ -38,6 +38,7 @@ void archive_exit(struct cmd_context *cmd);
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 archive_display_file(struct cmd_context *cmd, const char *file);
int backup_init(struct cmd_context *cmd, const char *dir);
void backup_exit(struct cmd_context *cmd);

View File

@@ -160,7 +160,7 @@ static int _out_with_comment_file(struct formatter *f, const char *comment,
for (i = 0; i < f->indent; i++)
white_space[i] = '\t';
white_space[i] = '\0';
fprintf(f->data.fp, white_space);
fputs(white_space, f->data.fp);
i = vfprintf(f->data.fp, fmt, ap);
if (comment) {
@@ -176,7 +176,7 @@ static int _out_with_comment_file(struct formatter *f, const char *comment,
while (++i < COMMENT_TAB);
fprintf(f->data.fp, comment);
fputs(comment, f->data.fp);
}
fputc('\n', f->data.fp);

View File

@@ -39,6 +39,9 @@
#define FMT_TEXT_NAME "lvm2"
#define FMT_TEXT_ALIAS "text"
static struct mda_header *_raw_read_mda_header(const struct format_type *fmt,
struct device_area *dev_area);
static struct format_instance *_text_create_text_instance(const struct format_type
*fmt, const char *vgname,
const char *vgid,
@@ -80,6 +83,164 @@ static int _text_vg_setup(struct format_instance *fid __attribute((unused)),
return 1;
}
/*
* Check if metadata area belongs to vg
*/
static int _mda_in_vg_raw(struct format_instance *fid __attribute((unused)),
struct volume_group *vg, struct metadata_area *mda)
{
struct mda_context *mdac = (struct mda_context *) mda->metadata_locn;
struct pv_list *pvl;
list_iterate_items(pvl, &vg->pvs)
if (pvl->pv->dev == mdac->area.dev)
return 1;
return 0;
}
/*
* For circular region between region_start and region_start + region_size,
* back up one SECTOR_SIZE from 'region_ptr' and return the value.
* This allows reverse traversal through text metadata area to find old
* metadata.
*
* Parameters:
* region_start: start of the region (bytes)
* region_size: size of the region (bytes)
* region_ptr: pointer within the region (bytes)
* NOTE: region_start <= region_ptr <= region_start + region_size
*/
static uint64_t _get_prev_sector_circular(uint64_t region_start,
uint64_t region_size,
uint64_t region_ptr)
{
if (region_ptr >= region_start + SECTOR_SIZE)
return region_ptr - SECTOR_SIZE;
else
return (region_start + region_size - SECTOR_SIZE);
}
/*
* Analyze a metadata area for old metadata records in the circular buffer.
* This function just looks through and makes a first pass at the data in
* the sectors for particular things.
* FIXME: do something with each metadata area (try to extract vg, write
* raw data to file, etc)
*/
static int _pv_analyze_mda_raw (const struct format_type * fmt,
struct metadata_area *mda)
{
struct mda_header *mdah;
struct raw_locn *rlocn;
uint64_t area_start;
uint64_t area_size;
uint64_t prev_sector;
uint64_t latest_mrec_offset;
int i;
uint64_t offset;
uint64_t offset2;
uint64_t size;
uint64_t size2;
char *buf=NULL;
struct device_area *area;
struct mda_context *mdac;
int r=0;
mdac = (struct mda_context *) mda->metadata_locn;
log_print("Found text metadata area, offset=%"PRIu64", size=%"PRIu64,
mdac->area.start,
mdac->area.size);
area = &mdac->area;
if (!dev_open(area->dev))
return_0;
if (!(mdah = _raw_read_mda_header(fmt, area)))
goto_out;
rlocn = mdah->raw_locns;
/*
* The device area includes the metadata header as well as the
* records, so remove the metadata header from the start and size
*/
area_start = area->start + MDA_HEADER_SIZE;
area_size = area->size - MDA_HEADER_SIZE;
latest_mrec_offset = rlocn->offset + area->start;
/*
* Start searching at rlocn (point of live metadata) and go
* backwards.
*/
prev_sector = _get_prev_sector_circular(area_start, area_size,
latest_mrec_offset);
offset = prev_sector;
size = SECTOR_SIZE;
offset2 = size2 = 0;
i = 0;
while (prev_sector != latest_mrec_offset) {
prev_sector = _get_prev_sector_circular(area_start, area_size,
prev_sector);
/*
* FIXME: for some reason, the whole metadata region from
* area->start to area->start+area->size is not used.
* Only ~32KB seems to contain valid metadata records
* (LVM2 format - format_text). As a result, I end up with
* "maybe_config_section" returning true when there's no valid
* metadata in a sector (sectors with all nulls).
*/
if (!(buf = dm_pool_alloc(fmt->cmd->mem, size + size2)))
goto_out;
if (!dev_read_circular(area->dev, offset, size,
offset2, size2, buf))
goto_out;
/*
* FIXME: We could add more sophisticated metadata detection
*/
if (maybe_config_section(buf, size+size2)) {
/* FIXME: Validate region, pull out timestamp?, etc */
/* FIXME: Do something with this region */
log_verbose ("Found LVM2 metadata record at "
"offset=%"PRIu64", size=%"PRIu64", "
"offset2=%"PRIu64" size2=%"PRIu64,
offset, size, offset2, size2);
offset = prev_sector;
size = SECTOR_SIZE;
offset2 = size2 = 0;
} else {
/*
* Not a complete metadata record, assume we have
* metadata and just increase the size and offset.
* Start the second region if the previous sector is
* wrapping around towards the end of the disk.
*/
if (prev_sector > offset) {
offset2 = prev_sector;
size2 += SECTOR_SIZE;
} else {
offset = prev_sector;
size += SECTOR_SIZE;
}
}
dm_pool_free(fmt->cmd->mem, buf);
buf = NULL;
}
r = 1;
out:
if (buf)
dm_pool_free(fmt->cmd->mem, buf);
if (!dev_close(area->dev))
stack;
return r;
}
static int _text_lv_setup(struct format_instance *fid __attribute((unused)),
struct logical_volume *lv)
{
@@ -689,7 +850,7 @@ static int _vg_write_file(struct format_instance *fid, struct volume_group *vg,
char *slash;
char temp_file[PATH_MAX], temp_dir[PATH_MAX];
slash = rindex(tc->path_edit, '/');
slash = strrchr(tc->path_edit, '/');
if (slash == 0)
strcpy(temp_dir, ".");
@@ -787,7 +948,7 @@ static int _vg_commit_file(struct format_instance *fid, struct volume_group *vg,
return 0;
/* vgrename? */
if ((slash = rindex(tc->path_live, '/')))
if ((slash = strrchr(tc->path_live, '/')))
slash = slash + 1;
else
slash = tc->path_live;
@@ -1043,8 +1204,8 @@ static int _mda_setup(const struct format_type *fmt,
/* Ensure it's not going to be bigger than the disk! */
if (start1 + mda_size1 > disk_size) {
log_print("Warning: metadata area fills disk leaving no "
"space for data on %s.", dev_name(pv->dev));
log_warn("WARNING: metadata area fills disk leaving no "
"space for data on %s.", dev_name(pv->dev));
/* Leave some free space for rounding */
/* Avoid empty data area as could cause tools problems */
mda_size1 = disk_size - start1 - alignment * 2;
@@ -1271,7 +1432,7 @@ static int _text_pv_read(const struct format_type *fmt, const char *pv_name,
}
/* FIXME Optimise out repeated reading when cache lock held */
if (!(label_read(dev, &label))) {
if (!(label_read(dev, &label, UINT64_C(0)))) {
stack;
return 0;
}
@@ -1395,7 +1556,9 @@ static struct metadata_area_ops _metadata_text_raw_ops = {
.vg_remove = _vg_remove_raw,
.vg_precommit = _vg_precommit_raw,
.vg_commit = _vg_commit_raw,
.vg_revert = _vg_revert_raw
.vg_revert = _vg_revert_raw,
.mda_in_vg = _mda_in_vg_raw,
.pv_analyze_mda = _pv_analyze_mda_raw,
};
/* pvmetadatasize in sectors */

View File

@@ -33,6 +33,7 @@ int archive_vg(struct volume_group *vg,
* Displays a list of vg backups in a particular archive directory.
*/
int archive_list(struct cmd_context *cmd, const char *dir, const char *vgname);
int archive_list_file(struct cmd_context *cmd, const char *file);
int backup_list(struct cmd_context *cmd, const char *dir, const char *vgname);
/*

View File

@@ -660,15 +660,11 @@ static struct volume_group *_read_vg(struct format_instance *fid,
/* eg Set to instance of fmt1 here if reading a format1 backup? */
vg->fid = fid;
if (!(vg->name = dm_pool_strdup(mem, vgn->key))) {
stack;
goto bad;
}
if (!(vg->name = dm_pool_strdup(mem, vgn->key)))
goto_bad;
if (!(vg->system_id = dm_pool_zalloc(mem, NAME_LEN))) {
stack;
goto bad;
}
if (!(vg->system_id = dm_pool_zalloc(mem, NAME_LEN)))
goto_bad;
vgn = vgn->child;

View File

@@ -107,7 +107,8 @@ struct labeller *label_get_handler(const char *name)
}
static struct labeller *_find_labeller(struct device *dev, char *buf,
uint64_t *label_sector)
uint64_t *label_sector,
uint64_t scan_sector)
{
struct labeller_i *li;
struct labeller *r = NULL;
@@ -117,12 +118,13 @@ static struct labeller *_find_labeller(struct device *dev, char *buf,
int found = 0;
char readbuf[LABEL_SCAN_SIZE] __attribute((aligned(8)));
if (!dev_read(dev, UINT64_C(0), LABEL_SCAN_SIZE, readbuf)) {
if (!dev_read(dev, scan_sector << SECTOR_SHIFT,
LABEL_SCAN_SIZE, readbuf)) {
log_debug("%s: Failed to read label area", dev_name(dev));
goto out;
}
/* Scan first few sectors for a valid label */
/* Scan a few sectors for a valid label */
for (sector = 0; sector < LABEL_SCAN_SECTORS;
sector += LABEL_SIZE >> SECTOR_SHIFT) {
lh = (struct label_header *) (readbuf +
@@ -132,13 +134,14 @@ static struct labeller *_find_labeller(struct device *dev, char *buf,
if (found) {
log_error("Ignoring additional label on %s at "
"sector %" PRIu64, dev_name(dev),
sector);
sector + scan_sector);
}
if (xlate64(lh->sector_xl) != sector) {
if (xlate64(lh->sector_xl) != sector + scan_sector) {
log_info("%s: Label for sector %" PRIu64
" found at sector %" PRIu64
" - ignoring", dev_name(dev),
xlate64(lh->sector_xl), sector);
xlate64(lh->sector_xl),
sector + scan_sector);
continue;
}
if (calc_crc(INITIAL_CRC, &lh->offset_xl, LABEL_SIZE -
@@ -153,19 +156,21 @@ static struct labeller *_find_labeller(struct device *dev, char *buf,
}
list_iterate_items(li, &_labellers) {
if (li->l->ops->can_handle(li->l, (char *) lh, sector)) {
if (li->l->ops->can_handle(li->l, (char *) lh,
sector + scan_sector)) {
log_very_verbose("%s: %s label detected",
dev_name(dev), li->name);
if (found) {
log_error("Ignoring additional label "
"on %s at sector %" PRIu64,
dev_name(dev), sector);
dev_name(dev),
sector + scan_sector);
continue;
}
r = li->l;
memcpy(buf, lh, LABEL_SIZE);
if (label_sector)
*label_sector = sector;
*label_sector = sector + scan_sector;
found = 1;
break;
}
@@ -256,7 +261,8 @@ int label_remove(struct device *dev)
}
/* FIXME Avoid repeated re-reading if cache lock held */
int label_read(struct device *dev, struct label **result)
int label_read(struct device *dev, struct label **result,
uint64_t scan_sector)
{
char buf[LABEL_SIZE] __attribute((aligned(8)));
struct labeller *l;
@@ -274,7 +280,7 @@ int label_read(struct device *dev, struct label **result)
return r;
}
if (!(l = _find_labeller(dev, buf, &sector)))
if (!(l = _find_labeller(dev, buf, &sector, scan_sector)))
goto_out;
if ((r = (l->ops->read)(l, dev, buf, result)) && result && *result)
@@ -354,7 +360,7 @@ int label_verify(struct device *dev)
return_0;
}
if (!(l = _find_labeller(dev, buf, &sector)))
if (!(l = _find_labeller(dev, buf, &sector, UINT64_C(0))))
goto_out;
r = l->ops->verify ? l->ops->verify(l, buf, sector) : 1;

View File

@@ -96,7 +96,8 @@ int label_register_handler(const char *name, struct labeller *handler);
struct labeller *label_get_handler(const char *name);
int label_remove(struct device *dev);
int label_read(struct device *dev, struct label **result);
int label_read(struct device *dev, struct label **result,
uint64_t scan_sector);
int label_write(struct device *dev, struct label *label);
int label_verify(struct device *dev);
struct label *label_create(struct labeller *labeller);

View File

@@ -34,6 +34,90 @@ static int _vg_lock_count = 0; /* Number of locks held */
static int _vg_write_lock_held = 0; /* VG write lock held? */
static int _signals_blocked = 0;
static volatile sig_atomic_t _sigint_caught = 0;
static volatile sig_atomic_t _handler_installed;
static struct sigaction _oldhandler;
static int _oldmasked;
static void _catch_sigint(int unused __attribute__((unused)))
{
_sigint_caught = 1;
}
int sigint_caught(void) {
return _sigint_caught;
}
void sigint_clear(void)
{
_sigint_caught = 0;
}
/*
* Temporarily allow keyboard interrupts to be intercepted and noted;
* saves interrupt handler state for sigint_restore(). Users should
* use the sigint_caught() predicate to check whether interrupt was
* requested and act appropriately. Interrupt flags are never
* cleared automatically by this code, but the tools clear the flag
* before running each command in lvm_run_command(). All other places
* where the flag needs to be cleared need to call sigint_clear().
*/
void sigint_allow(void)
{
struct sigaction handler;
sigset_t sigs;
/*
* Do not overwrite the backed-up handler data -
* just increase nesting count.
*/
if (_handler_installed) {
_handler_installed++;
return;
}
/* Grab old sigaction for SIGINT: shall not fail. */
sigaction(SIGINT, NULL, &handler);
handler.sa_flags &= ~SA_RESTART; /* Clear restart flag */
handler.sa_handler = _catch_sigint;
_handler_installed = 1;
/* Override the signal handler: shall not fail. */
sigaction(SIGINT, &handler, &_oldhandler);
/* Unmask SIGINT. Remember to mask it again on restore. */
sigprocmask(0, NULL, &sigs);
if ((_oldmasked = sigismember(&sigs, SIGINT))) {
sigdelset(&sigs, SIGINT);
sigprocmask(SIG_SETMASK, &sigs, NULL);
}
}
void sigint_restore(void)
{
if (!_handler_installed)
return;
if (_handler_installed > 1) {
_handler_installed--;
return;
}
/* Nesting count went down to 0. */
_handler_installed = 0;
if (_oldmasked) {
sigset_t sigs;
sigprocmask(0, NULL, &sigs);
sigaddset(&sigs, SIGINT);
sigprocmask(SIG_SETMASK, &sigs, NULL);
}
sigaction(SIGINT, &_oldhandler, NULL);
}
static void _block_signals(int flags __attribute((unused)))
{
sigset_t set;
@@ -130,7 +214,7 @@ int init_locking(int type, struct cmd_context *cmd)
switch (type) {
case 0:
init_no_locking(&_locking, cmd);
log_print("WARNING: Locking disabled. Be careful! "
log_warn("WARNING: Locking disabled. Be careful! "
"This could corrupt your metadata.");
return 1;
@@ -171,8 +255,8 @@ int init_locking(int type, struct cmd_context *cmd)
if ((type == 2 || type == 3) &&
find_config_tree_int(cmd, "locking/fallback_to_local_locking",
DEFAULT_FALLBACK_TO_LOCAL_LOCKING)) {
log_print("WARNING: Falling back to local file-based locking.");
log_print("Volume Groups with the clustered attribute will "
log_warn("WARNING: Falling back to local file-based locking.");
log_warn("Volume Groups with the clustered attribute will "
"be inaccessible.");
if (init_file_locking(&_locking, cmd))
return 1;

View File

@@ -115,4 +115,10 @@ int suspend_lvs(struct cmd_context *cmd, struct list *lvs);
int resume_lvs(struct cmd_context *cmd, struct list *lvs);
int activate_lvs_excl(struct cmd_context *cmd, struct list *lvs);
/* Interrupt handling */
void sigint_clear(void);
void sigint_allow(void);
void sigint_restore(void);
int sigint_caught(void);
#endif

View File

@@ -81,7 +81,7 @@ int init_no_locking(struct locking_type *locking, struct cmd_context *cmd)
locking->lock_resource = _no_lock_resource;
locking->reset_locking = _no_reset_locking;
locking->fin_locking = _no_fin_locking;
locking->flags = 0;
locking->flags = LCK_CLUSTERED;
return 1;
}

View File

@@ -302,6 +302,9 @@ void print_log(int level, const char *file, int line, const char *format, ...)
int bufused, n;
const char *message;
const char *trformat; /* Translated format string */
int use_stderr = level & _LOG_STDERR;
level &= ~_LOG_STDERR;
if (_log_suppress == 2)
return;
@@ -373,9 +376,9 @@ void print_log(int level, const char *file, int line, const char *format, ...)
break;
case _LOG_WARN:
if (_verbose_level >= _LOG_WARN) {
printf("%s%s", _cmd_name, _msg_prefix);
vprintf(trformat, ap);
putchar('\n');
fprintf(use_stderr ? stderr : stdout, "%s%s", _cmd_name, _msg_prefix);
vfprintf(use_stderr ? stderr : stdout, trformat, ap);
fputc('\n', use_stderr ? stderr : stdout);
}
break;
case _LOG_ERR:

View File

@@ -41,6 +41,8 @@
#include <string.h> /* strerror() */
#include <errno.h>
#define _LOG_STDERR 128 /* force things to go to stderr, even if loglevel
would make them go to stdout */
#define _LOG_DEBUG 7
#define _LOG_INFO 6
#define _LOG_NOTICE 5
@@ -116,14 +118,14 @@ void print_log(int level, const char *file, int line, const char *format, ...)
#define log_debug(x...) plog(_LOG_DEBUG, x)
#define log_info(x...) plog(_LOG_INFO, x)
#define log_notice(x...) plog(_LOG_NOTICE, x)
#define log_warn(x...) plog(_LOG_WARN, x)
#define log_warn(x...) plog(_LOG_WARN | _LOG_STDERR, x)
#define log_err(x...) plog(_LOG_ERR, x)
#define log_fatal(x...) plog(_LOG_FATAL, x)
#define stack log_debug("<backtrace>") /* Backtrace on error */
#define log_error(args...) log_err(args)
#define log_print(args...) log_warn(args)
#define log_print(args...) plog(_LOG_WARN, args)
#define log_verbose(args...) log_notice(args)
#define log_very_verbose(args...) log_info(args)
@@ -138,5 +140,6 @@ void print_log(int level, const char *file, int line, const char *format, ...)
#define return_0 do { stack; return 0; } while (0)
#define return_NULL do { stack; return NULL; } while (0)
#define goto_out do { stack; goto out; } while (0)
#define goto_bad do { stack; goto bad; } while (0)
#endif

View File

@@ -146,9 +146,9 @@ int check_lv_segments(struct logical_volume *lv, int complete_vg)
if (complete_vg && seg_lv(seg, s) &&
(seg_lv(seg, s)->status & MIRROR_IMAGE) &&
(find_seg_by_le(seg_lv(seg, s),
seg_le(seg, s))->mirror_seg
!= seg)) {
(!(seg2 = find_seg_by_le(seg_lv(seg, s),
seg_le(seg, s))) ||
seg2->mirror_seg != seg)) {
log_error("LV %s: segment %u mirror "
"image %u missing mirror ptr",
lv->name, seg_count, s);

View File

@@ -24,21 +24,65 @@
#include "pv_alloc.h"
#include "activate.h"
#include "display.h"
#include "locking.h"
#include <sys/param.h>
/*
* FIXME: Check for valid handle before dereferencing field or log error?
*/
#define pv_field(handle, field) \
(((struct physical_volume *)(handle))->field)
static struct physical_volume *_pv_read(struct cmd_context *cmd,
const char *pv_name,
struct list *mdas,
uint64_t *label_sector,
int warnings);
static struct physical_volume *_pv_create(const struct format_type *fmt,
struct device *dev,
struct id *id, uint64_t size,
uint64_t pe_start,
uint32_t existing_extent_count,
uint32_t existing_extent_size,
int pvmetadatacopies,
uint64_t pvmetadatasize, struct list *mdas);
static int _pv_write(struct cmd_context *cmd __attribute((unused)),
struct physical_volume *pv,
struct list *mdas, int64_t label_sector);
static struct physical_volume *_find_pv_by_name(struct cmd_context *cmd,
const char *pv_name);
static struct pv_list *_find_pv_in_vg(struct volume_group *vg, const char *pv_name);
static struct physical_volume *_find_pv_in_vg_by_uuid(struct volume_group *vg,
struct id *id);
unsigned long pe_align(void)
{
return MAX(65536UL, lvm_getpagesize()) >> SECTOR_SHIFT;
}
static int _add_pv_to_vg(struct format_instance *fid, struct volume_group *vg,
const char *pv_name)
/**
* add_pv_to_vg - Add a physical volume to a volume group
* @vg - volume group to add to
* @pv_name - name of the pv (to be removed)
* @pv - physical volume to add to volume group
*
* Returns:
* 0 - failure
* 1 - success
* FIXME: remove pv_name - obtain safely from pv
*/
int add_pv_to_vg(struct volume_group *vg, const char *pv_name,
struct physical_volume *pv)
{
struct pv_list *pvl;
struct physical_volume *pv;
struct format_instance *fid = vg->fid;
struct dm_pool *mem = fid->fmt->cmd->mem;
struct list mdas;
log_verbose("Adding physical volume '%s' to volume group '%s'",
pv_name, vg->name);
@@ -48,13 +92,6 @@ static int _add_pv_to_vg(struct format_instance *fid, struct volume_group *vg,
return 0;
}
list_init(&mdas);
if (!(pv = pv_read(fid->fmt->cmd, pv_name, &mdas, NULL, 1))) {
log_error("%s not identified as an existing physical volume",
pv_name);
return 0;
}
if (*pv->vg_name) {
log_error("Physical volume '%s' is already in volume group "
"'%s'", pv_name, pv->vg_name);
@@ -102,7 +139,7 @@ static int _add_pv_to_vg(struct format_instance *fid, struct volume_group *vg,
return 0;
}
if (find_pv_in_vg(vg, pv_name)) {
if (_find_pv_in_vg(vg, pv_name)) {
log_error("Physical volume '%s' listed more than once.",
pv_name);
return 0;
@@ -173,8 +210,8 @@ int get_pv_from_vg_by_id(const struct format_type *fmt, const char *vg_name,
}
if (!consistent)
log_error("Warning: Volume group %s is not consistent",
vg_name);
log_warn("WARNING: Volume group %s is not consistent",
vg_name);
list_iterate_items(pvl, &vg->pvs) {
if (id_equal(&pvl->pv->id, (const struct id *) pvid)) {
@@ -211,22 +248,31 @@ int vg_rename(struct cmd_context *cmd, struct volume_group *vg,
return 1;
}
int vg_extend(struct format_instance *fid,
struct volume_group *vg, int pv_count, char **pv_names)
int vg_extend(struct volume_group *vg, int pv_count, char **pv_names)
{
int i;
struct physical_volume *pv;
/* attach each pv */
for (i = 0; i < pv_count; i++)
if (!_add_pv_to_vg(fid, vg, pv_names[i])) {
log_error("Unable to add physical volume '%s' to "
"volume group '%s'.", pv_names[i], vg->name);
return 0;
for (i = 0; i < pv_count; i++) {
if (!(pv = pv_by_path(vg->fid->fmt->cmd, pv_names[i]))) {
log_error("%s not identified as an existing "
"physical volume", pv_names[i]);
goto bad;
}
if (!add_pv_to_vg(vg, pv_names[i], pv))
goto bad;
}
/* FIXME Decide whether to initialise and add new mdahs to format instance */
return 1;
bad:
log_error("Unable to add physical volume '%s' to "
"volume group '%s'.", pv_names[i], vg->name);
return 0;
}
const char *strip_dir(const char *vg_name, const char *dev_dir)
@@ -280,10 +326,9 @@ struct volume_group *vg_create(struct cmd_context *cmd, const char *vg_name,
vg->seqno = 0;
vg->status = (RESIZEABLE_VG | LVM_READ | LVM_WRITE);
if (!(vg->system_id = dm_pool_alloc(mem, NAME_LEN))) {
stack;
goto bad;
}
if (!(vg->system_id = dm_pool_alloc(mem, NAME_LEN)))
goto_bad;
*vg->system_id = '\0';
vg->extent_size = extent_size;
@@ -319,8 +364,8 @@ struct volume_group *vg_create(struct cmd_context *cmd, const char *vg_name,
}
/* attach the pv's */
if (!vg_extend(vg->fid, vg, pv_count, pv_names))
goto bad;
if (!vg_extend(vg, pv_count, pv_names))
goto_bad;
return vg;
@@ -505,8 +550,72 @@ int vg_change_pesize(struct cmd_context *cmd, struct volume_group *vg,
return 1;
}
int vg_split_mdas(struct cmd_context *cmd, struct volume_group *vg_from,
struct volume_group *vg_to)
{
struct metadata_area *mda, *mda2;
struct list *mdas_from, *mdas_to;
int common_mda = 0;
mdas_from = &vg_from->fid->metadata_areas;
mdas_to = &vg_to->fid->metadata_areas;
list_iterate_items_safe(mda, mda2, mdas_from) {
if (!mda->ops->mda_in_vg) {
common_mda = 1;
continue;
}
if (!mda->ops->mda_in_vg(vg_from->fid, vg_from, mda)) {
list_del(&mda->list);
list_add(mdas_to, &mda->list);
}
}
if (list_empty(mdas_from) || list_empty(mdas_to))
return common_mda;
return 1;
}
/**
* pv_create - initialize a physical volume for use with a volume group
* @fmt: format type
* @dev: PV device to initialize
* @id: PV UUID to use for initialization
* @size: size of the PV in sectors
* @pe_start: physical extent start
* @existing_extent_count
* @existing_extent_size
* @pvmetadatacopies
* @pvmetadatasize
* @mdas
*
* Returns:
* PV handle - physical volume initialized successfully
* NULL - invalid parameter or problem initializing the physical volume
*
* Note:
* FIXME - liblvm todo - tidy up arguments for external use (fmt, mdas, etc)
*/
pv_t *pv_create(const struct format_type *fmt,
struct device *dev,
struct id *id, uint64_t size,
uint64_t pe_start,
uint32_t existing_extent_count,
uint32_t existing_extent_size,
int pvmetadatacopies,
uint64_t pvmetadatasize, struct list *mdas)
{
return _pv_create(fmt, dev, id, size, pe_start,
existing_extent_count,
existing_extent_size,
pvmetadatacopies,
pvmetadatasize, mdas);
}
/* Sizes in sectors */
struct physical_volume *pv_create(const struct format_type *fmt,
static struct physical_volume *_pv_create(const struct format_type *fmt,
struct device *dev,
struct id *id, uint64_t size,
uint64_t pe_start,
@@ -533,10 +642,8 @@ struct physical_volume *pv_create(const struct format_type *fmt,
pv->dev = dev;
if (!(pv->vg_name = dm_pool_zalloc(mem, NAME_LEN))) {
stack;
goto bad;
}
if (!(pv->vg_name = dm_pool_zalloc(mem, NAME_LEN)))
goto_bad;
pv->status = ALLOCATABLE_PV;
@@ -547,7 +654,7 @@ struct physical_volume *pv_create(const struct format_type *fmt,
if (size) {
if (size > pv->size)
log_print("WARNING: %s: Overriding real size. "
log_warn("WARNING: %s: Overriding real size. "
"You could lose data.", dev_name(pv->dev));
log_verbose("%s: Pretending size is %" PRIu64 " sectors.",
dev_name(pv->dev), size);
@@ -584,7 +691,13 @@ struct physical_volume *pv_create(const struct format_type *fmt,
return NULL;
}
/* FIXME: liblvm todo - make into function that returns handle */
struct pv_list *find_pv_in_vg(struct volume_group *vg, const char *pv_name)
{
return _find_pv_in_vg(vg, pv_name);
}
static struct pv_list *_find_pv_in_vg(struct volume_group *vg, const char *pv_name)
{
struct pv_list *pvl;
@@ -606,8 +719,26 @@ int pv_is_in_vg(struct volume_group *vg, struct physical_volume *pv)
return 0;
}
struct physical_volume *find_pv_in_vg_by_uuid(struct volume_group *vg,
struct id *id)
/**
* find_pv_in_vg_by_uuid - Find PV in VG by PV UUID
* @vg: volume group to search
* @id: UUID of the PV to match
*
* Returns:
* PV handle - if UUID of PV found in VG
* NULL - invalid parameter or UUID of PV not found in VG
*
* Note
* FIXME - liblvm todo - make into function that takes VG handle
*/
pv_t *find_pv_in_vg_by_uuid(struct volume_group *vg, struct id *id)
{
return _find_pv_in_vg_by_uuid(vg, id);
}
static struct physical_volume *_find_pv_in_vg_by_uuid(struct volume_group *vg,
struct id *id)
{
struct pv_list *pvl;
@@ -665,12 +796,20 @@ struct physical_volume *find_pv(struct volume_group *vg, struct device *dev)
return NULL;
}
/* FIXME: liblvm todo - make into function that returns handle */
struct physical_volume *find_pv_by_name(struct cmd_context *cmd,
const char *pv_name)
{
return _find_pv_by_name(cmd, pv_name);
}
static struct physical_volume *_find_pv_by_name(struct cmd_context *cmd,
const char *pv_name)
{
struct physical_volume *pv;
if (!(pv = pv_read(cmd, pv_name, NULL, NULL, 1))) {
if (!(pv = _pv_read(cmd, pv_name, NULL, NULL, 1))) {
log_error("Physical volume %s not found", pv_name);
return NULL;
}
@@ -759,6 +898,12 @@ int vg_validate(struct volume_group *vg)
r = 0;
}
}
if (strcmp(pvl->pv->vg_name, vg->name)) {
log_error("Internal error: VG name for PV %s is corrupted",
dev_name(pvl->pv->dev));
r = 0;
}
}
if (!check_pv_segments(vg)) {
@@ -948,7 +1093,7 @@ static struct volume_group *_vg_read_orphans(struct cmd_context *cmd)
}
list_iterate_items(info, &vginfo->infos) {
if (!(pv = pv_read(cmd, dev_name(info->dev), NULL, NULL, 1))) {
if (!(pv = _pv_read(cmd, dev_name(info->dev), NULL, NULL, 1))) {
continue;
}
if (!(pvl = dm_pool_zalloc(cmd->mem, sizeof(*pvl)))) {
@@ -963,6 +1108,30 @@ static struct volume_group *_vg_read_orphans(struct cmd_context *cmd)
return vg;
}
static int _update_pv_list(struct list *all_pvs, struct volume_group *vg)
{
struct pv_list *pvl, *pvl2;
list_iterate_items(pvl, &vg->pvs) {
list_iterate_items(pvl2, all_pvs) {
if (pvl->pv->dev == pvl2->pv->dev)
goto next_pv;
}
/* PV is not on list so add it. Note that we don't copy it. */
if (!(pvl2 = dm_pool_zalloc(vg->cmd->mem, sizeof(*pvl2)))) {
log_error("pv_list allocation for '%s' failed",
dev_name(pvl->pv->dev));
return 0;
}
pvl2->pv = pvl->pv;
list_add(all_pvs, &pvl2->list);
next_pv:
;
}
return 1;
}
/* Caller sets consistent to 1 if it's safe for vg_read to correct
* inconsistent metadata on disk (i.e. the VG write lock is held).
* This guarantees only consistent metadata is returned unless PARTIAL_VG.
@@ -982,9 +1151,12 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
struct volume_group *vg, *correct_vg = NULL;
struct metadata_area *mda;
int inconsistent = 0;
int inconsistent_vgid = 0;
int use_precommitted = precommitted;
struct list *pvids;
struct pv_list *pvl;
struct pv_list *pvl, *pvl2;
struct list all_pvs;
char uuid[64] __attribute((aligned(8)));
if (!*vgname) {
if (use_precommitted) {
@@ -1069,6 +1241,8 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
}
}
list_init(&all_pvs);
/* Failed to find VG where we expected it - full scan and retry */
if (!correct_vg) {
inconsistent = 0;
@@ -1104,13 +1278,25 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
}
if (!correct_vg) {
correct_vg = vg;
if (!_update_pv_list(&all_pvs, correct_vg))
return_NULL;
continue;
}
if (strncmp((char *)vg->id.uuid,
(char *)correct_vg->id.uuid, ID_LEN)) {
inconsistent = 1;
inconsistent_vgid = 1;
}
/* FIXME Also ensure contents same - checksums same? */
if (correct_vg->seqno != vg->seqno) {
inconsistent = 1;
if (vg->seqno > correct_vg->seqno)
if (vg->seqno > correct_vg->seqno) {
if (!_update_pv_list(&all_pvs, vg))
return_NULL;
correct_vg = vg;
}
}
}
@@ -1143,17 +1329,42 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
return correct_vg;
}
log_print("Inconsistent metadata copies found - updating "
"to use version %u", correct_vg->seqno);
/* Don't touch if vgids didn't match */
if (inconsistent_vgid) {
log_error("Inconsistent metadata UUIDs found for "
"volume group %s", vgname);
*consistent = 0;
return correct_vg;
}
log_warn("WARNING: Inconsistent metadata found for VG %s - updating "
"to use version %u", vgname, correct_vg->seqno);
if (!vg_write(correct_vg)) {
log_error("Automatic metadata correction failed");
return NULL;
}
if (!vg_commit(correct_vg)) {
log_error("Automatic metadata correction commit "
"failed");
return NULL;
}
list_iterate_items(pvl, &all_pvs) {
list_iterate_items(pvl2, &correct_vg->pvs) {
if (pvl->pv->dev == pvl2->pv->dev)
goto next_pv;
}
if (!id_write_format(&pvl->pv->id, uuid, sizeof(uuid)))
return_NULL;
log_error("Removing PV %s (%s) that no longer belongs to VG %s",
dev_name(pvl->pv->dev), uuid, correct_vg->name);
if (!pv_write_orphan(cmd, pvl->pv))
return_NULL;
next_pv:
;
}
}
if ((correct_vg->status & PVMOVE) && !pvmove_mode()) {
@@ -1288,10 +1499,34 @@ struct logical_volume *lv_from_lvid(struct cmd_context *cmd, const char *lvid_s,
return lvl->lv;
}
/* FIXME Use label functions instead of PV functions */
/**
* pv_read - read and return a handle to a physical volume
* @cmd: LVM command initiating the pv_read
* @pv_name: full device name of the PV, including the path
* @mdas: list of metadata areas of the PV
* @label_sector: sector number where the PV label is stored on @pv_name
* @warnings:
*
* Returns:
* PV handle - valid pv_name and successful read of the PV, or
* NULL - invalid parameter or error in reading the PV
*
* Note:
* FIXME - liblvm todo - make into function that returns handle
*/
struct physical_volume *pv_read(struct cmd_context *cmd, const char *pv_name,
struct list *mdas, uint64_t *label_sector,
int warnings)
{
return _pv_read(cmd, pv_name, mdas, label_sector, warnings);
}
/* FIXME Use label functions instead of PV functions */
static struct physical_volume *_pv_read(struct cmd_context *cmd,
const char *pv_name,
struct list *mdas,
uint64_t *label_sector,
int warnings)
{
struct physical_volume *pv;
struct label *label;
@@ -1303,7 +1538,7 @@ struct physical_volume *pv_read(struct cmd_context *cmd, const char *pv_name,
return NULL;
}
if (!(label_read(dev, &label))) {
if (!(label_read(dev, &label, UINT64_C(0)))) {
if (warnings)
log_error("No physical volume label read from %s",
pv_name);
@@ -1398,8 +1633,8 @@ struct list *get_pvs(struct cmd_context *cmd)
continue;
}
if (!consistent)
log_print("Warning: Volume Group %s is not consistent",
vgname);
log_warn("WARNING: Volume Group %s is not consistent",
vgname);
/* Move PVs onto results list */
list_iterate_safe(pvh, tmp, &vg->pvs) {
@@ -1412,8 +1647,17 @@ struct list *get_pvs(struct cmd_context *cmd)
return results;
}
int pv_write(struct cmd_context *cmd __attribute((unused)), struct physical_volume *pv,
/* FIXME: liblvm todo - make into function that takes handle */
int pv_write(struct cmd_context *cmd __attribute((unused)),
struct physical_volume *pv,
struct list *mdas, int64_t label_sector)
{
return _pv_write(cmd, pv, mdas, label_sector);
}
static int _pv_write(struct cmd_context *cmd __attribute((unused)),
struct physical_volume *pv,
struct list *mdas, int64_t label_sector)
{
if (!pv->fmt->ops->pv_write) {
log_error("Format does not support writing physical volumes");
@@ -1433,3 +1677,201 @@ int pv_write(struct cmd_context *cmd __attribute((unused)), struct physical_volu
return 1;
}
int pv_write_orphan(struct cmd_context *cmd, struct physical_volume *pv)
{
const char *old_vg_name = pv->vg_name;
pv->vg_name = ORPHAN;
pv->status = ALLOCATABLE_PV;
if (!dev_get_size(pv->dev, &pv->size)) {
log_error("%s: Couldn't get size.", dev_name(pv->dev));
return 0;
}
if (!_pv_write(cmd, pv, NULL, INT64_C(-1))) {
log_error("Failed to clear metadata from physical "
"volume \"%s\" after removal from \"%s\"",
dev_name(pv->dev), old_vg_name);
return 0;
}
return 1;
}
/**
* is_orphan - Determine whether a pv is an orphan based on its vg_name
* @pv: handle to the physical volume
*/
int is_orphan(pv_t *pv)
{
return (pv_field(pv, vg_name)[0] ? 0 : 1);
}
/*
* Returns:
* 0 - fail
* 1 - success
*/
int pv_analyze(struct cmd_context *cmd, const char *pv_name,
int64_t label_sector)
{
struct label *label;
struct device *dev;
struct metadata_area *mda;
struct lvmcache_info *info;
dev = dev_cache_get(pv_name, cmd->filter);
if (!dev) {
log_error("Device %s not found (or ignored by filtering).",
pv_name);
return 0;
}
/*
* First, scan for LVM labels.
*/
if (!label_read(dev, &label, label_sector)) {
log_error("Could not find LVM label on %s",
pv_name);
return 0;
}
log_print("Found label on %s, sector %"PRIu64", type=%s",
pv_name, label->sector, label->type);
/*
* Next, loop through metadata areas
*/
info = label->info;
list_iterate_items(mda, &info->mdas)
mda->ops->pv_analyze_mda(info->fmt, mda);
return 1;
}
/**
* vg_check_status - check volume group status flags and log error
* @vg - volume group to check status flags
* @status - specific status flags to check (e.g. EXPORTED_VG)
*
* Returns:
* 0 - fail
* 1 - success
*/
int vg_check_status(struct volume_group *vg, uint32_t status)
{
if ((status & CLUSTERED) &&
(vg->status & CLUSTERED) && !locking_is_clustered() &&
!lockingfailed()) {
log_error("Skipping clustered volume group %s", vg->name);
return 0;
}
if ((status & EXPORTED_VG) &&
(vg->status & EXPORTED_VG)) {
log_error("Volume group %s is exported", vg->name);
return 0;
}
if ((status & LVM_WRITE) &&
!(vg->status & LVM_WRITE)) {
log_error("Volume group %s is read-only", vg->name);
return 0;
}
if ((status & RESIZEABLE_VG) &&
!(vg->status & RESIZEABLE_VG)) {
log_error("Volume group %s is not resizeable.", vg->name);
return 0;
}
return 1;
}
/*
* Gets/Sets for external LVM library
*/
struct id pv_id(pv_t *pv)
{
return pv_field(pv, id);
}
const struct format_type *pv_format_type(pv_t *pv)
{
return pv_field(pv, fmt);
}
struct id pv_vgid(pv_t *pv)
{
return pv_field(pv, vgid);
}
struct device *pv_dev(pv_t *pv)
{
return pv_field(pv, dev);
}
const char *pv_vg_name(pv_t *pv)
{
return pv_field(pv, vg_name);
}
uint64_t pv_size(pv_t *pv)
{
return pv_field(pv, size);
}
uint32_t pv_status(pv_t *pv)
{
return pv_field(pv, status);
}
uint32_t pv_pe_size(pv_t *pv)
{
return pv_field(pv, pe_size);
}
uint64_t pv_pe_start(pv_t *pv)
{
return pv_field(pv, pe_start);
}
uint32_t pv_pe_count(pv_t *pv)
{
return pv_field(pv, pe_count);
}
uint32_t pv_pe_alloc_count(pv_t *pv)
{
return pv_field(pv, pe_alloc_count);
}
uint32_t vg_status(vg_t *vg)
{
return vg->status;
}
/**
* pv_by_path - Given a device path return a PV handle if it is a PV
* @cmd - handle to the LVM command instance
* @pv_name - device path to read for the PV
*
* Returns:
* NULL - device path does not contain a valid PV
* non-NULL - PV handle corresponding to device path
*
* FIXME: merge with find_pv_by_name ?
*/
pv_t *pv_by_path(struct cmd_context *cmd, const char *pv_name)
{
struct list mdas;
list_init(&mdas);
return _pv_read(cmd, pv_name, &mdas, NULL, 1);
}

View File

@@ -142,6 +142,7 @@ struct physical_volume {
struct list tags;
};
typedef struct physical_volume pv_t;
struct metadata_area;
struct format_instance;
@@ -178,6 +179,17 @@ struct metadata_area_ops {
struct volume_group * vg, struct metadata_area * mda);
int (*vg_remove) (struct format_instance * fi, struct volume_group * vg,
struct metadata_area * mda);
/*
* Check if metadata area belongs to vg
*/
int (*mda_in_vg) (struct format_instance * fi,
struct volume_group * vg, struct metadata_area *mda);
/*
* Analyze a metadata area on a PV.
*/
int (*pv_analyze_mda) (const struct format_type * fmt,
struct metadata_area *mda);
};
struct metadata_area {
@@ -223,6 +235,8 @@ struct volume_group {
struct list tags;
};
typedef struct volume_group vg_t;
/* There will be one area for each stripe */
struct lv_segment_area {
area_type_t type;
@@ -423,20 +437,24 @@ struct list *get_vgids(struct cmd_context *cmd, int full_scan);
int pv_write(struct cmd_context *cmd, struct physical_volume *pv,
struct list *mdas, int64_t label_sector);
int pv_write_orphan(struct cmd_context *cmd, struct physical_volume *pv);
int is_orphan(pv_t *pv);
/* pe_start and pe_end relate to any existing data so that new metadata
* areas can avoid overlap */
struct physical_volume *pv_create(const struct format_type *fmt,
struct device *dev,
struct id *id,
uint64_t size,
uint64_t pe_start,
uint32_t existing_extent_count,
uint32_t existing_extent_size,
int pvmetadatacopies,
uint64_t pvmetadatasize, struct list *mdas);
pv_t *pv_create(const struct format_type *fmt,
struct device *dev,
struct id *id,
uint64_t size,
uint64_t pe_start,
uint32_t existing_extent_count,
uint32_t existing_extent_size,
int pvmetadatacopies,
uint64_t pvmetadatasize, struct list *mdas);
int pv_resize(struct physical_volume *pv, struct volume_group *vg,
uint32_t new_pe_count);
int pv_analyze(struct cmd_context *cmd, const char *pv_name,
int64_t label_sector);
struct volume_group *vg_create(struct cmd_context *cmd, const char *name,
uint32_t extent_size, uint32_t max_pv,
@@ -445,10 +463,11 @@ struct volume_group *vg_create(struct cmd_context *cmd, const char *name,
int vg_remove(struct volume_group *vg);
int vg_rename(struct cmd_context *cmd, struct volume_group *vg,
const char *new_name);
int vg_extend(struct format_instance *fi, struct volume_group *vg,
int pv_count, char **pv_names);
int vg_extend(struct volume_group *vg, int pv_count, char **pv_names);
int vg_change_pesize(struct cmd_context *cmd, struct volume_group *vg,
uint32_t new_extent_size);
int vg_split_mdas(struct cmd_context *cmd, struct volume_group *vg_from,
struct volume_group *vg_to);
/* Manipulate LVs */
struct logical_volume *lv_create_empty(struct format_instance *fi,
@@ -484,8 +503,7 @@ struct physical_volume *pv_find(struct volume_group *vg, const char *pv_name);
/* Find a PV within a given VG */
struct pv_list *find_pv_in_vg(struct volume_group *vg, const char *pv_name);
struct physical_volume *find_pv_in_vg_by_uuid(struct volume_group *vg,
struct id *id);
pv_t *find_pv_in_vg_by_uuid(struct volume_group *vg, struct id *id);
int get_pv_from_vg_by_id(const struct format_type *fmt, const char *vg_name,
const char *vgid, const char *pvid,
struct physical_volume *pv);
@@ -562,6 +580,8 @@ int vg_add_snapshot(struct format_instance *fid, const char *name,
int vg_remove_snapshot(struct logical_volume *cow);
int vg_check_status(struct volume_group *vg, uint32_t status);
/*
* Mirroring functions
*/
@@ -617,4 +637,25 @@ uint32_t find_free_lvnum(struct logical_volume *lv);
char *generate_lv_name(struct volume_group *vg, const char *format,
char *buffer, size_t len);
/*
* Begin skeleton for external LVM library
*/
struct id pv_id(pv_t *pv);
const struct format_type *pv_format_type(pv_t *pv);
struct id pv_vgid(pv_t *pv);
struct device *pv_dev(pv_t *pv);
const char *pv_vg_name(pv_t *pv);
uint64_t pv_size(pv_t *pv);
uint32_t pv_status(pv_t *pv);
uint32_t pv_pe_size(pv_t *pv);
uint64_t pv_pe_start(pv_t *pv);
uint32_t pv_pe_count(pv_t *pv);
uint32_t pv_pe_alloc_count(pv_t *pv);
uint32_t vg_status(vg_t *vg);
pv_t *pv_by_path(struct cmd_context *cmd, const char *pv_name);
int add_pv_to_vg(struct volume_group *vg, const char *pv_name,
struct physical_volume *pv);
#endif

View File

@@ -21,6 +21,7 @@
#include "activate.h"
#include "lv_alloc.h"
#include "lvm-string.h"
#include "str_list.h"
#include "locking.h" /* FIXME Should not be used in this file */
#include "defaults.h" /* FIXME: should this be defaults.h? */
@@ -77,6 +78,42 @@ static void _move_lv_segments(struct logical_volume *lv_to, struct logical_volum
lv_from->size = 0;
}
/*
* Delete independent/orphan LV, it must acquire lock.
*/
static int _delete_lv(struct lv_segment *mirrored_seg, struct logical_volume *lv)
{
struct cmd_context *cmd = mirrored_seg->lv->vg->cmd;
struct str_list *sl;
/* Inherit tags - maybe needed for activation */
if (!str_list_match_list(&mirrored_seg->lv->tags, &lv->tags)) {
list_iterate_items(sl, &mirrored_seg->lv->tags)
if (!str_list_add(cmd->mem, &lv->tags, sl->str)) {
log_error("Aborting. Unable to tag.");
return 0;
}
if (!vg_write(mirrored_seg->lv->vg) ||
!vg_commit(mirrored_seg->lv->vg)) {
log_error("Intermediate VG commit for orphan volume failed.");
return 0;
}
}
if (!activate_lv(cmd, lv))
return_0;
if (!deactivate_lv(cmd, lv))
return_0;
if (!lv_remove(lv))
return_0;
return 1;
}
/*
* Reduce mirrored_seg to num_mirrors images.
*/
@@ -205,57 +242,15 @@ int remove_mirror_images(struct lv_segment *mirrored_seg, uint32_t num_mirrors,
}
/* Delete the 'orphan' LVs */
for (m = num_mirrors; m < old_area_count; m++) {
/* LV is now independent of the mirror so must acquire lock. */
if (!activate_lv(mirrored_seg->lv->vg->cmd, seg_lv(mirrored_seg, m))) {
stack;
for (m = num_mirrors; m < old_area_count; m++)
if (!_delete_lv(mirrored_seg, seg_lv(mirrored_seg, m)))
return 0;
}
if (!deactivate_lv(mirrored_seg->lv->vg->cmd, seg_lv(mirrored_seg, m))) {
stack;
return 0;
}
if (lv1 && !_delete_lv(mirrored_seg, lv1))
return 0;
if (!lv_remove(seg_lv(mirrored_seg, m))) {
stack;
return 0;
}
}
if (lv1) {
if (!activate_lv(mirrored_seg->lv->vg->cmd, lv1)) {
stack;
return 0;
}
if (!deactivate_lv(mirrored_seg->lv->vg->cmd, lv1)) {
stack;
return 0;
}
if (!lv_remove(lv1)) {
stack;
return 0;
}
}
if (log_lv) {
if (!activate_lv(mirrored_seg->lv->vg->cmd, log_lv)) {
stack;
return 0;
}
if (!deactivate_lv(mirrored_seg->lv->vg->cmd, log_lv)) {
stack;
return 0;
}
if (!lv_remove(log_lv)) {
stack;
return 0;
}
}
if (log_lv && !_delete_lv(mirrored_seg, log_lv))
return 0;
return 1;
}
@@ -382,7 +377,7 @@ int reconfigure_mirror_images(struct lv_segment *mirrored_seg, uint32_t num_mirr
/* Unable to remove bad devices */
return 0;
log_print("WARNING: Bad device removed from mirror volume, %s/%s",
log_warn("WARNING: Bad device removed from mirror volume, %s/%s",
mirrored_seg->lv->vg->name, mirrored_seg->lv->name);
log_policy = get_mirror_log_fault_policy(mirrored_seg->lv->vg->cmd);
@@ -399,15 +394,15 @@ int reconfigure_mirror_images(struct lv_segment *mirrored_seg, uint32_t num_mirr
mirrored_seg->lv->vg->name, mirrored_seg->lv->name);
else if (r > 0)
/* Success in replacing device(s) */
log_print("WARNING: Mirror volume, %s/%s restored - substitute for failed device found.",
log_warn("WARNING: Mirror volume, %s/%s restored - substitute for failed device found.",
mirrored_seg->lv->vg->name, mirrored_seg->lv->name);
else
/* Bad device removed, but not replaced because of policy */
if (mirrored_seg->area_count == 1) {
log_print("WARNING: Mirror volume, %s/%s converted to linear due to device failure.",
log_warn("WARNING: Mirror volume, %s/%s converted to linear due to device failure.",
mirrored_seg->lv->vg->name, mirrored_seg->lv->name);
} else if (had_log && !mirrored_seg->log_lv) {
log_print("WARNING: Mirror volume, %s/%s disk log removed due to device failure.",
log_warn("WARNING: Mirror volume, %s/%s disk log removed due to device failure.",
mirrored_seg->lv->vg->name, mirrored_seg->lv->name);
}
/*

View File

@@ -19,7 +19,7 @@
#ifndef _LVM_LIB_H
#define _LVM_LIB_H
#include <configure.h>
#include "configure.h"
#define _REENTRANT
#define _GNU_SOURCE

View File

@@ -256,6 +256,8 @@ void sync_dir(const char *file)
int fcntl_lock_file(const char *file, short lock_type, int warn_if_read_only)
{
int lockfd;
char *dir;
char *c;
struct flock lock = {
.l_type = lock_type,
.l_whence = 0,
@@ -263,6 +265,21 @@ int fcntl_lock_file(const char *file, short lock_type, int warn_if_read_only)
.l_len = 0
};
if (!(dir = dm_strdup(file))) {
log_error("fcntl_lock_file failed in strdup.");
return -1;
}
if ((c = strrchr(dir, '/')))
*c = '\0';
if (!create_dir(dir)) {
dm_free(dir);
return -1;
}
dm_free(dir);
log_very_verbose("Locking %s (%s, %hd)", file,
(lock_type == F_WRLCK) ? "F_WRLCK" : "F_RDLCK",
lock_type);

View File

@@ -36,18 +36,38 @@ int emit_to_buffer(char **buffer, size_t *size, const char *fmt, ...)
}
/*
* Device layer names are all of the form <vg>-<lv>-<layer>, any
* other hyphens that appear in these names are quoted with yet
* another hyphen. The top layer of any device has no layer
* name. eg, vg0-lvol0.
* Count occurences of 'c' in 'str' until we reach a null char.
*
* Returns:
* len - incremented for each char we encounter, whether 'c' or not.
* count - number of occurences of 'c'
*/
static void _count_hyphens(const char *str, size_t *len, int *hyphens)
void count_chars(const char *str, size_t *len, int *count,
const char c)
{
const char *ptr;
for (ptr = str; *ptr; ptr++, (*len)++)
if (*ptr == '-')
(*hyphens)++;
if (*ptr == c)
(*count)++;
}
/*
* Count occurences of 'c' in 'str' of length 'size'.
*
* Returns:
* # of occurences of 'c'
*/
unsigned count_chars_len(const char *str, size_t size, const char c)
{
int i;
unsigned count=0;
for (i=0; i < size; i++)
if (str[i] == c)
count++;
return count;
}
/*
@@ -73,11 +93,11 @@ char *build_dm_name(struct dm_pool *mem, const char *vgname,
int hyphens = 1;
char *r, *out;
_count_hyphens(vgname, &len, &hyphens);
_count_hyphens(lvname, &len, &hyphens);
count_chars(vgname, &len, &hyphens, '-');
count_chars(lvname, &len, &hyphens, '-');
if (layer && *layer) {
_count_hyphens(layer, &len, &hyphens);
count_chars(layer, &len, &hyphens, '-');
hyphens++;
}
@@ -105,6 +125,12 @@ char *build_dm_name(struct dm_pool *mem, const char *vgname,
return r;
}
/*
* Device layer names are all of the form <vg>-<lv>-<layer>, any
* other hyphens that appear in these names are quoted with yet
* another hyphen. The top layer of any device has no layer
* name. eg, vg0-lvol0.
*/
int validate_name(const char *n)
{
register char c;

View File

@@ -30,4 +30,8 @@ char *build_dm_name(struct dm_pool *mem, const char *vg,
int validate_name(const char *n);
void count_chars(const char *str, size_t *len, int *count,
char c);
unsigned count_chars_len(const char *str, size_t size, char c);
#endif

View File

@@ -1,25 +0,0 @@
/*
* 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
*/
#ifndef _LVM_MATCHER_H
#define _LVM_MATCHER_H
struct matcher;
struct matcher *matcher_create(struct dm_pool *mem, const char **patterns,
unsigned num);
int matcher_run(struct matcher *m, const char *begin);
#endif

View File

@@ -47,6 +47,7 @@ FIELD(PVS, pv, STR, "Attr", status, 4, pvstatus, "pv_attr", "Various attributes
FIELD(PVS, pv, NUM, "PE", pe_count, 3, uint32, "pv_pe_count", "Total number of Physical Extents.")
FIELD(PVS, pv, NUM, "Alloc", pe_alloc_count, 5, uint32, "pv_pe_alloc_count", "Total number of allocated Physical Extents.")
FIELD(PVS, pv, STR, "PV Tags", tags, 7, tags, "pv_tags", "Tags, if any.")
FIELD(PVS, pv, NUM, "#PMda", id, 5, pvmdas, "pv_mda_count", "Number of metadata areas on this device.")
FIELD(VGS, vg, STR, "Fmt", cmd, 3, vgfmt, "vg_fmt", "Type of metadata.")
FIELD(VGS, vg, STR, "VG UUID", id, 38, uuid, "vg_uuid", "Unique identifier.")
@@ -65,6 +66,7 @@ FIELD(VGS, vg, NUM, "#LV", lv_count, 3, uint32, "lv_count", "Number of LVs.")
FIELD(VGS, vg, NUM, "#SN", snapshot_count, 3, uint32, "snap_count", "Number of snapshots.")
FIELD(VGS, vg, NUM, "Seq", seqno, 3, uint32, "vg_seqno", "Revision number of internal metadata. Incremented whenever it changes.")
FIELD(VGS, vg, STR, "VG Tags", tags, 7, tags, "vg_tags", "Tags, if any.")
FIELD(VGS, vg, NUM, "#VMda", cmd, 5, vgmdas, "vg_mda_count", "Number of metadata areas in use by this VG.")
FIELD(SEGS, seg, STR, "Type", list, 4, segtype, "segtype", "Type of LV segment")
FIELD(SEGS, seg, NUM, "#Str", area_count, 4, uint32, "stripes", "Number of stripes or mirror legs.")

View File

@@ -49,7 +49,7 @@ static char _alloc_policy_char(alloc_policy_t alloc)
case ALLOC_CONTIGUOUS:
return 'c';
case ALLOC_CLING:
return 'C';
return 'l';
case ALLOC_NORMAL:
return 'n';
case ALLOC_ANYWHERE:
@@ -718,6 +718,32 @@ static int _int32_disp(struct dm_report *rh, struct dm_pool *mem,
return dm_report_field_int32(rh, field, data);
}
static int _pvmdas_disp(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field,
const void *data, void *private)
{
struct lvmcache_info *info;
uint32_t count;
const char *pvid = (const char *)(&((struct id *) data)->uuid);
info = info_from_pvid(pvid);
count = info ? list_size(&info->mdas) : 0;
return _uint32_disp(rh, mem, field, &count, private);
}
static int _vgmdas_disp(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field,
const void *data, void *private)
{
const struct volume_group *vg = (const struct volume_group *) data;
uint32_t count;
count = list_size(&vg->fid->metadata_areas);
return _uint32_disp(rh, mem, field, &count, private);
}
static int _lvsegcount_disp(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field,
const void *data, void *private)
@@ -868,11 +894,11 @@ static const struct dm_report_object_type _report_types[] = {
#define STR DM_REPORT_FIELD_TYPE_STRING
#define NUM DM_REPORT_FIELD_TYPE_NUMBER
#define FIELD(type, strct, sorttype, head, field, width, func, id, desc) {type, id, (off_t)((void *)&_dummy._ ## strct.field - (void *)&_dummy._ ## strct), head, width, sorttype, &_ ## func ## _disp, desc},
#define FIELD(type, strct, sorttype, head, field, width, func, id, desc) {type, sorttype, (off_t)((void *)&_dummy._ ## strct.field - (void *)&_dummy._ ## strct), width, id, head, &_ ## func ## _disp, desc},
static struct dm_report_field_type _fields[] = {
#include "columns.h"
{0, "", 0, "", 0, 0, NULL, NULL},
{0, 0, 0, 0, "", "", NULL, NULL},
};
#undef STR
@@ -880,8 +906,8 @@ static struct dm_report_field_type _fields[] = {
#undef FIELD
void *report_init(struct cmd_context *cmd, const char *format, const char *keys,
report_type_t *report_type, const char *separator,
int aligned, int buffered, int headings)
report_type_t *report_type, const char *separator,
int aligned, int buffered, int headings)
{
uint32_t report_flags = 0;
@@ -894,7 +920,7 @@ void *report_init(struct cmd_context *cmd, const char *format, const char *keys,
if (headings)
report_flags |= DM_REPORT_OUTPUT_HEADINGS;
return dm_report_init(report_type, _report_types, _fields, format,
return dm_report_init(report_type, _report_types, _fields, format,
separator, report_flags, keys, cmd);
}

View File

@@ -98,7 +98,7 @@ static int _snap_target_percent(void **target_state __attribute((unused)),
float percent2;
uint64_t numerator, denominator;
if (index(params, '/')) {
if (strchr(params, '/')) {
if (sscanf(params, "%" PRIu64 "/%" PRIu64,
&numerator, &denominator) == 2) {
*total_numerator += numerator;

View File

@@ -127,3 +127,5 @@ dm_report_field_int32
dm_report_field_uint32
dm_report_field_uint64
dm_report_field_set_value
dm_regex_create
dm_regex_match

View File

@@ -27,6 +27,9 @@ SOURCES =\
libdm-report.c \
mm/dbg_malloc.c \
mm/pool.c \
regex/matcher.c \
regex/parse_rx.c \
regex/ttree.c \
$(interface)/libdm-iface.c
INCLUDES = -I$(interface)

View File

@@ -13,8 +13,8 @@
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _LVM_BITSET_H
#define _LVM_BITSET_H
#ifndef _DM_BITSET_H
#define _DM_BITSET_H
#include "pool.h"

View File

@@ -68,14 +68,14 @@ static struct dm_hash_node *_create_node(const char *str, unsigned len)
return n;
}
static unsigned long _hash(const unsigned char *str, unsigned len)
static unsigned long _hash(const char *str, unsigned len)
{
unsigned long h = 0, g;
unsigned i;
for (i = 0; i < len; i++) {
h <<= 4;
h += _nums[*str++];
h += _nums[(unsigned char) *str++];
g = h & ((unsigned long) 0xf << 16u);
if (g) {
h ^= g >> 16u;

View File

@@ -13,8 +13,8 @@
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _LVM_HASH_H
#define _LVM_HASH_H
#ifndef _DM_HASH_H
#define _DM_HASH_H
struct hash_table;
struct hash_node;

View File

@@ -433,12 +433,12 @@ static int _dm_task_get_info_v1(struct dm_task *dmt, struct dm_info *info)
return 1;
}
static const char *_dm_task_get_name_v1(struct dm_task *dmt)
static const char *_dm_task_get_name_v1(const struct dm_task *dmt)
{
return (dmt->dmi.v1->name);
}
static const char *_dm_task_get_uuid_v1(struct dm_task *dmt)
static const char *_dm_task_get_uuid_v1(const struct dm_task *dmt)
{
return (dmt->dmi.v1->uuid);
}
@@ -592,9 +592,9 @@ static int _dm_names_v1(struct dm_ioctl_v1 *dmi)
struct stat buf;
char path[PATH_MAX];
log_print("Warning: Device list may be incomplete with interface "
log_warn("WARNING: Device list may be incomplete with interface "
"version 1.");
log_print("Please upgrade your kernel device-mapper driver.");
log_warn("Please upgrade your kernel device-mapper driver.");
if (!(d = opendir(dev_dir))) {
log_error("%s: opendir failed: %s", dev_dir, strerror(errno));
@@ -693,7 +693,7 @@ static int _dm_task_run_v1(struct dm_task *dmt)
if (dmi->flags & DM_BUFFER_FULL_FLAG)
/* FIXME Increase buffer size and retry operation (if query) */
log_error("Warning: libdevmapper buffer too small for data");
log_error("WARNING: libdevmapper buffer too small for data");
switch (dmt->type) {
case DM_DEVICE_CREATE:
@@ -924,7 +924,7 @@ int dm_task_get_info(struct dm_task *dmt, struct dm_info *info)
return 1;
}
const char *dm_task_get_name(struct dm_task *dmt)
const char *dm_task_get_name(const struct dm_task *dmt)
{
#ifdef DM_COMPAT
if (_dm_version == 1)
@@ -934,7 +934,7 @@ const char *dm_task_get_name(struct dm_task *dmt)
return (dmt->dmi.v4->name);
}
const char *dm_task_get_uuid(struct dm_task *dmt)
const char *dm_task_get_uuid(const struct dm_task *dmt)
{
#ifdef DM_COMPAT
if (_dm_version == 1)
@@ -1555,7 +1555,7 @@ static struct dm_ioctl *_do_dm_ioctl(struct dm_task *dmt, unsigned command,
dmi->flags |= DM_SKIP_BDGET_FLAG;
log_debug("dm %s %s %s%s%s %s%.0d%s%.0d%s"
"%s%c%c%s %.0llu %s [%u]",
"%s%c%c%s %.0" PRIu64 " %s [%u]",
_cmd_data_v4[dmt->type].name,
dmi->name, dmi->uuid, dmt->newname ? " " : "",
dmt->newname ? dmt->newname : "",
@@ -1650,7 +1650,7 @@ repeat_ioctl:
dm_free(dmi);
goto repeat_ioctl;
default:
log_error("Warning: libdevmapper buffer too small for data");
log_error("WARNING: libdevmapper buffer too small for data");
}
}

View File

@@ -133,8 +133,8 @@ struct dm_versions {
int dm_get_library_version(char *version, size_t size);
int dm_task_get_driver_version(struct dm_task *dmt, char *version, size_t size);
int dm_task_get_info(struct dm_task *dmt, struct dm_info *dmi);
const char *dm_task_get_name(struct dm_task *dmt);
const char *dm_task_get_uuid(struct dm_task *dmt);
const char *dm_task_get_name(const struct dm_task *dmt);
const char *dm_task_get_uuid(const struct dm_task *dmt);
struct dm_deps *dm_task_get_deps(struct dm_task *dmt);
struct dm_names *dm_task_get_names(struct dm_task *dmt);
@@ -630,6 +630,25 @@ char *dm_basename(const char *path);
*/
int dm_asprintf(char **buf, const char *format, ...);
/*********************
* regular expressions
*********************/
struct dm_regex;
/*
* Initialise an array of num patterns for matching.
* Uses memory from mem.
*/
struct dm_regex *dm_regex_create(struct dm_pool *mem, const char **patterns,
unsigned num_patterns);
/*
* Match string s against the patterns.
* Returns the index of the highest pattern in the array that matches,
* or -1 if none match.
*/
int dm_regex_match(struct dm_regex *regex, const char *s);
/*********************
* reporting functions
*********************/
@@ -657,11 +676,11 @@ struct dm_report_field;
struct dm_report;
struct dm_report_field_type {
uint32_t type; /* object type id */
const char id[32]; /* string used to specify the field */
unsigned int offset; /* byte offset in the object */
const char heading[32]; /* string printed in header */
int width; /* default width */
uint32_t flags; /* DM_REPORT_FIELD_* */
uint32_t offset; /* byte offset in the object */
int32_t width; /* default width */
const char id[32]; /* string used to specify the field */
const char heading[32]; /* string printed in header */
int (*report_fn)(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field, const void *data,
void *private);

View File

@@ -42,6 +42,9 @@ static void _default_log(int level, const char *file __attribute((unused)),
int line __attribute((unused)), const char *f, ...)
{
va_list ap;
int use_stderr = level & _LOG_STDERR;
level &= ~_LOG_STDERR;
if (level > _LOG_WARN && !_verbose)
return;
@@ -51,14 +54,14 @@ static void _default_log(int level, const char *file __attribute((unused)),
if (level < _LOG_WARN)
vfprintf(stderr, f, ap);
else
vprintf(f, ap);
vfprintf(use_stderr ? stderr : stdout, f, ap);
va_end(ap);
if (level < _LOG_WARN)
fprintf(stderr, "\n");
else
fprintf(stdout, "\n");
fprintf(use_stderr ? stderr : stdout, "\n");
}
dm_log_fn dm_log = _default_log;

View File

@@ -60,7 +60,7 @@ struct field_properties {
struct list list;
uint32_t field_num;
uint32_t sort_posn;
unsigned width;
int32_t width;
const struct dm_report_object_type *type;
uint32_t flags;
};
@@ -296,35 +296,74 @@ static int _copy_field(struct dm_report *rh, struct field_properties *dest,
return 1;
}
static struct field_properties * _add_field(struct dm_report *rh,
uint32_t field_num, uint32_t flags)
{
struct field_properties *fp;
rh->report_types |= rh->fields[field_num].type;
if (!(fp = dm_pool_zalloc(rh->mem, sizeof(struct field_properties)))) {
log_error("dm_report: struct field_properties allocation "
"failed");
return NULL;
}
if (!_copy_field(rh, fp, field_num)) {
stack;
dm_pool_free(rh->mem, fp);
return NULL;
}
fp->flags |= flags;
/*
* Place hidden fields at the front so list_end() will
* tell us when we've reached the last visible field.
*/
if (fp->flags & FLD_HIDDEN)
list_add_h(&rh->field_props, &fp->list);
else
list_add(&rh->field_props, &fp->list);
return fp;
}
/*
* Compare name1 against name2 or prefix plus name2
* name2 is not necessarily null-terminated.
* len2 is the length of name2.
*/
static int _is_same_field(const char *name1, const char *name2,
size_t len2, const char *prefix)
{
size_t prefix_len;
/* Exact match? */
if (!strncasecmp(name1, name2, len2) && strlen(name1) == len2)
return 1;
/* Match including prefix? */
prefix_len = strlen(prefix);
if (!strncasecmp(prefix, name1, prefix_len) &&
!strncasecmp(name1 + prefix_len, name2, len2) &&
strlen(name1) == prefix_len + len2)
return 1;
return 0;
}
static int _field_match(struct dm_report *rh, const char *field, size_t flen)
{
uint32_t f, l;
struct field_properties *fp;
uint32_t f;
if (!flen)
return 0;
for (f = 0; rh->fields[f].report_fn; f++) {
if ((!strncasecmp(rh->fields[f].id, field, flen) &&
strlen(rh->fields[f].id) == flen) ||
(l = strlen(rh->field_prefix),
!strncasecmp(rh->field_prefix, rh->fields[f].id, l) &&
!strncasecmp(rh->fields[f].id + l, field, flen) &&
strlen(rh->fields[f].id) == l + flen)) {
rh->report_types |= rh->fields[f].type;
if (!(fp = dm_pool_zalloc(rh->mem, sizeof(*fp)))) {
log_error("dm_report: "
"struct field_properties allocation "
"failed");
return 0;
}
if (!_copy_field(rh, fp, f))
return 0;
list_add(&rh->field_props, &fp->list);
return 1;
}
}
for (f = 0; rh->fields[f].report_fn; f++)
if (_is_same_field(rh->fields[f].id, field, flen,
rh->field_prefix))
return _add_field(rh, f, 0) ? 1 : 0;
return 0;
}
@@ -341,21 +380,8 @@ static int _add_sort_key(struct dm_report *rh, uint32_t field_num,
}
}
if (!found) {
rh->report_types |= rh->fields[field_num].type;
if (!(found = dm_pool_zalloc(rh->mem, sizeof(*found)))) {
log_error("dm_report: "
"struct field_properties allocation failed");
return 0;
}
if (!_copy_field(rh, found, field_num))
return 0;
/* Add as a non-display field */
found->flags |= FLD_HIDDEN;
list_add(&rh->field_props, &found->list);
}
if (!found && !(found = _add_field(rh, field_num, FLD_HIDDEN)))
return_0;
if (found->flags & FLD_SORT_KEY) {
log_error("dm_report: Ignoring duplicate sort field: %s",
@@ -372,7 +398,7 @@ static int _add_sort_key(struct dm_report *rh, uint32_t field_num,
static int _key_match(struct dm_report *rh, const char *key, size_t len)
{
uint32_t f, l;
uint32_t f;
uint32_t flags;
if (!len)
@@ -394,16 +420,10 @@ static int _key_match(struct dm_report *rh, const char *key, size_t len)
return 0;
}
for (f = 0; rh->fields[f].report_fn; f++) {
if ((!strncasecmp(rh->fields[f].id, key, len) &&
strlen(rh->fields[f].id) == len) ||
(l = strlen(rh->field_prefix),
!strncasecmp(rh->field_prefix, rh->fields[f].id, l) &&
!strncasecmp(rh->fields[f].id + l, key, len) &&
strlen(rh->fields[f].id) == l + len)) {
for (f = 0; rh->fields[f].report_fn; f++)
if (_is_same_field(rh->fields[f].id, key, len,
rh->field_prefix))
return _add_sort_key(rh, f, flags);
}
}
return 0;
}
@@ -504,15 +524,20 @@ struct dm_report *dm_report_init(uint32_t *report_types,
if (!(rh->mem = dm_pool_create("report", 10 * 1024))) {
log_error("dm_report_init: allocation of memory pool failed");
dm_free(rh);
return NULL;
}
/* Generate list of fields for output based on format string & flags */
if (!_parse_options(rh, output_fields))
if (!_parse_options(rh, output_fields)) {
dm_report_free(rh);
return NULL;
}
if (!_parse_keys(rh, sort_keys))
if (!_parse_keys(rh, sort_keys)) {
dm_report_free(rh);
return NULL;
}
/* Return updated types value for further compatility check by caller */
if (report_types)
@@ -750,7 +775,7 @@ int dm_report_output(struct dm_report *rh)
struct dm_report_field *field;
const char *repstr;
char buf[4096];
unsigned width;
int32_t width;
uint32_t align;
if (list_empty(&rh->rows))

View File

@@ -117,7 +117,7 @@ int dm_snprintf(char *buf, size_t bufsize, const char *format, ...)
n = vsnprintf(buf, bufsize, format, ap);
va_end(ap);
if (n < 0 || (n > bufsize - 1))
if (n < 0 || ((unsigned) n + 1 > bufsize))
return -1;
return n;

View File

@@ -13,8 +13,8 @@
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _LVM_DBG_MALLOC_H
#define _LVM_DBG_MALLOC_H
#ifndef _DM_DBG_MALLOC_H
#define _DM_DBG_MALLOC_H
#include <stdlib.h>
#include <string.h>

View File

@@ -13,8 +13,8 @@
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _LVM_POOL_H
#define _LVM_POOL_H
#ifndef _DM_POOL_H
#define _DM_POOL_H
#include <string.h>
#include <stdlib.h>

View File

@@ -1,8 +1,8 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
* 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
@@ -14,9 +14,9 @@
*/
#include "lib.h"
#include "matcher.h"
#include "parse_rx.h"
#include "ttree.h"
#include "assert.h"
struct dfa_state {
int final;
@@ -29,7 +29,7 @@ struct state_queue {
struct state_queue *next;
};
struct matcher { /* Instance variables for the lexer */
struct dm_regex { /* Instance variables for the lexer */
struct dfa_state *start;
unsigned num_nodes;
int nodes_entered;
@@ -52,7 +52,7 @@ static int _count_nodes(struct rx_node *rx)
return r;
}
static void _fill_table(struct matcher *m, struct rx_node *rx)
static void _fill_table(struct dm_regex *m, struct rx_node *rx)
{
assert((rx->type != OR) || (rx->left && rx->right));
@@ -65,7 +65,7 @@ static void _fill_table(struct matcher *m, struct rx_node *rx)
m->nodes[m->nodes_entered++] = rx;
}
static void _create_bitsets(struct matcher *m)
static void _create_bitsets(struct dm_regex *m)
{
int i;
@@ -77,7 +77,7 @@ static void _create_bitsets(struct matcher *m)
}
}
static void _calc_functions(struct matcher *m)
static void _calc_functions(struct dm_regex *m)
{
int i, j, final = 1;
struct rx_node *rx, *c1, *c2;
@@ -189,7 +189,7 @@ static struct state_queue *_create_state_queue(struct dm_pool *mem,
return r;
}
static int _calc_states(struct matcher *m, struct rx_node *rx)
static int _calc_states(struct dm_regex *m, struct rx_node *rx)
{
unsigned iwidth = (m->num_nodes / DM_BITS_PER_INT) + 1;
struct ttree *tt = ttree_create(m->scratch, iwidth);
@@ -263,43 +263,38 @@ static int _calc_states(struct matcher *m, struct rx_node *rx)
return 1;
}
struct matcher *matcher_create(struct dm_pool *mem, const char **patterns,
unsigned num)
struct dm_regex *dm_regex_create(struct dm_pool *mem, const char **patterns,
unsigned num_patterns)
{
char *all, *ptr;
int i;
size_t len = 0;
struct rx_node *rx;
struct dm_pool *scratch = dm_pool_create("regex matcher", 10 * 1024);
struct matcher *m;
struct dm_regex *m;
if (!scratch) {
stack;
return NULL;
}
if (!scratch)
return_NULL;
if (!(m = dm_pool_alloc(mem, sizeof(*m)))) {
stack;
dm_pool_destroy(scratch);
return NULL;
return_NULL;
}
memset(m, 0, sizeof(*m));
/* join the regexps together, delimiting with zero */
for (i = 0; i < num; i++)
for (i = 0; i < num_patterns; i++)
len += strlen(patterns[i]) + 8;
ptr = all = dm_pool_alloc(scratch, len + 1);
if (!all) {
stack;
goto bad;
}
if (!all)
goto_bad;
for (i = 0; i < num; i++) {
for (i = 0; i < num_patterns; i++) {
ptr += sprintf(ptr, "(.*(%s)%c)", patterns[i], TARGET_TRANS);
if (i < (num - 1))
if (i < (num_patterns - 1))
*ptr++ = '|';
}
@@ -314,10 +309,8 @@ struct matcher *matcher_create(struct dm_pool *mem, const char **patterns,
m->num_nodes = _count_nodes(rx);
m->nodes = dm_pool_alloc(scratch, sizeof(*m->nodes) * m->num_nodes);
if (!m->nodes) {
stack;
goto bad;
}
if (!m->nodes)
goto_bad;
_fill_table(m, rx);
_create_bitsets(m);
@@ -330,7 +323,7 @@ struct matcher *matcher_create(struct dm_pool *mem, const char **patterns,
bad:
dm_pool_destroy(scratch);
dm_pool_destroy(mem);
dm_pool_free(mem, m);
return NULL;
}
@@ -345,16 +338,16 @@ static struct dfa_state *_step_matcher(int c, struct dfa_state *cs, int *r)
return cs;
}
int matcher_run(struct matcher *m, const char *b)
int dm_regex_match(struct dm_regex *regex, const char *s)
{
struct dfa_state *cs = m->start;
struct dfa_state *cs = regex->start;
int r = 0;
if (!(cs = _step_matcher(HAT_CHAR, cs, &r)))
goto out;
for (; *b; b++)
if (!(cs = _step_matcher(*b, cs, &r)))
for (; *s; s++)
if (!(cs = _step_matcher(*s, cs, &r)))
goto out;
_step_matcher(DOLLAR_CHAR, cs, &r);

View File

@@ -1,8 +1,8 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
* 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

View File

@@ -1,8 +1,8 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
* 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
@@ -13,8 +13,8 @@
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _LVM_PARSE_REGEX_H
#define _LVM_PARSE_REGEX_H
#ifndef _DM_PARSE_REGEX_H
#define _DM_PARSE_REGEX_H
enum {
CAT,

View File

@@ -1,8 +1,8 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
* 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

View File

@@ -1,8 +1,8 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
* 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
@@ -13,8 +13,8 @@
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _LVM_TTREE_H
#define _LVM_TTREE_H
#ifndef _DM_TTREE_H
#define _DM_TTREE_H
struct ttree;

View File

@@ -56,7 +56,7 @@ endif
.SUFFIXES: .c .d .o .so .a .po .pot .mo .dylib
CFLAGS += -fPIC -Wall -Wundef -Wshadow -Wcast-align -Wwrite-strings -Wmissing-prototypes -Wmissing-declarations -Wnested-externs -Winline -Wmissing-noreturn
CFLAGS += -fPIC -Wall -Wundef -Wshadow -Wcast-align -Wwrite-strings -Wmissing-prototypes -Wmissing-declarations -Wnested-externs -Winline -Wmissing-noreturn -Wformat-security
#CFLAGS += -W -Wconversion -Wpointer-arith -Wredundant-decls -Wbad-function-cast -Wcast-qual
#CFLAGS += -pedantic -std=gnu99
@@ -94,7 +94,7 @@ STRIP=
LIB_VERSION := $(shell cat $(top_srcdir)/VERSION | \
awk -F '.' '{printf "%s.%s",$$1,$$2}')
INCLUDES += -I. -I$(top_srcdir)/include
INCLUDES += -I$(top_srcdir)/include
ifneq ("@DMDIR@", "")
INCLUDES += -I@DMDIR@/include

View File

@@ -20,7 +20,7 @@ MAN5=lvm.conf.5
MAN8=lvchange.8 lvconvert.8 lvcreate.8 lvdisplay.8 lvextend.8 lvm.8 \
lvmchange.8 lvmdiskscan.8 lvmdump.8 \
lvreduce.8 lvremove.8 lvrename.8 lvresize.8 lvs.8 \
lvscan.8 pvchange.8 pvcreate.8 pvdisplay.8 pvmove.8 pvremove.8 \
lvscan.8 pvchange.8 pvck.8 pvcreate.8 pvdisplay.8 pvmove.8 pvremove.8 \
pvresize.8 pvs.8 pvscan.8 vgcfgbackup.8 vgcfgrestore.8 vgchange.8 \
vgck.8 vgcreate.8 vgconvert.8 vgdisplay.8 vgexport.8 vgextend.8 \
vgimport.8 vgmerge.8 vgmknodes.8 vgreduce.8 vgremove.8 vgrename.8 \

View File

@@ -3,6 +3,9 @@
dmsetup \- low level logical volume management
.SH SYNOPSIS
.ad l
.B dmsetup help
.I [-c|-C|--columns]
.br
.B dmsetup create
.I device_name [-u uuid] [--notable | --table <table> | table_file]
.br
@@ -33,21 +36,25 @@ dmsetup \- low level logical volume management
.B dmsetup message
.I device_name sector message
.br
.B dmsetup ls [--target target_type] [--exec command] [--tree [-o options]]
.B dmsetup ls
.I [--target target_type] [--exec command] [--tree [-o options]]
.br
.B dmsetup info
.I [device_name]
.br
.B dmsetup info -c|-C|--columns [--noheadings] [-o name]
.B dmsetup info -c|-C|--columns
.I [--noheadings] [--separator separator] [-o fields] [-O|--sort sort_fields]
.I [device_name]
.br
.B dmsetup deps
.I [device_name]
.br
.B dmsetup status [--target target_type]
.B dmsetup status
.I [--target target_type]
.I [device_name]
.br
.B dmsetup table [--target target_type]
.B dmsetup table
.I [--target target_type]
.I [device_name]
.br
.B dmsetup wait
@@ -103,7 +110,7 @@ Tell the kernel not to supply the open reference count for the device.
When creating a device, don't load any table.
.IP \fB-o|--options
.br
Specify which fields to display. Only \fB-o\ name\fP is supported.
Specify which fields to display.
.IP \fB-r|--readonly
.br
Set the table being loaded read-only.
@@ -136,6 +143,11 @@ See below for information on the table format.
.br
Outputs a list of (major, minor) pairs for devices referenced by the
live table for the specified device.
.IP \fBhelp
.I [-c|-C|--columns]
.br
Outputs a summary of the commands available, optionally including
the list of report fields.
.IP \fBinfo
.I [device_name]
.br
@@ -154,6 +166,17 @@ Outputs some brief information about the device in the form:
Number of targets in the live table
.br
UUID
.IP \fBinfo -c|-C|--columns
.I [--noheadings] [--separator separator] [-o fields] [-O|--sort sort_fields]
.I [device_name]
.br
Output you can customise.
Fields are comma-separated and chosen from the following list:
name, major, minor, attr, open, segments, events, uuid.
Attributes are: (L)ive, (I)nactive, (s)uspended, (r)ead-only, read-(w)rite.
Precede the list with '+' to append
to the default selection of columns instead of replacing it.
Precede any sort_field with - for a reverse sort on that column.
.IP \fBls
.I [--target target_type]
.I [--exec command]

View File

@@ -10,9 +10,10 @@ lvchange \- change attributes of a logical volume
[\-\-resync]
[\-h/\-?/\-\-help]
[\-\-ignorelockingfailure]
[\-\-ignoremonitoring]
[\-\-monitor {y|n}]
[\-M/\-\-persistent y/n] [\-\-minor minor]
[\-P/\-\-partial y/n]
[\-P/\-\-partial]
[\-p/\-\-permission r/w] [\-r/\-\-readahead ReadAheadSectors]
[\-\-refresh]
[\-t/\-\-test]
@@ -60,6 +61,11 @@ the failure is handled according to
\fBmirror_image_fault_policy\fP and \fBmirror_log_fault_policy\fP
set in \fBlvm.conf\fP.
.TP
.I \-\-ignoremonitoring
Make no attempt to interact with dmeventd unless \-\-monitor
is specified.
Do not use this if dmeventd is already monitoring a device.
.TP
.I \-M, \-\-persistent y/n
Set to y to make the minor number specified persistent.
.TP

View File

@@ -194,6 +194,7 @@ All tools return a status code of zero on success or non-zero on failure.
.BR lvs (8),
.BR lvscan (8),
.BR pvchange (8),
.BR pvck (8),
.BR pvcreate (8),
.BR pvdisplay (8),
.BR pvmove (8),

View File

@@ -81,6 +81,11 @@ LVM physical volumes.
Devices in directories outside this hierarchy will be ignored.
Defaults to "/dev".
.IP
\fBpreferred_names\fP \(em List of patterns compared in turn against
all the pathnames referencing the same device in in the scanned directories.
The pathname that matches the earliest pattern in the list is the
one used in any output.
.IP
\fBfilter\fP \(em List of patterns to apply to devices found by a scan.
Patterns are regular expressions delimited by any character and preceded
by \fBa\fP (for accept) or \fBr\fP (for reject). The list is traversed
@@ -95,8 +100,8 @@ pattern it is rejected; otherwise it is accepted.
As an example, to ignore /dev/cdrom you could use:
\fBdevices { filter=["r|cdrom|"] }\fP
.IP
\fBcache\fP \(em Persistent filter cache file.
Defaults to "/etc/lvm/.cache".
\fBcache_dir\fP \(em Persistent filter cache file directory.
Defaults to "/etc/lvm/cache".
.IP
\fBwrite_cache_state\fP \(em Set to 0 to disable the writing out of the
persistent filter cache file when \fBlvm\fP exits.
@@ -364,9 +369,9 @@ understand how things work: to make changes you should always use
the tools as normal, or else vgcfgbackup, edit backup, vgcfgrestore.
.SH FILES
.I /etc/lvm/lvm.conf
.I /etc/lvm/.cache
.I /etc/lvm/archive
.I /etc/lvm/backup
.I /etc/lvm/cache/.cache
.I /var/lock/lvm
.SH SEE ALSO
.BR lvm (8),

View File

@@ -51,7 +51,7 @@ invalid (S)napshot, (v)irtual
.IP 2 3
Permissions: (w)riteable, (r)ead-only
.IP 3 3
Allocation policy: (c)ontiguous, (n)ormal, (a)nywhere, (i)nherited
Allocation policy: (c)ontiguous, c(l)ing, (n)ormal, (a)nywhere, (i)nherited
This is capitalised if the volume is currently locked against allocation
changes, for example during \fBpvmove\fP (8).
.IP 4 3

33
man/pvck.8 Normal file
View File

@@ -0,0 +1,33 @@
.TH PVCK 8 "LVM TOOLS" "Sistina Software UK" \" -*- nroff -*-
.SH NAME
pvck \- check physical volume metadata
.SH SYNOPSIS
.B pvck
.RB [ \-d | \-\-debug ]
.RB [ \-h | \-\-help ]
.RB [ \-v | \-\-verbose ]
.RB [ \-\-labelsector ]
.IR PhysicalVolume " [" PhysicalVolume ...]
.SH DESCRIPTION
pvck checks physical volume LVM metadata for consistency.
.SH OPTIONS
See \fBlvm\fP for common options.
.TP
.BR \-\-labelsector " sector"
By default, 4 sectors of \fBPhysicalVolume\fP are scanned for an LVM label,
starting at sector 0. This parameter allows you to specify a different
starting sector for the scan and is useful for recovery situations. For
example, suppose the partition table is corrupted or lost on /dev/sda,
but you suspect there was an LVM partition at approximately 100 MB. This
area of the disk may be scanned by using the \fB--labelsector\fP parameter
with a value of 204800 (100 * 1024 * 1024 / 512 = 204800):
.sp
.BI "pvck --labelsector 204800 /dev/sda"
.sp
Note that a script can be used with \fB--labelsector\fP to automate the
process of finding LVM labels.
.SH SEE ALSO
.BR lvm (8),
.BR pvcreate (8),
.BR pvscan (8)
.BR vgck (8)

View File

@@ -5,7 +5,7 @@ pvmove \- move physical extents
.B pvmove
[\-\-abort]
[\-\-alloc AllocationPolicy]
[\-\-background]
[\-b/\-\-background]
[\-d/\-\-debug] [\-h/\-\-help] [\-i/\-\-interval Seconds] [\-v/\-\-verbose]
[\-n/\-\-name LogicalVolume]
[SourcePhysicalVolume[:PE[-PE]...] [DestinationPhysicalVolume[:PE[-PE]...]...]]
@@ -73,7 +73,7 @@ type of on-disk metadata. Metadata can be converted using \fBvgconvert\fP(8).
.I \-\-abort
Abort any moves in progress.
.TP
.I \-\-background
.I \-b, \-\-background
Run the daemon in the background.
.TP
.I \-i, \-\-interval Seconds

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