1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-09-29 13:44:18 +03:00

Compare commits

...

582 Commits

Author SHA1 Message Date
Alasdair Kergon
a636299680 Add field name prefix option to reporting functions. 2008-04-20 00:11:08 +00:00
Alasdair Kergon
08e5bd5b72 Calculate string size within dm_pool_grow_object. 2008-04-19 15:50:18 +00:00
Alasdair Kergon
2f057bef5e Fix lvconvert -m0 allocatable space check. 2008-04-18 12:50:24 +00:00
Alasdair Kergon
5ab4f21444 post-release 2008-04-15 15:01:18 +00:00
Alasdair Kergon
9ec26ed481 missing stack 2008-04-15 14:57:12 +00:00
Alasdair Kergon
29c9df1389 pre-release 2008-04-15 14:49:17 +00:00
Milan Broz
867e9c51d4 Drop cached VG metadata before and after committing changes to it. 2008-04-15 14:46:19 +00:00
Alasdair Kergon
0170f7b42a rename P_global to P_#global 2008-04-15 11:36:46 +00:00
Alasdair Kergon
74bb6ead95 Don't attempt remote metadata backups of non-clustered VGs. (2.02.29) 2008-04-14 19:49:12 +00:00
Alasdair Kergon
303388e5cb Don't store fid in VG metadata cache to avoid clvmd segfault. (2.02.34) 2008-04-14 19:24:16 +00:00
Dave Wysochanski
8388779937 Fix vgsplit and vgmerge tests for updated lv counting. 2008-04-11 14:06:16 +00:00
Dave Wysochanski
fc7dfca452 Update vgsplit test to verify loosening of active LV restriction.
This and prior 2 commits resolve Red Hat bz 252041:
Ability to vgsplit an active Volume Group where the split involves only inactive LVs
2008-04-10 21:38:52 +00:00
Dave Wysochanski
e5a1db2392 Update vgsplit to only restrict split with active LVs involved in split.
Existing code will reject a vgsplit if any LVs in the source VG are active.
This patch updates vgsplit to only check LVs involved in the split.
2008-04-10 21:34:53 +00:00
Dave Wysochanski
6790656af6 Add lv_is_active() to determine whether an lv is active.
Handles non-clustered as well as clustered.  For clustered,
the best we can do is try exclusive local activation.  If this
succeeds, we know it is not active elsewhere in the cluster.
Otherwise, we assume it is active elsewhere.
2008-04-10 21:34:18 +00:00
Alasdair Kergon
b7477bdc15 post-release 2008-04-10 20:07:19 +00:00
Alasdair Kergon
ffc61f31de . 2008-04-10 20:02:04 +00:00
Alasdair Kergon
e612871ea7 more pre-release cleanup 2008-04-10 19:59:43 +00:00
Alasdair Kergon
7f40f09f10 fix 3rd copy 2008-04-10 19:16:35 +00:00
Alasdair Kergon
456e42257c make list_move consistent with other list fns 2008-04-10 19:14:27 +00:00
Dave Wysochanski
8618c271cf Update vgsplit tests that count LVs for adjusted LV counting. 2008-04-10 18:55:40 +00:00
Alasdair Kergon
72ca1ccc23 . 2008-04-10 18:53:36 +00:00
Alasdair Kergon
075b4bef3f pre-release 2008-04-10 18:19:49 +00:00
Alasdair Kergon
b59fce4393 post-release 2008-04-10 18:04:31 +00:00
Alasdair Kergon
8674a25eb8 pre-release 2008-04-10 18:00:45 +00:00
Alasdair Kergon
10bf8fd2cd Fix vgdisplay 'Cur LV' field to match lvdisplay output.
Fix lv_count report field to exclude hidden LVs.
2008-04-10 17:19:02 +00:00
Dave Wysochanski
57cb22ff3c Add vg_is_clustered() helper function.
Should be no functional change.
2008-04-10 17:09:32 +00:00
Dave Wysochanski
0162abdcae Minor vgsplit cleanups. 2008-04-10 02:15:56 +00:00
Dave Wysochanski
5801171518 Add _move_one_lv() helper function for vgsplit. 2008-04-10 01:30:22 +00:00
Dave Wysochanski
bf1edbd1e2 Fix lvm tool exit code display in some tests. 2008-04-10 01:06:48 +00:00
Dave Wysochanski
a8484d987d Add vgsplit tests to verify mirror is not moved unnecessarily. 2008-04-09 21:10:13 +00:00
Dave Wysochanski
9b2147f608 Fix vgsplit to only move hidden 'snapshotN' LVs when necessary.
This bug has been around for a long time as far as I can tell.
Without this fix, a vgsplit would unconditionally move the
'hidden/internal' snapshot LVs, and result in corrupted metadata
in the following case:
vg1: contains lv1, lv1snap, both on pvset1
vg1: contains lv2, on pvset2

"vgsplit vg1 vg2 pvset2"
would result in "snapshot0" hidden LV being moved to vg2, and
the origin and cow being left in vg1.  The tools detect the
corruption in vg2, but not in vg1.
2008-04-09 20:56:06 +00:00
Dave Wysochanski
32530b378e Update vgsplit tests for lvnames on the cmdline. 2008-04-09 14:47:34 +00:00
Dave Wysochanski
a42905efa6 Update vgsplit man page to reflect lvnames on cmdline. 2008-04-09 14:39:55 +00:00
Dave Wysochanski
c59745f9dd Update vgsplit to take "-n LogicalVolumeName" on the commandline. 2008-04-09 13:47:13 +00:00
Alasdair Kergon
b4ad9a5d08 Use clustered mirror log with pvmove in clustered VGs, if available. 2008-04-09 12:56:34 +00:00
Alasdair Kergon
3ead7a38b1 Fix some pvmove error status codes. 2008-04-09 12:45:32 +00:00
Dave Wysochanski
bf90435200 *** empty log message *** 2008-04-08 22:02:16 +00:00
Dave Wysochanski
9c181fa3d3 Fix vgsplit error display - fully remove log_suppress.
Author: Dave Wysochanski <dwysocha@redhat.com>
2008-04-08 21:47:54 +00:00
Dave Wysochanski
3af0b1eb90 Fix vgsplit error paths to release vg_to lock. 2008-04-08 21:38:09 +00:00
Alasdair Kergon
7110c318ee Indicate whether or not VG is clustered in vgcreate log message.
Mention default --clustered setting in vgcreate man page.
2008-04-08 14:22:13 +00:00
Christine Caulfield
49a552ccdc Add config file overrides to clvmd when it reads the LVs list so that
config items 'command_names' and 'prefix' don't prevent it working.
2008-04-08 13:03:13 +00:00
Alasdair Kergon
57685f17a9 Fix vgreduce to use vg_split_mdas to check sufficient mdas remain.
Add (empty) orphan VGs to lvmcache during initialisation.
Fix orphan VG name used for format_pool.
2008-04-08 12:49:21 +00:00
Alasdair Kergon
a1c09a463f create fids for internal orphan VGs 2008-04-07 22:12:37 +00:00
Milan Broz
194121760a Update lvmcache VG lock state for all locking types now. 2008-04-07 19:17:29 +00:00
Milan Broz
6a987d46bf Fix output if overriding command_names on cmdline. 2008-04-07 13:53:26 +00:00
Milan Broz
e3db0b39b9 Add detection of clustered mirror log capability.
Currently only check for kernel module presence.
2008-04-07 10:23:47 +00:00
Dave Wysochanski
4d4f0ee188 Add check to vg_commit() to ensure lock is held before writing new VG metadata. 2008-04-04 15:41:20 +00:00
Milan Broz
ac7334c167 Add validation of LV name to pvmove -n. 2008-04-04 11:59:31 +00:00
Christine Caulfield
e7bdd69af0 If lvm.conf was touched, clvmd attempted to update the toolcontext
but only did half of the job. It now shares the do_refresh_cache()
function that vgscan invokes.
2008-04-04 08:53:47 +00:00
Alasdair Kergon
fefc655969 Add some basic internal VG lock validation. 2008-04-03 18:56:40 +00:00
Alasdair Kergon
4dceaef60e . 2008-04-03 14:40:34 +00:00
Alasdair Kergon
6fc10dd3ae . 2008-04-03 14:32:31 +00:00
Alasdair Kergon
1ecd05a584 fix vd->virtblk 2008-04-03 10:29:00 +00:00
Alasdair Kergon
976acaca31 enable vg metadata cache by default 2008-04-02 21:31:14 +00:00
Alasdair Kergon
b4e5131d59 Add per-command flags to control which commands use the VG metadata cache. 2008-04-02 21:23:39 +00:00
Dave Wysochanski
49f7cfefd7 Fix vgsplit locking and remove unneeded error messages when split into new VG.
When vg_lock_and_read() calls were added, they were done so incorrectly for
the destination VG (vg_to).  This resulted in the VG lock not obtained when
a new VG was the destination (vg_lock_and_read() would fail in the vg_read()
clause, which would then release the lock before returning NULL), and could
result in corrupted destination VG.

The fix was to put back the original lock_vol() and vg_read() calls for 'vg_to'.
The failure of vg_read() indicates "vg does not exist", and we key off that
to determine whether we are dealing with a new or existing VG as the
destination.

The first two error messages were also the result of the incorrect
vg_lock_and_read() calls:
  Volume group "new" not found
  cluster request failed: Invalid argument
  New volume group "new" successfully split from "vg"

Fixes https://bugzilla.redhat.com/show_bug.cgi?id=438249
2008-04-02 19:30:12 +00:00
Dave Wysochanski
fc365092f6 Suppress "Volume group not found" message when vgsplit of new VG. 2008-04-02 13:08:49 +00:00
Dave Wysochanski
7f26240442 Fix lvresize to dump stack if vg_lock_and_read() fails.
Necessary because vg_lock_and_read() may fail silently if the vg_check_status() call fails.

Also add lvresize tests.
2008-04-02 12:17:30 +00:00
Alasdair Kergon
db559bb20a Cache VG metadata internally while VG lock is held. 2008-04-01 22:40:13 +00:00
Dave Wysochanski
52850faa15 Fix redundant lvresize message if vg doesn't exist.
BEFORE:
tools/lvm lvresize -l +4 vg22/lv1linear
  Volume group "vg22" not found
  Volume group vg22 doesn't exist

AFTER:
tools/lvm lvresize -l +4 vg22/lv1linear
  Volume group "vg22" not found
2008-04-01 22:15:16 +00:00
Christine Caulfield
57d9a6c836 Fix another allocation bug with clvmd and large node IDs.` 2008-04-01 15:01:30 +00:00
Dave Wysochanski
752c880bfc Add find_lv_in_lv_list() and find_pv_in_pv_list().
Update _add_pvs() to call find_pv_in_pv_list().
2008-03-28 19:08:23 +00:00
Dave Wysochanski
d83a354781 Enhance test debugging by updating verbose mode of check_*_field_ functions.
Author: Dave Wysochanski <dwysocha@redhat.com>
2008-03-28 18:02:22 +00:00
Christine Caulfield
17dd81336d Fix a couple of uninitialised variables. The newfd one could cause
some obscure hangs.
2008-03-28 12:58:09 +00:00
Dave Wysochanski
eaa46a2575 Add vgmerge tests. 2008-03-26 18:03:35 +00:00
Dave Wysochanski
fc0ec1e71e Use list_move() in applicable places. 2008-03-26 17:26:32 +00:00
Dave Wysochanski
fb2f92df1d Add pvseg_is_allocated() for identifying a PV segment allocated to a LV. 2008-03-26 16:48:10 +00:00
Dave Wysochanski
74adbb77b7 Add list_move() support function for list manipulation. 2008-03-26 16:20:54 +00:00
Dave Wysochanski
788e544e1d Add 'is_reserved_lvname()' helper function.
Very similar to apply_lvname_restrictions but without the error messages.
2008-03-25 15:24:59 +00:00
Alasdair Kergon
368a0d4d2d Correct command name in lvmdiskscan man page. 2008-03-25 12:37:48 +00:00
Christine Caulfield
962b7222d0 When reallocating the node IDs array, make it bigger rather than smaller! 2008-03-25 10:41:59 +00:00
Dave Wysochanski
17c1f54369 Add vgsplit tests to verfy attributes of new VG match source VG.
Author: Dave Wysochanski <dwysocha@redhat.com>
2008-03-23 15:40:35 +00:00
Dave Wysochanski
33ae38e71b Fixup vgsplit tests in preparation for vgsplit changes. 2008-03-21 22:00:29 +00:00
Dave Wysochanski
ef58af4bf1 Update vgsplit tests to execute twice (existing and new VG as destination). 2008-03-21 21:14:38 +00:00
Dave Wysochanski
3fad2db2f8 Add LV and VG name restrictions to the lvm man page.
Original patch by: Gerrard Geldenhuis <Gerrard.Geldenhuis@datacash.com>
2008-03-20 18:34:29 +00:00
Alasdair Kergon
9feaeb28ca preparation for vg cache 2008-03-17 16:51:31 +00:00
Christine Caulfield
0075364715 Fix potential thread deadlock.
Also make local sockets non-blocking.
2008-03-17 09:37:47 +00:00
Dave Wysochanski
99c5da5da5 Const cleanups in find_* functions. 2008-03-13 22:51:24 +00:00
Alasdair Kergon
22c957bc20 Refactor text format initialisation into _init_text_import. 2008-03-13 12:33:22 +00:00
Milan Broz
3316d59910 Add metadata test for escaping double quotes in device names (bz431474). 2008-03-12 17:34:58 +00:00
Alasdair Kergon
a109ce1eca Escape double quotes and backslashes in external metadata and config data.
Add functions for escaping double quotes in strings.
Rename count_chars_len to count_chars.
2008-03-12 16:03:22 +00:00
Alasdair Kergon
e581a78d65 Use return_0 in a couple more places.
Correct a function name typo in _line_append error message.
2008-03-10 18:51:27 +00:00
Christine Caulfield
3c78f9900c Include limits.h so it compiles with newer headers. 2008-03-06 08:41:05 +00:00
Alasdair Kergon
bd606943e6 add vd to filters 2008-03-05 18:15:04 +00:00
Dave Wysochanski
6381666df4 Update vgsplit tests.
- Add validation on pv_count, lv_count, and snap_count after split
NOTE: Some of these counts are misleading.  If you compare "lvs" output
with these counts you will be left scratching your head what a "logical volume"
really is.  ;-)
2008-03-04 22:49:00 +00:00
Dave Wysochanski
736f1aa301 Update vgsplit tests.
- Divide into 'usage' and 'operation' tests.
- Add operation tests for specific LV types.
2008-03-04 19:48:32 +00:00
Dave Wysochanski
b1a4eac7a8 Refactor _move_pv() in vgsplit.
Should be no functional change.
2008-02-29 00:13:48 +00:00
Dave Wysochanski
8226a5276b Add vgsplit test to check failure when PV not in source volume group. 2008-02-29 00:09:21 +00:00
Dave Wysochanski
77ad0bb12e Fix t-vgsplit-operation.sh lv2-3 definitions to include test signature. 2008-02-28 17:39:47 +00:00
Dave Wysochanski
9412b42206 Fix t-vgsplit-operation.sh lv1 definition to include test signature. 2008-02-28 16:48:09 +00:00
Alasdair Kergon
2a91d87074 Fix resetting of MIRROR_IMAGE and VISIBLE_LV after removal of LV. 2008-02-22 13:28:29 +00:00
Alasdair Kergon
4a23617d79 Fix remove_layer_from_lv to empty the LV before removing it. (2.02.30) 2008-02-22 13:22:44 +00:00
Alasdair Kergon
0e2ceed74d Add missing no-longer-used segs_using_this_lv test to check_lv_segments. 2008-02-22 13:22:21 +00:00
Jim Meyering
ed56aed8eb Remove redundant if-before-free tests. 2008-02-15 14:14:58 +00:00
Jim Meyering
8d909cbdc0 Remove redundant if-before-free tests in clvmd.c. 2008-02-15 14:12:32 +00:00
Jim Meyering
bf98943cbb is_orphan: make parameter "const" to avoid compiler warning 2008-02-13 20:01:48 +00:00
Alasdair Kergon
6ff4552be2 Fix lvconvert detection of mirror conversion in progress. 2008-02-12 13:29:08 +00:00
Alasdair Kergon
1c7eb79370 Avoid automatic lvconvert polldaemon invocation when -R specified. 2008-02-12 13:26:53 +00:00
Dave Wysochanski
f095a75f1e Reflect actual default setting of preferred_names in example.conf and
update comments.
2008-02-11 16:57:40 +00:00
Alasdair Kergon
f70af6018c Fix 'pvs -a' to detect VGs of PVs without metadata areas. 2008-02-06 16:09:51 +00:00
Alasdair Kergon
71b3b1ff4c split orphan VG by format type 2008-02-06 15:47:28 +00:00
Zdeněk Kabeláč
d9fefa0c6c Fix lvresize to support /dev/mapper prefix in the lvname
Fix unfilled paramater passed to fsadm from lvresize
  Update fsadm to call lvresize if the partition size differs (with option -l)
  Fix fsadm to support vg/lv name (like the rest of lv-tools)
2008-02-06 12:45:32 +00:00
Patrick Caulfield
3bfe922381 Update usage message for clvmd.
Fix clvmd man page printing <br>, clarified debug options.
2008-02-05 09:38:04 +00:00
Dave Wysochanski
a85cf17bf1 Fix default preferred_names filter to use /dev/mapper/mpath devices.
If these devices exist, we should be using them for multipath rather than any
underlying device names.
Reference: http://kbase.redhat.com/faq/FAQ_96_11196.shtma
bz195685
2008-02-04 20:26:14 +00:00
Alasdair Kergon
dbb5a09918 post-release 2008-01-31 12:41:13 +00:00
Alasdair Kergon
93e5097f20 pre-release 2008-01-31 12:36:58 +00:00
Alasdair Kergon
dd53f2dc83 a couple more compiler warnings 2008-01-31 12:35:31 +00:00
Alasdair Kergon
2b83c80593 Fix mirror log name construction during lvconvert. (2.02.30)
Make monitor_dev_for_events recurse through the stack of LVs.
Clean up some more compiler warnings.
Add mirror names test script.
2008-01-31 12:19:36 +00:00
Alasdair Kergon
6930f60c06 only read labels once between each lock event 2008-01-30 16:18:37 +00:00
Alasdair Kergon
376b76e75c undo a few 'stack' moves 2008-01-30 14:17:29 +00:00
Alasdair Kergon
1ddd4509dc Some whitespace tidy-ups. 2008-01-30 14:00:02 +00:00
Alasdair Kergon
6af3f4f4cf Use stack return macros throughout. 2008-01-30 13:19:47 +00:00
Alasdair Kergon
6726c5f958 Rely upon internally-cached PV labels while corresponding VG lock is held. 2008-01-29 23:45:48 +00:00
Alasdair Kergon
d5a9c43cb2 post-release 2008-01-29 12:02:04 +00:00
Alasdair Kergon
19a5a6a4eb pre-release 2008-01-29 11:48:11 +00:00
Alasdair Kergon
617a599ee9 Fix two check_lv_segments error messages to show whole segment. 2008-01-26 00:30:28 +00:00
Alasdair Kergon
25e2d4da44 . 2008-01-26 00:25:45 +00:00
Alasdair Kergon
ad2e7218cb Refactor mirror log attachment code. 2008-01-26 00:25:04 +00:00
Alasdair Kergon
917637fa9b Fix internal metadata corruption in lvchange --resync. 2008-01-26 00:13:45 +00:00
Alasdair Kergon
b595ee1c0b suppress compiler warning 2008-01-22 16:02:26 +00:00
Alasdair Kergon
c8260a4a56 update 2008-01-22 15:58:31 +00:00
Dave Wysochanski
d2eaff3204 Fix vgsplit test mode 2008-01-22 03:49:39 +00:00
Dave Wysochanski
b65f5a844f Fix vgsplit tests 12-13 2008-01-22 03:30:14 +00:00
Dave Wysochanski
95a69f99ba Fix vgsplit - print different message on successful split of existing / new vg
Fix vgsplit - fix a couple error paths that forgot to call unlock_vg
Update vgsplit test cases
2008-01-22 03:25:45 +00:00
Dave Wysochanski
71d609895a Fix vgsplit - print error if vgcreate option given w/existing vg destination
Fix vgsplit - reject split if metadata types or clustered attributes differ
Fix vgsplit - remove physicalextentsize option
Add vgsplit test cases
2008-01-22 02:48:53 +00:00
Patrick Caulfield
9229630447 Remove redundant cnxman-socket.h file. 2008-01-21 14:07:46 +00:00
Alasdair Kergon
eb18a0b7dc Fix pvs, vgs, lvs error exit status on some error paths.
(note -o help is now considered error)
2008-01-20 01:23:46 +00:00
Alasdair Kergon
05ed5c0d74 Use log_warn for reporting field help text instead of log_print. 2008-01-20 01:14:38 +00:00
Alasdair Kergon
41330ecc5e clarify 2008-01-19 12:36:37 +00:00
Alasdair Kergon
16fbcc6e36 post-release 2008-01-19 12:30:55 +00:00
Alasdair Kergon
d87da9c7de Pre-release 2008-01-19 12:28:03 +00:00
Alasdair Kergon
94563b6017 Fix lvcreate --nosync not to wait for non-happening sync. 2008-01-18 22:02:37 +00:00
Alasdair Kergon
34d22f7047 add lvconvert messages 2008-01-18 22:00:46 +00:00
Alasdair Kergon
e24d996fbe Fix lvcreate -M1 readahead. 2008-01-18 21:56:39 +00:00
Dave Wysochanski
9b52617919 Add a test case for 'vgreduce --removemissing' on stacked mirror 2008-01-17 18:29:36 +00:00
Dave Wysochanski
efc1d46c89 More test script fixes. 2008-01-17 18:05:57 +00:00
Alasdair Kergon
9397833ceb pre-release review cleanups 2008-01-17 17:17:09 +00:00
Dave Wysochanski
e9433e83cd Minor test fix 2008-01-17 15:56:53 +00:00
Alasdair Kergon
f3c58100a0 fix default stripesize 2008-01-17 15:53:01 +00:00
Alasdair Kergon
8900231d99 fix default extent_size 2008-01-17 15:31:18 +00:00
Alasdair Kergon
c7a63b8a2b pre-release 2008-01-17 15:02:59 +00:00
Alasdair Kergon
90e90672a4 rename lv_remap_error 2008-01-17 13:54:05 +00:00
Alasdair Kergon
fa51e5c762 mirror log stuff 2008-01-17 13:37:51 +00:00
Alasdair Kergon
911f55d005 lvconvert/vgreduce fixes 2008-01-17 13:13:54 +00:00
Dave Wysochanski
d30eb4e570 Fixup vgsplit man page 2008-01-17 03:18:18 +00:00
Dave Wysochanski
67bcfb6947 Fix descriptions in the newly added test cases 2008-01-17 02:20:48 +00:00
Alasdair Kergon
3915a61b1e another lvconvert fix 2008-01-16 22:54:49 +00:00
Alasdair Kergon
c170d321e8 fix a _get_vgs return 2008-01-16 22:52:46 +00:00
Dave Wysochanski
2802c476ee Fix 'make check' runnable with recent versions of dmsetup.
Fix 'make check' to use DMDIR to check DM_DEV_DIR support in dmsetup.
Add basic test cases for mirrored LV.
Add basic test cases for lvconvert mirror.
Add basic test cases for pvmove.
	Jun'ichi Nomura <j-nomura@ce.jp.nec.com>

Add new vgsplit and vgmerge tests.
	Dave Wysochanski <dwysocha@redhat.com>
2008-01-16 21:21:22 +00:00
Alasdair Kergon
1050cebf7f additional safety check on new segment list 2008-01-16 20:00:01 +00:00
Dave Wysochanski
dad73465fc Create vgs_are_compatible() fn to check whether vgs are compatible for merging.
Add new vgmerge and vgsplit tests to check rejection of incompatible vgs.
Cleanup comments.
Bugzilla: bz251992

---
 lib/metadata/metadata-exported.h |    3 +
 lib/metadata/metadata.c          |   89 +++++++++++++++++++++++++++++++++-
 test/t-vgmerge-usage.sh          |  101 +++++++++++++++++++++++++++++++++++++++
 test/t-vgsplit-operation.sh      |   20 +++++++
 tools/vgmerge.c                  |   69 --------------------------
 tools/vgsplit.c                  |    5 -
 6 files changed, 215 insertions(+), 72 deletions(-)
2008-01-16 19:54:39 +00:00
Alasdair Kergon
8e2ac98fe2 adjust mirror log error message 2008-01-16 19:50:23 +00:00
Alasdair Kergon
9aaf0c36d5 fix to earlier checkin 2008-01-16 19:40:42 +00:00
Alasdair Kergon
1cb07e9cfd cope with stacked LVs as well as PVs when deciding which bits of mirrors to remove 2008-01-16 19:38:39 +00:00
Alasdair Kergon
f1ccdf25b1 allow a mirror to contain only one mimage 2008-01-16 19:18:51 +00:00
Alasdair Kergon
6dca497b27 fix mirror log manipulation during lv convert 2008-01-16 19:16:48 +00:00
Alasdair Kergon
42a83262a1 export find_temporary_mirror() 2008-01-16 19:13:51 +00:00
Alasdair Kergon
63ee9cbee6 move removable_pvs checking 2008-01-16 19:11:39 +00:00
Alasdair Kergon
3862f8ca7c reorder funcs 2008-01-16 19:09:35 +00:00
Alasdair Kergon
4ada7cffd0 Maintain lists of stacked LV segments using each LV. 2008-01-16 19:00:59 +00:00
Alasdair Kergon
a664ce4298 use scan_vgs_for_pvs to detect non-orphans without MDAs 2008-01-16 18:15:26 +00:00
Dave Wysochanski
8d7b6c6905 Remove unused 'list' param from vgsplit - conflict with maxlogicalvolumes param.
Initialize lvm command getopt buffer to zero before building options string.
Bugzilla: bz251992

---
 man/vgsplit.8      |    3 +--
 tools/commands.h   |    3 +--
 tools/lvmcmdline.c |    1 +
 3 files changed, 3 insertions(+), 4 deletions(-)
2008-01-16 17:14:56 +00:00
Alasdair Kergon
16d22d404a revert temp change 2008-01-16 15:26:40 +00:00
Alasdair Kergon
ccb24d5779 reword 2008-01-16 15:25:10 +00:00
Alasdair Kergon
8795b45cb4 Don't use block_on_error with mirror targets above version 1.12. 2008-01-16 15:24:25 +00:00
Dave Wysochanski
628d3bff45 Move more parameter validation into the library.
Update vgrename to call validate_vg_rename_params().
Fix vgcreate and vgsplit default arguments by adding defaults parameter to
fill_vg_create_params().
Add t-vgrename-usage.sh test.
Bugzilla: bz251992
---
 tools/toollib.c  |   32 ++++++++------------------------
 tools/toollib.h  |    5 ++---
 tools/vgcreate.c |   35 +++++++++++++++++++++--------------
 tools/vgrename.c |   35 ++++++-----------------------------
 tools/vgsplit.c  |   21 ++++++++++++++-------
 5 files changed, 51 insertions(+), 77 deletions(-)
2008-01-15 22:56:30 +00:00
Jonathan Earl Brassow
0336bc9de9 - The automatic log module loading patch proposed for the upstream kernel
works on '-'s, not '_'s.  This is due to the preference to have log
  module file names that do not mix '_'s and '-'s.
2008-01-15 22:48:11 +00:00
Dave Wysochanski
033cb21797 Update WHATS_NEW for vgsplit changes 2008-01-15 20:37:49 +00:00
Alasdair Kergon
09b98a45df lvconvert waits for initial completion by default 2008-01-14 21:11:47 +00:00
Dave Wysochanski
38857ba29e Allow vgcreate options as input to vgsplit when new vg is split destination. 2008-01-14 21:07:58 +00:00
Dave Wysochanski
1c7520ec8f Allow vgsplit into existing vg.
Add vgsplit tests to validate operation for new and existing vg destinations.
2008-01-11 21:43:16 +00:00
Dave Wysochanski
362b9769b2 Fixup lvm man pg 2008-01-11 20:24:25 +00:00
Dave Wysochanski
b2d68bd3d2 Refactor vgsplit for accepting existing vg as destination 2008-01-11 20:17:18 +00:00
Dave Wysochanski
0dc7e635d4 Update lvm man page to enumerate lvm tools. 2008-01-11 19:24:25 +00:00
Dave Wysochanski
80e070a857 Fix warning on conditional compile, unused variable 2008-01-11 17:44:26 +00:00
Dave Wysochanski
cc203245e4 Refactor vgcreate for parameter validation and add tests 2008-01-11 07:02:35 +00:00
Alasdair Kergon
2f9a65fc93 convert_lv 2008-01-10 22:21:44 +00:00
Alasdair Kergon
62738e8001 correct field name 2008-01-10 22:21:25 +00:00
Alasdair Kergon
5ecacf0c7f Add lv_convert field to default lvs output. 2008-01-10 19:25:07 +00:00
Alasdair Kergon
06b103c8d4 Various lvconvert/polldaemon-related fixes from NEC. See lvm-devel
for original patches & explanations.
2008-01-10 18:35:51 +00:00
Petr Rockai
d473b7bca8 Print warning when lvm tools are running as non-root. 2008-01-09 15:55:44 +00:00
Petr Rockai
50a1e81ba7 Amend previous commit. * does not match .files... 2008-01-09 15:33:25 +00:00
Petr Rockai
d9885b1b64 Add snapshot dmeventd library (enables dmeventd snapshot monitoring). 2008-01-09 15:32:19 +00:00
Zdeněk Kabeláč
0a9c8cada2 install conditionally fsadm.8 manpage 2008-01-09 14:17:58 +00:00
Petr Rockai
60f55f8461 Prevent pvcreate from overwriting MDA-less PVs belonging to active VGs. 2008-01-09 00:18:36 +00:00
Zdeněk Kabeláč
7bedaea38f added manpage 2008-01-08 17:01:42 +00:00
Zdeněk Kabeláč
9e4b87e798 readahead at least twice the strip size (same as raid0 driver does) 2008-01-08 16:47:10 +00:00
Zdeněk Kabeláč
95bf59095c added more safety checks
fixed error reporting commands
extended with Exa and Peta support
2008-01-08 16:45:43 +00:00
Milan Broz
e0f34a9720 Fix a segfault if using pvs with --all argument. (2.02.29) 2008-01-07 20:42:57 +00:00
Milan Broz
f3797c2a8e Update --uuid argument description in man pages. 2008-01-04 11:48:40 +00:00
Alasdair Kergon
30cbcccc80 Fix vgreduce PV list processing not to process every PV in the VG. 2008-01-03 19:03:32 +00:00
Alasdair Kergon
f49c0d696f typo 2007-12-28 15:13:38 +00:00
Alasdair Kergon
71f564ee5b lvconvert uses polldaemon now 2007-12-22 12:13:29 +00:00
Alasdair Kergon
4b0950aba5 a few more changes/fixes to recent code 2007-12-22 02:13:00 +00:00
Alasdair Kergon
8c3af822ec auto-collapse layers 2007-12-21 01:08:18 +00:00
Alasdair Kergon
878a207d19 more fixes 2007-12-20 23:12:27 +00:00
Alasdair Kergon
0537ad860a various cleanups in recent patches 2007-12-20 22:37:42 +00:00
Alasdair Kergon
2cdbbb1aea stacked mirror support (incomplete) 2007-12-20 18:55:46 +00:00
Alasdair Kergon
7af977d36b avoid some compiler warnings 2007-12-20 16:49:37 +00:00
Alasdair Kergon
9afff4cf30 Major restructuring of pvmove and lvconvert layer manipulation code 2007-12-20 15:42:55 +00:00
Alasdair Kergon
48ba9734aa post-release 2007-12-20 15:16:14 +00:00
Alasdair Kergon
897fc59f72 pre-release 2007-12-20 15:12:57 +00:00
Alasdair Kergon
947e44ae67 tweak usage text 2007-12-17 14:47:22 +00:00
Alasdair Kergon
e44843beba replace fsadm.c with fsadm.sh 2007-12-17 12:31:50 +00:00
Alasdair Kergon
147482ea69 Build changes to replace fsadm C program with shell script. 2007-12-17 12:23:24 +00:00
Alasdair Kergon
09091c5cf8 Append fields to report/pvsegs_cols_verbose.
Permit LV segment fields with PV segment reports.
  Add seg_start_pe and seg_pe_ranges to reports.
2007-12-14 21:53:02 +00:00
Alasdair Kergon
50827a5f69 more readahead node fixes/debug messages 2007-12-14 19:49:27 +00:00
Alasdair Kergon
2d6444c924 Fix deptree to pass new name to _resume_node after a rename. 2007-12-14 17:57:04 +00:00
Alasdair Kergon
1d2675d9aa Add node operation stack debug messages. 2007-12-14 17:26:09 +00:00
Alasdair Kergon
ad98990a8e Report error when empty device name passed to readahead functions. 2007-12-13 02:25:45 +00:00
Alasdair Kergon
8e58c143f2 post-release 2007-12-05 22:48:06 +00:00
Alasdair Kergon
556a4a2395 clarify 2007-12-05 22:45:56 +00:00
Alasdair Kergon
5be987b40f pre-release
N.B. This is a big release and some regressions are inevitable.
2007-12-05 22:19:24 +00:00
Alasdair Kergon
066bc35e69 export can_split parameter until rest of pvmove allocation restructuring gets done 2007-12-05 22:11:20 +00:00
Alasdair Kergon
403779437c round readahead to multiple of page size in tools 2007-12-05 19:24:32 +00:00
Alasdair Kergon
fb806f61d4 Fix minimum readahead debug message. 2007-12-05 18:57:34 +00:00
Alasdair Kergon
6ce306661c post-release 2007-12-05 17:14:30 +00:00
Alasdair Kergon
3c08ff94d4 pre-release 2007-12-05 17:05:04 +00:00
Alasdair Kergon
a6afae2356 clarify when read_ahead may be set 2007-12-05 16:28:19 +00:00
Alasdair Kergon
0eea7070a7 work out device name to use for read ahead request 2007-12-05 16:24:41 +00:00
Alasdair Kergon
105c2b1eea read_ahead in report with underscore to match lvm2 field 2007-12-05 14:42:10 +00:00
Alasdair Kergon
82bb0e8dda fix ioctls to use long not int
update dm-ioctl.h after compat tidy-up
2007-12-05 14:11:26 +00:00
Patrick Caulfield
8c01179075 Tidy the clvmd backup code.
Move the backups inside the protection of the VG lock,
Don't backup if we have a suspended LV
Correct the vg_read() call
2007-12-05 13:17:18 +00:00
Jim Meyering
c9d9a96630 Avoid spurious test failure when compiled with readline support.
* test/t-000-basic.sh: Invoke initial test of lvm with its "version"
argument, so that the behavior of the tool doesn't depend on whether
readline was enabled at configure time.


Author: Jun'ichi Nomura <j-nomura@ce.jp.nec.com>
Committer: Jim Meyering <meyering@redhat.com>
2007-12-05 09:49:08 +00:00
Patrick Caulfield
8f21c9a920 When we unlock a VG tell the clvmds to see if a backup of the metadata needs
to be done.
2007-12-04 15:39:26 +00:00
Alasdair Kergon
0ba7d05ea7 fixme 2007-12-03 22:53:04 +00:00
Alasdair Kergon
5a4c5b4155 fixes 2007-12-03 22:48:36 +00:00
Alasdair Kergon
55323fb497 fix changed parms 2007-12-03 18:00:38 +00:00
Alasdair Kergon
7c082d2471 missing #include 2007-12-03 17:56:36 +00:00
Alasdair Kergon
f3cafcf983 fix 2007-11-30 16:44:42 +00:00
Alasdair Kergon
75073e4aa6 readahead support completed - untested 2007-11-30 16:42:26 +00:00
Alasdair Kergon
a3c23f650c read_ahead node ops 2007-11-30 14:59:57 +00:00
Alasdair Kergon
0545cd5879 uncomment libdevmapper readahead calls 2007-11-29 15:04:12 +00:00
Alasdair Kergon
c96506f22c refine specification of dmsetup readahead 2007-11-29 14:44:28 +00:00
Alasdair Kergon
49b2006824 add read_ahead functions to library and dmsetup --readahead
(Not live yet.)
2007-11-27 20:57:05 +00:00
Petr Rockai
8c6f96faab Fix a possible double-free in libdevmapper-event. 2007-11-27 12:26:06 +00:00
Alasdair Kergon
a0e648abfd drop mirrored_pv/mirrored_pe from alloc handle 2007-11-22 14:54:35 +00:00
Alasdair Kergon
6350cd12fc Start refactoring pvmove allocation code. 2007-11-22 13:57:21 +00:00
Alasdair Kergon
f2fab0677b FIXMEs for case where dm itself has device open 2007-11-22 01:25:06 +00:00
Alasdair Kergon
edffc52927 note pvmove breakage 2007-11-19 18:24:08 +00:00
Alasdair Kergon
d6e5e3d103 Decode cluster locking state in log message. (untested)
Change file locking state messages from debug to very verbose.
2007-11-16 21:16:20 +00:00
Alasdair Kergon
5be7a0ebf7 move pvresize_single back under tools 2007-11-15 22:11:18 +00:00
Alasdair Kergon
7f722fe7d3 Fix --addtag to drop @ prefix from name 2007-11-15 21:59:11 +00:00
Alasdair Kergon
a01732ee9b more vg_read lock fixes 2007-11-15 21:30:52 +00:00
Patrick Caulfield
85ac11b69b If the pre_command fails then go back and wait patiently for the next
pre function rather than retrying it until we get stuck!
2007-11-15 10:16:14 +00:00
Alasdair Kergon
590cfb77a5 define LCK_NONE for cases when vg_lock_and_read already holds lock
(temporary - library will use internal ref counting instead)
2007-11-15 02:55:22 +00:00
Alasdair Kergon
f01dd16a27 another vg_lock_and_read 2007-11-15 02:53:49 +00:00
Alasdair Kergon
df49287e5f Convert some vg_reads into vg_lock_and_reads 2007-11-15 02:20:03 +00:00
Alasdair Kergon
c8ec8391ee Avoid nested vg_reads when processing PVs in VGs and fix associated locking. 2007-11-14 18:41:05 +00:00
Patrick Caulfield
3499e48064 Make it compile with new lv_info_by_lvid() prototype 2007-11-14 13:37:51 +00:00
Alasdair Kergon
2e379cb8a5 Accept sizes with --readahead argument.
Store size arguments as sectors internally.
2007-11-14 00:08:25 +00:00
Alasdair Kergon
f8ee3c2369 fix precedence 2007-11-12 21:50:21 +00:00
Alasdair Kergon
c74fa11518 readahead activation code (but no dm support yet) 2007-11-12 20:51:54 +00:00
Alasdair Kergon
ceec4455df Add DM_READ_AHEAD_MINIMUM_FLAG 2007-11-12 20:47:18 +00:00
Dave Wysochanski
17c9975c0b Fix compile warnings / minor errors introduced recently. 2007-11-12 20:02:55 +00:00
Alasdair Kergon
6c1cdff912 Remove new mirror logs when creation fails. 2007-11-12 14:36:57 +00:00
Alasdair Kergon
79f53f569d Attempt to remove incomplete LVs with lvcreate zeroing/activation problems. 2007-11-12 13:34:14 +00:00
Alasdair Kergon
ccb85cc719 Define DM_READ_AHEAD_AUTO and DM_READ_AHEAD_NONE. 2007-11-09 16:52:36 +00:00
Alasdair Kergon
c0eff8a07f Enhance the management of readahead settings. 2007-11-09 16:51:54 +00:00
Alasdair Kergon
954626f157 Prevent lvconvert -s from using same LV as origin and snapshot. 2007-11-07 16:33:12 +00:00
Alasdair Kergon
17e7dfa4bd Add pv_mda_free and vg_mda_free fields to reports for raw text format. 2007-11-05 17:17:55 +00:00
Alasdair Kergon
971f233fb7 attempt to fix human-readable unit output when number of sectors is odd 2007-11-05 17:13:54 +00:00
Alasdair Kergon
b12bc692af fix inverted orphan test 2007-11-05 17:12:50 +00:00
Alasdair Kergon
730301b34d adjust sizes for metadata 2007-11-05 02:10:39 +00:00
Alasdair Kergon
c443bcf43c Show 'not usable' space when PV is too large for device in pvdisplay.
Ignore and fix up any excessive device size found in metadata.
2007-11-05 01:47:49 +00:00
Alasdair Kergon
b77e7eeddc Add LVM2 version to 'Generated by' comment in metadata. 2007-11-04 19:16:34 +00:00
Alasdair Kergon
031b7b57a1 fix new lvremove checks - mustn't fail when activation is disabled 2007-11-04 16:28:57 +00:00
Alasdair Kergon
5123fab525 Fix error message when fixing up PV size in lvm2 metadata (2.02.11). 2007-11-04 15:43:50 +00:00
Alasdair Kergon
705b96c6f9 Fix orphan-related locking in pvdisplay and pvs.
Fix missing VG unlocks in some pvchange error paths.
Add some missing validation of VG names.
Rename validate_vg_name() to validate_new_vg_name().
Change orphan lock to VG_ORPHANS.
Change format1 to use ORPHAN as orphan VG name.
2007-11-02 20:40:05 +00:00
Bryn M. Reeves
9ec582002b Convert pvchange, pvdisplay, pvscan to use is_orphan() 2007-11-02 14:54:40 +00:00
Bryn M. Reeves
ee79277774 Add is_orphan_vg() and change all hardcoded checks to use it. 2007-11-02 13:06:42 +00:00
Alasdair Kergon
db02dc218e explanation of md superblock location & avoid compilation warnings 2007-10-24 11:24:24 +00:00
Alasdair Kergon
b66ce1089e Detect md superblocks version 1.0, 1.1 and 1.2. 2007-10-24 00:51:05 +00:00
Alasdair Kergon
ec0e70b599 refactor dev-md.c, separating out the magic number detection 2007-10-24 00:30:30 +00:00
Dave Wysochanski
a273482f9d Remove comment about allocation of pv->vg_name. 2007-10-12 21:08:38 +00:00
Dave Wysochanski
76cf8c4cf7 Add _alloc_pv() and _free_pv() from _pv_create() code and fix error paths.
Modified original patch by Jun'ichi Nomura <j-nomura@ce.jp.nec.com>
2007-10-12 18:37:19 +00:00
Dave Wysochanski
9691ecc839 Add pv_dev_name() to access PV device name.
Patch by Jun'ichi Nomura <j-nomura@ce.jp.nec.com>
2007-10-12 14:29:32 +00:00
Dave Wysochanski
59b2a86359 Accessor functions for PV will not modify the given PV.
So we can add 'const' to it.
Patch by Jun'ichi Nomura <j-nomura@ce.jp.nec.com>
2007-10-12 14:08:10 +00:00
Dave Wysochanski
fe7cd72cff Non-functional change - refactor lv_create_empty().
Remove struct format_instance param - we can safely obtain
this from vg->fid inside the function.
2007-10-11 19:20:38 +00:00
Dave Wysochanski
f0761fc570 Non-functional change - refactor vg_add_snapshot fid parameter. 2007-10-11 18:51:21 +00:00
Alasdair Kergon
90990aa19d Handle new sysfs subsystem/block/devices directory structure. 2007-10-10 11:31:21 +00:00
Alasdair Kergon
a3d3ce82e4 Fix configure --with-dmeventd-path substitution. 2007-10-10 00:02:03 +00:00
Jim Meyering
b8e48113a3 Run tests with LVM_SYSTEM_DIR pointing to private root and /dev dirs.
This makes the tests more reproducible and helps isolate
them from any existing LVM set-up.
* test/Makefile.in (abs_builddir): Define.
(init.sh): Emit definition of abs_builddir.
* test/lvm-utils.sh (unsafe_losetup_): Keep only the portable,
iterative approach.
(dmsetup_has_dm_devdir_support_): New function.
(init_root_dir_): New function.
Invoke init_root_dir_ for all but the first test.
* test/test-lib.sh (this_test_): Adapt to test-name change.
Invoke lvm-utils.sh much later (after tmpdir creation), and
only if the current test is not being skipped.
Remove useless abs_top_srcdir definition.
Rename t0->test_dir_rand_.
* test/t-lvcreate-pvtags.sh: Skip this test if the available
version of dmsetup is not new enough.
Use global, $G_dev_, rather than hard-coded "/dev".
* test/t-lvcreate-usage.sh: Make --verbose output more useful.


Author: Jim Meyering <jim@meyering.net>
Committer: Jim Meyering <meyering@redhat.com>
2007-10-09 13:13:06 +00:00
Jim Meyering
d4b1003a97 Allow $DM_DEV_DIR envvar to override default of "/dev".
* dmsetup/dmsetup.c (DEV_PATH): Remove definition.
(parse_loop_device_name): Add parameter: dev_dir.
Declare the "dev" parameter to be "const".
Use dev_dir, not DEV_PATH.  Handle the case in which dev_dir
does not end in a "/".
(_get_abspath): Declare "path" parameter "const", to match.
(_process_losetup_switches): Add parameter: dev_dir.
Pass dev_dir to parse_loop_device_name.
(_process_switches): Add parameter: dev_dir.
Pass dev_dir to _process_losetup_switches.
(main): Set dev_dir from the DM_DEV_DIR envvar, else to "/dev".
Call dm_set_dev_dir.
* lib/libdm-common.c (dm_set_dev_dir): Rewrite to be careful
about boundary conditions, now that dev_dir may be tainted.
* man/dmsetup.8: Mention $DM_DEV_DIR.


Author: Jim Meyering <meyering@redhat.com>
2007-10-09 12:14:48 +00:00
Jim Meyering
efd83567c9 Fix the fsadm build failure without using -llvm.
* lib/misc/util.c (last_path_component): Move definition to ...
* lib/misc/last-path-component.h (last_path_component): ...here.
New file.  Make the function "static inline".
* include/.symlinks: Add last-path-component.h.
* lib/misc/util.h (last_path_component): Remove declaration.
* tools/fsadm/fsadm.c: Include "last-path-component.h".
* tools/lvmcmdline.c: Likewise.

Author: Jim Meyering <meyering@redhat.com>
2007-10-03 16:10:04 +00:00
Jim Meyering
5563f373f7 Revert last change. fsadm must not depend on -llvm.
Author: Jim Meyering <meyering@redhat.com>
2007-10-03 16:08:18 +00:00
Petr Rockai
15a36619fe a) use dmsetup version to check for dmsetup, but if it fails, set
DMSETUP=: to disable dmsetup checks (but let the script run
nevertheless); warn the user if this is the case
b) put the non-root and dmsetup warnings both at start and end of
output
2007-10-03 15:00:51 +00:00
Jim Meyering
38e54b626e Arrange for "make clean" to remove the symlink, too.
* make.tmpl.in ($(VERSIONED_SHLIB)): Move rule to...
* lib/Makefile.in ($(VERSIONED_SHLIB)): ...here, removing the
$(interface)/ prefix.
Reported by Milan Broz.

Author: Jim Meyering <meyering@redhat.com>
2007-10-03 10:48:27 +00:00
Jim Meyering
8aa30fb56a Avoid link failure when building fsadm.
* tools/fsadm/Makefile.in (LVMLIBS): Define.
(fsadm): Link with $(LVMLIBS).

Author: Nix <nix@esperi.org.uk>
2007-10-03 09:46:57 +00:00
Petr Rockai
b764becd1b Fix underquotations in lvm_dump.sh. 2007-10-02 16:09:46 +00:00
Petr Rockai
219370932e Fix a bug in lvm_dump.sh checks for lvm/dmsetup binaries quote the
invocations a bit more (although i'm fairly sure there are still
quotes missing somewhere due to the eval in log).
2007-10-02 15:48:58 +00:00
Dave Wysochanski
90afae186c Remove unused pargc parameter 2007-10-01 15:01:26 +00:00
Jim Meyering
84e49a809d doc/testing.txt: Fix typo: s/this/thing/.
Author: Jim Meyering <jim@meyering.net>
2007-09-25 08:28:57 +00:00
Dave Wysochanski
1cfb9ff46a Some const fixups for previous checkins 2007-09-24 21:30:00 +00:00
Jim Meyering
f35026c74f Avoid over-quoting in shell scripts.
Do not use "..." around the RHS of VAR= assignment,
nor on the argument of "case ... in ...".


Author: Jim Meyering <jim@meyering.net>
2007-09-24 19:19:18 +00:00
Dave Wysochanski
5f2d3da8c5 Refactor lvcreate mirror parameter validation. 2007-09-24 13:29:49 +00:00
Dave Wysochanski
4e61f32a28 Refactor lvcreate stripe parameter validation. 2007-09-24 13:25:31 +00:00
Dave Wysochanski
d7814c7011 add tests to validate lvextend %PVS 2007-09-21 21:14:25 +00:00
Jim Meyering
aa40668e84 Don't emit a trailing newline to stderr.
* tools/lvmcmdline.c (_short_usage): Remove trailing "\n".
Spotted by Alasdair G. Kergon.


Author: Jim Meyering <jim@meyering.net>
2007-09-21 18:43:55 +00:00
Jim Meyering
3767e6e96f Print --help output to stdout, not stderr.
* tools/lvmcmdline.c (_usage): Use log_print, not log_error.


Author: Jim Meyering <jim@meyering.net>
2007-09-21 18:06:56 +00:00
Jim Meyering
44976cef6c After a diagnostic, suggest --help, rather than printing all --help output.
Print just one line:
Use `COMMAND --help' for more information.
after "real" diagnostic(s), rather than all of the usage lines.
Otherwise, the 30-40+ lines of --help output could obscure the real diagnostic.


Author: Jim Meyering <jim@meyering.net>
2007-09-21 18:06:33 +00:00
Jim Meyering
eba4417947 Rename test scripts not to include the 4-digit number.
Author: Jim Meyering <jim@meyering.net>
2007-09-21 17:12:13 +00:00
Jim Meyering
c99204d370 Correct typo in comments: s/is part of the LVM2/is part of LVM2/.
Signed-off-by: Jim Meyering <jim@meyering.net>


Author: Jim Meyering <jim@meyering.net>
2007-09-21 10:16:45 +00:00
Dave Wysochanski
1bfc4335bb Add %PVS extents option to lvresize, lvextend, and lvcreate. 2007-09-20 21:39:08 +00:00
Jim Meyering
6b9c7485f1 test/t3000-lvcreate-pvtags.sh: Use better test names.
Author: Jim Meyering <jim@meyering.net>
2007-09-18 21:07:21 +00:00
Jim Meyering
737f3d78f2 * configure.in (AC_CONFIG_FILES): Remove the test/*/Makefile names
corresponding to the recently-removed directories.
* configure: Regenerate.
Reported by Dave Wysochanski.


Author: Jim Meyering <jim@meyering.net>
2007-09-18 18:26:32 +00:00
Jim Meyering
b1d5e1b5e3 test/Makefile.in (lvm-wrapper): Use $(DMDIR)/lib/, not $(DMDIR)/lib/ioctl/.
Author: Jim Meyering <jim@meyering.net>
2007-09-18 14:29:06 +00:00
Jim Meyering
8d92a5cc14 Clean-up and wording changes; add copyright notices.
* test/Makefile.in (srcdir, top_srcdir): Use @srcdir@, etc.
(top_builddir, abs_srcdir, abs_top_builddir, abs_top_srcdir): Likewise.
(so_name): Remove definition.
(.bin-dir-stamp): No longer create symlink in $(DMDIR) tree.
Prompted by suggestions from Alasdair Kergon.
* test/t1000-lvcreate-usage.sh (cleanup_): Redirect to a file,
rather than to /dev/null.
Change wording of some test titles.
Suggestions from Alasdair Kergon.

* test/Makefile.in: Add a copyright notice.
* test/lvm-utils.sh: Likewise.
* test/mkdtemp: Likewise.
* test/t0000-basic.sh: Likewise.
* test/t1000-lvcreate-usage.sh: Likewise.
* test/t3000-lvcreate-pvtags.sh: Likewise.
* test/t4000-pv-range-overflow.sh: Likewise.
* test/test-lib.sh: Likewise.


Author: Jim Meyering <jim@meyering.net>
2007-09-18 14:02:22 +00:00
Jim Meyering
fc455df92c Test how lvcreate handles its command-line options.
* test/t1000-lvcreate-usage.sh: New tests.
* test/Makefile.in (T): Add it.
Derived from test cases by Dave Wysochanski.


Author: Jim Meyering <jim@meyering.net>
2007-09-18 14:01:46 +00:00
Jim Meyering
c0076ebfa1 Clean up shared-lib support in test/.
* test/Makefile.in (so_name): Use @DMDIR@.
(.bin-dir-stamp): Create symlink only if @DMDIR@ is nonempty.
(lvm-wrapper): Emit LD_LIBRARY_PATH setting only if @DMDIR@ is nonempty.
Based on a patch from Jun'ichi Nomura.


Author: Jim Meyering <jim@meyering.net>
2007-09-18 14:01:24 +00:00
Jim Meyering
5d607aa3cd Allow relative dir name in: --with-dmdir=../device-mapper
* configure.in: Convert a relative dmdir directory name to the required
absolute form, e.g. in ./configure --with-dmdir=../device-mapper
Suggestion from Jun'ichi Nomura.
* configure: Regenerate.


Author: Jim Meyering <jim@meyering.net>
2007-09-18 14:01:08 +00:00
Jim Meyering
fa1b9a4098 Add testing framework, along with first few tests.
* Makefile.in (check): New target.
* configure.in (AC_CONFIG_FILES): Add test/Makefile.
* configure: Regenerate.
* test/.gitignore: New file.
* test/Makefile.in: New file.
* test/lvm-utils.sh: New script.
* test/mkdtemp (die, rand_bytes, mkdtemp): New script.
* test/t0000-basic.sh: New tests.
* test/t3000-lvcreate-pvtags.sh: New, failing test.
Derived from a script by Jun'ichi Nomura.
* test/t4000-pv-range-overflow.sh: New test.
* test/test-lib.sh: Testing framework, based on the one from git.


Author: Jim Meyering <jim@meyering.net>
2007-09-18 14:00:42 +00:00
Jim Meyering
c8c4dbb409 Create a symlink, e.g., libdevmapper.so.1.02, in the build dir,
alongside the .so file.  This helps build dynamically linked LVM.

* lib/Makefile.in (VERSIONED_SHLIB): Define.
* make.tmpl.in (TARGETS): Append $(VERSIONED_SHLIB).
($(VERSIONED_SHLIB)): New rule.


Author: Jim Meyering <jim@meyering.net>
2007-09-18 13:02:58 +00:00
Alasdair Kergon
16628e6cea Moved the obsolete test subdirectory to old-tests.
If you're using the CVS repository you'll need to remove it and check
it out again when we repopulate it.
2007-09-17 19:51:02 +00:00
Alasdair Kergon
7067c12991 Remove no-longer-correct restrictions on PV arg count with stripes/mirrors.
[E.g. They fail if tags or --alloc anywhere used.]
2007-09-17 17:18:37 +00:00
Alasdair Kergon
7b47e241e0 clarification 2007-09-17 17:06:31 +00:00
Alasdair Kergon
d1e46207a5 Fix strdup memory leak in str_list_dup(). 2007-09-17 16:02:46 +00:00
Jim Meyering
2a04b97cbd configure: regenerate, to remove vestige of an upcoming patch 2007-09-12 18:23:02 +00:00
Jim Meyering
e6c8ef59e0 Avoid static link failure with some SELinux libraries.
Author: Jim Meyering <jim@meyering.net>
2007-09-12 16:54:23 +00:00
Jim Meyering
d3380f41de Diagnose invalid PE values given on the pvmove command line (64-bit systems).
* tools/toollib.c (xstrtouint32): New function.
(_parse_pes): Use xstrtouint32; don't cast strtoul's unsigned
long to uint32_t.  Detect overflow.


Author: Jim Meyering <jim@meyering.net>
2007-09-11 20:12:54 +00:00
Dave Wysochanski
4ef1633969 Undo previous checkin - output format not good, info already available in other form(s) 2007-09-11 13:49:52 +00:00
Dave Wysochanski
57e593aab2 Add pvseg_free field to 'pvs' output 2007-09-10 20:05:29 +00:00
Jim Meyering
6461caacbb Include strerror string in dev_open_flags' stat failure message.
* lib/device/dev-io.c (dev_open_flags):
Use log_sys_error after failed stat to report strerror(errno).
Use a slightly different diagnostic to report mismatched device number.
2007-09-07 11:24:19 +00:00
Dave Wysochanski
e5531e2a93 Fix last checkin 2007-09-06 22:35:01 +00:00
Dave Wysochanski
329402a614 Fixup _lvresize error return codes and modularize function 2007-09-06 21:08:16 +00:00
Dave Wysochanski
4656ed462e prepare to move guts of vgrename into library function 2007-08-31 19:09:49 +00:00
Dave Wysochanski
96ddad91a9 move guts of pvresize into library 2007-08-30 20:30:41 +00:00
Dave Wysochanski
5eb40588d2 prepare to move guts of pvresize into library 2007-08-30 20:16:01 +00:00
Alasdair Kergon
58def149aa Avoid error when --corelog is provided without --mirrorlog. (2.02.28)
Correct --mirrorlog argument name in man pages (not --log).
2007-08-30 19:34:19 +00:00
Jonathan Earl Brassow
0ee5743d75 - I neglected to update this file on last check-in, which fixed
the MIRROR_NOTSYNCED flag being passed on to a linear lv when
  converting from a mirror.
2007-08-30 18:53:32 +00:00
Jonathan Earl Brassow
7c266f3e81 When mirrors are created with the --nosync option, a status flag
(MIRROR_NOTSYNCED) is added to the LVM metadata.  This flag is
not cleared when converting to linear.  Subsequently, if you
up-convert the linear to a mirror, the flag remains - even though
an up-convert will always force a complete resync.
2007-08-29 20:19:11 +00:00
Dave Wysochanski
d7ce981cd1 Modify lvremove to prompt for removal if LV active on other cluster nodes.
Add '-f' to vgremove to force removal of VG even if LVs exist.
Update vgremove man page for '-f'.
2007-08-28 16:14:49 +00:00
Alasdair Kergon
eadadf6299 post-release 2007-08-24 21:05:15 +00:00
Alasdair Kergon
8ac9fabd07 pre-release 2007-08-24 21:01:52 +00:00
Patrick Caulfield
44c2b4b281 Fix clvmd logging so you can get lvm-level debugging out of it. 2007-08-24 08:29:39 +00:00
Patrick Caulfield
4cd97611e5 Locking P_global causes a cache refresh. 2007-08-23 15:43:20 +00:00
Alasdair Kergon
da27380ab5 Introduce VG_GLOBAL lock type for vgscan/pvscan to trigger clvmd -R. 2007-08-23 15:02:26 +00:00
Patrick Caulfield
756e539661 Force a device scan after init_full_scan_done() per agk. 2007-08-23 12:44:09 +00:00
Patrick Caulfield
cde44e3172 Call init_full_scan_done() when refreshing the cache. This should fix clvmd -R. 2007-08-23 12:19:13 +00:00
Alasdair Kergon
e79a4b34b0 Change lvconvert_mirrors to use mirror segtype not striped. 2007-08-22 20:03:46 +00:00
Alasdair Kergon
e9f0bdd72c Fix lvconvert_mirrors detection of number of existing mirrors. 2007-08-22 19:32:39 +00:00
Alasdair Kergon
d080291150 Clean up numerous compiler warnings that crept in recently.
Remove several unused parameters from _allocate().
2007-08-22 14:38:18 +00:00
Jim Meyering
06c69c56ba Avoid static link failure with some SELinux libraries. 2007-08-21 20:32:29 +00:00
Alasdair Kergon
d79710ba9d Fix (C) ! 2007-08-21 19:56:18 +00:00
Alasdair Kergon
c9bc7dd0b6 Clean up mirrorlog argument processing.
Only permit --force, --verbose and --debug arguments to be repeated.
2007-08-21 19:46:36 +00:00
Alasdair Kergon
ebc26c7421 Remove obsolete dmfs code from tree and update INSTALL. 2007-08-21 18:41:58 +00:00
Dave Wysochanski
3769425f6b Move guts of vgremove into lvm library.
Include archiver.h in metadata.c as a result of prior move.
2007-08-21 17:38:20 +00:00
Alasdair Kergon
a50957443e post-release 2007-08-21 17:03:07 +00:00
Dave Wysochanski
63fa007af0 Prepare to move guts of vgremove into lvm library.
Fixup force_t.
2007-08-21 16:40:33 +00:00
Alasdair Kergon
a6a52a128b pre-release 2007-08-21 16:33:18 +00:00
Alasdair Kergon
1ad58e1121 Fix inconsistent licence notices: executables are GPLv2; libraries LGPLv2.1. 2007-08-21 16:26:07 +00:00
Alasdair Kergon
3f507a26fb Fix inconsistent licence notices: executables are GPLv2; libraries LGPLv2.1. 2007-08-20 20:55:30 +00:00
Dave Wysochanski
bfc368764a Update WHATS_NEW for last checkin 2007-08-20 17:05:49 +00:00
Dave Wysochanski
53fbce932b Move lv_remove_single() into library (lv_manip.c, metadata-exported.h).
Move yes_no_prompt() into library (display.c, display.h).
Fixup includes as a result of movement of prior two functions.
Fixup force_t enum to be more descriptive.
2007-08-20 17:04:53 +00:00
Dave Wysochanski
a94195c6cd Prepare to move guts of lvremove into lvm library 2007-08-20 16:16:54 +00:00
Jim Meyering
626c6d1124 factor out some duplication -- mostly I/O redirection 2007-08-20 12:06:35 +00:00
Patrick Caulfield
471ab92bbb Allow clvmd debug to be turned on in a running daemon using clvmd -d
You can do with cluster-wide too, by adding -C
2007-08-17 11:51:23 +00:00
Alasdair Kergon
fbccd12924 Update to use autoconf 2.61, while still supporting 2.57. 2007-08-14 19:11:31 +00:00
Dave Wysochanski
e5928bbaea Remove unneeded WHATS_NEW entry 2007-08-10 14:24:43 +00:00
Dave Wysochanski
3c1597bc67 Fix "lvconvert -s" from always failing with argument error message.
Patch by Jun'ichi Nomura <j-nomura@ce.jp.nec.com>.
2007-08-10 13:33:49 +00:00
Jonathan Earl Brassow
295019815e - change new log_ARG variable to more explicit mirrorlog_ARG. 2007-08-09 21:25:08 +00:00
Jonathan Earl Brassow
654a391250 minor updates to the lvcreate/lvconvert man pages.
- put back reference to '--corelog'.  It now says that it
is the same as '--log core'.
- other minor touches
2007-08-09 20:43:29 +00:00
Patrick Caulfield
9ee1465d3c Add more cluster/clvmd information to lvmdump 2007-08-09 09:53:33 +00:00
Dave Wysochanski
52197cf4d2 Remove extra checks for sub LV renaming.
Patch by Jun'ichi Nomura <j-nomura@ce.jp.nec.com>.
2007-08-08 18:00:36 +00:00
Dave Wysochanski
cfbb2afac5 A few more cleanups for lvrename of mirrors checkin:
* add struct lv_names for old/new names
* replace lv->status & MIRROR checks with lv_is_visible()
2007-08-07 18:55:38 +00:00
Dave Wysochanski
8f154f65f9 Some simple fixups for last checkin:
* remove "_" from "return_0"
* improve some naming and terminology
* add 'const'
2007-08-07 16:57:09 +00:00
Jim Meyering
7454664997 Add "const" attributes where possible: first cut. 2007-08-07 09:06:05 +00:00
Dave Wysochanski
3393b7aedd Update a few comments 2007-08-06 21:11:27 +00:00
Dave Wysochanski
133ccc95b5 Add entry for last checkin of lvrename mirror support 2007-08-06 20:38:41 +00:00
Dave Wysochanski
c392ff1cd3 Add support for renaming mirrored LVs.
Patch by Jun'ichi Nomura <j-nomura@ce.jp.nec.com>
2007-08-06 20:35:48 +00:00
Jim Meyering
30a0f831a5 For consistency, rename local variable: s/newname/new_name/g. 2007-08-06 14:57:48 +00:00
Alasdair Kergon
541ea4dc63 improve changelog 2007-08-06 13:09:46 +00:00
Jim Meyering
afc5e0e3e5 Make lv_rename's interface "const correct".
* lib/metadata/lv_manip.c (lv_rename): Make char* param "const".
* lib/metadata/metadata-exported.h: Update prototype, too.
2007-08-06 09:04:21 +00:00
Alasdair Kergon
bcb31df10d Use NULL not 0.
Remove worthless comment.
2007-08-05 00:13:02 +00:00
Dave Wysochanski
2192c4e269 Factor out core of lvrename to lv_rename library function.
Patch by Jun'ichi Nomura <j-nomura@ce.jp.nec.com>
2007-08-03 21:22:10 +00:00
Petr Rockai
eec17858c4 Fix a possible segfault in libdevmapper-event. Thanks to Brian J. Wood
for noticing this.
2007-08-02 22:31:59 +00:00
Jonathan Earl Brassow
6d696706be This patch changes the arguments that specify the mirror
log type.  Previously, we had a '--corelog' argument that
would change the default type from 'disk' to 'core'.  I
think that creates too much confusion - especially when
doing conversions on mirrors.

The new argument '--log' takes either "disk" or "core"
as a parameter.  This could be expanded in the future
for additional logging types as well.

Examples:
# Creating a 2-way mirror
$> lvcreate -m1 ... # implicitly use default disk logging
$> lvcreate -m1 --log disk ... # explicit disk logging
$> lvcreate -m1 --log core ... # specify core logging
$> lvcreate -m1 --corelog ... # old way still works

# Conversion examples
$> lvconvert --log core ... # convert to core logging
$> lvconvert --log disk ... # convert to disk logging
$> lvconvert -mX --corelog ... # old way still works
$> lvconvert -mX ... # old way of converting to disk logging still works

Changes are reflected in the man pages.
2007-08-01 21:01:06 +00:00
Jonathan Earl Brassow
8cd88b6051 - cleanup excessive indentation in tools/lvconvert.c:lvconvert_mirrors 2007-08-01 20:54:28 +00:00
Jonathan Earl Brassow
9dbf53fdb9 lib/activate/activate.c:_lv_activate tries to monitor a device
regardless of whether it was successfully activated.  Now fixed
to only monitor if it was successfully activated.
2007-08-01 20:29:07 +00:00
Jim Meyering
38b6963c8b Don't leak a file descriptor in fcntl_lock_file(), when fcntl fails. 2007-07-28 15:20:36 +00:00
Jim Meyering
7b6248983d Remove create_dir function; use now-equivalent dm_create_dir instead.
* lib/misc/lvm-file.c (_create_dir_recursive, create_dir): Remove functions.
* lib/misc/lvm-file.h (create_dir): Remove declaration.
* lib/commands/toolcontext.c (create_toolcontext): s/create_dir/dm_create_dir/
* lib/format_text/archiver.c (archive, backup): Likewise.
* lib/format_text/format-text.c (_add_dir): Likewise.
* lib/locking/file_locking.c (init_file_locking): Likewise.
Patch by Jun'ichi Nomura.
2007-07-28 12:26:21 +00:00
Jim Meyering
4d418dee0e Export dm_create_dir (was create_dir) to help fix LVM2 link error
* lib/libdm-file.c (dm_create_dir): Rename from create_dir.
* lib/libdevmapper.h (dm_create_dir): Declare.
* lib/.exported_symbols: Add dm_create_dir.
* lib/ioctl/libdm-iface.c (_create_control): Update sole use.
Patch by Jun'ichi Nomura.  Details in
http://www.redhat.com/archives/lvm-devel/2007-July/msg00040.html
2007-07-28 10:48:36 +00:00
Jim Meyering
06fe319347 Make the libdevmapper version of create_dir equivalent to the LVM2 one.
(_create_dir_recursive): Refrain from logging a mkdir failure due to EROFS.
Patch by Jun'ichi Nomura.
2007-07-28 10:27:34 +00:00
Jim Meyering
9dd7e3fb24 Introduce log_sys_* macros from LVM2.
Convert existing "<string>: <function> failed: <strerror>" type messages
to use this macro.  Patch by Jun'ichi Nomura.
2007-07-28 10:23:02 +00:00
Alasdair Kergon
d5a46396b0 Add ps3disk devices. 2007-07-26 13:28:32 +00:00
Jim Meyering
5e84cb560d Detect stream write failure reliably; new fn: lvm_fclose; use dm_fclose
* lib/misc/lvm-file.c (lvm_fclose): New function.
* lib/misc/lvm-file.h (lvm_fclose): Declare it.
* lib/config/config.c (write_config_file): Use the new function to detect
and diagnose unlikely write failure.
* lib/filters/filter-persistent.c (persistent_filter_dump): Likewise.
* lib/format_text/archive.c (archive_vg): Likewise.
* lib/format_text/format-text.c (_vg_write_file): Likewise.
* lib/log/log.c (fin_log): Similar, but use dm_fclose directly.
Include "\n" at end of each fprintf format string.
2007-07-24 17:48:08 +00:00
Milan Broz
756c6f8560 Fix clvmd if compiled with gulm support. (2.02.26) 2007-07-24 15:35:11 +00:00
Jim Meyering
6fa6ce35da libdevmapper, dmeventd: be paranoid about detecting write failure
* dmeventd/dmeventd.c (_set_oom_adj): When writing to /proc/self/oom_adj,
detect failure even if it's hidden behind ferror.  [Using dm_fclose's
extra ferror test here is probably not needed, since the amount written
is nowhere near BUFSIZ, but use it regardless, for consistency. ]
* lib/fs/libdevmapper.c (do_suspend): Detect fclose failure when
writing to suspend.
2007-07-24 14:16:48 +00:00
Jim Meyering
b14b97599d dm_fclose: new function
* lib/libdevmapper.h: Declare it.
* lib/libdm-file.c (dm_fclose): Define it.
* lib/.exported_symbols: Add dm_fclose.
2007-07-24 14:15:45 +00:00
Dave Wysochanski
db6f60d6fc Trivial fix to lvdisplay man pg to recommend lvs 2007-07-24 11:29:55 +00:00
Dave Wysochanski
25c348d7c8 Trivial fix to lvdisplay man pg to correct volume size units 2007-07-24 10:58:01 +00:00
Dave Wysochanski
2e4bf8b034 Update lvconvert and lvrename to use vg_lock_and_read 2007-07-23 22:20:42 +00:00
Dave Wysochanski
c1490e2f7b Fix error introduced with previous checkin 2007-07-23 21:10:36 +00:00
Dave Wysochanski
b004fe9556 Add CORRECT_INCONSISTENT and FAIL_INCONSISTENT flags to vg_lock_and_read 2007-07-23 21:03:42 +00:00
Dave Wysochanski
67142ad046 Add vg_lock_and_read() external library function. 2007-07-23 17:27:55 +00:00
Milan Broz
3c3ec06b12 Fix loading of persistent cache if cache_dir is used. (2.02.23)
Move lstat warning in _compare_paths to verbose output only.
2007-07-23 10:45:49 +00:00
Milan Broz
5b5caa8a16 Fix compilation warning in util.c. 2007-07-23 10:41:19 +00:00
Jim Meyering
b2cba098bb Eliminate uses of strdup+basename. Use last_path_component instead.
* lib/misc/util.c, lib/misc/util.h (last_path_component): New files.
* lib/Makefile.in (SOURCES): Add misc/util.c.
* lib/misc/lib.h: Include "util.h".
* tools/fsadm/fsadm.c: Include "util.h". (_usage): Use last_path_component,
not basename.
* tools/lvmcmdline.c (_find_command, lvm2_main): Likewise.
* include/.symlinks: Add lib/misc/util.h.
2007-07-20 15:48:39 +00:00
Jim Meyering
1ec0d47f10 Use gcc's printf attribute wherever possible.
* daemons/clvmd/clvmd.h (debuglog): Add __attribute__((printf)).
* lib/config/config.c (_line_append): Likewise.
* lib/misc/lvm-string.h (emit_to_buffer): Likewise.
2007-07-20 15:38:19 +00:00
Jim Meyering
f232606ec7 In _line_append, use "sizeof buf - 1" rather than equivalent "4095"
* lib/config/config.c:
2007-07-20 15:26:39 +00:00
Jim Meyering
fa28cea152 Introduce is_same_inode macro, now including a comparison of st_dev.
* lib/misc/lvm-file.h (is_same_inode): Define.
* lib/filters/filter-persistent.c (persistent_filter_dump): Use is_same_inode
in place of a direct st_ino-only comparison.
* lib/locking/file_locking.c (_release_lock, _lock_file): Likewise.
2007-07-20 15:22:46 +00:00
Jim Meyering
c8da1647a1 Don't leak a file descriptor in _lock_file when flock fails.
* lib/locking/file_locking.c (_lock_file): Close fd upon flock failure.
2007-07-20 12:12:52 +00:00
Patrick Caulfield
505a0a8718 Add SUN's LDOM virtual block device to filters
Thanks to Fabio Massimo Di Nitto
2007-07-19 07:06:47 +00:00
Alasdair Kergon
10d3496a17 Split metadata-external.h out from metadata.h for the tools to use. 2007-07-18 15:38:58 +00:00
Alasdair Kergon
a13c755370 post-release 2007-07-17 20:53:51 +00:00
Alasdair Kergon
62f9996fd7 pre-release 2007-07-17 20:45:17 +00:00
Milan Broz
edbcd8a1b2 Fix snapshot cow area deactivation if origin is not active. (2.02.13) 2007-07-17 16:13:12 +00:00
Alasdair Kergon
a5308d1689 Fix configure libdevmapper.h check when --with-dmdir is used. 2007-07-13 17:08:00 +00:00
Alasdair Kergon
cbfe6e8fcc post-release 2007-07-13 16:10:24 +00:00
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
Alasdair Kergon
34a74e81e3 pre-release 2007-01-25 23:36:59 +00:00
Alasdair Kergon
cb120ddb15 dmeventd mirror sets ignore_suspended_devices and avoids scanning mirrors. 2007-01-25 23:32:29 +00:00
Alasdair Kergon
f9ee4395b0 also ignore mirrors 2007-01-25 23:03:48 +00:00
Alasdair Kergon
71f06d51ed Add devices/ignore_suspended_devices to ignore suspended dm devices. 2007-01-25 21:22:30 +00:00
Alasdair Kergon
217f70952f don't remove libdm-common.h any more 2007-01-25 15:45:10 +00:00
Alasdair Kergon
f813d41a76 Add some missing close() and fclose() return code checks.
Fix exit statuses of reporting tools (2.02.19).
2007-01-25 14:37:48 +00:00
Alasdair Kergon
d851289d8a Add some missing close() and fclose() return value checks. 2007-01-25 14:16:20 +00:00
Alasdair Kergon
b115b8a2ea Add init script for dmeventd monitoring. 2007-01-24 23:44:43 +00:00
Alasdair Kergon
d0f7067471 lvm.static no longer interacts with dmeventd unless explicitly asked to. 2007-01-24 23:43:27 +00:00
Alasdair Kergon
be5b4c38a7 fix earlier checkin 2007-01-24 22:06:11 +00:00
Alasdair Kergon
d6d597e3dd Migrate dmsetup column-based output over to new libdevmapper report framework. 2007-01-24 18:09:07 +00:00
Alasdair Kergon
84e348fade Add field definitions to report help text.
Remove unnecessary cmd arg from target_*monitor_events().
2007-01-24 16:51:24 +00:00
Alasdair Kergon
910054657e Adjust report field help description layout. 2007-01-24 16:41:33 +00:00
Alasdair Kergon
8357a11249 fix earlier checkin 2007-01-23 23:58:55 +00:00
Alasdair Kergon
9b021ba057 Add descriptions to reporting field definitions. 2007-01-23 19:18:52 +00:00
Alasdair Kergon
317e588efd Add private variable to dmeventd shared library interface. 2007-01-23 17:40:40 +00:00
Alasdair Kergon
b1d32a03c7 add a dso-private variable to dmeventd interface
more inline docn
2007-01-23 17:38:39 +00:00
Alasdair Kergon
ee6e6529ee Long-lived processes write out persistent dev cache in refresh_toolcontext(). 2007-01-23 16:03:54 +00:00
Alasdair Kergon
9d944d6cf9 Fix refresh_toolcontext() always to wipe persistent device filter cache.
Add is_long_lived to toolcontext.
2007-01-23 15:58:06 +00:00
Alasdair Kergon
13635d281a Add --clustered to man pages. 2007-01-23 13:08:34 +00:00
Alasdair Kergon
2493c46970 Streamline dm_report_field_* interface. 2007-01-22 15:07:21 +00:00
344 changed files with 29679 additions and 16980 deletions

View File

@@ -1,14 +1,14 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
GNU LIBRARY GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1991 Free Software Foundation, Inc.
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the library GPL. It is
numbered 2 because it goes with version 2 of the ordinary GPL.]
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
@@ -17,97 +17,109 @@ freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Library General Public License, applies to some
specially designated Free Software Foundation software, and to any
other libraries whose authors decide to use it. You can use it for
your libraries, too.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if
you distribute copies of the library, or if you modify it.
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link a program with the library, you must provide
complete object files to the recipients so that they can relink them
with the library, after making changes to the library and recompiling
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
Our method of protecting your rights has two steps: (1) copyright
the library, and (2) offer you this license which gives you legal
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
Also, for each distributor's protection, we want to make certain
that everyone understands that there is no warranty for this free
library. If the library is modified by someone else and passed on, we
want its recipients to know that what they have is not the original
version, so that any problems introduced by others will not reflect on
the original authors' reputations.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that companies distributing free
software will individually obtain patent licenses, thus in effect
transforming the program into proprietary software. To prevent this,
we have made it clear that any patent must be licensed for everyone's
free use or not licensed at all.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the ordinary
GNU General Public License, which was designed for utility programs. This
license, the GNU Library General Public License, applies to certain
designated libraries. This license is quite different from the ordinary
one; be sure to read it in full, and don't assume that anything in it is
the same as in the ordinary license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
The reason we have a separate public license for some libraries is that
they blur the distinction we usually make between modifying or adding to a
program and simply using it. Linking a program with a library, without
changing the library, is in some sense simply using the library, and is
analogous to running a utility program or application program. However, in
a textual and legal sense, the linked executable is a combined work, a
derivative of the original library, and the ordinary General Public License
treats it as such.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
Because of this blurred distinction, using the ordinary General
Public License for libraries did not effectively promote software
sharing, because most developers did not use the libraries. We
concluded that weaker conditions might promote sharing better.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
However, unrestricted linking of non-free programs would deprive the
users of those programs of all benefit from the free status of the
libraries themselves. This Library General Public License is intended to
permit developers of non-free programs to use free libraries, while
preserving your freedom as a user of such programs to change the free
libraries that are incorporated in them. (We have not seen how to achieve
this as regards changes in header files, but we have achieved it as regards
changes in the actual functions of the Library.) The hope is that this
will lead to faster development of free libraries.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, while the latter only
works together with the library.
Note that it is possible for a library to be covered by the ordinary
General Public License rather than by this special one.
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LIBRARY GENERAL PUBLIC LICENSE
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library which
contains a notice placed by the copyright holder or other authorized
party saying it may be distributed under the terms of this Library
General Public License (also called "this License"). Each licensee is
addressed as "you".
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
@@ -256,7 +268,7 @@ distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also compile or
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
@@ -283,23 +295,31 @@ of these things:
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Accompany the work with a written offer, valid for at
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
c) If distribution of the work is made by offering access to copy
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
d) Verify that the user has already received a copy of these
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the source code distributed need not include anything that is normally
distributed (in either source or binary form) with the major
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
@@ -348,7 +368,7 @@ Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
@@ -391,7 +411,7 @@ excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Library General Public License from time to time.
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
@@ -437,7 +457,7 @@ DAMAGES.
END OF TERMS AND CONDITIONS
Appendix: How to Apply These Terms to Your New Libraries
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
@@ -454,19 +474,18 @@ convey the exclusion of warranty; and each file should have at least the
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
Lesser General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
@@ -481,3 +500,5 @@ necessary. Here is a sample; alter the names:
Ty Coon, President of Vice
That's all there is to it!

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 the LVM2.
# 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
@@ -68,3 +68,6 @@ cscope.out: tools
@CSCOPE_CMD@ -b -R
all: cscope.out
endif
check: all
$(MAKE) -C test all

View File

@@ -1 +1 @@
2.02.20-cvs (2007-01-17)
2.02.36-cvs (2008-04-15)

375
WHATS_NEW
View File

@@ -1,8 +1,362 @@
Version 2.02.20 -
Version 2.02.36 -
=================================
Fix lvconvert -m0 allocatable space check.
Version 2.02.35 - 15th April 2008
=================================
Drop cached VG metadata before and after committing changes to it.
Rename P_global to P_#global.
Don't attempt remote metadata backups of non-clustered VGs. (2.02.29)
Don't store fid in VG metadata cache to avoid clvmd segfault. (2.02.34)
Update vgsplit tests to verify loosening of active LV restriction.
Update vgsplit to only restrict split with active LVs involved in split.
Add lv_is_active() to determine whether an lv is active.
Version 2.02.34 - 10th April 2008
=================================
Improve preferred_names lvm.conf example.
Fix vgdisplay 'Cur LV' field to match lvdisplay output.
Fix lv_count report field to exclude hidden LVs.
Add vg_is_clustered() helper function.
Fix vgsplit to only move hidden 'snapshotN' LVs when necessary.
Update vgsplit tests for lvnames on the cmdline.
Update vgsplit man page to reflect lvnames on the cmdline.
Update vgsplit to take "-n LogicalVolumeName" on the cmdline.
Use clustered mirror log with pvmove in clustered VGs, if available.
Fix some pvmove error status codes.
Fix vgsplit error paths to release vg_to lock.
Indicate whether or not VG is clustered in vgcreate log message.
Mention default --clustered setting in vgcreate man page.
Add config file overrides to clvmd when it reads the active LVs list.
Fix vgreduce to use vg_split_mdas to check sufficient mdas remain.
Add (empty) orphan VGs to lvmcache during initialisation.
Fix orphan VG name used for format_pool.
Create a fid for internal orphan VGs.
Update lvmcache VG lock state for all locking types now.
Fix output if overriding command_names on cmdline.
Add detection of clustered mirror log capability.
Add check to vg_commit() ensuring VG lock held before writing new VG metadata.
Add validation of LV name to pvmove -n.
Make clvmd refresh the context correctly when lvm.conf is updated.
Add some basic internal VG lock validation.
Add per-command flags to control which commands use the VG metadata cache.
Fix vgsplit locking of new VG (2.02.30).
Avoid erroneous vgsplit error message for new VG. (2.02.29)
Suppress duplicate message when lvresize fails because of invalid vgname.
Cache VG metadata internally while VG lock is held.
Fix redundant lvresize message if vg doesn't exist.
Fix another allocation bug with clvmd and large node IDs.
Add find_lv_in_lv_list() and find_pv_in_pv_list().
Fix uninitialised variable in clvmd that could cause odd hangs.
Add vgmerge tests.
Add pvseg_is_allocated() for identifying a PV segment allocated to a LV.
Add list_move() for moving elements from one list to another.
Add 'is_reserved_lvname()' for identifying hidden LVs.
Correct command name in lvmdiskscan man page.
clvmd no longer crashes if it sees nodeids over 50.
Fix potential deadlock in clvmd thread handling.
Refactor text format initialisation into _init_text_import.
Escape double quotes and backslashes in external metadata and config data.
Add functions for escaping double quotes in strings.
Rename count_chars_len to count_chars.
Use return_0 in a couple more places.
Correct a function name typo in _line_append error message.
Include limits.h in clvmd so it compiles with newer headers.
Add VirtIO disks (virtblk) to filters.
Fix resetting of MIRROR_IMAGE and VISIBLE_LV after removal of LV. (2.02.30)
Fix remove_layer_from_lv to empty the LV before removing it. (2.02.30)
Add missing no-longer-used segs_using_this_lv test to check_lv_segments.
Remove redundant non-NULL tests before calling free in clvmd.c.
Avoid a compiler warning: make is_orphan's parameter const.
Fix lvconvert detection of mirror conversion in progress. (2.02.30)
Avoid automatic lvconvert polldaemon invocation when -R specified. (2.02.30)
Fix 'pvs -a' to detect VGs of PVs without metadata areas.
Divide up internal orphan volume group by format type.
Update usage message for clvmd.
Fix clvmd man page not to print <br> and clarified debug options.
Fix lvresize to support /dev/mapper prefix in the LV name.
Fix unfilled parameter passed to fsadm from lvresize.
Update fsadm to call lvresize if the partition size differs (with option -l).
Fix fsadm to support VG/LV names.
Version 2.02.33 - 31st January 2008
===================================
Fix mirror log name construction during lvconvert. (2.02.30)
Make monitor_dev_for_events recurse through the stack of LVs.
Clean up some more compiler warnings.
Some whitespace tidy-ups.
Use stack return macros throughout.
Rely upon internally-cached PV labels while corresponding VG lock is held.
Version 2.02.32 - 29th January 2008
===================================
Fix two check_lv_segments error messages to show whole segment.
Refactor mirror log attachment code.
Fix internal metadata corruption in lvchange --resync. (2.02.30)
Fix new parameter validation in vgsplit and test mode. (2.02.30)
Remove redundant cnxman-socket.h file from clvmd directory.
Fix pvs, vgs, lvs error exit status on some error paths.
Version 2.02.31 - 19th January 2008
===================================
Fix lvcreate --nosync not to wait for non-happening sync. (2.02.30)
Add very_verbose lvconvert messages.
Avoid readahead error message with default setting of lvcreate -M1. (2.02.29)
Version 2.02.30 - 17th January 2008
===================================
Set default readahead to twice maximium stripe size.
Reinstate VG extent size and stripe size defaults (halved). (2.02.29)
Add lists of stacked LV segments using each LV to the internal metadata.
Change vgsplit -l (for unimplemented --list) into --maxlogicalvolumes.
Fix process_all_pvs to detect non-orphans with no MDAs correctly.
Don't use block_on_error with mirror targets version 1.12 and above.
Update vgsplit to accept vgcreate options when new VG is destination.
Update vgsplit to accept existing VG as destination.
lvconvert waits for completion of initial sync by default.
Refactor vgcreate for parameter validation and add tests.
Add new convert_lv field to lvs output.
Print warning when lvm tools are running as non-root.
Add snapshot dmeventd library (enables dmeventd snapshot monitoring).
Prevent pvcreate from overwriting MDA-less PVs belonging to active VGs.
Fix a segfault if using pvs with --all argument. (2.02.29)
Update --uuid argument description in man pages.
Fix vgreduce PV list processing not to process every PV in the VG. (2.02.29)
Extend lvconvert to use polldaemon.
Add support for stacked mirrors.
Major restructuring of pvmove and lvconvert layer manipulation code.
Replace tools/fsadm with scripts/fsadm.sh.
Append fields to report/pvsegs_cols_verbose.
Permit LV segment fields with PV segment reports.
Add seg_start_pe and seg_pe_ranges to reports.
Version 2.02.29 - 5th December 2007
===================================
Make clvmd backup vg metadata on remote nodes.
Refactor pvmove allocation code.
Decode cluster locking state in log message.
Change file locking state messages from debug to very verbose.
Fix --addtag to drop @ prefix from name.
Stop clvmd going haywire if a pre_function fails.
Convert some vg_reads into vg_lock_and_reads.
Avoid nested vg_reads when processing PVs in VGs and fix associated locking.
Accept sizes with --readahead argument.
Store size arguments as sectors internally.
Attempt to remove incomplete LVs with lvcreate zeroing/activation problems.
Add read_ahead activation code.
Add activation/readahead configuration option and FMT_RESTRICTED_READAHEAD.
Extend readahead arg to accept "auto" and "none".
Add lv_read_ahead and lv_kernel_read_ahead fields to reports and lvdisplay.
Prevent lvconvert -s from using same LV as origin and snapshot.
Fix human-readable output of odd numbers of sectors.
Add pv_mda_free and vg_mda_free fields to reports for raw text format.
Add LVM2 version to 'Generated by' comment in metadata.
Show 'not usable' space when PV is too large for device in pvdisplay.
Ignore and fix up any excessive device size found in metadata.
Fix error message when fixing up PV size in lvm2 metadata (2.02.11).
Fix orphan-related locking in pvdisplay and pvs.
Fix missing VG unlocks in some pvchange error paths.
Add some missing validation of VG names.
Rename validate_vg_name() to validate_new_vg_name().
Change orphan lock to VG_ORPHANS.
Change format1 to use ORPHAN as orphan VG name.
Convert pvchange, pvdisplay, pvscan to use is_orphan()
Add is_orphan_vg() and change all hard-coded checks to use it.
Detect md superblocks version 1.0, 1.1 and 1.2.
Add _alloc_pv() and _free_pv() from _pv_create() code and fix error paths.
Add pv_dev_name() to access PV device name.
Add const attributes to pv accessor functions.
Refactor vg_add_snapshot() and lv_create_empty().
Handle new sysfs subsystem/block/devices directory structure.
Run test with LVM_SYSTEM_DIR pointing to private root and /dev dirs.
Fix a bug in lvm_dump.sh checks for lvm/dmsetup binaries.
Fix underquotations in lvm_dump.sh.
Refactor lvcreate stripe and mirror parameter validation.
Print --help output to stdout, not stderr.
After a cmdline processing error, don't print help text but suggest --help.
Add %PVS extents option to lvresize, lvextend, and lvcreate.
Add 'make check' to run tests in new subdirectory 'test'.
Moved the obsolete test subdirectory to old-tests.
Cope with relative paths in configure --with-dmdir.
Remove no-longer-correct restrictions on PV arg count with stripes/mirrors.
Fix strdup memory leak in str_list_dup().
Link with -lpthread when static SELinux libraries require that.
Detect command line PE values that exceed their 32-bit range.
Include strerror string in dev_open_flags' stat failure message.
Move guts of pvresize into library.
Avoid error when --corelog is provided without --mirrorlog. (2.02.28)
Correct --mirrorlog argument name in man pages (not --log).
Clear MIRROR_NOTSYNCED LV flag when converting from mirror to linear.
Modify lvremove to prompt for removal if LV active on other cluster nodes.
Add '-f' to vgremove to force removal of VG even if LVs exist.
Version 2.02.28 - 24th August 2007
==================================
Fix clvmd logging so you can get lvm-level debugging out of it.
Introduce VG_GLOBAL lock type for vgscan/pvscan to trigger clvmd -R.
Change locking_flags from int to uint32_t.
Fix clvmd -R, so it fully refreshes the caches.
Change lvconvert_mirrors to use mirror segtype not striped.
Fix lvconvert_mirrors detection of number of existing mirrors.
Clean up numerous compiler warnings that appeared in recent releases.
Remove several unused parameters from _allocate().
Only permit --force, --verbose and --debug arguments to be repeated.
Fix inconsistent licence notices: executables are GPLv2; libraries LGPLv2.1.
Move guts of vgremove and lvremove into library, including yes_no_prompt.
Allow clvmd debug to be turned on in a running daemon using clvmd -d [-C].
Update to use autoconf 2.61, while still supporting 2.57.
Add more cluster info to lvmdump.
Add further const attributes throughout.
Add support for renaming mirrored LVs.
Factor out core of lvrename() to library function.
Add --mirrorlog argument to specify log type for mirrors.
Don't attempt to monitor devices if their creation failed in _lv_activate.
Don't leak a file descriptor in fcntl_lock_file() when fcntl fails.
Replace create_dir with dm_create_dir.
Detect stream write failure reliably with lvm_fclose using dm_fclose.
Fix clvmd if compiled with gulm support. (2.02.26)
Fix lvdisplay man page to say LV size is reported in sectors, not KB.
Add vg_lock_and_read() external library function.
Fix loading of persistent cache if cache_dir is used. (2.02.23)
Reduce _compare_paths lstat error message from log_error to log_very_verbose.
Create util.h with last_path_component replacing strdup + basename.
Use gcc's printf attribute wherever possible.
In _line_append, use "sizeof buf - 1" rather than equivalent "4095".
Introduce is_same_inode macro, now including a comparison of st_dev.
Don't leak a file descriptor in _lock_file() when flock fails.
Add SUN's LDOM virtual block device (vdisk) and ps3disk to filters.
Split metadata-external.h out from metadata.h for the tools to use.
Version 2.02.27 - 17th July 2007
================================
Fix snapshot cow area deactivation if origin is not active. (2.02.13)
Fix configure libdevmapper.h check when --with-dmdir is used.
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.
Add devices/ignore_suspended_devices to ignore suspended dm devices.
Add some missing close() and fclose() return code checks.
Fix exit statuses of reporting tools (2.02.19).
Add init script for dmeventd monitoring.
lvm.static no longer interacts with dmeventd unless explicitly asked to.
Add field definitions to report help text.
Remove unnecessary cmd arg from target_*monitor_events().
Add private variable to dmeventd shared library interface.
Long-lived processes write out persistent dev cache in refresh_toolcontext().
Fix refresh_toolcontext() always to wipe persistent device filter cache.
Add is_long_lived to toolcontext.
Add --clustered to man pages.
Streamline dm_report_field_* interface.
Change remaining dmeventd terminology 'register' to 'monitor'.
Update reporting man pages.
No longer necessary to specify alignment for report fields.
No longer necessary to specify alignment type for report fields.
Version 2.02.19 - 17th January 2007
===================================
@@ -798,7 +1152,7 @@ Some bug fixes & minor enhancements, including:
You need to update libdevmapper before using 'vgmknodes' or 'vgscan --mknodes'.
If your root filesystem is on an LV, you should run one of those two
commands to fix up the special files in /dev in your real root filesystem
commands to fix up the special files in /dev in your real root filesystem
after finishing with your initrd. Also, remember you can use
'vgchange --ignorelockingfailure' on your initrd if the tool fails because
it can't write a lock file to a read-only filesystem.
@@ -808,7 +1162,7 @@ Wednesday 30th April 2003
A pvmove implementation is now available for the new metadata format.
When running a command that allocates space (e.g. lvcreate), you can now
restrict not only which disk(s) may be used but also the Physical Extents
restrict not only which disk(s) may be used but also the Physical Extents
on those disks. e.g. lvcreate -L 10 vg1 /dev/hda6:1000-2000:3000-4000
@@ -820,12 +1174,12 @@ The new format of LVM metadata is ready for you to test!
It's more compact and supports transactional changes and replication.
Should things go wrong on a system, it's human-readable (and editable).
Please report any problems you find to the mailing list,
Please report any problems you find to the mailing list,
linux-lvm@sistina.com. The software has NOT yet been thoroughly
tested and so quite possibly there'll still be some bugs in it.
Be aware of the disclaimer in the COPYING file.
While testing, we recommend turning logging on in the configuration file
While testing, we recommend turning logging on in the configuration file
to provide us with diagnostic information:
log {
file="/tmp/lvm2.log"
@@ -836,7 +1190,7 @@ to provide us with diagnostic information:
You should schedule regular backups of your configuration file and
metadata backups and archives (normally kept under /etc/lvm).
Please read docs/example.conf and "man lvm.conf" to find out more about
Please read docs/example.conf and "man lvm.conf" to find out more about
the configuration file.
To convert an existing volume group called vg1 to the new format using
@@ -865,7 +1219,7 @@ first segment could have 3 stripes while the second segment has just 2.
LVM2 maintains a backup of the current metadata for each volume group
in /etc/lvm/backup, and puts copies of previous versions in
/etc/lvm/archive. "vgcfgbackup" and "vgcfgrestore" can be used to
create and restore from these files. If you fully understand what
create and restore from these files. If you fully understand what
you're doing, metadata can be changed by editing a copy of a current
backup file and using vgcfgrestore to reload it.
@@ -882,8 +1236,8 @@ What's not finished?
The internal cache. If you turn on debugging output you'll see lots of
repeated messages, many of which will eventually get optimised out.
--test sometimes causes a command to fail (e.g. vgconvert --test) even
though the real command would work: again, fixing this is waiting for
--test sometimes causes a command to fail (e.g. vgconvert --test) even
though the real command would work: again, fixing this is waiting for
the work on the cache.
Several of the tools do not yet contain the logic to handle full
@@ -896,4 +1250,3 @@ Display output. Some metadata information cannot yet be displayed.
Recovery tools to salvage "lost" metadata directly from the disks:
but we hope the new format will mean such tools are hardly ever needed!

View File

@@ -1,5 +1,82 @@
Version 1.02.16 -
Version 1.02.26 -
=================================
Add field name prefix option to reporting functions.
Calculate string size within dm_pool_grow_object.
Version 1.02.25 - 10th April 2008
=================================
Remove redundant if-before-free tests.
Use log_warn for reporting field help text instead of log_print.
Change cluster mirror log type name (s/clustered_/clustered-/)
Version 1.02.24 - 20th December 2007
====================================
Fix deptree to pass new name to _resume_node after a rename.
Suppress other node operations if node is deleted.
Add node operation stack debug messages.
Report error when empty device name passed to readahead functions.
Fix minimum readahead debug message.
Version 1.02.23 - 5th December 2007
===================================
Update dm-ioctl.h after removal of compat code.
Add readahead support to libdevmapper and dmsetup.
Fix double free in a libdevmapper-event error path.
Fix configure --with-dmeventd-path substitution.
Allow a DM_DEV_DIR environment variable to override /dev in dmsetup.
Create a libdevmapper.so.$LIB_VERSION symlink within the build tree.
Avoid static link failure with some SELinux libraries that require libpthread.
Remove obsolete dmfs code from tree and update INSTALL.
Version 1.02.22 - 21st August 2007
==================================
Fix inconsistent licence notices: executables are GPLv2; libraries LGPLv2.1.
Update to use autoconf 2.61, while still supporting 2.57.
Avoid repeated dm_task free on some dm_event_get_registered_device errors.
Introduce log_sys_* macros from LVM2.
Export dm_fclose and dm_create_dir; remove libdm-file.h.
Don't log EROFS mkdir failures in _create_dir_recursive (for LVM2).
Add fclose wrapper dm_fclose that catches write failures (using ferror).
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.
Migrate dmsetup column-based output over to new libdevmapper report framework.
Add descriptions to reporting field definitions.
Add a dso-private variable to dmeventd dso interface.
Add dm_event_handler_[gs]et_timeout functions.
Streamline dm_report_field_* interface.
Add cmdline debug & version options to dmeventd.
@@ -252,4 +329,3 @@ Version 1.00.08 - 27 Feb 2004
Fixed DESTDIR for make install/install_static_lib.
Updated README/INSTALL to reflect move to sources.redhat.com.
Updated autoconf files to 2003-06-17.

650
autoconf/config.guess vendored

File diff suppressed because it is too large Load Diff

224
autoconf/config.sub vendored
View File

@@ -1,9 +1,10 @@
#! /bin/sh
# Configuration validation subroutine script.
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
# 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
# Inc.
timestamp='2003-06-17'
timestamp='2006-09-20'
# This file is (in principle) common to ALL GNU software.
# The presence of a machine in this file suggests that SOME GNU software
@@ -21,14 +22,15 @@ timestamp='2003-06-17'
#
# 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.
# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
# 02110-1301, USA.
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# Please send patches to <config-patches@gnu.org>. Submit a context
# diff and a properly formatted ChangeLog entry.
#
@@ -70,7 +72,7 @@ Report bugs and patches to <config-patches@gnu.org>."
version="\
GNU config.sub ($timestamp)
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
@@ -83,11 +85,11 @@ Try \`$me --help' for more information."
while test $# -gt 0 ; do
case $1 in
--time-stamp | --time* | -t )
echo "$timestamp" ; exit 0 ;;
echo "$timestamp" ; exit ;;
--version | -v )
echo "$version" ; exit 0 ;;
echo "$version" ; exit ;;
--help | --h* | -h )
echo "$usage"; exit 0 ;;
echo "$usage"; exit ;;
-- ) # Stop option processing
shift; break ;;
- ) # Use stdin as input.
@@ -99,7 +101,7 @@ while test $# -gt 0 ; do
*local*)
# First pass through any local machine types.
echo $1
exit 0;;
exit ;;
* )
break ;;
@@ -118,7 +120,9 @@ esac
# Here we must recognize all the valid KERNEL-OS combinations.
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
case $maybe_os in
nto-qnx* | linux-gnu* | freebsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*)
nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
storm-chaos* | os2-emx* | rtmk-nova*)
os=-$maybe_os
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
;;
@@ -144,7 +148,7 @@ case $os in
-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
-apple | -axis)
-apple | -axis | -knuth | -cray)
os=
basic_machine=$1
;;
@@ -169,6 +173,10 @@ case $os in
-hiux*)
os=-hiuxwe2
;;
-sco6)
os=-sco5v6
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-sco5)
os=-sco3.2v5
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
@@ -185,6 +193,10 @@ case $os in
# Don't forget version if it is 3.2v4 or newer.
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-sco5v6*)
# Don't forget version if it is 3.2v4 or newer.
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-sco*)
os=-sco3.2v2
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
@@ -228,14 +240,17 @@ case $basic_machine in
| a29k \
| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
| am33_2.0 \
| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
| bfin \
| c4x | clipper \
| d10v | d30v | dlx | dsp16xx \
| fr30 | frv \
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
| i370 | i860 | i960 | ia64 \
| ip2k \
| m32r | m68000 | m68k | m88k | mcore \
| ip2k | iq2000 \
| m32c | m32r | m32rle | m68000 | m68k | m88k \
| maxq | mb | microblaze | mcore \
| mips | mipsbe | mipseb | mipsel | mipsle \
| mips16 \
| mips64 | mips64el \
@@ -244,27 +259,33 @@ case $basic_machine in
| mips64vr4100 | mips64vr4100el \
| mips64vr4300 | mips64vr4300el \
| mips64vr5000 | mips64vr5000el \
| mips64vr5900 | mips64vr5900el \
| mipsisa32 | mipsisa32el \
| mipsisa32r2 | mipsisa32r2el \
| mipsisa64 | mipsisa64el \
| mipsisa64r2 | mipsisa64r2el \
| mipsisa64sb1 | mipsisa64sb1el \
| mipsisa64sr71k | mipsisa64sr71kel \
| mipstx39 | mipstx39el \
| mn10200 | mn10300 \
| mt \
| msp430 \
| nios | nios2 \
| ns16k | ns32k \
| openrisc | or32 \
| or32 \
| pdp10 | pdp11 | pj | pjl \
| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
| pyramid \
| sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
| score \
| sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
| sh64 | sh64le \
| sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \
| strongarm \
| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
| spu | strongarm \
| tahoe | thumb | tic4x | tic80 | tron \
| v850 | v850e \
| we32k \
| x86 | xscale | xstormy16 | xtensa \
| x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \
| z8k)
basic_machine=$basic_machine-unknown
;;
@@ -275,6 +296,9 @@ case $basic_machine in
;;
m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
;;
ms1)
basic_machine=mt-unknown
;;
# We use `pc' rather than `unknown'
# because (1) that's what they normally are, and
@@ -294,20 +318,20 @@ case $basic_machine in
| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
| arm-* | armbe-* | armle-* | armeb-* | armv*-* \
| avr-* \
| bs2000-* \
| avr-* | avr32-* \
| bfin-* | bs2000-* \
| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
| clipper-* | cydra-* \
| clipper-* | craynv-* | cydra-* \
| d10v-* | d30v-* | dlx-* \
| elxsi-* \
| f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \
| h8300-* | h8500-* \
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
| i*86-* | i860-* | i960-* | ia64-* \
| ip2k-* \
| m32r-* \
| ip2k-* | iq2000-* \
| m32c-* | m32r-* | m32rle-* \
| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
| m88110-* | m88k-* | mcore-* \
| m88110-* | m88k-* | maxq-* | mcore-* \
| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
| mips16-* \
| mips64-* | mips64el-* \
@@ -316,30 +340,36 @@ case $basic_machine in
| mips64vr4100-* | mips64vr4100el-* \
| mips64vr4300-* | mips64vr4300el-* \
| mips64vr5000-* | mips64vr5000el-* \
| mips64vr5900-* | mips64vr5900el-* \
| mipsisa32-* | mipsisa32el-* \
| mipsisa32r2-* | mipsisa32r2el-* \
| mipsisa64-* | mipsisa64el-* \
| mipsisa64r2-* | mipsisa64r2el-* \
| mipsisa64sb1-* | mipsisa64sb1el-* \
| mipsisa64sr71k-* | mipsisa64sr71kel-* \
| mipstx39-* | mipstx39el-* \
| mmix-* \
| mt-* \
| msp430-* \
| none-* | np1-* | nv1-* | ns16k-* | ns32k-* \
| nios-* | nios2-* \
| none-* | np1-* | ns16k-* | ns32k-* \
| orion-* \
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
| pyramid-* \
| romp-* | rs6000-* \
| sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \
| sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
| sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \
| sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
| sparclite-* \
| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
| tahoe-* | thumb-* \
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
| tron-* \
| v850-* | v850e-* | vax-* \
| we32k-* \
| x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \
| xtensa-* \
| x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \
| xstormy16-* | xtensa-* \
| ymp-* \
| z8k-*)
;;
@@ -359,6 +389,9 @@ case $basic_machine in
basic_machine=a29k-amd
os=-udi
;;
abacus)
basic_machine=abacus-unknown
;;
adobe68k)
basic_machine=m68010-adobe
os=-scout
@@ -376,6 +409,9 @@ case $basic_machine in
amd64)
basic_machine=x86_64-pc
;;
amd64-*)
basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
amdahl)
basic_machine=580-amdahl
os=-sysv
@@ -435,12 +471,27 @@ case $basic_machine in
basic_machine=j90-cray
os=-unicos
;;
craynv)
basic_machine=craynv-cray
os=-unicosmp
;;
cr16c)
basic_machine=cr16c-unknown
os=-elf
;;
crds | unos)
basic_machine=m68k-crds
;;
crisv32 | crisv32-* | etraxfs*)
basic_machine=crisv32-axis
;;
cris | cris-* | etrax*)
basic_machine=cris-axis
;;
crx)
basic_machine=crx-unknown
os=-elf
;;
da30 | da30-*)
basic_machine=m68k-da30
;;
@@ -463,6 +514,10 @@ case $basic_machine in
basic_machine=m88k-motorola
os=-sysv3
;;
djgpp)
basic_machine=i586-pc
os=-msdosdjgpp
;;
dpx20 | dpx20-*)
basic_machine=rs6000-bull
os=-bosx
@@ -641,10 +696,6 @@ case $basic_machine in
mips3*)
basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
;;
mmix*)
basic_machine=mmix-knuth
os=-mmixware
;;
monitor)
basic_machine=m68k-rom68k
os=-coff
@@ -657,6 +708,9 @@ case $basic_machine in
basic_machine=i386-pc
os=-msdos
;;
ms1-*)
basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
;;
mvs)
basic_machine=i370-ibm
os=-mvs
@@ -725,10 +779,6 @@ case $basic_machine in
np1)
basic_machine=np1-gould
;;
nv1)
basic_machine=nv1-cray
os=-unicosmp
;;
nsr-tandem)
basic_machine=nsr-tandem
;;
@@ -736,9 +786,12 @@ case $basic_machine in
basic_machine=hppa1.1-oki
os=-proelf
;;
or32 | or32-*)
openrisc | openrisc-*)
basic_machine=or32-unknown
os=-coff
;;
os400)
basic_machine=powerpc-ibm
os=-os400
;;
OSE68000 | ose68000)
basic_machine=m68000-ericsson
@@ -765,6 +818,12 @@ case $basic_machine in
pc532 | pc532-*)
basic_machine=ns32k-pc532
;;
pc98)
basic_machine=i386-pc
;;
pc98-*)
basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
pentium | p5 | k5 | k6 | nexgen | viac3)
basic_machine=i586-pc
;;
@@ -821,6 +880,10 @@ case $basic_machine in
basic_machine=i586-unknown
os=-pw32
;;
rdos)
basic_machine=i386-pc
os=-rdos
;;
rom68k)
basic_machine=m68k-rom68k
os=-coff
@@ -847,6 +910,10 @@ case $basic_machine in
sb1el)
basic_machine=mipsisa64sb1el-unknown
;;
sde)
basic_machine=mipsisa32-sde
os=-elf
;;
sei)
basic_machine=mips-sei
os=-seiux
@@ -960,6 +1027,10 @@ case $basic_machine in
tower | tower-32)
basic_machine=m68k-ncr
;;
tpf)
basic_machine=s390x-ibm
os=-tpf
;;
udi29k)
basic_machine=a29k-amd
os=-udi
@@ -1003,6 +1074,10 @@ case $basic_machine in
basic_machine=hppa1.1-winbond
os=-proelf
;;
xbox)
basic_machine=i686-pc
os=-mingw32
;;
xps | xps100)
basic_machine=xps100-honeywell
;;
@@ -1033,6 +1108,9 @@ case $basic_machine in
romp)
basic_machine=romp-ibm
;;
mmix)
basic_machine=mmix-knuth
;;
rs6000)
basic_machine=rs6000-ibm
;;
@@ -1049,13 +1127,10 @@ case $basic_machine in
we32k)
basic_machine=we32k-att
;;
sh3 | sh4 | sh[34]eb | sh[1234]le | sh[23]ele)
sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele)
basic_machine=sh-unknown
;;
sh64)
basic_machine=sh64-unknown
;;
sparc | sparcv9 | sparcv9b)
sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
basic_machine=sparc-sun
;;
cydra)
@@ -1128,19 +1203,23 @@ case $os in
| -aos* \
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
| -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \
| -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
| -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
| -openbsd* | -solidbsd* \
| -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
| -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
| -chorusos* | -chorusrdb* \
| -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
| -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \
| -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
| -uxpv* | -beos* | -mpeix* | -udk* \
| -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
| -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
| -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
| -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
| -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
| -powermax* | -dnix* | -nx6 | -nx7 | -sei*)
| -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
| -skyos* | -haiku* | -rdos* | -toppers*)
# Remember, each alternative MUST END IN *, to match a version number.
;;
-qnx*)
@@ -1158,12 +1237,15 @@ case $os in
os=`echo $os | sed -e 's|nto|nto-qnx|'`
;;
-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
| -windows* | -osx | -abug | -netware* | -os9* | -beos* \
| -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
| -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
;;
-mac*)
os=`echo $os | sed -e 's|mac|macos|'`
;;
-linux-dietlibc)
os=-linux-dietlibc
;;
-linux*)
os=`echo $os | sed -e 's|linux|linux-gnu|'`
;;
@@ -1176,6 +1258,9 @@ case $os in
-opened*)
os=-openedition
;;
-os400*)
os=-os400
;;
-wince*)
os=-wince
;;
@@ -1197,6 +1282,9 @@ case $os in
-atheos*)
os=-atheos
;;
-syllable*)
os=-syllable
;;
-386bsd)
os=-bsd
;;
@@ -1219,6 +1307,9 @@ case $os in
-sinix*)
os=-sysv4
;;
-tpf*)
os=-tpf
;;
-triton*)
os=-sysv3
;;
@@ -1255,6 +1346,9 @@ case $os in
-kaos*)
os=-kaos
;;
-zvmoe)
os=-zvmoe
;;
-none)
;;
*)
@@ -1277,6 +1371,12 @@ else
# system, and we'll never get to this point.
case $basic_machine in
score-*)
os=-elf
;;
spu-*)
os=-elf
;;
*-acorn)
os=-riscix1.2
;;
@@ -1286,9 +1386,9 @@ case $basic_machine in
arm*-semi)
os=-aout
;;
c4x-* | tic4x-*)
os=-coff
;;
c4x-* | tic4x-*)
os=-coff
;;
# This must come before the *-dec entry.
pdp10-*)
os=-tops20
@@ -1332,9 +1432,15 @@ case $basic_machine in
*-be)
os=-beos
;;
*-haiku)
os=-haiku
;;
*-ibm)
os=-aix
;;
*-knuth)
os=-mmixware
;;
*-wec)
os=-proelf
;;
@@ -1467,9 +1573,15 @@ case $basic_machine in
-mvs* | -opened*)
vendor=ibm
;;
-os400*)
vendor=ibm
;;
-ptx*)
vendor=sequent
;;
-tpf*)
vendor=ibm
;;
-vxsim* | -vxworks* | -windiss*)
vendor=wrs
;;
@@ -1494,7 +1606,7 @@ case $basic_machine in
esac
echo $basic_machine$os
exit 0
exit
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)

View File

@@ -1,7 +1,7 @@
#!/bin/sh
# install - install a program, script, or datafile
scriptversion=2003-06-13.21
scriptversion=2006-10-14.15
# This originates from X11R5 (mit/util/scripts/install.sh), which was
# later released in X11R6 (xc/config/util/install.sh) with the
@@ -39,15 +39,24 @@ scriptversion=2003-06-13.21
# when there is no Makefile.
#
# This script is compatible with the BSD install script, but was written
# from scratch. It can only install one file at a time, a restriction
# shared with many OS's install programs.
# from scratch.
nl='
'
IFS=" "" $nl"
# set DOITPROG to echo to test this script
# Don't use :- since 4.3BSD and earlier shells don't like it.
doit="${DOITPROG-}"
if test -z "$doit"; then
doit_exec=exec
else
doit_exec=$doit
fi
# put in absolute paths if you don't have them in your path; or use env. vars.
# Put in absolute file names if you don't have them in your path;
# or use environment vars.
mvprog="${MVPROG-mv}"
cpprog="${CPPROG-cp}"
@@ -58,10 +67,13 @@ stripprog="${STRIPPROG-strip}"
rmprog="${RMPROG-rm}"
mkdirprog="${MKDIRPROG-mkdir}"
transformbasename=
transform_arg=
instcmd="$mvprog"
chmodcmd="$chmodprog 0755"
posix_glob=
posix_mkdir=
# Desired mode of installed file.
mode=0755
chmodcmd=$chmodprog
chowncmd=
chgrpcmd=
stripcmd=
@@ -70,22 +82,27 @@ mvcmd="$mvprog"
src=
dst=
dir_arg=
dstarg=
no_target_directory=
usage="Usage: $0 [OPTION]... SRCFILE DSTFILE
or: $0 -d DIR1 DIR2...
usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
or: $0 [OPTION]... SRCFILES... DIRECTORY
or: $0 [OPTION]... -t DIRECTORY SRCFILES...
or: $0 [OPTION]... -d DIRECTORIES...
In the first form, install SRCFILE to DSTFILE, removing SRCFILE by default.
In the second, create the directory path DIR.
In the 1st form, copy SRCFILE to DSTFILE.
In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
In the 4th, create DIRECTORIES.
Options:
-b=TRANSFORMBASENAME
-c copy source (using $cpprog) instead of moving (using $mvprog).
-c (ignored)
-d create directories instead of installing files.
-g GROUP $chgrp installed files to GROUP.
-m MODE $chmod installed files to MODE.
-o USER $chown installed files to USER.
-s strip installed files (using $stripprog).
-t=TRANSFORM
-g GROUP $chgrpprog installed files to GROUP.
-m MODE $chmodprog installed files to MODE.
-o USER $chownprog installed files to USER.
-s $stripprog installed files.
-t DIRECTORY install into DIRECTORY.
-T report an error if DSTFILE is a directory.
--help display this help and exit.
--version display version info and exit.
@@ -93,14 +110,9 @@ Environment variables override the default commands:
CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG
"
while test -n "$1"; do
while test $# -ne 0; do
case $1 in
-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
shift
continue;;
-c) instcmd=$cpprog
shift
-c) shift
continue;;
-d) dir_arg=true
@@ -112,11 +124,17 @@ while test -n "$1"; do
shift
continue;;
--help) echo "$usage"; exit 0;;
--help) echo "$usage"; exit $?;;
-m) chmodcmd="$chmodprog $2"
-m) mode=$2
shift
shift
case $mode in
*' '* | *' '* | *'
'* | *'*'* | *'?'* | *'['*)
echo "$0: invalid mode: $mode" >&2
exit 1;;
esac
continue;;
-o) chowncmd="$chownprog $2"
@@ -128,155 +146,358 @@ while test -n "$1"; do
shift
continue;;
-t=*) transformarg=`echo $1 | sed 's/-t=//'`
shift
continue;;
-t) dstarg=$2
shift
shift
continue;;
--version) echo "$0 $scriptversion"; exit 0;;
-T) no_target_directory=true
shift
continue;;
*) if test -z "$src"; then
src=$1
else
# this colon is to work around a 386BSD /bin/sh bug
:
dst=$1
fi
shift
continue;;
--version) echo "$0 $scriptversion"; exit $?;;
--) shift
break;;
-*) echo "$0: invalid option: $1" >&2
exit 1;;
*) break;;
esac
done
if test -z "$src"; then
echo "$0: no input file specified." >&2
exit 1
fi
if test -n "$dir_arg"; then
dst=$src
src=
if test -d "$dst"; then
instcmd=:
chmodcmd=
else
instcmd=$mkdirprog
fi
else
# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
# might cause directories to be created, which would be especially bad
# if $src (and thus $dsttmp) contains '*'.
if test ! -f "$src" && test ! -d "$src"; then
echo "$0: $src does not exist." >&2
exit 1
fi
if test -z "$dst"; then
echo "$0: no destination specified." >&2
exit 1
fi
# If destination is a directory, append the input filename; won't work
# if double slashes aren't ignored.
if test -d "$dst"; then
dst=$dst/`basename "$src"`
fi
fi
## this sed command emulates the dirname command
dstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
# Make sure that the destination directory exists.
# (this part is taken from Noah Friedman's mkinstalldirs script.)
# Skip lots of stat calls in the usual case.
if test ! -d "$dstdir"; then
defaultIFS='
'
IFS="${IFS-$defaultIFS}"
oIFS=$IFS
# Some sh's can't handle IFS=/ for some reason.
IFS='%'
set - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
IFS=$oIFS
pathcomp=
while test $# -ne 0 ; do
pathcomp=$pathcomp$1
shift
test -d "$pathcomp" || $mkdirprog "$pathcomp"
pathcomp=$pathcomp/
if test $# -ne 0 && test -z "$dir_arg$dstarg"; then
# When -d is used, all remaining arguments are directories to create.
# When -t is used, the destination is already specified.
# Otherwise, the last argument is the destination. Remove it from $@.
for arg
do
if test -n "$dstarg"; then
# $@ is not empty: it contains at least $arg.
set fnord "$@" "$dstarg"
shift # fnord
fi
shift # arg
dstarg=$arg
done
fi
if test -n "$dir_arg"; then
$doit $instcmd "$dst" \
&& { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \
&& { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \
&& { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \
&& { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; }
else
# If we're going to rename the final executable, determine the name now.
if test -z "$transformarg"; then
dstfile=`basename "$dst"`
else
dstfile=`basename "$dst" $transformbasename \
| sed $transformarg`$transformbasename
if test $# -eq 0; then
if test -z "$dir_arg"; then
echo "$0: no input file specified." >&2
exit 1
fi
# It's OK to call `install-sh -d' without argument.
# This can happen when creating conditional directories.
exit 0
fi
# don't allow the sed command to completely eliminate the filename.
test -z "$dstfile" && dstfile=`basename "$dst"`
# Make a couple of temp file names in the proper directory.
dsttmp=$dstdir/_inst.$$_
rmtmp=$dstdir/_rm.$$_
# Trap to clean up those temp files at exit.
trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0
if test -z "$dir_arg"; then
trap '(exit $?); exit' 1 2 13 15
# Move or copy the file name to the temp name
$doit $instcmd "$src" "$dsttmp" &&
# Set umask so as not to create temps with too-generous modes.
# However, 'strip' requires both read and write access to temps.
case $mode in
# Optimize common cases.
*644) cp_umask=133;;
*755) cp_umask=22;;
# and set any options; do chmod last to preserve setuid bits.
#
# If any of these fail, we abort the whole thing. If we want to
# ignore errors from any of these, just make sure not to ignore
# errors from the above "$doit $instcmd $src $dsttmp" command.
#
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \
&& { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \
&& { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \
&& { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } &&
*[0-7])
if test -z "$stripcmd"; then
u_plus_rw=
else
u_plus_rw='% 200'
fi
cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
*)
if test -z "$stripcmd"; then
u_plus_rw=
else
u_plus_rw=,u+rw
fi
cp_umask=$mode$u_plus_rw;;
esac
fi
# Now remove or move aside any old file at destination location. We
# try this two ways since rm can't unlink itself on some systems and
# the destination file might be busy for other reasons. In this case,
# the final cleanup might fail but the new file should still install
# successfully.
{
if test -f "$dstdir/$dstfile"; then
$doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \
|| $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \
|| {
echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
(exit 1); exit
}
else
:
for src
do
# Protect names starting with `-'.
case $src in
-*) src=./$src ;;
esac
if test -n "$dir_arg"; then
dst=$src
dstdir=$dst
test -d "$dstdir"
dstdir_status=$?
else
# Waiting for this to be detected by the "$cpprog $src $dsttmp" command
# might cause directories to be created, which would be especially bad
# if $src (and thus $dsttmp) contains '*'.
if test ! -f "$src" && test ! -d "$src"; then
echo "$0: $src does not exist." >&2
exit 1
fi
} &&
# Now rename the file to the real destination.
$doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
fi &&
if test -z "$dstarg"; then
echo "$0: no destination specified." >&2
exit 1
fi
# The final little trick to "correctly" pass the exit status to the exit trap.
{
(exit 0); exit
}
dst=$dstarg
# Protect names starting with `-'.
case $dst in
-*) dst=./$dst ;;
esac
# If destination is a directory, append the input filename; won't work
# if double slashes aren't ignored.
if test -d "$dst"; then
if test -n "$no_target_directory"; then
echo "$0: $dstarg: Is a directory" >&2
exit 1
fi
dstdir=$dst
dst=$dstdir/`basename "$src"`
dstdir_status=0
else
# Prefer dirname, but fall back on a substitute if dirname fails.
dstdir=`
(dirname "$dst") 2>/dev/null ||
expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$dst" : 'X\(//\)[^/]' \| \
X"$dst" : 'X\(//\)$' \| \
X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
echo X"$dst" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
}
/^X\(\/\/\)[^/].*/{
s//\1/
q
}
/^X\(\/\/\)$/{
s//\1/
q
}
/^X\(\/\).*/{
s//\1/
q
}
s/.*/./; q'
`
test -d "$dstdir"
dstdir_status=$?
fi
fi
obsolete_mkdir_used=false
if test $dstdir_status != 0; then
case $posix_mkdir in
'')
# Create intermediate dirs using mode 755 as modified by the umask.
# This is like FreeBSD 'install' as of 1997-10-28.
umask=`umask`
case $stripcmd.$umask in
# Optimize common cases.
*[2367][2367]) mkdir_umask=$umask;;
.*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
*[0-7])
mkdir_umask=`expr $umask + 22 \
- $umask % 100 % 40 + $umask % 20 \
- $umask % 10 % 4 + $umask % 2
`;;
*) mkdir_umask=$umask,go-w;;
esac
# With -d, create the new directory with the user-specified mode.
# Otherwise, rely on $mkdir_umask.
if test -n "$dir_arg"; then
mkdir_mode=-m$mode
else
mkdir_mode=
fi
posix_mkdir=false
case $umask in
*[123567][0-7][0-7])
# POSIX mkdir -p sets u+wx bits regardless of umask, which
# is incompatible with FreeBSD 'install' when (umask & 300) != 0.
;;
*)
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
if (umask $mkdir_umask &&
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
then
if test -z "$dir_arg" || {
# Check for POSIX incompatibilities with -m.
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
# other-writeable bit of parent directory when it shouldn't.
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
ls_ld_tmpdir=`ls -ld "$tmpdir"`
case $ls_ld_tmpdir in
d????-?r-*) different_mode=700;;
d????-?--*) different_mode=755;;
*) false;;
esac &&
$mkdirprog -m$different_mode -p -- "$tmpdir" && {
ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
}
}
then posix_mkdir=:
fi
rmdir "$tmpdir/d" "$tmpdir"
else
# Remove any dirs left behind by ancient mkdir implementations.
rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
fi
trap '' 0;;
esac;;
esac
if
$posix_mkdir && (
umask $mkdir_umask &&
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
)
then :
else
# The umask is ridiculous, or mkdir does not conform to POSIX,
# or it failed possibly due to a race condition. Create the
# directory the slow way, step by step, checking for races as we go.
case $dstdir in
/*) prefix=/ ;;
-*) prefix=./ ;;
*) prefix= ;;
esac
case $posix_glob in
'')
if (set -f) 2>/dev/null; then
posix_glob=true
else
posix_glob=false
fi ;;
esac
oIFS=$IFS
IFS=/
$posix_glob && set -f
set fnord $dstdir
shift
$posix_glob && set +f
IFS=$oIFS
prefixes=
for d
do
test -z "$d" && continue
prefix=$prefix$d
if test -d "$prefix"; then
prefixes=
else
if $posix_mkdir; then
(umask=$mkdir_umask &&
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
# Don't fail if two instances are running concurrently.
test -d "$prefix" || exit 1
else
case $prefix in
*\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
*) qprefix=$prefix;;
esac
prefixes="$prefixes '$qprefix'"
fi
fi
prefix=$prefix/
done
if test -n "$prefixes"; then
# Don't fail if two instances are running concurrently.
(umask $mkdir_umask &&
eval "\$doit_exec \$mkdirprog $prefixes") ||
test -d "$dstdir" || exit 1
obsolete_mkdir_used=true
fi
fi
fi
if test -n "$dir_arg"; then
{ test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
{ test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
else
# Make a couple of temp file names in the proper directory.
dsttmp=$dstdir/_inst.$$_
rmtmp=$dstdir/_rm.$$_
# Trap to clean up those temp files at exit.
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
# Copy the file name to the temp name.
(umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
# and set any options; do chmod last to preserve setuid bits.
#
# If any of these fail, we abort the whole thing. If we want to
# ignore errors from any of these, just make sure not to ignore
# errors from the above "$doit $cpprog $src $dsttmp" command.
#
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \
&& { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \
&& { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \
&& { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
# Now rename the file to the real destination.
{ $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null \
|| {
# The rename failed, perhaps because mv can't rename something else
# to itself, or perhaps because mv is so ancient that it does not
# support -f.
# Now remove or move aside any old file at destination location.
# We try this two ways since rm can't unlink itself on some
# systems and the destination file might be busy for other
# reasons. In this case, the final cleanup might fail but the new
# file should still install successfully.
{
if test -f "$dst"; then
$doit $rmcmd -f "$dst" 2>/dev/null \
|| { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null \
&& { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }; }\
|| {
echo "$0: cannot unlink or rename $dst" >&2
(exit 1); exit 1
}
else
:
fi
} &&
# Now rename the file to the real destination.
$doit $mvcmd "$dsttmp" "$dst"
}
} || exit 1
trap '' 0
fi
done
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)

9657
configure vendored

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +1,8 @@
##
## Copyright (C) 2000-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 the LVM2.
## 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
@@ -13,21 +13,22 @@
## Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
################################################################################
AC_PREREQ(2.53)
AC_PREREQ(2.57)
################################################################################
dnl -- Process this file with autoconf to produce a configure script.
AC_INIT(lib/device/dev-cache.h)
AC_INIT
AC_CONFIG_SRCDIR([lib/device/dev-cache.h])
################################################################################
AC_CONFIG_HEADERS(lib/misc/configure.h)
################################################################################
dnl -- Setup the directory where autoconf has auxilary files
AC_CONFIG_AUX_DIR(autoconf)
AC_CONFIG_AUX_DIR(autoconf)
################################################################################
dnl -- Get system type
AC_CANONICAL_SYSTEM
AC_CANONICAL_TARGET([])
case "$host_os" in
linux*)
@@ -98,7 +99,7 @@ AC_TYPE_OFF_T
AC_TYPE_PID_T
AC_TYPE_SIZE_T
AC_TYPE_MODE_T
AC_STRUCT_ST_RDEV
AC_CHECK_MEMBERS([struct stat.st_rdev])
AC_STRUCT_TM
################################################################################
@@ -362,7 +363,7 @@ AC_MSG_RESULT($CMDLIB)
################################################################################
dnl -- Enable fsadm
AC_MSG_CHECKING(whether to build fsadm)
AC_MSG_CHECKING(whether to install fsadm)
AC_ARG_ENABLE(fsadm, [ --enable-fsadm Enable fsadm],
FSADM=$enableval)
AC_MSG_RESULT($FSADM)
@@ -452,6 +453,18 @@ if test x$SELINUX = xyes; then
else
AC_MSG_WARN(Disabling selinux)
fi
# With --enable-static_link and selinux enabled, linking lvm.static
# fails on at least Debian unstable due to unsatisfied references
# to pthread_mutex_lock and _unlock. See if we need -lpthread.
if test "$STATIC_LINK-$HAVE_SELINUX" = yes-yes; then
lvm_saved_libs=$LIBS
LIBS="$LIBS -static"
AC_SEARCH_LIBS([pthread_mutex_lock], [pthread],
[test "$ac_cv_search_pthread_mutex_lock" = "none required" ||
LIB_PTHREAD=-lpthread])
LIBS=$lvm_saved_libs
fi
fi
################################################################################
@@ -522,9 +535,15 @@ AC_ARG_WITH(staticdir,
AC_ARG_WITH(dmdir,
[ --with-dmdir=DIR Build against device-mapper source tree in DIR],
[ DMDIR="$withval" ],
[ DMDIR="$withval" CPPFLAGS="$CPPFLAGS -I$DMDIR/include"],
[ DMDIR= ])
# Convert a relative dir name to absolute.
case $DMDIR in
/*) ;;
*) DMDIR="`pwd`/$DMDIR" ;;
esac
################################################################################
dnl -- Ensure additional headers required
if test x$READLINE = xyes; then
@@ -539,11 +558,6 @@ if test x$CLVMD != xnone; then
AC_FUNC_SELECT_ARGTYPES
fi
if test x$FSADM = xyes; then
AC_CHECK_HEADERS(fstab.h sys/mount.h sys/vfs.h,,AC_MSG_ERROR(bailing out))
AC_CHECK_FUNCS(memmove,,AC_MSG_ERROR(bailing out))
fi
if test x$CLUSTER != xnone; then
AC_CHECK_HEADERS(sys/socket.h sys/un.h,,AC_MSG_ERROR(bailing out))
AC_CHECK_FUNCS(socket,,AC_MSG_ERROR(bailing out))
@@ -616,37 +630,35 @@ AC_SUBST(FSADM)
AC_SUBST(DMEVENTD)
AC_SUBST(CFLOW_CMD)
AC_SUBST(CSCOPE_CMD)
AC_SUBST([LIB_PTHREAD])
################################################################################
dnl -- First and last lines should not contain files to generate in order to
dnl -- First and last lines should not contain files to generate in order to
dnl -- keep utility scripts running properly
AC_OUTPUT( \
Makefile \
make.tmpl \
daemons/Makefile \
daemons/clvmd/Makefile \
dmeventd/Makefile \
dmeventd/mirror/Makefile \
doc/Makefile \
include/Makefile \
lib/Makefile \
lib/format1/Makefile \
lib/format_pool/Makefile \
lib/locking/Makefile \
lib/mirror/Makefile \
lib/snapshot/Makefile \
man/Makefile \
po/Makefile \
scripts/Makefile \
tools/Makefile \
tools/version.h \
tools/fsadm/Makefile \
test/mm/Makefile \
test/device/Makefile \
test/format1/Makefile \
test/regex/Makefile \
test/filters/Makefile \
)
AC_CONFIG_FILES([
Makefile
make.tmpl
daemons/Makefile
daemons/clvmd/Makefile
dmeventd/Makefile
dmeventd/mirror/Makefile
dmeventd/snapshot/Makefile
doc/Makefile
include/Makefile
lib/Makefile
lib/format1/Makefile
lib/format_pool/Makefile
lib/locking/Makefile
lib/mirror/Makefile
lib/snapshot/Makefile
test/Makefile
man/Makefile
po/Makefile
scripts/Makefile
tools/Makefile
tools/version.h
])
AC_OUTPUT
if test x$ODIRECT != xyes; then
AC_MSG_WARN(Warning: O_DIRECT disabled: low-memory pvmove may lock up)

View File

@@ -1,7 +1,7 @@
#
# Copyright (C) 2004 Red Hat, Inc. All rights reserved.
#
# This file is part of the LVM2.
# 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

View File

@@ -1,7 +1,7 @@
#
# Copyright (C) 2004 Red Hat, Inc. All rights reserved.
#
# This file is part of the LVM2.
# 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
@@ -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

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
@@ -66,5 +66,6 @@ static const char CLVMD_SOCKNAME[] = "\0clvmd";
/* Misc functions */
#define CLVMD_CMD_REFRESH 40
#define CLVMD_CMD_GET_CLUSTERNAME 41
#define CLVMD_CMD_SET_DEBUG 42
#define CLVMD_CMD_VG_BACKUP 43
#endif

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,14 +234,14 @@ 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);
if (nodeid >= max_updown_nodes) {
int new_size = nodeid + 10;
int *new_updown = realloc(node_updown, new_size);
int *new_updown = realloc(node_updown, sizeof(int) * new_size);
if (new_updown) {
node_updown = new_updown;
@@ -292,6 +297,8 @@ static void get_members()
{
int retnodes;
int status;
int i;
int high_nodeid = 0;
num_nodes = cman_get_node_count(c_handle);
if (num_nodes == -1) {
@@ -320,18 +327,26 @@ static void get_members()
exit(6);
}
/* Get the highest nodeid */
for (i=0; i<retnodes; i++) {
if (nodes[i].cn_nodeid > high_nodeid)
high_nodeid = nodes[i].cn_nodeid;
}
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;
if (high_nodeid >= max_updown_nodes)
max_updown_nodes = high_nodeid + 1;
buf_len = sizeof(int) * 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 +360,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 +392,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,8 +74,8 @@
#include "clvmd-comms.h"
#include "clvm.h"
#include "clvmd.h"
#include "libdlm.h"
extern debug_t debug;
extern struct cluster_ops *clops;
/* This is where all the real work happens:
@@ -95,18 +96,34 @@ 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:
lockname = &args[2];
/* Check to see if the VG is in use by LVM1 */
status = do_check_lvm1(&args[2]);
status = do_check_lvm1(lockname);
/* P_#global causes a cache refresh */
if (strcmp(lockname, "P_#global") == 0)
do_refresh_cache();
else if (strncmp(lockname, "P_", 2) == 0)
lvmcache_drop_metadata(lockname + 2);
break;
case CLVMD_CMD_LOCK_LV:
@@ -118,7 +135,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;
}
@@ -128,10 +145,18 @@ int do_command(struct local_client *client, struct clvm_header *msg, int msglen,
do_refresh_cache();
break;
case CLVMD_CMD_SET_DEBUG:
debug = args[0];
break;
case CLVMD_CMD_GET_CLUSTERNAME:
status = clops->get_cluster_name(*buf, buflen);
if (!status)
*retlen = strlen(*buf);
*retlen = strlen(*buf)+1;
break;
case CLVMD_CMD_VG_BACKUP:
lvm_do_backup(&args[2]);
break;
default:
@@ -141,7 +166,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;
@@ -240,6 +265,8 @@ int do_pre_command(struct local_client *client)
case CLVMD_CMD_REFRESH:
case CLVMD_CMD_GET_CLUSTERNAME:
case CLVMD_CMD_SET_DEBUG:
case CLVMD_CMD_VG_BACKUP:
break;
default:
@@ -269,6 +296,7 @@ int do_post_command(struct local_client *client)
break;
case CLVMD_CMD_LOCK_VG:
case CLVMD_CMD_VG_BACKUP:
/* Nothing to do here */
break;

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;
@@ -86,12 +86,12 @@ struct lock_wait
};
/* Forward */
static int read_from_core_sock(struct local_client *client, char *buf, int len, char *csid,
static int read_from_core_sock(struct local_client *client, char *buf, int len, const char *csid,
struct local_client **new_client);
static int read_from_lock_sock(struct local_client *client, char *buf, int len, char *csid,
static int read_from_lock_sock(struct local_client *client, char *buf, int len, const char *csid,
struct local_client **new_client);
static int get_all_cluster_nodes(void);
static int _csid_from_name(char *csid, char *name);
static int _csid_from_name(char *csid, const char *name);
static void _cluster_closedown(void);
/* In tcp-comms.c */
@@ -278,7 +278,7 @@ static void drop_expired_locks(char *nodename)
}
static int read_from_core_sock(struct local_client *client, char *buf, int len, char *csid,
static int read_from_core_sock(struct local_client *client, char *buf, int len, const char *csid,
struct local_client **new_client)
{
int status;
@@ -288,7 +288,7 @@ static int read_from_core_sock(struct local_client *client, char *buf, int len,
return status<0 ? status : 1;
}
static int read_from_lock_sock(struct local_client *client, char *buf, int len, char *csid,
static int read_from_lock_sock(struct local_client *client, char *buf, int len, const char *csid,
struct local_client **new_client)
{
int status;
@@ -582,7 +582,7 @@ int get_next_node_csid(void **context, char *csid)
return 1;
}
int gulm_name_from_csid(char *csid, char *name)
int gulm_name_from_csid(const char *csid, char *name)
{
struct node_info *ninfo;
@@ -598,7 +598,7 @@ int gulm_name_from_csid(char *csid, char *name)
}
static int _csid_from_name(char *csid, char *name)
static int _csid_from_name(char *csid, const char *name)
{
struct dm_hash_node *hn;
struct node_info *ninfo;
@@ -622,7 +622,7 @@ static int _get_num_nodes()
}
/* Node is now known to be running a clvmd */
void gulm_add_up_node(char *csid)
void gulm_add_up_node(const char *csid)
{
struct node_info *ninfo;
@@ -661,7 +661,7 @@ void add_down_node(char *csid)
/* 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 *, char *csid, int node_up))
void (*callback)(struct local_client *, const char *csid, int node_up))
{
struct dm_hash_node *hn;
struct node_info *ninfo;
@@ -965,14 +965,14 @@ static int _get_main_cluster_fd(void)
return get_main_gulm_cluster_fd();
}
static int _cluster_fd_callback(struct local_client *fd, char *buf, int len, char *csid, struct local_client **new_client)
static int _cluster_fd_callback(struct local_client *fd, char *buf, int len, const char *csid, struct local_client **new_client)
{
return cluster_fd_gulm_callback(fd, buf, len, csid, new_client);
}
static int _cluster_send_message(void *buf, int msglen, char *csid, const char *errtext)
static int _cluster_send_message(const void *buf, int msglen, const char *csid, const char *errtext)
{
return gulm_cluster_send_message(buf, msglen, csid, errtext);
return gulm_cluster_send_message((char *)buf, msglen, csid, errtext);
}
static int _get_cluster_name(char *buf, int buflen)

View File

@@ -5,9 +5,9 @@
extern int get_next_node_csid(void **context, char *csid);
extern void add_down_node(char *csid);
extern int gulm_fd(void);
extern int get_ip_address(char *node, char *addr);
extern void tcp_remove_client(char *csid);
extern int alloc_client(int fd, char *csid, struct local_client **new_client);
extern int get_ip_address(const char *node, char *addr);
extern void tcp_remove_client(const char *csid);
extern int alloc_client(int fd, const char *csid, struct local_client **new_client);
void gulm_add_up_node(char *csid);
int gulm_name_from_csid(char *csid, char *name);
void gulm_add_up_node(const char *csid);
int gulm_name_from_csid(const char *csid, char *name);

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

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
@@ -37,6 +37,8 @@
#include <getopt.h>
#include <syslog.h>
#include <errno.h>
#include <limits.h>
#include <libdlm.h>
#include "clvmd-comms.h"
#include "lvm-functions.h"
@@ -44,8 +46,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 +56,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)
@@ -86,7 +84,8 @@ struct lvm_thread_cmd {
int msglen;
unsigned short xid;
};
static int debug = 0;
debug_t debug;
static pthread_t lvm_thread;
static pthread_mutex_t lvm_thread_mutex;
static pthread_cond_t lvm_thread_cond;
@@ -113,31 +112,33 @@ 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 int check_local_clvmd(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)
{
@@ -146,8 +147,10 @@ static void usage(char *prog, FILE *file)
fprintf(file, "\n");
fprintf(file, " -V Show version of clvmd\n");
fprintf(file, " -h Show this help information\n");
fprintf(file, " -d Don't fork, run in the foreground\n");
fprintf(file, " -d Set debug level\n");
fprintf(file, " If starting clvmd then don't fork, run in the foreground\n");
fprintf(file, " -R Tell all running clvmds in the cluster to reload their device cache\n");
fprintf(file, " -C Sets debug level (from -d) on all clvmd instances clusterwide\n");
fprintf(file, " -t<secs> Command timeout (default 60 seconds)\n");
fprintf(file, " -T<secs> Startup timeout (default none)\n");
fprintf(file, "\n");
@@ -169,15 +172,23 @@ void debuglog(const char *fmt, ...)
{
time_t P;
va_list ap;
static int syslog_init = 0;
if (!debug)
return;
if (debug == DEBUG_STDERR) {
va_start(ap,fmt);
time(&P);
fprintf(stderr, "CLVMD[%x]: %.15s ", (int)pthread_self(), ctime(&P)+4 );
vfprintf(stderr, fmt, ap);
va_end(ap);
}
if (debug == DEBUG_SYSLOG) {
if (!syslog_init)
openlog("clvmd", LOG_PID, LOG_DAEMON);
va_start(ap,fmt);
time(&P);
fprintf(stderr, "CLVMD[%x]: %.15s ", (int)pthread_self(), ctime(&P)+4 );
vfprintf(stderr, fmt, ap);
va_end(ap);
va_start(ap,fmt);
vsyslog(LOG_DEBUG, fmt, ap);
va_end(ap);
}
}
int main(int argc, char *argv[])
@@ -190,11 +201,13 @@ int main(int argc, char *argv[])
int start_timeout = 0;
sigset_t ss;
int using_gulm = 0;
int debug_opt = 0;
int clusterwide_opt = 0;
/* Deal with command-line arguments */
opterr = 0;
optind = 0;
while ((opt = getopt(argc, argv, "?vVhdt:RT:")) != EOF) {
while ((opt = getopt(argc, argv, "?vVhd::t:RT:C")) != EOF) {
switch (opt) {
case 'h':
usage(argv[0], stdout);
@@ -207,8 +220,16 @@ int main(int argc, char *argv[])
case 'R':
return refresh_clvmd();
case 'C':
clusterwide_opt = 1;
break;
case 'd':
debug++;
debug_opt = 1;
if (optarg)
debug = atoi(optarg);
else
debug = DEBUG_STDERR;
break;
case 't':
@@ -239,8 +260,17 @@ int main(int argc, char *argv[])
}
}
/* Setting debug options on an existing clvmd */
if (debug_opt && !check_local_clvmd()) {
/* Sending to stderr makes no sense for a detached daemon */
if (debug == DEBUG_STDERR)
debug = DEBUG_SYSLOG;
return debug_clvmd(debug, clusterwide_opt);
}
/* Fork into the background (unless requested not to) */
if (!debug) {
if (debug != DEBUG_STDERR) {
be_daemon(start_timeout);
}
@@ -293,6 +323,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 +364,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 +396,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 +405,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 +415,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 +446,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 +455,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 +522,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) {
@@ -588,7 +633,7 @@ static void main_loop(int local_sock, int cmd_timeout)
}
if (FD_ISSET(thisfd->fd, &in)) {
struct local_client *newfd;
struct local_client *newfd = NULL;
int ret;
/* Do callback */
@@ -786,6 +831,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);
@@ -857,8 +904,7 @@ static int read_from_local_sock(struct local_client *thisfd)
}
/* Free the command buffer */
if (thisfd->bits.localsock.cmd)
free(thisfd->bits.localsock.cmd);
free(thisfd->bits.localsock.cmd);
/* Clear out the cross-link */
if (thisfd->bits.localsock.pipe_client != NULL)
@@ -893,16 +939,19 @@ static int read_from_local_sock(struct local_client *thisfd)
}
/* Free any old buffer space */
if (thisfd->bits.localsock.cmd)
free(thisfd->bits.localsock.cmd);
free(thisfd->bits.localsock.cmd);
/* See if we have the whole message */
argslen =
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 +976,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 +1087,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 +1113,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 +1136,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 +1155,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 +1170,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 +1181,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 +1244,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 +1282,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 +1337,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,10 +1367,23 @@ 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));
if (status)
continue; /* Wait for another PRE command */
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) {
client->bits.localsock.state = POST_COMMAND;
goto next_pre;
}
/* We may need to wait for the condition variable before running the post command */
pthread_mutex_lock(&client->bits.localsock.mutex);
@@ -1446,12 +1402,22 @@ 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);
next_pre:
DEBUGLOG("Waiting for next pre command\n");
pthread_mutex_lock(&client->bits.localsock.mutex);
if (client->bits.localsock.state != PRE_COMMAND) {
if (client->bits.localsock.state != PRE_COMMAND &&
!client->bits.localsock.finished) {
pthread_cond_wait(&client->bits.localsock.cond,
&client->bits.localsock.mutex);
}
@@ -1496,7 +1462,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;
@@ -1581,8 +1547,7 @@ static void send_local_reply(struct local_client *client, int status, int fd)
}
thisreply = thisreply->next;
if (tempreply->replymsg)
free(tempreply->replymsg);
free(tempreply->replymsg);
free(tempreply);
}
@@ -1613,8 +1578,7 @@ static void free_reply(struct local_client *client)
thisreply = thisreply->next;
if (tempreply->replymsg)
free(tempreply->replymsg);
free(tempreply->replymsg);
free(tempreply);
}
client->bits.localsock.replies = NULL;
@@ -1646,10 +1610,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 len = 0;
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 +1629,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;
}
@@ -1737,8 +1730,7 @@ static __attribute__ ((noreturn)) void *lvm_thread_fn(void *arg)
pthread_mutex_unlock(&lvm_thread_mutex);
process_work_item(cmd);
if (cmd->msg)
free(cmd->msg);
free(cmd->msg);
free(cmd);
pthread_mutex_lock(&lvm_thread_mutex);
@@ -1749,7 +1741,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;
@@ -1791,6 +1783,32 @@ static int add_to_lvmqueue(struct local_client *client, struct clvm_header *msg,
return 0;
}
/* Return 0 if we can talk to an existing clvmd */
static int check_local_clvmd(void)
{
int local_socket;
struct sockaddr_un sockaddr;
int ret = 0;
/* Open local socket */
if ((local_socket = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
return -1;
}
memset(&sockaddr, 0, sizeof(sockaddr));
memcpy(sockaddr.sun_path, CLVMD_SOCKNAME, sizeof(CLVMD_SOCKNAME));
sockaddr.sun_family = AF_UNIX;
if (connect(local_socket,(struct sockaddr *) &sockaddr,
sizeof(sockaddr))) {
ret = -1;
}
close(local_socket);
return ret;
}
/* Open the local socket, that's the one we talk to libclvm down */
static int open_local_sock()
{
@@ -1805,8 +1823,9 @@ static int open_local_sock()
log_error("Can't create local socket: %m");
return -1;
}
/* Set Close-on-exec */
/* Set Close-on-exec & non-blocking */
fcntl(local_socket, F_SETFD, 1);
fcntl(local_socket, F_SETFL, fcntl(local_socket, F_GETFL, 0) | O_NONBLOCK);
memset(&sockaddr, 0, sizeof(sockaddr));
memcpy(sockaddr.sun_path, CLVMD_SOCKNAME, sizeof(CLVMD_SOCKNAME));
@@ -1827,7 +1846,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 +1860,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

@@ -35,6 +35,8 @@ struct node_reply {
struct node_reply *next;
};
typedef enum {DEBUG_OFF, DEBUG_STDERR, DEBUG_SYSLOG} debug_t;
/*
* These exist for the use of local sockets only when we are
* collecting responses from all cluster nodes
@@ -76,7 +78,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,8 +115,10 @@ 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 debuglog(const char *fmt, ... );
extern void process_message(struct local_client *client, const char *buf,
int len, const char *csid);
extern void debuglog(const char *fmt, ... )
__attribute__ ((format(printf, 1, 2)));
int sync_lock(const char *resource, int mode, int flags, int *lockid);
int sync_unlock(const char *resource, int lockid);

View File

@@ -1,226 +0,0 @@
/******************************************************************************
*******************************************************************************
**
** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
** Copyright (C) 2004 Red Hat, Inc. All rights reserved.
**
** 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.
**
*******************************************************************************
******************************************************************************/
/* CMAN socket interface header,
may be include by user or kernel code */
#ifndef __CNXMAN_SOCKET_H
#define __CNXMAN_SOCKET_H
/* A currently unused number. TIPC also uses this number and you're unlikely
to be using both.
*/
#define AF_CLUSTER 30
#define PF_CLUSTER AF_CLUSTER
/* Protocol(socket) types */
#define CLPROTO_MASTER 2
#define CLPROTO_CLIENT 3
/* ioctls -- should register these properly */
#define SIOCCLUSTER_NOTIFY _IOW('x', 0x01, int)
#define SIOCCLUSTER_REMOVENOTIFY _IO( 'x', 0x02)
#define SIOCCLUSTER_GETMEMBERS _IOR('x', 0x03, struct cl_cluster_nodelist)
#define SIOCCLUSTER_SETEXPECTED_VOTES _IOW('x', 0x04, int)
#define SIOCCLUSTER_ISQUORATE _IO( 'x', 0x05)
#define SIOCCLUSTER_ISLISTENING _IOW('x', 0x06, struct cl_listen_request)
#define SIOCCLUSTER_GETALLMEMBERS _IOR('x', 0x07, struct cl_cluster_nodelist)
#define SIOCCLUSTER_SET_VOTES _IOW('x', 0x08, int)
#define SIOCCLUSTER_GET_VERSION _IOR('x', 0x09, struct cl_version)
#define SIOCCLUSTER_SET_VERSION _IOW('x', 0x0a, struct cl_version)
#define SIOCCLUSTER_ISACTIVE _IO( 'x', 0x0b)
#define SIOCCLUSTER_KILLNODE _IOW('x', 0x0c, int)
#define SIOCCLUSTER_GET_JOINCOUNT _IO( 'x', 0x0d)
#define SIOCCLUSTER_SERVICE_REGISTER _IOW('x', 0x0e, char)
#define SIOCCLUSTER_SERVICE_UNREGISTER _IO('x', 0x0f)
#define SIOCCLUSTER_SERVICE_JOIN _IO( 'x', 0x10)
#define SIOCCLUSTER_SERVICE_LEAVE _IO( 'x', 0x20)
#define SIOCCLUSTER_SERVICE_SETSIGNAL _IOW('x', 0x30, int)
#define SIOCCLUSTER_SERVICE_STARTDONE _IOW('x', 0x40, unsigned int)
#define SIOCCLUSTER_SERVICE_GETEVENT _IOR('x', 0x50, struct cl_service_event)
#define SIOCCLUSTER_SERVICE_GETMEMBERS _IOR('x', 0x60, struct cl_cluster_nodelist)
#define SIOCCLUSTER_SERVICE_GLOBALID _IOR('x', 0x70, uint32_t)
#define SIOCCLUSTER_SERVICE_SETLEVEL _IOR('x', 0x80, int)
#define SIOCCLUSTER_GETNODE _IOWR('x', 0x90, struct cl_cluster_node)
#define SIOCCLUSTER_BARRIER _IOW('x', 0x0a0, struct cl_barrier_info)
/* These were setsockopts */
#define SIOCCLUSTER_PASS_SOCKET _IOW('x', 0x0b0, struct cl_passed_sock)
#define SIOCCLUSTER_SET_NODENAME _IOW('x', 0x0b1, char *)
#define SIOCCLUSTER_SET_NODEID _IOW('x', 0x0b2, int)
#define SIOCCLUSTER_JOIN_CLUSTER _IOW('x', 0x0b3, struct cl_join_cluster_info)
#define SIOCCLUSTER_LEAVE_CLUSTER _IOW('x', 0x0b4, int)
/* Maximum size of a cluster message */
#define CMAN_MAX_CLUSTER_MESSAGE 1500
#define CMAN_MAX_CLUSTER_MEMBER_NAME_LEN 255
#define MAX_BARRIER_NAME_LEN 33
#define MAX_SA_ADDR_LEN 12
#define MAX_CLUSTER_NAME_LEN 16
/* Well-known cluster port numbers */
#define CLUSTER_PORT_MEMBERSHIP 1 /* Mustn't block during cluster
* transitions! */
#define CLUSTER_PORT_SERVICES 2
#define CLUSTER_PORT_SYSMAN 10 /* Remote execution daemon */
#define CLUSTER_PORT_CLVMD 11 /* Cluster LVM daemon */
#define CLUSTER_PORT_SLM 12 /* LVM SLM (simple lock manager) */
/* Port numbers above this will be blocked when the cluster is inquorate or in
* transition */
#define HIGH_PROTECTED_PORT 9
/* Reasons for leaving the cluster */
#define CLUSTER_LEAVEFLAG_DOWN 0 /* Normal shutdown */
#define CLUSTER_LEAVEFLAG_KILLED 1
#define CLUSTER_LEAVEFLAG_PANIC 2
#define CLUSTER_LEAVEFLAG_REMOVED 3 /* This one can reduce quorum */
#define CLUSTER_LEAVEFLAG_REJECTED 4 /* Not allowed into the cluster in the
* first place */
#define CLUSTER_LEAVEFLAG_INCONSISTENT 5 /* Our view of the cluster is
* in a minority */
#define CLUSTER_LEAVEFLAG_DEAD 6 /* Discovered to be dead */
#define CLUSTER_LEAVEFLAG_FORCE 0x10 /* Forced by command-line */
/* OOB messages sent to a local socket */
#define CLUSTER_OOB_MSG_PORTCLOSED 1
#define CLUSTER_OOB_MSG_STATECHANGE 2
#define CLUSTER_OOB_MSG_SERVICEEVENT 3
/* Sendmsg flags, these are above the normal sendmsg flags so they don't
* interfere */
#define MSG_NOACK 0x010000 /* Don't need an ACK for this message */
#define MSG_QUEUE 0x020000 /* Queue the message for sending later */
#define MSG_MULTICAST 0x080000 /* Message was sent to all nodes in the cluster
*/
#define MSG_ALLINT 0x100000 /* Send out of all interfaces */
#define MSG_REPLYEXP 0x200000 /* Reply is expected */
typedef enum { NODESTATE_REMOTEMEMBER, NODESTATE_JOINING, NODESTATE_MEMBER,
NODESTATE_DEAD } nodestate_t;
struct sockaddr_cl {
unsigned short scl_family;
unsigned char scl_flags;
unsigned char scl_port;
int scl_nodeid;
};
/*
* This is how we pass the multicast & receive sockets into kernel space.
*/
struct cl_passed_sock {
int fd; /* FD of master socket to do multicast on */
int number; /* Socket number, to match up recvonly & bcast
* sockets */
int multicast; /* Is it multicast or receive ? */
};
/* Cluster configuration info passed when we join the cluster */
struct cl_join_cluster_info {
unsigned char votes;
unsigned int expected_votes;
unsigned int two_node;
unsigned int config_version;
char cluster_name[17];
};
/* This is the structure, per node, returned from the membership ioctl */
struct cl_cluster_node {
unsigned int size;
unsigned int node_id;
unsigned int us;
unsigned int leave_reason;
unsigned int incarnation;
nodestate_t state;
char name[CMAN_MAX_CLUSTER_MEMBER_NAME_LEN];
unsigned char votes;
};
/* The struct passed to the membership ioctls */
struct cl_cluster_nodelist {
uint32_t max_members;
struct cl_cluster_node *nodes;
};
/* Structure passed to SIOCCLUSTER_ISLISTENING */
struct cl_listen_request {
unsigned char port;
int nodeid;
};
/* A Cluster PORTCLOSED message - received by a local user as an OOB message */
struct cl_portclosed_oob {
unsigned char cmd; /* CLUSTER_OOB_MSG_PORTCLOSED */
unsigned char port;
};
/* Get all version numbers or set the config version */
struct cl_version {
unsigned int major;
unsigned int minor;
unsigned int patch;
unsigned int config;
};
/* structure passed to barrier ioctls */
struct cl_barrier_info {
char cmd;
char name[MAX_BARRIER_NAME_LEN];
unsigned int flags;
unsigned long arg;
};
typedef enum { SERVICE_EVENT_STOP, SERVICE_EVENT_START, SERVICE_EVENT_FINISH,
SERVICE_EVENT_LEAVEDONE } service_event_t;
typedef enum { SERVICE_START_FAILED, SERVICE_START_JOIN, SERVICE_START_LEAVE }
service_start_t;
struct cl_service_event {
service_event_t type;
service_start_t start_type;
unsigned int event_id;
unsigned int last_stop;
unsigned int last_start;
unsigned int last_finish;
unsigned int node_count;
};
/* Commands to the barrier ioctl */
#define BARRIER_IOCTL_REGISTER 1
#define BARRIER_IOCTL_CHANGE 2
#define BARRIER_IOCTL_DELETE 3
#define BARRIER_IOCTL_WAIT 4
/* Attributes of a barrier - bitmask */
#define BARRIER_ATTR_AUTODELETE 1
#define BARRIER_ATTR_MULTISTEP 2
#define BARRIER_ATTR_MANUAL 4
#define BARRIER_ATTR_ENABLED 8
#define BARRIER_ATTR_CALLBACK 16
/* Attribute setting commands */
#define BARRIER_SETATTR_AUTODELETE 1
#define BARRIER_SETATTR_MULTISTEP 2
#define BARRIER_SETATTR_ENABLED 3
#define BARRIER_SETATTR_NODES 4
#define BARRIER_SETATTR_CALLBACK 5
#define BARRIER_SETATTR_TIMEOUT 6
#endif

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
* Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
@@ -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"
@@ -42,15 +42,19 @@
/* LVM2 headers */
#include "toolcontext.h"
#include "lvmcache.h"
#include "log.h"
#include "activate.h"
#include "locking.h"
#include "archiver.h"
#include "defaults.h"
static struct cmd_context *cmd = NULL;
static struct dm_hash_table *lv_hash = NULL;
static pthread_mutex_t lv_hash_lock;
static pthread_mutex_t lvm_lock;
static char last_error[1024];
static int suspended = 0;
struct lv_info {
int lock_id;
@@ -221,7 +225,7 @@ static int do_activate_lv(char *resource, unsigned char lock_flags, int mode)
}
/* If it's suspended then resume it */
if (!lv_info_by_lvid(cmd, resource, &lvi, 0))
if (!lv_info_by_lvid(cmd, resource, &lvi, 0, 0))
return EIO;
if (lvi.suspended)
@@ -267,7 +271,7 @@ static int do_suspend_lv(char *resource)
}
/* Only suspend it if it exists */
if (!lv_info_by_lvid(cmd, resource, &lvi, 0))
if (!lv_info_by_lvid(cmd, resource, &lvi, 0, 0))
return EIO;
if (lvi.exists) {
@@ -311,10 +315,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)) {
if (do_refresh_cache()) {
log_error("Updated config file invalid. Aborting.");
pthread_mutex_unlock(&lvm_lock);
return EINVAL;
}
}
@@ -335,11 +341,15 @@ int do_lock_lv(unsigned char command, unsigned char lock_flags, char *resource)
case LCK_LV_SUSPEND:
status = do_suspend_lv(resource);
if (!status)
suspended++;
break;
case LCK_UNLOCK:
case LCK_LV_RESUME: /* if active */
status = do_resume_lv(resource);
if (!status)
suspended--;
break;
case LCK_LV_ACTIVATE:
@@ -367,6 +377,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 +404,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 +419,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, 0);
pthread_mutex_unlock(&lvm_lock);
if (!status)
return EIO;
if (lvi.exists) {
@@ -421,8 +437,8 @@ int post_lock_lv(unsigned char command, unsigned char lock_flags,
return 0;
}
/* Check if a VG is un use by LVM1 so we don't stomp on it */
int do_check_lvm1(char *vgname)
/* Check if a VG is in use by LVM1 so we don't stomp on it */
int do_check_lvm1(const char *vgname)
{
int status;
@@ -433,9 +449,15 @@ int do_check_lvm1(char *vgname)
int do_refresh_cache()
{
int ret;
DEBUGLOG("Refreshing context\n");
log_notice("Refreshing context");
return refresh_toolcontext(cmd)==1?0:-1;
ret = refresh_toolcontext(cmd);
init_full_scan_done(0);
lvmcache_label_scan(cmd, 2);
return ret==1?0:-1;
}
@@ -448,7 +470,7 @@ static void drop_vg_locks()
char line[255];
FILE *vgs =
popen
("lvm pvs --nolocking --noheadings -o vg_name", "r");
("lvm pvs --config 'log{command_names=0 prefix=\"\"}' --nolocking --noheadings -o vg_name", "r");
sync_unlock("P_orphans", LCK_EXCL);
@@ -473,7 +495,8 @@ static void drop_vg_locks()
sync_unlock(vg, LCK_EXCL);
}
fclose(vgs);
if (fclose(vgs))
DEBUGLOG("vgs fclose failed: %s\n", strerror(errno));
}
/*
@@ -488,7 +511,7 @@ static void *get_initial_state()
char line[255];
FILE *lvs =
popen
("lvm lvs --nolocking --noheadings -o vg_uuid,lv_uuid,lv_attr,vg_attr",
("lvm lvs --config 'log{command_names=0 prefix=\"\"}' --nolocking --noheadings -o vg_uuid,lv_uuid,lv_attr,vg_attr",
"r");
if (!lvs)
@@ -523,15 +546,25 @@ static void *get_initial_state()
}
}
}
fclose(lvs);
if (fclose(lvs))
DEBUGLOG("lvs fclose failed: %s\n", strerror(errno));
return NULL;
}
static void lvm2_log_fn(int level, const char *file, int line,
const char *message)
{
/* Send messages to the normal LVM2 logging system too,
so we get debug output when it's asked for.
We need to NULL the function ptr otherwise it will just call
back into here! */
init_log_fn(NULL);
print_log(level, file, line, "%s", message);
init_log_fn(lvm2_log_fn);
/*
* 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)
@@ -570,19 +603,44 @@ 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);
}
/* Backups up the LVM metadata if it's changed */
void lvm_do_backup(const char *vgname)
{
struct volume_group * vg;
int consistent = 0;
DEBUGLOG("Triggering backup of VG metadata for %s. suspended=%d\n", vgname, suspended);
vg = vg_read(cmd, vgname, NULL /*vgid*/, &consistent);
if (vg) {
if (consistent)
check_current_backup(vg);
}
else {
log_error("Error backing up metadata, can't find VG for group %s", vgname);
}
}
/* Called to initialise the LVM context of the daemon */
int init_lvm(int using_gulm)
{
if (!(cmd = create_toolcontext(NULL, 0))) {
if (!(cmd = create_toolcontext(NULL, 0, 1))) {
log_error("Failed to allocate command context");
return 0;
}
/* Use LOG_DAEMON for syslog messages instead of LOG_USER */
init_syslog(LOG_DAEMON);
init_debug(_LOG_ERR);
openlog("clvmd", LOG_PID, LOG_DAEMON);
init_debug(cmd->current_settings.debug);
init_verbose(cmd->current_settings.verbose + VERBOSE_BASE_LEVEL);
set_activation(cmd->current_settings.activation);
archive_enable(cmd, cmd->current_settings.archive);
backup_enable(cmd, cmd->current_settings.backup);
cmd->cmd_line = (char *)"clvmd";
/* Check lvm.conf is setup for cluster-LVM */
check_config();

View File

@@ -24,11 +24,11 @@ extern int do_lock_lv(unsigned char lock_cmd, unsigned char lock_flags,
char *resource);
extern int post_lock_lv(unsigned char lock_cmd, unsigned char lock_flags,
char *resource);
extern int do_check_lvm1(char *vgname);
extern int do_check_lvm1(const char *vgname);
extern int do_refresh_cache(void);
extern int init_lvm(int using_gulm);
extern void init_lvhash(void);
extern void lvm_do_backup(const char *vgname);
extern int hold_unlock(char *resource);
extern int hold_lock(char *resource, int mode, int flags);
extern void unlock_all(void);

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
@@ -26,6 +26,7 @@
#include <libdevmapper.h>
#include <stdint.h>
#include <stdio.h>
#include <limits.h>
#include "clvm.h"
#include "refresh_clvmd.h"
@@ -45,7 +46,7 @@ typedef struct lvm_response {
static int _clvmd_sock = -1;
/* Open connection to the Cluster Manager daemon */
/* Open connection to the clvm daemon */
static int _open_local_sock(void)
{
int local_socket;
@@ -79,7 +80,7 @@ static int _open_local_sock(void)
}
/* Send a request and return the status */
static int _send_request(char *inbuf, int inlen, char **retbuf)
static int _send_request(const char *inbuf, int inlen, char **retbuf)
{
char outbuf[PIPE_BUF];
struct clvm_header *outheader = (struct clvm_header *) outbuf;
@@ -318,3 +319,46 @@ int refresh_clvmd()
return status;
}
int debug_clvmd(int level, int clusterwide)
{
int num_responses;
char args[1];
const char *nodes;
lvm_response_t *response;
int saved_errno;
int status;
int i;
args[0] = level;
if (clusterwide)
nodes = "*";
else
nodes = ".";
status = _cluster_request(CLVMD_CMD_SET_DEBUG, nodes, args, 1, &response, &num_responses);
/* If any nodes were down then display them and return an error */
for (i = 0; i < num_responses; i++) {
if (response[i].status == EHOSTDOWN) {
fprintf(stderr, "clvmd not running on node %s",
response[i].node);
status = 0;
errno = response[i].status;
} else if (response[i].status) {
fprintf(stderr, "Error setting debug on node %s: %s",
response[i].node,
response[i].response[0] ?
response[i].response :
strerror(response[i].status));
status = 0;
errno = response[i].status;
}
}
saved_errno = errno;
_cluster_free_request(response, num_responses);
errno = saved_errno;
return status;
}

View File

@@ -1,2 +1,18 @@
int refresh_clvmd(void);
/*
* Copyright (C) 2007 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
*/
int refresh_clvmd(void);
int debug_clvmd(int level, int clusterwide);

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));
@@ -181,7 +177,7 @@ int get_main_gulm_cluster_fd()
/* Read on main comms (listen) socket, accept it */
int cluster_fd_gulm_callback(struct local_client *fd, char *buf, int len, char *csid,
int cluster_fd_gulm_callback(struct local_client *fd, char *buf, int len, const char *csid,
struct local_client **new_client)
{
int newfd;
@@ -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;
@@ -394,7 +390,7 @@ static int tcp_send_message(void *buf, int msglen, unsigned char *csid, const ch
}
int gulm_cluster_send_message(void *buf, int msglen, char *csid, const char *errtext)
int gulm_cluster_send_message(void *buf, int msglen, const char *csid, const char *errtext)
{
int status=0;
@@ -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);
int cluster_fd_gulm_callback(struct local_client *fd, char *buf, int len, const char *csid, struct local_client **new_client);
int gulm_cluster_send_message(void *buf, int msglen, const 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

@@ -1,5 +1,5 @@
#
# Copyright (C) 2005 Red Hat, Inc. All rights reserved.
# Copyright (C) 2005-2007 Red Hat, Inc. All rights reserved.
#
# This file is part of the device-mapper userspace tools.
#

View File

@@ -77,6 +77,19 @@ static int _debug = 0;
*/
static pthread_mutex_t _global_mutex;
/*
There are three states a thread can attain (see struct
thread_status, field int status):
- DM_THREAD_RUNNING: thread has started up and is either working or
waiting for events... transitions to either SHUTDOWN or DONE
- DM_THREAD_SHUTDOWN: thread is still doing something, but it is
supposed to terminate (and transition to DONE) as soon as it
finishes whatever it was doing at the point of flipping state to
SHUTDOWN... the thread is still on the thread list
- DM_THREAD_DONE: thread has terminated and has been moved over to
unused thread list, cleanup pending
*/
#define DM_THREAD_RUNNING 0
#define DM_THREAD_SHUTDOWN 1
#define DM_THREAD_DONE 2
@@ -106,7 +119,7 @@ struct dso_data {
* DM_DEVICE_STATUS). It should not destroy it.
* The caller must dispose of the task.
*/
void (*process_event)(struct dm_task *dmt, enum dm_event_mask event);
void (*process_event)(struct dm_task *dmt, enum dm_event_mask event, void **user);
/*
* Device registration.
@@ -117,7 +130,7 @@ struct dso_data {
* and activate a mapping).
*/
int (*register_device)(const char *device, const char *uuid, int major,
int minor);
int minor, void **user);
/*
* Device unregistration.
@@ -127,12 +140,13 @@ struct dso_data {
* steps (eg, deactivate mapping, metadata update).
*/
int (*unregister_device)(const char *device, const char *uuid,
int major, int minor);
int major, int minor, void **user);
};
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 {
@@ -166,13 +180,16 @@ struct thread_status {
} device;
uint32_t event_nr; /* event number */
int processing; /* Set when event is being processed */
int status; /* running/shutdown/done */
int status; /* see DM_THREAD_{RUNNING,SHUTDOWN,DONE}
constants above */
enum dm_event_mask events; /* bitfield for event filter. */
enum dm_event_mask current_events; /* bitfield for occured events. */
struct dm_task *current_task;
time_t next_time;
uint32_t timeout;
struct list timeout_list;
void *dso_private; /* dso per-thread status variable */
};
static LIST_INIT(_thread_registry);
static LIST_INIT(_thread_registry_unused);
@@ -209,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;
}
@@ -228,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);
@@ -241,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;
}
@@ -304,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);
@@ -326,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, ' ')) {
@@ -601,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));
@@ -630,7 +654,8 @@ static int _do_register_device(struct thread_status *thread)
return thread->dso_data->register_device(thread->device.name,
thread->device.uuid,
thread->device.major,
thread->device.minor);
thread->device.minor,
&(thread->dso_private));
}
/* Unregister a device with the DSO. */
@@ -639,13 +664,14 @@ static int _do_unregister_device(struct thread_status *thread)
return thread->dso_data->unregister_device(thread->device.name,
thread->device.uuid,
thread->device.major,
thread->device.minor);
thread->device.minor,
&(thread->dso_private));
}
/* Process an event in the DSO. */
static void _do_process_event(struct thread_status *thread, struct dm_task *task)
{
thread->dso_data->process_event(task, thread->current_events);
thread->dso_data->process_event(task, thread->current_events, &(thread->dso_private));
}
/* Thread cleanup handler to unregister device. */
@@ -789,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);
}
@@ -857,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;
}
@@ -1038,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)
@@ -1048,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();
@@ -1107,22 +1129,25 @@ static int _get_registered_dev(struct message_data *message_data, int next)
if (!hit)
goto out;
goto out; /* FIXME the next == 1 thing is currently horridly
broken, do something about it... */
thread = hit;
do {
while (1) {
if (list_end(&_thread_registry, &thread->list))
goto out;
thread = list_item(thread->list.n, struct thread_status);
} while (!_want_registered_device(message_data->dso_name, NULL, thread));
if (_want_registered_device(message_data->dso_name, NULL, thread)) {
hit = thread;
break;
}
}
_unlock_mutex();
return _registered_device(message_data, thread);
return _registered_device(message_data, hit);
out:
_unlock_mutex();
return -ENOENT;
}
@@ -1159,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;
@@ -1354,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;
@@ -1384,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;
@@ -1545,7 +1579,8 @@ static int _set_oom_adj(int val)
}
fprintf(fp, "%i", val);
fclose(fp);
if (dm_fclose(fp))
perror(OOM_ADJ_FILE ": fclose failed");
return 1;
}
@@ -1562,7 +1597,7 @@ static void _daemonize(void)
sigemptyset(&my_sigset);
if (sigprocmask(SIG_SETMASK, &my_sigset, NULL) < 0) {
fprintf(stderr, "Unable to restore signals.");
fprintf(stderr, "Unable to restore signals.\n");
exit(EXIT_FAILURE);
}
signal(SIGTERM, &_exit_handler);

View File

@@ -1,3 +1,17 @@
/*
* Copyright (C) 2005-2007 Red Hat, Inc. All rights reserved.
*
* This file is part of the device-mapper userspace tools.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __DMEVENTD_DOT_H__
#define __DMEVENTD_DOT_H__
@@ -20,6 +34,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

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2005 Red Hat, Inc. All rights reserved.
* Copyright (C) 2005-2007 Red Hat, Inc. All rights reserved.
*
* This file is part of the device-mapper userspace tools.
*
@@ -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,35 +652,34 @@ 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;
}
/*
* dm_event_get_registered_device
* @dso_name
* @device_path
* @mask
* @next
*
* Returns: 0 if handler found, error (-ENOMEM, -ENOENT) otherwise
* Returns 0 if handler found; error (-ENOMEM, -ENOENT) otherwise.
*/
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;
@@ -647,6 +700,7 @@ int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next)
}
dm_task_destroy(dmt);
dmt = NULL;
if (msg.data) {
dm_free(msg.data);
@@ -667,6 +721,17 @@ 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);
reply_dso = NULL;
}
if (reply_uuid) {
dm_free(reply_uuid);
reply_uuid = NULL;
}
dmevh->dev_name = dm_strdup(dm_task_get_name(dmt));
if (!dmevh->dev_name) {
ret = -ENOMEM;
@@ -689,16 +754,29 @@ 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);
if (dmt)
dm_task_destroy(dmt);
return ret;
}
#if 0 /* left out for now */
static char *_skip_string(char *src, const int delimiter)
{
src = srtchr(src, delimiter);
if (src && *(src + 1))
return src + 1;
return NULL;
}
int dm_event_set_timeout(const char *device_path, uint32_t timeout)
{
struct dm_event_daemon_message msg;
struct dm_event_daemon_message msg = { 0, 0, NULL };
if (!device_exists(device_path))
return -ENODEV;
@@ -710,13 +788,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

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2005 Red Hat, Inc. All rights reserved.
* Copyright (C) 2005-2007 Red Hat, Inc. All rights reserved.
*
* This file is part of the device-mapper userspace tools.
*
@@ -98,9 +98,9 @@ int dm_event_unregister_handler(const struct dm_event_handler *dmevh);
/* Prototypes for DSO interface, see dmeventd.c, struct dso_data for
detailed descriptions. */
void process_event(struct dm_task *dmt, enum dm_event_mask evmask);
int register_device(const char *device_name, const char *uuid, int major, int minor);
void process_event(struct dm_task *dmt, enum dm_event_mask evmask, void **user);
int register_device(const char *device_name, const char *uuid, int major, int minor, void **user);
int unregister_device(const char *device_name, const char *uuid, int major,
int minor);
int minor, void **user);
#endif

View File

@@ -2,7 +2,7 @@
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
# Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
#
# This file is part of the LVM2.
# This 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
@@ -16,7 +16,7 @@ srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
SUBDIRS += mirror
SUBDIRS += mirror snapshot
include $(top_srcdir)/make.tmpl

View File

@@ -2,7 +2,7 @@
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
# Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
#
# This file is part of the LVM2.
# This 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

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>
@@ -125,8 +125,9 @@ out_parse:
return ME_IGNORE;
}
static void _temporary_log_fn(int level, const char *file,
int line, const char *format)
static void _temporary_log_fn(int level, const char *file __attribute((unused)),
int line __attribute((unused)),
const char *format)
{
if (!strncmp(format, "WARNING: ", 9) && (level < 5))
syslog(LOG_CRIT, "%s", format);
@@ -151,7 +152,7 @@ static int _remove_failed_devices(const char *device)
}
/* FIXME Is any sanity-checking required on %s? */
if (CMD_SIZE <= snprintf(cmd_str, CMD_SIZE, "vgreduce --removemissing %s", vg)) {
if (CMD_SIZE <= snprintf(cmd_str, CMD_SIZE, "vgreduce --config devices{ignore_suspended_devices=1} --removemissing %s", vg)) {
/* this error should be caught above, but doesn't hurt to check again */
syslog(LOG_ERR, "Unable to form LVM command: Device name too long");
dm_pool_empty(_mem_pool); /* FIXME: not safe with multiple threads */
@@ -164,7 +165,9 @@ static int _remove_failed_devices(const char *device)
return (r == 1) ? 0 : -1;
}
void process_event(struct dm_task *dmt, enum dm_event_mask event)
void process_event(struct dm_task *dmt,
enum dm_event_mask event __attribute((unused)),
void **unused __attribute((unused)))
{
void *next = NULL;
uint64_t start, length;
@@ -221,7 +224,11 @@ void process_event(struct dm_task *dmt, enum dm_event_mask event)
pthread_mutex_unlock(&_event_mutex);
}
int register_device(const char *device, const char *uuid, int major, int minor)
int register_device(const char *device,
const char *uuid __attribute((unused)),
int major __attribute((unused)),
int minor __attribute((unused)),
void **unused __attribute((unused)))
{
int r = 0;
@@ -257,7 +264,11 @@ out:
return r;
}
int unregister_device(const char *device, const char *uuid, int major, int minor)
int unregister_device(const char *device,
const char *uuid __attribute((unused)),
int major __attribute((unused)),
int minor __attribute((unused)),
void **unused __attribute((unused)))
{
pthread_mutex_lock(&_register_mutex);

View File

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

View File

@@ -1,6 +1,6 @@
#
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
# Copyright (C) 2004 Red Hat, Inc. All rights reserved.
# Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
#
# This file is part of the LVM2.
#
@@ -16,16 +16,21 @@ srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
SOURCES = fsadm.c
INCLUDES += -I${top_srcdir}/tools
CLDFLAGS += -L${top_srcdir}/tools -ldevmapper -llvm2cmd
TARGETS = fsadm
SOURCES = dmeventd_snapshot.c
ifeq ("@LIB_SUFFIX@","dylib")
LIB_SHARED = libdevmapper-event-lvm2snapshot.dylib
else
LIB_SHARED = libdevmapper-event-lvm2snapshot.so
endif
include $(top_srcdir)/make.tmpl
fsadm: $(OBJECTS)
$(CC) -o $@ $(CFLAGS) $(OBJECTS) -rdynamic
install: fsadm
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) fsadm \
$(sbindir)/fsadm
install: libdevmapper-event-lvm2snapshot.$(LIB_SUFFIX)
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
$(libdir)/$<.$(LIB_VERSION)
$(LN_S) -f $<.$(LIB_VERSION) $(libdir)/$<

View File

@@ -0,0 +1,232 @@
/*
* Copyright (C) 2007-2008 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "libdevmapper.h"
#include "libdevmapper-event.h"
#include "lvm2cmd.h"
#include "lvm-string.h"
#include <errno.h>
#include <signal.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <syslog.h> /* FIXME Replace syslog with multilog */
/* FIXME Missing openlog? */
/* First warning when snapshot is 80% full. */
#define WARNING_THRESH 80
/* Further warnings at 85%, 90% and 95% fullness. */
#define WARNING_STEP 5
static pthread_mutex_t _register_mutex = PTHREAD_MUTEX_INITIALIZER;
/*
* Number of active registrations.
*/
static int _register_count = 0;
static struct dm_pool *_mem_pool = NULL;
static void *_lvm_handle = NULL;
struct snap_status {
int invalid;
int used;
int max;
};
/*
* Currently only one event can be processed at a time.
*/
static pthread_mutex_t _event_mutex = PTHREAD_MUTEX_INITIALIZER;
static void _temporary_log_fn(int level,
const char *file __attribute((unused)),
int line __attribute((unused)),
const char *format)
{
if (!strncmp(format, "WARNING: ", 9) && (level < 5))
syslog(LOG_CRIT, "%s", format);
else
syslog(LOG_DEBUG, "%s", format);
}
/* FIXME possibly reconcile this with target_percent when we gain
access to regular LVM library here. */
static void _parse_snapshot_params(char *params, struct snap_status *stat)
{
char *p;
/*
* xx/xx -- fractions used/max
* Invalid -- snapshot invalidated
* Unknown -- status unknown
*/
stat->used = stat->max = 0;
if (!strncmp(params, "Invalid", 7)) {
stat->invalid = 1;
return;
}
/*
* When we return without setting non-zero max, the parent is
* responsible for reporting errors.
*/
if (!strncmp(params, "Unknown", 7))
return;
if (!(p = strstr(params, "/")))
return;
*p = '\0';
p++;
stat->used = atoi(params);
stat->max = atoi(p);
}
/* send unregister command to itself */
static void _unregister_self(struct dm_task *dmt)
{
const char *name = dm_task_get_name(dmt);
struct dm_event_handler *dmevh;
if (!(dmevh = dm_event_handler_create()))
return;
if (dm_event_handler_set_dev_name(dmevh, name))
goto fail;
dm_event_handler_set_event_mask(dmevh, DM_EVENT_ALL_ERRORS|DM_EVENT_TIMEOUT);
dm_event_unregister_handler(dmevh);
fail:
dm_event_handler_destroy(dmevh);
}
void process_event(struct dm_task *dmt,
enum dm_event_mask event __attribute((unused)),
void **private)
{
void *next = NULL;
uint64_t start, length;
char *target_type = NULL;
char *params;
struct snap_status stat = { 0 };
const char *device = dm_task_get_name(dmt);
int percent, *percent_warning = (int*)private;
/* No longer monitoring, waiting for remove */
if (!*percent_warning)
return;
if (pthread_mutex_trylock(&_event_mutex)) {
syslog(LOG_NOTICE, "Another thread is handling an event. Waiting...");
pthread_mutex_lock(&_event_mutex);
}
dm_get_next_target(dmt, next, &start, &length, &target_type, &params);
if (!target_type)
goto out;
_parse_snapshot_params(params, &stat);
/*
* If the snapshot has been invalidated or we failed to parse
* the status string. Report the full status string to syslog.
*/
if (stat.invalid || !stat.max) {
syslog(LOG_ERR, "Snapshot %s changed state to: %s\n", device, params);
_unregister_self(dmt);
*percent_warning = 0;
goto out;
}
percent = 100 * stat.used / stat.max;
if (percent >= *percent_warning) {
syslog(LOG_WARNING, "Snapshot %s is now %i%% full.\n", device, percent);
/* Print warning on the next multiple of WARNING_STEP. */
*percent_warning = (percent / WARNING_STEP) * WARNING_STEP + WARNING_STEP;
}
out:
pthread_mutex_unlock(&_event_mutex);
}
int register_device(const char *device,
const char *uuid __attribute((unused)),
int major __attribute((unused)),
int minor __attribute((unused)),
void **private)
{
int r = 0;
int *percent_warning = (int*)private;
pthread_mutex_lock(&_register_mutex);
/*
* Need some space for allocations. 1024 should be more
* than enough for what we need (device mapper name splitting)
*/
if (!_mem_pool && !(_mem_pool = dm_pool_create("snapshot_dso", 1024)))
goto out;
*percent_warning = WARNING_THRESH; /* Print warning if snapshot is full */
if (!_lvm_handle) {
lvm2_log_fn(_temporary_log_fn);
if (!(_lvm_handle = lvm2_init())) {
dm_pool_destroy(_mem_pool);
_mem_pool = NULL;
goto out;
}
lvm2_log_level(_lvm_handle, LVM2_LOG_SUPPRESS);
/* FIXME Temporary: move to dmeventd core */
lvm2_run(_lvm_handle, "_memlock_inc");
}
syslog(LOG_INFO, "Monitoring snapshot %s\n", device);
_register_count++;
r = 1;
out:
pthread_mutex_unlock(&_register_mutex);
return r;
}
int unregister_device(const char *device,
const char *uuid __attribute((unused)),
int major __attribute((unused)),
int minor __attribute((unused)),
void **unused __attribute((unused)))
{
pthread_mutex_lock(&_register_mutex);
syslog(LOG_INFO, "No longer monitoring snapshot %s\n",
device);
if (!--_register_count) {
dm_pool_destroy(_mem_pool);
_mem_pool = NULL;
lvm2_run(_lvm_handle, "_memlock_dec");
lvm2_exit(_lvm_handle);
_lvm_handle = NULL;
}
pthread_mutex_unlock(&_register_mutex);
return 1;
}

View File

@@ -2,7 +2,7 @@
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
# Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
#
# This file is part of the LVM2.
# This 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
@@ -16,7 +16,7 @@ srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
SUBDIRS += mirror
SUBDIRS += mirror snapshot
include $(top_srcdir)/make.tmpl

View File

@@ -2,7 +2,7 @@
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
# Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
#
# This file is part of the LVM2.
# This 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

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>
@@ -125,8 +125,9 @@ out_parse:
return ME_IGNORE;
}
static void _temporary_log_fn(int level, const char *file,
int line, const char *format)
static void _temporary_log_fn(int level, const char *file __attribute((unused)),
int line __attribute((unused)),
const char *format)
{
if (!strncmp(format, "WARNING: ", 9) && (level < 5))
syslog(LOG_CRIT, "%s", format);
@@ -151,7 +152,7 @@ static int _remove_failed_devices(const char *device)
}
/* FIXME Is any sanity-checking required on %s? */
if (CMD_SIZE <= snprintf(cmd_str, CMD_SIZE, "vgreduce --removemissing %s", vg)) {
if (CMD_SIZE <= snprintf(cmd_str, CMD_SIZE, "vgreduce --config devices{ignore_suspended_devices=1} --removemissing %s", vg)) {
/* this error should be caught above, but doesn't hurt to check again */
syslog(LOG_ERR, "Unable to form LVM command: Device name too long");
dm_pool_empty(_mem_pool); /* FIXME: not safe with multiple threads */
@@ -164,7 +165,9 @@ static int _remove_failed_devices(const char *device)
return (r == 1) ? 0 : -1;
}
void process_event(struct dm_task *dmt, enum dm_event_mask event)
void process_event(struct dm_task *dmt,
enum dm_event_mask event __attribute((unused)),
void **unused __attribute((unused)))
{
void *next = NULL;
uint64_t start, length;
@@ -221,7 +224,11 @@ void process_event(struct dm_task *dmt, enum dm_event_mask event)
pthread_mutex_unlock(&_event_mutex);
}
int register_device(const char *device, const char *uuid, int major, int minor)
int register_device(const char *device,
const char *uuid __attribute((unused)),
int major __attribute((unused)),
int minor __attribute((unused)),
void **unused __attribute((unused)))
{
int r = 0;
@@ -257,7 +264,11 @@ out:
return r;
}
int unregister_device(const char *device, const char *uuid, int major, int minor)
int unregister_device(const char *device,
const char *uuid __attribute((unused)),
int major __attribute((unused)),
int minor __attribute((unused)),
void **unused __attribute((unused)))
{
pthread_mutex_lock(&_register_mutex);

View File

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

View File

@@ -0,0 +1,36 @@
#
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
# Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
#
# This file is part of the LVM2.
#
# This copyrighted material is made available to anyone wishing to use,
# modify, copy, or redistribute it subject to the terms and conditions
# of the GNU General Public License v.2.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
INCLUDES += -I${top_srcdir}/tools
CLDFLAGS += -L${top_srcdir}/tools -ldevmapper -llvm2cmd
SOURCES = dmeventd_snapshot.c
ifeq ("@LIB_SUFFIX@","dylib")
LIB_SHARED = libdevmapper-event-lvm2snapshot.dylib
else
LIB_SHARED = libdevmapper-event-lvm2snapshot.so
endif
include $(top_srcdir)/make.tmpl
install: libdevmapper-event-lvm2snapshot.$(LIB_SUFFIX)
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
$(libdir)/$<.$(LIB_VERSION)
$(LN_S) -f $<.$(LIB_VERSION) $(libdir)/$<

View File

@@ -0,0 +1,232 @@
/*
* Copyright (C) 2007-2008 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "libdevmapper.h"
#include "libdevmapper-event.h"
#include "lvm2cmd.h"
#include "lvm-string.h"
#include <errno.h>
#include <signal.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <syslog.h> /* FIXME Replace syslog with multilog */
/* FIXME Missing openlog? */
/* First warning when snapshot is 80% full. */
#define WARNING_THRESH 80
/* Further warnings at 85%, 90% and 95% fullness. */
#define WARNING_STEP 5
static pthread_mutex_t _register_mutex = PTHREAD_MUTEX_INITIALIZER;
/*
* Number of active registrations.
*/
static int _register_count = 0;
static struct dm_pool *_mem_pool = NULL;
static void *_lvm_handle = NULL;
struct snap_status {
int invalid;
int used;
int max;
};
/*
* Currently only one event can be processed at a time.
*/
static pthread_mutex_t _event_mutex = PTHREAD_MUTEX_INITIALIZER;
static void _temporary_log_fn(int level,
const char *file __attribute((unused)),
int line __attribute((unused)),
const char *format)
{
if (!strncmp(format, "WARNING: ", 9) && (level < 5))
syslog(LOG_CRIT, "%s", format);
else
syslog(LOG_DEBUG, "%s", format);
}
/* FIXME possibly reconcile this with target_percent when we gain
access to regular LVM library here. */
static void _parse_snapshot_params(char *params, struct snap_status *stat)
{
char *p;
/*
* xx/xx -- fractions used/max
* Invalid -- snapshot invalidated
* Unknown -- status unknown
*/
stat->used = stat->max = 0;
if (!strncmp(params, "Invalid", 7)) {
stat->invalid = 1;
return;
}
/*
* When we return without setting non-zero max, the parent is
* responsible for reporting errors.
*/
if (!strncmp(params, "Unknown", 7))
return;
if (!(p = strstr(params, "/")))
return;
*p = '\0';
p++;
stat->used = atoi(params);
stat->max = atoi(p);
}
/* send unregister command to itself */
static void _unregister_self(struct dm_task *dmt)
{
const char *name = dm_task_get_name(dmt);
struct dm_event_handler *dmevh;
if (!(dmevh = dm_event_handler_create()))
return;
if (dm_event_handler_set_dev_name(dmevh, name))
goto fail;
dm_event_handler_set_event_mask(dmevh, DM_EVENT_ALL_ERRORS|DM_EVENT_TIMEOUT);
dm_event_unregister_handler(dmevh);
fail:
dm_event_handler_destroy(dmevh);
}
void process_event(struct dm_task *dmt,
enum dm_event_mask event __attribute((unused)),
void **private)
{
void *next = NULL;
uint64_t start, length;
char *target_type = NULL;
char *params;
struct snap_status stat = { 0 };
const char *device = dm_task_get_name(dmt);
int percent, *percent_warning = (int*)private;
/* No longer monitoring, waiting for remove */
if (!*percent_warning)
return;
if (pthread_mutex_trylock(&_event_mutex)) {
syslog(LOG_NOTICE, "Another thread is handling an event. Waiting...");
pthread_mutex_lock(&_event_mutex);
}
dm_get_next_target(dmt, next, &start, &length, &target_type, &params);
if (!target_type)
goto out;
_parse_snapshot_params(params, &stat);
/*
* If the snapshot has been invalidated or we failed to parse
* the status string. Report the full status string to syslog.
*/
if (stat.invalid || !stat.max) {
syslog(LOG_ERR, "Snapshot %s changed state to: %s\n", device, params);
_unregister_self(dmt);
*percent_warning = 0;
goto out;
}
percent = 100 * stat.used / stat.max;
if (percent >= *percent_warning) {
syslog(LOG_WARNING, "Snapshot %s is now %i%% full.\n", device, percent);
/* Print warning on the next multiple of WARNING_STEP. */
*percent_warning = (percent / WARNING_STEP) * WARNING_STEP + WARNING_STEP;
}
out:
pthread_mutex_unlock(&_event_mutex);
}
int register_device(const char *device,
const char *uuid __attribute((unused)),
int major __attribute((unused)),
int minor __attribute((unused)),
void **private)
{
int r = 0;
int *percent_warning = (int*)private;
pthread_mutex_lock(&_register_mutex);
/*
* Need some space for allocations. 1024 should be more
* than enough for what we need (device mapper name splitting)
*/
if (!_mem_pool && !(_mem_pool = dm_pool_create("snapshot_dso", 1024)))
goto out;
*percent_warning = WARNING_THRESH; /* Print warning if snapshot is full */
if (!_lvm_handle) {
lvm2_log_fn(_temporary_log_fn);
if (!(_lvm_handle = lvm2_init())) {
dm_pool_destroy(_mem_pool);
_mem_pool = NULL;
goto out;
}
lvm2_log_level(_lvm_handle, LVM2_LOG_SUPPRESS);
/* FIXME Temporary: move to dmeventd core */
lvm2_run(_lvm_handle, "_memlock_inc");
}
syslog(LOG_INFO, "Monitoring snapshot %s\n", device);
_register_count++;
r = 1;
out:
pthread_mutex_unlock(&_register_mutex);
return r;
}
int unregister_device(const char *device,
const char *uuid __attribute((unused)),
int major __attribute((unused)),
int minor __attribute((unused)),
void **unused __attribute((unused)))
{
pthread_mutex_lock(&_register_mutex);
syslog(LOG_INFO, "No longer monitoring snapshot %s\n",
device);
if (!--_register_count) {
dm_pool_destroy(_mem_pool);
_mem_pool = NULL;
lvm2_run(_lvm_handle, "_memlock_dec");
lvm2_exit(_lvm_handle);
_lvm_handle = NULL;
}
pthread_mutex_unlock(&_register_mutex);
return 1;
}

View File

@@ -1,7 +1,7 @@
#
# Copyright (C) 2004 Red Hat, Inc. All rights reserved.
#
# This file is part of the LVM2.
# 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

View File

@@ -19,6 +19,15 @@ 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 = [ ]
# Try to avoid using undescriptive /dev/dm-N names, if present.
# preferred_names = [ "^/dev/mpath/", "^/dev/mapper/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 +65,14 @@ devices {
# filter = [ "a|^/dev/hda8$|", "r/.*/" ]
# The results of the filtering are cached on disk to avoid
# rescanning dud devices (which can take a very long time). By
# default this cache file is hidden in the /etc/lvm directory.
# It is safe to delete this file: the tools regenerate it.
cache = "/etc/lvm/.cache"
# rescanning dud devices (which can take a very long time).
# By default this cache is stored in the /etc/lvm/cache directory
# in a file called '.cache'.
# It is safe to delete the contents: the tools regenerate it.
# (The old setting 'cache' is still respected if neither of
# these new ones is present.)
cache_dir = "/etc/lvm/cache"
cache_file_prefix = ""
# You can turn off writing this cache file by setting this to 0.
write_cache_state = 1
@@ -79,6 +92,12 @@ devices {
# software RAID (md) devices by looking for md superblocks.
# 1 enables; 0 disables.
md_component_detection = 1
# If, while scanning the system for PVs, LVM2 encounters a device-mapper
# device that has its I/O suspended, it waits for it to become accessible.
# Set this to 1 to skip such devices. This should only be needed
# in recovery situations.
ignore_suspended_devices = 0
}
# This section that allows you to configure the nature of the
@@ -182,6 +201,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.
@@ -270,6 +292,12 @@ activation {
# Size (in KB) of each copy operation when mirroring
mirror_region_size = 512
# Setting to use when there is no readahead value stored in the metadata.
#
# "none" - Disable readahead.
# "auto" - Use default value chosen by kernel.
readahead = "auto"
# 'mirror_image_fault_policy' and 'mirror_log_fault_policy' define
# how a device failure affecting a mirror is handled.
# A mirror is composed of mirror images (copies) and a log.
@@ -357,10 +385,20 @@ activation {
# dmeventd {
# mirror_library is the library used when monitoring a mirror device.
#
# "libdevmapper-event-lvm2mirror.so" attempts to recover from failures.
# It removes failed devices from a volume group and reconfigures a
# mirror as necessary.
#
# "libdevmapper-event-lvm2mirror.so" attempts to recover from
# failures. It removes failed devices from a volume group and
# reconfigures a mirror as necessary. If no mirror library is
# provided, mirrors are not monitored through dmeventd.
# mirror_library = "libdevmapper-event-lvm2mirror.so"
# snapshot_library is the library used when monitoring a snapshot device.
#
# "libdevmapper-event-lvm2snapshot.so" monitors the filling of
# snapshots and emits a warning through syslog, when the use of
# snapshot exceedes 80%. The warning is repeated when 85%, 90% and
# 95% of the snapshot are filled.
# snapshot_library = "libdevmapper-event-lvm2snapshot.so"
#}

View File

@@ -22,8 +22,8 @@ LVM2 that is running the LV's on my development box.
}
The important this to note is the devices section which makes sure that
only the loopback devices are considered for LVM2 operations.
The important thing to note is the devices section which makes sure
that only the loopback devices are considered for LVM2 operations.
4) When you want to use this test setup just set the environment
variable LVM_SYSTEM_DIR to point to your config directory
@@ -39,8 +39,3 @@ LVM2 that is running the LV's on my development box.
7) Test away. Make sure that you are explicit about which lvm
executable you want to execute (eg, ./lvm if you are in
LVM2/tools).

View File

@@ -30,6 +30,7 @@
../lib/log/log.h
../lib/metadata/lv_alloc.h
../lib/metadata/metadata.h
../lib/metadata/metadata-exported.h
../lib/metadata/pv_alloc.h
../lib/metadata/segtype.h
../lib/mm/memlock.h
@@ -37,13 +38,14 @@
../lib/misc/configure.h
../lib/misc/crc.h
../lib/misc/intl.h
../lib/misc/util.h
../lib/misc/last-path-component.h
../lib/misc/lib.h
../lib/misc/lvm-exec.h
../lib/misc/lvm-file.h
../lib/misc/lvm-string.h
../lib/misc/lvm-wrappers.h
../lib/misc/sharedlib.h
../lib/regex/matcher.h
../lib/report/report.h
../lib/uuid/uuid.h
../po/pogen.h

View File

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

View File

@@ -1,8 +1,8 @@
#
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
# Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
# Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
#
# This file is part of the LVM2.
# 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
@@ -80,10 +80,8 @@ SOURCES =\
misc/lvm-string.c \
misc/lvm-wrappers.c \
misc/timestamp.c \
misc/util.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

@@ -1,14 +1,14 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004-2007 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.
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU General Public License
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
@@ -146,12 +146,12 @@ int target_present(const char *target_name, int use_modprobe)
return 0;
}
int lv_info(struct cmd_context *cmd, const struct logical_volume *lv, struct lvinfo *info,
int with_open_count)
int with_open_count, int with_read_ahead)
{
return 0;
}
int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s,
struct lvinfo *info, int with_open_count)
struct lvinfo *info, int with_open_count, int with_read_ahead)
{
return 0;
}
@@ -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;
@@ -387,12 +391,26 @@ int target_version(const char *target_name, uint32_t *maj,
return r;
}
int module_present(const char *target_name)
{
int ret = 0;
#ifdef MODPROBE_CMD
char module[128];
if (dm_snprintf(module, sizeof(module), "dm-%s", target_name) < 0) {
log_error("module_present module name too long: %s",
target_name);
return 0;
}
ret = exec_cmd(MODPROBE_CMD, module, "", "");
#endif
return ret;
}
int target_present(const char *target_name, int use_modprobe)
{
uint32_t maj, min, patchlevel;
#ifdef MODPROBE_CMD
char module[128];
#endif
if (!activation())
return 0;
@@ -402,14 +420,7 @@ int target_present(const char *target_name, int use_modprobe)
if (target_version(target_name, &maj, &min, &patchlevel))
return 1;
if (dm_snprintf(module, sizeof(module), "dm-%s", target_name)
< 0) {
log_error("target_present module name too long: %s",
target_name);
return 0;
}
if (!exec_cmd(MODPROBE_CMD, module, "", ""))
if (!module_present(target_name))
return_0;
}
#endif
@@ -421,21 +432,24 @@ 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, int with_read_ahead, 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);
with_open_count, with_read_ahead, &dminfo,
&info->read_ahead)) {
if (name)
dm_pool_free(cmd->mem, name);
return_0;
}
@@ -448,25 +462,27 @@ 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)
int with_open_count, int with_read_ahead)
{
return _lv_info(cmd, lv, 0, info, with_open_count);
return _lv_info(cmd, lv, 0, info, with_open_count, with_read_ahead, 0);
}
int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s,
struct lvinfo *info, int with_open_count)
struct lvinfo *info, int with_open_count, int with_read_ahead)
{
struct logical_volume *lv;
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, with_read_ahead, 0);
}
/*
@@ -499,10 +515,17 @@ int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv,
struct dev_manager *dm;
struct lvinfo info;
/* If mirrored LV is temporarily shrinked to 1 area (= linear),
* it should be considered in-sync. */
if (list_size(&lv->segments) == 1 && first_seg(lv)->area_count == 1) {
*percent = 100.0;
return 1;
}
if (!activation())
return 0;
if (!lv_info(cmd, lv, &info, 0))
if (!lv_info(cmd, lv, &info, 0, 0))
return_0;
if (!info.exists)
@@ -519,11 +542,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, 0, by_uuid_only)) {
stack;
return -1;
}
@@ -535,7 +559,7 @@ static int _lv_open_count(struct cmd_context *cmd, struct logical_volume *lv)
{
struct lvinfo info;
if (!lv_info(cmd, lv, &info, 1)) {
if (!lv_info(cmd, lv, &info, 1, 0)) {
stack;
return -1;
}
@@ -607,7 +631,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,15 +641,25 @@ 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_opened(struct volume_group *vg)
int lvs_in_vg_activated_by_uuid_only(struct volume_group *vg)
{
struct lv_list *lvl;
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(const struct volume_group *vg)
{
const struct lv_list *lvl;
int count = 0;
if (!activation())
@@ -639,6 +673,38 @@ int lvs_in_vg_opened(struct volume_group *vg)
return count;
}
/*
* Determine whether an LV is active locally or in a cluster.
* Assumes vg lock held.
* Returns:
* 0 - not active locally or on any node in cluster
* 1 - active either locally or some node in the cluster
*/
int lv_is_active(struct logical_volume *lv)
{
if (_lv_active(lv->vg->cmd, lv, 0))
return 1;
if (!vg_is_clustered(lv->vg))
return 0;
/*
* FIXME: Cluster does not report per-node LV activation status.
* Currently the best we can do is try exclusive local activation.
* If that succeeds, we know the LV is not active elsewhere in the
* cluster.
*/
if (activate_lv_excl(lv->vg->cmd, lv)) {
deactivate_lv(lv->vg->cmd, lv);
return 0;
}
/*
* Exclusive local activation failed so assume it is active elsewhere.
*/
return 1;
}
/*
* Returns 0 if an attempt to (un)monitor the device failed.
* Returns 1 otherwise.
@@ -649,9 +715,14 @@ int monitor_dev_for_events(struct cmd_context *cmd,
#ifdef DMEVENTD
int i, pending = 0, monitored;
int r = 1;
struct list *tmp;
struct list *tmp, *snh, *snht;
struct lv_segment *seg;
int (*monitor_fn) (struct cmd_context *c, struct lv_segment *s, int e);
int (*monitor_fn) (struct lv_segment *s, int e);
uint32_t s;
/* skip dmeventd code altogether */
if (dmeventd_monitor_mode() == DMEVENTD_MONITOR_IGNORE)
return 1;
/*
* Nothing to do if dmeventd configured not to be used.
@@ -659,9 +730,44 @@ int monitor_dev_for_events(struct cmd_context *cmd,
if (monitor && !dmeventd_monitor_mode())
return 1;
/*
* In case of a snapshot device, we monitor lv->snapshot->lv,
* not the actual LV itself.
*/
if (lv_is_cow(lv))
return monitor_dev_for_events(cmd, lv->snapshot->lv, monitor);
/*
* In case this LV is a snapshot origin, we instead monitor
* each of its respective snapshots (the origin itself does
* not need to be monitored).
*
* TODO: This may change when snapshots of mirrors are allowed.
*/
if (lv_is_origin(lv)) {
list_iterate_safe(snh, snht, &lv->snapshot_segs)
if (!monitor_dev_for_events(cmd, list_struct_base(snh,
struct lv_segment, origin_list)->cow, monitor))
r = 0;
return r;
}
list_iterate(tmp, &lv->segments) {
seg = list_item(tmp, struct lv_segment);
/* Recurse for AREA_LV */
for (s = 0; s < seg->area_count; s++) {
if (seg_type(seg, s) != AREA_LV)
continue;
if (!monitor_dev_for_events(cmd, seg_lv(seg, s),
monitor)) {
log_error("Failed to %smonitor %s",
monitor ? "" : "un",
seg_lv(seg, s)->name);
r = 0;
}
}
if (!seg_monitored(seg) || (seg->status & PVMOVE))
continue;
@@ -697,7 +803,7 @@ int monitor_dev_for_events(struct cmd_context *cmd,
log_verbose("%sonitoring %s/%s", monitor ? "M" : "Not m", lv->vg->name, lv->name);
/* FIXME specify events */
if (!monitor_fn(cmd, seg, 0)) {
if (!monitor_fn(seg, 0)) {
log_error("%s/%s: %s segment monitoring function failed.",
lv->vg->name, lv->name, seg->segtype->name);
return 0;
@@ -749,7 +855,7 @@ static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
return 1;
}
if (!lv_info(cmd, lv, &info, 0))
if (!lv_info(cmd, lv, &info, 0, 0))
return_0;
if (!info.exists || info.suspended)
@@ -809,7 +915,7 @@ static int _lv_resume(struct cmd_context *cmd, const char *lvid_s,
return 1;
}
if (!lv_info(cmd, lv, &info, 0))
if (!lv_info(cmd, lv, &info, 0, 0))
return_0;
if (!info.exists || !info.suspended)
@@ -855,7 +961,7 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s)
return 1;
}
if (!lv_info(cmd, lv, &info, 1))
if (!lv_info(cmd, lv, &info, 1, 0))
return_0;
if (!info.exists)
@@ -926,7 +1032,7 @@ static int _lv_activate(struct cmd_context *cmd, const char *lvid_s,
return 1;
}
if (!lv_info(cmd, lv, &info, 0))
if (!lv_info(cmd, lv, &info, 0, 0))
return_0;
if (info.exists && !info.suspended && info.live_table)
@@ -940,7 +1046,7 @@ static int _lv_activate(struct cmd_context *cmd, const char *lvid_s,
memlock_dec();
fs_unlock();
if (!monitor_dev_for_events(cmd, lv, 1))
if (r && !monitor_dev_for_events(cmd, lv, 1))
stack;
return r;
@@ -969,7 +1075,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, 0))
return_0;
if (info.exists)

View File

@@ -1,14 +1,14 @@
/*
* 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 copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License v.2.
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU General Public License
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
@@ -16,7 +16,7 @@
#ifndef LVM_ACTIVATE_H
#define LVM_ACTIVATE_H
#include "metadata.h"
#include "metadata-exported.h"
struct lvinfo {
int exists;
@@ -27,8 +27,12 @@ struct lvinfo {
int read_only;
int live_table;
int inactive_table;
uint32_t read_ahead;
};
/* target attribute flags */
#define MIRROR_LOG_CLUSTERED 0x00000001U
void set_activation(int activation);
int activation(void);
@@ -36,6 +40,7 @@ int driver_version(char *version, size_t size);
int library_version(char *version, size_t size);
int lvm1_present(struct cmd_context *cmd);
int module_present(const char *target_name);
int target_present(const char *target_name, int use_modprobe);
int target_version(const char *target_name, uint32_t *maj,
uint32_t *min, uint32_t *patchlevel);
@@ -62,9 +67,9 @@ int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv);
* Returns 1 if info structure has been populated, else 0.
*/
int lv_info(struct cmd_context *cmd, const struct logical_volume *lv, struct lvinfo *info,
int with_open_count);
int with_open_count, int with_read_ahead);
int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s,
struct lvinfo *info, int with_open_count);
struct lvinfo *info, int with_open_count, int with_read_ahead);
/*
* Returns 1 if activate_lv has been set: 1 = activate; 0 = don't.
@@ -83,8 +88,10 @@ 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_opened(struct volume_group *vg);
int lvs_in_vg_activated_by_uuid_only(struct volume_group *vg);
int lvs_in_vg_opened(const struct volume_group *vg);
int lv_is_active(struct logical_volume *lv);
int monitor_dev_for_events(struct cmd_context *cmd,
struct logical_volume *lv, int do_reg);
@@ -95,4 +102,9 @@ int monitor_dev_for_events(struct cmd_context *cmd,
int pv_uses_vg(struct physical_volume *pv,
struct volume_group *vg);
/*
* Returns 1 if mapped device is not suspended.
*/
int device_is_usable(dev_t dev);
#endif

View File

@@ -1,14 +1,14 @@
/*
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004-2007 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.
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU General Public License
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
@@ -25,6 +25,7 @@
#include "targets.h"
#include "config.h"
#include "filter.h"
#include "activate.h"
#include <limits.h>
#include <dirent.h>
@@ -99,10 +100,8 @@ static struct dm_task *_setup_task(const char *name, const char *uuid,
{
struct dm_task *dmt;
if (!(dmt = dm_task_create(task))) {
stack;
return NULL;
}
if (!(dmt = dm_task_create(task)))
return_NULL;
if (name)
dm_task_set_name(dmt, name);
@@ -117,20 +116,17 @@ 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)
uint32_t *read_ahead, int mknodes, int with_open_count,
int with_read_ahead)
{
int r = 0;
struct dm_task *dmt;
const char *u;
int dmtask;
dmtask = mknodes ? DM_DEVICE_MKNODES : DM_DEVICE_INFO;
if (!(dmt = _setup_task(name, dlid, 0, dmtask))) {
stack;
return 0;
}
if (!(dmt = _setup_task(name, dlid, 0, dmtask)))
return_0;
if (!with_open_count)
if (!dm_task_no_open_count(dmt))
@@ -142,11 +138,64 @@ 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)))
if (with_read_ahead) {
if (!dm_task_get_read_ahead(dmt, read_ahead))
goto_out;
*uuid_out = dm_pool_strdup(mem, u);
} else if (read_ahead)
*read_ahead = DM_READ_AHEAD_NONE;
r = 1;
out:
dm_task_destroy(dmt);
return r;
}
int device_is_usable(dev_t dev)
{
struct dm_task *dmt;
struct dm_info info;
const char *name;
uint64_t start, length;
char *target_type = NULL;
char *params;
void *next = NULL;
int r = 0;
if (!(dmt = dm_task_create(DM_DEVICE_STATUS))) {
log_error("Failed to allocate dm_task struct to check dev status");
return 0;
}
if (!dm_task_set_major(dmt, MAJOR(dev)) || !dm_task_set_minor(dmt, MINOR(dev)))
goto_out;
if (!dm_task_run(dmt)) {
log_error("Failed to get state of mapped device");
goto out;
}
if (!dm_task_get_info(dmt, &info))
goto_out;
if (!info.exists || info.suspended)
goto out;
name = dm_task_get_name(dmt);
/* FIXME Also check for mirror block_on_error and mpath no paths */
/* For now, we exclude all mirrors */
do {
next = dm_get_next_target(dmt, next, &start, &length,
&target_type, &params);
/* Skip if target type doesn't match */
if (target_type && !strcmp(target_type, "mirror"))
goto out;
} while (next);
/* FIXME Also check dependencies? */
r = 1;
out:
@@ -155,30 +204,32 @@ static int _info_run(const char *name, const char *dlid, struct dm_info *info,
}
static int _info(const char *name, const char *dlid, int mknodes,
int with_open_count, struct dm_info *info,
struct dm_pool *mem, char **uuid_out)
int with_open_count, int with_read_ahead,
struct dm_info *info, uint32_t *read_ahead)
{
if (!mknodes && dlid && *dlid) {
if (_info_run(NULL, dlid, info, 0, with_open_count, mem,
uuid_out) &&
if (_info_run(NULL, dlid, info, read_ahead, 0, with_open_count,
with_read_ahead) &&
info->exists)
return 1;
else if (_info_run(NULL, dlid + sizeof(UUID_PREFIX) - 1, info,
0, with_open_count, mem, uuid_out) &&
read_ahead, 0, with_open_count,
with_read_ahead) &&
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, read_ahead, mknodes,
with_open_count, with_read_ahead);
return 0;
}
int dev_manager_info(struct dm_pool *mem, const char *name,
const struct logical_volume *lv, int with_mknodes,
int with_open_count, struct dm_info *info)
int with_open_count, int with_read_ahead,
struct dm_info *info, uint32_t *read_ahead)
{
const char *dlid;
@@ -187,8 +238,8 @@ 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, with_read_ahead,
info, read_ahead);
}
/* FIXME Interface must cope with multiple targets */
@@ -204,10 +255,8 @@ static int _status_run(const char *name, const char *uuid,
char *type = NULL;
char *params = NULL;
if (!(dmt = _setup_task(name, uuid, 0, DM_DEVICE_STATUS))) {
stack;
return 0;
}
if (!(dmt = _setup_task(name, uuid, 0, DM_DEVICE_STATUS)))
return_0;
if (!dm_task_no_open_count(dmt))
log_error("Failed to disable open_count");
@@ -293,10 +342,8 @@ static int _percent_run(struct dev_manager *dm, const char *name,
*percent = -1;
if (!(dmt = _setup_task(name, dlid, event_nr,
wait ? DM_DEVICE_WAITEVENT : DM_DEVICE_STATUS))) {
stack;
return 0;
}
wait ? DM_DEVICE_WAITEVENT : DM_DEVICE_STATUS)))
return_0;
if (!dm_task_no_open_count(dmt))
log_error("Failed to disable open_count");
@@ -388,15 +435,11 @@ struct dev_manager *dev_manager_create(struct cmd_context *cmd,
struct dm_pool *mem;
struct dev_manager *dm;
if (!(mem = dm_pool_create("dev_manager", 16 * 1024))) {
stack;
return NULL;
}
if (!(mem = dm_pool_create("dev_manager", 16 * 1024)))
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;
@@ -408,10 +451,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;
@@ -458,10 +499,8 @@ int dev_manager_snapshot_percent(struct dev_manager *dm,
*/
log_debug("Getting device status percentage for %s", name);
if (!(_percent(dm, name, dlid, "snapshot", 0, NULL, percent,
NULL))) {
stack;
return 0;
}
NULL)))
return_0;
/* FIXME dm_pool_free ? */
@@ -493,10 +532,8 @@ int dev_manager_mirror_percent(struct dev_manager *dm,
log_debug("Getting device mirror status percentage for %s", name);
if (!(_percent(dm, name, dlid, "mirror", wait, lv, percent,
event_nr))) {
stack;
return 0;
}
event_nr)))
return_0;
return 1;
}
@@ -523,9 +560,9 @@ 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,
new_name = build_dm_name(dm->mem, dm->vg_name, dl->lv->name,
suffix);
static int _belong_to_vg(const char *vgname, const char *name)
@@ -592,11 +629,11 @@ static int _add_dev_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
if (!(dlid = build_dlid(dm, lv->lvid.s, layer)))
return_0;
log_debug("Getting device info for %s [%s]", name, dlid);
if (!_info(name, dlid, 0, 1, &info, dm->mem, NULL)) {
log_error("Failed to get info for %s [%s].", name, dlid);
return 0;
}
log_debug("Getting device info for %s [%s]", name, dlid);
if (!_info(name, dlid, 0, 1, 0, &info, NULL)) {
log_error("Failed to get info for %s [%s].", name, dlid);
return 0;
}
if (info.exists && !dm_tree_add_dev(dtree, info.major, info.minor)) {
log_error("Failed to add device (%" PRIu32 ":%" PRIu32") to dtree",
@@ -640,31 +677,25 @@ static struct dm_tree *_create_partial_dtree(struct dev_manager *dm, struct logi
return NULL;
}
if (!_add_lv_to_dtree(dm, dtree, lv)) {
stack;
goto fail;
}
if (!_add_lv_to_dtree(dm, dtree, lv))
goto_bad;
/* Add any snapshots of this LV */
list_iterate_safe(snh, snht, &lv->snapshot_segs)
if (!_add_lv_to_dtree(dm, dtree, list_struct_base(snh, struct lv_segment, origin_list)->cow)) {
stack;
goto fail;
}
if (!_add_lv_to_dtree(dm, dtree, list_struct_base(snh, struct lv_segment, origin_list)->cow))
goto_bad;
/* Add any LVs used by segments in this LV */
list_iterate_items(seg, &lv->segments)
for (s = 0; s < seg->area_count; s++)
if (seg_type(seg, s) == AREA_LV && seg_lv(seg, s)) {
if (!_add_lv_to_dtree(dm, dtree, seg_lv(seg, s))) {
stack;
goto fail;
}
if (!_add_lv_to_dtree(dm, dtree, seg_lv(seg, s)))
goto_bad;
}
return dtree;
fail:
bad:
dm_tree_free(dtree);
return NULL;
}
@@ -792,7 +823,7 @@ static int _add_segment_to_dtree(struct dev_manager *dm,
layer ? "-" : "", layer ? : "");
if (seg_present->segtype->ops->target_present &&
!seg_present->segtype->ops->target_present(seg_present)) {
!seg_present->segtype->ops->target_present(seg_present, NULL)) {
log_error("Can't expand LV %s: %s target support missing "
"from kernel?", seg->lv->name, seg_present->segtype->name);
return 0;
@@ -805,7 +836,7 @@ static int _add_segment_to_dtree(struct dev_manager *dm,
/* If this is a snapshot origin, add real LV */
if (lv_is_origin(seg->lv) && !layer) {
if (seg->lv->vg->status & CLUSTERED) {
if (vg_is_clustered(seg->lv->vg)) {
log_error("Clustered snapshots are not yet supported");
return 0;
}
@@ -848,6 +879,9 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
struct lv_layer *lvlayer;
struct dm_tree_node *dnode;
char *name, *dlid;
uint32_t max_stripe_size = UINT32_C(0);
uint32_t read_ahead = lv->read_ahead;
uint32_t read_ahead_flags = UINT32_C(0);
if (!(name = build_dm_name(dm->mem, lv->vg->name, lv->name, layer)))
return_0;
@@ -894,11 +928,25 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
break;
if (lv_is_cow(lv) && !layer)
break;
if (max_stripe_size < seg->stripe_size)
max_stripe_size = seg->stripe_size;
}
if (read_ahead == DM_READ_AHEAD_AUTO) {
/* we need RA at least twice a whole stripe - see the comment in md/raid0.c */
read_ahead = max_stripe_size * 2;
read_ahead_flags = DM_READ_AHEAD_MINIMUM_FLAG;
}
dm_tree_node_set_read_ahead(dnode, read_ahead, read_ahead_flags);
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.
*/
@@ -919,10 +967,10 @@ static int _create_lv_symlinks(struct dev_manager *dm, struct dm_tree_node *root
name = dm_tree_node_get_name(child);
if (name && lvlayer->old_name && *lvlayer->old_name && strcmp(name, lvlayer->old_name)) {
if (!dm_split_lvm_name(dm->mem, lvlayer->old_name, &vgname, &lvname, &layer)) {
log_error("_create_lv_symlinks: Couldn't split up old device name %s", lvlayer->old_name);
return 0;
}
if (!dm_split_lvm_name(dm->mem, lvlayer->old_name, &vgname, &lvname, &layer)) {
log_error("_create_lv_symlinks: Couldn't split up old device name %s", lvlayer->old_name);
return 0;
}
fs_rename_lv(lvlayer->lv, name, lvname);
} else if (!dev_manager_lv_mknodes(lvlayer->lv))
r = 0;
@@ -931,6 +979,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;
@@ -945,10 +1019,10 @@ static int _clean_tree(struct dev_manager *dm, struct dm_tree_node *root)
if (!(uuid = dm_tree_node_get_uuid(child)))
continue;
if (!dm_split_lvm_name(dm->mem, name, &vgname, &lvname, &layer)) {
log_error("_clean_tree: Couldn't split up device name %s.", name);
return 0;
}
if (!dm_split_lvm_name(dm->mem, name, &vgname, &lvname, &layer)) {
log_error("_clean_tree: Couldn't split up device name %s.", name);
return 0;
}
/* Not meant to be top level? */
if (!*layer)
@@ -990,6 +1064,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

@@ -1,14 +1,14 @@
/*
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
* Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License v.2.
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU General Public License
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
@@ -40,7 +40,8 @@ void dev_manager_exit(void);
*/
int dev_manager_info(struct dm_pool *mem, const char *name,
const struct logical_volume *lv,
int mknodes, int with_open_count, struct dm_info *info);
int mknodes, int with_open_count, int with_read_ahead,
struct dm_info *info, uint32_t *read_ahead);
int dev_manager_snapshot_percent(struct dev_manager *dm,
const struct logical_volume *lv,
float *percent);

View File

@@ -1,14 +1,14 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004-2007 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.
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU General Public License
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
@@ -138,7 +138,7 @@ static int _mk_link(const char *dev_dir, const char *vg_name,
}
/* To reach this point, the VG must have been locked.
* As locking fails if the VG is active under LVM1, it's
* As locking fails if the VG is active under LVM1, it's
* now safe to remove any LVM1 devices we find here
* (as well as any existing LVM2 symlink). */
if (!lstat(lvm1_group_path, &buf)) {
@@ -175,10 +175,8 @@ static int _mk_link(const char *dev_dir, const char *vg_name,
}
#ifdef HAVE_SELINUX
if (!dm_set_selinux_context(lv_path, S_IFLNK)) {
stack;
return 0;
}
if (!dm_set_selinux_context(lv_path, S_IFLNK))
return_0;
#endif
return 1;
@@ -225,17 +223,13 @@ static int _do_fs_op(fs_op_t type, const char *dev_dir, const char *vg_name,
switch (type) {
case FS_ADD:
if (!_mk_dir(dev_dir, vg_name) ||
!_mk_link(dev_dir, vg_name, lv_name, dev)) {
stack;
return 0;
}
!_mk_link(dev_dir, vg_name, lv_name, dev))
return_0;
break;
case FS_DEL:
if (!_rm_link(dev_dir, vg_name, lv_name) ||
!_rm_dir(dev_dir, vg_name)) {
stack;
return 0;
}
!_rm_dir(dev_dir, vg_name))
return_0;
break;
/* FIXME Use rename() */
case FS_RENAME:
@@ -316,10 +310,8 @@ static int _fs_op(fs_op_t type, const char *dev_dir, const char *vg_name,
{
if (memlock()) {
if (!_stack_fs_op(type, dev_dir, vg_name, lv_name, dev,
old_lv_name)) {
stack;
return 0;
}
old_lv_name))
return_0;
return 1;
}
@@ -338,6 +330,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

@@ -1,14 +1,14 @@
/*
* 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 copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License v.2.
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU General Public License
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
@@ -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);

View File

@@ -1,14 +1,14 @@
/*
* Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
* Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License v.2.
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU General Public License
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/

413
lib/cache/lvmcache.c vendored
View File

@@ -1,23 +1,23 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004-2008 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.
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU General Public License
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include "lib.h"
#include "lvmcache.h"
#include "toolcontext.h"
#include "dev-cache.h"
#include "locking.h"
#include "metadata.h"
#include "filter.h"
#include "memlock.h"
@@ -30,6 +30,7 @@ static struct dm_hash_table *_lock_hash = NULL;
static struct list _vginfos;
static int _has_scanned = 0;
static int _vgs_locked = 0;
static int _vg_global_lock_held = 0; /* Global lock held when cache wiped? */
int lvmcache_init(void)
{
@@ -47,9 +48,98 @@ int lvmcache_init(void)
if (!(_lock_hash = dm_hash_create(128)))
return 0;
if (_vg_global_lock_held)
lvmcache_lock_vgname(VG_GLOBAL, 0);
return 1;
}
/* Volume Group metadata cache functions */
static void _free_cached_vgmetadata(struct lvmcache_vginfo *vginfo)
{
if (!vginfo || !vginfo->vgmetadata)
return;
dm_free(vginfo->vgmetadata);
vginfo->vgmetadata = NULL;
log_debug("Metadata cache: VG %s wiped.", vginfo->vgname);
}
static void _store_metadata(struct lvmcache_vginfo *vginfo,
struct volume_group *vg, unsigned precommitted)
{
int size;
if (vginfo->vgmetadata)
_free_cached_vgmetadata(vginfo);
if (!(size = export_vg_to_buffer(vg, &vginfo->vgmetadata))) {
stack;
return;
}
vginfo->precommitted = precommitted;
log_debug("Metadata cache: VG %s stored (%d bytes%s).", vginfo->vgname,
size, precommitted ? ", precommitted" : "");
}
static void _update_cache_info_lock_state(struct lvmcache_info *info,
int locked,
int *cached_vgmetadata_valid)
{
int was_locked = (info->status & CACHE_LOCKED) ? 1 : 0;
/*
* Cache becomes invalid whenever lock state changes
*/
if (was_locked != locked) {
info->status |= CACHE_INVALID;
*cached_vgmetadata_valid = 0;
}
if (locked)
info->status |= CACHE_LOCKED;
else
info->status &= ~CACHE_LOCKED;
}
static void _update_cache_vginfo_lock_state(struct lvmcache_vginfo *vginfo,
int locked)
{
struct lvmcache_info *info;
int cached_vgmetadata_valid = 1;
list_iterate_items(info, &vginfo->infos)
_update_cache_info_lock_state(info, locked,
&cached_vgmetadata_valid);
if (!cached_vgmetadata_valid)
_free_cached_vgmetadata(vginfo);
}
static void _update_cache_lock_state(const char *vgname, int locked)
{
struct lvmcache_vginfo *vginfo;
if (!(vginfo = vginfo_from_vgname(vgname, NULL)))
return;
_update_cache_vginfo_lock_state(vginfo, locked);
}
void lvmcache_drop_metadata(const char *vgname)
{
struct lvmcache_vginfo *vginfo;
if (!(vginfo = vginfo_from_vgname(vgname, NULL)))
return;
_free_cached_vgmetadata(vginfo);
}
void lvmcache_lock_vgname(const char *vgname, int read_only __attribute((unused)))
{
if (!_lock_hash && !lvmcache_init()) {
@@ -57,9 +147,15 @@ void lvmcache_lock_vgname(const char *vgname, int read_only __attribute((unused)
return;
}
if (dm_hash_lookup(_lock_hash, vgname))
log_error("Internal error: Nested locking attempted on VG %s.",
vgname);
if (!dm_hash_insert(_lock_hash, vgname, (void *) 1))
log_error("Cache locking failure for %s", vgname);
_update_cache_lock_state(vgname, 1);
_vgs_locked++;
}
@@ -73,7 +169,12 @@ int vgname_is_locked(const char *vgname)
void lvmcache_unlock_vgname(const char *vgname)
{
/* FIXME: Clear all CACHE_LOCKED flags in this vg */
if (!dm_hash_lookup(_lock_hash, vgname))
log_error("Internal error: Attempt to unlock unlocked VG %s.",
vgname);
_update_cache_lock_state(vgname, 0);
dm_hash_remove(_lock_hash, vgname);
/* FIXME Do this per-VG */
@@ -98,7 +199,7 @@ struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname, const char *vgid)
return NULL;
if (vgid)
do
do
if (!strncmp(vgid, vginfo->vgid, ID_LEN))
return vginfo;
while ((vginfo = vginfo->next));
@@ -135,7 +236,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);
}
@@ -171,9 +272,6 @@ const char *vgname_from_vgid(struct dm_pool *mem, const char *vgid)
struct lvmcache_vginfo *vginfo;
const char *vgname = NULL;
if (!*vgid)
vgname = ORPHAN;
if ((vginfo = vginfo_from_vgid(vgid)))
vgname = vginfo->vgname;
@@ -183,7 +281,43 @@ const char *vgname_from_vgid(struct dm_pool *mem, const char *vgid)
return vgname;
}
struct lvmcache_info *info_from_pvid(const char *pvid)
static int _info_is_valid(struct lvmcache_info *info)
{
if (info->status & CACHE_INVALID)
return 0;
/*
* The caller must hold the VG lock to manipulate metadata.
* In a cluster, remote nodes sometimes read metadata in the
* knowledge that the controlling node is holding the lock.
* So if the VG appears to be unlocked here, it should be safe
* to use the cached value.
*/
if (info->vginfo && !vgname_is_locked(info->vginfo->vgname))
return 1;
if (!(info->status & CACHE_LOCKED))
return 0;
return 1;
}
static int _vginfo_is_valid(struct lvmcache_vginfo *vginfo)
{
struct lvmcache_info *info;
list_iterate_items(info, &vginfo->infos)
if (!_info_is_valid(info))
return 0;
return 1;
}
/*
* If valid_only is set, data will only be returned if the cached data is
* known still to be valid.
*/
struct lvmcache_info *info_from_pvid(const char *pvid, int valid_only)
{
struct lvmcache_info *info;
char id[ID_LEN + 1] __attribute((aligned(8)));
@@ -197,6 +331,9 @@ struct lvmcache_info *info_from_pvid(const char *pvid)
if (!(info = dm_hash_lookup(_pvid_hash, id)))
return NULL;
if (valid_only && !_info_is_valid(info))
return NULL;
return info;
}
@@ -205,7 +342,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 +384,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);
@@ -267,6 +404,38 @@ int lvmcache_label_scan(struct cmd_context *cmd, int full_scan)
return r;
}
struct volume_group *lvmcache_get_vg(const char *vgid, unsigned precommitted)
{
struct lvmcache_vginfo *vginfo;
struct volume_group *vg;
struct format_instance *fid;
if (!vgid || !(vginfo = vginfo_from_vgid(vgid)) || !vginfo->vgmetadata)
return NULL;
if (!_vginfo_is_valid(vginfo))
return NULL;
if ((precommitted && !vginfo->precommitted) ||
(!precommitted && vginfo->precommitted))
return NULL;
if (!(fid = vginfo->fmt->ops->create_instance(vginfo->fmt,
vginfo->vgname,
vgid, NULL)))
return_NULL;
if (!(vg = import_vg_from_buffer(vginfo->vgmetadata, fid)) ||
!vg_validate(vg)) {
_free_cached_vgmetadata(vginfo);
return_NULL;
}
log_debug("Using cached metadata for VG %s.", vginfo->vgname);
return vg;
}
struct list *lvmcache_get_vgids(struct cmd_context *cmd, int full_scan)
{
struct list *vgids;
@@ -280,7 +449,7 @@ struct list *lvmcache_get_vgids(struct cmd_context *cmd, int full_scan)
}
list_iterate_items(vginfo, &_vginfos) {
if (!str_list_add(cmd->mem, vgids,
if (!str_list_add(cmd->mem, vgids,
dm_pool_strdup(cmd->mem, vginfo->vgid))) {
log_error("strlist allocation failed");
return NULL;
@@ -303,7 +472,7 @@ struct list *lvmcache_get_vgnames(struct cmd_context *cmd, int full_scan)
}
list_iterate_items(vginfo, &_vginfos) {
if (!str_list_add(cmd->mem, vgnames,
if (!str_list_add(cmd->mem, vgnames,
dm_pool_strdup(cmd->mem, vginfo->vgname))) {
log_error("strlist allocation failed");
return NULL;
@@ -329,7 +498,7 @@ struct list *lvmcache_get_pvids(struct cmd_context *cmd, const char *vgname,
return pvids;
list_iterate_items(info, &vginfo->infos) {
if (!str_list_add(cmd->mem, pvids,
if (!str_list_add(cmd->mem, pvids,
dm_pool_strdup(cmd->mem, info->dev->pvid))) {
log_error("strlist allocation failed");
return NULL;
@@ -345,8 +514,8 @@ struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid)
struct lvmcache_info *info;
/* Already cached ? */
if ((info = info_from_pvid((char *) pvid))) {
if (label_read(info->dev, &label)) {
if ((info = info_from_pvid((char *) pvid, 0))) {
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;
@@ -356,8 +525,8 @@ struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid)
lvmcache_label_scan(cmd, 0);
/* Try again */
if ((info = info_from_pvid((char *) pvid))) {
if (label_read(info->dev, &label)) {
if ((info = info_from_pvid((char *) pvid, 0))) {
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;
@@ -370,8 +539,8 @@ struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid)
lvmcache_label_scan(cmd, 2);
/* Try again */
if ((info = info_from_pvid((char *) pvid))) {
if (label_read(info->dev, &label)) {
if ((info = info_from_pvid((char *) pvid, 0))) {
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;
@@ -381,34 +550,38 @@ struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid)
return NULL;
}
static int _drop_vginfo(struct lvmcache_info *info)
/*
* vginfo must be info->vginfo unless info is NULL
*/
static int _drop_vginfo(struct lvmcache_info *info, struct lvmcache_vginfo *vginfo)
{
if (!list_empty(&info->list)) {
if (info && !list_empty(&info->list)) {
list_del(&info->list);
list_init(&info->list);
}
if (info->vginfo && list_empty(&info->vginfo->infos)) {
dm_hash_remove(_vgname_hash, info->vginfo->vgname);
if (info->vginfo->next) {
if (!dm_hash_insert(_vgname_hash, info->vginfo->vgname, info->vginfo->next)) {
log_error("vg hash re-insertion failed: %s",
info->vginfo->vgname);
return 0;
if (vginfo && !is_orphan_vg(vginfo->vgname) && list_empty(&vginfo->infos)) {
dm_hash_remove(_vgname_hash, vginfo->vgname);
if (vginfo->next) {
if (!dm_hash_insert(_vgname_hash, vginfo->vgname, vginfo->next)) {
log_error("vg hash re-insertion failed: %s",
vginfo->vgname);
return 0;
}
}
}
if (info->vginfo->vgname)
dm_free(info->vginfo->vgname);
if (info->vginfo->creation_host)
dm_free(info->vginfo->creation_host);
if (*info->vginfo->vgid)
dm_hash_remove(_vgid_hash, info->vginfo->vgid);
list_del(&info->vginfo->list);
if (vginfo->vgname)
dm_free(vginfo->vgname);
if (vginfo->creation_host)
dm_free(vginfo->creation_host);
if (*vginfo->vgid)
dm_hash_remove(_vgid_hash, vginfo->vgid);
list_del(&vginfo->list);
dm_free(info->vginfo);
}
info->vginfo = NULL;
if (info)
info->vginfo = NULL;
return 1;
}
@@ -419,10 +592,10 @@ void lvmcache_del(struct lvmcache_info *info)
if (info->dev->pvid[0] && _pvid_hash)
dm_hash_remove(_pvid_hash, info->dev->pvid);
_drop_vginfo(info);
_drop_vginfo(info, info->vginfo);
info->label->labeller->ops->destroy_label(info->label->labeller,
info->label);
info->label);
dm_free(info);
return;
@@ -444,29 +617,36 @@ static int _lvmcache_update_pvid(struct lvmcache_info *info, const char *pvid)
return 1;
}
static int _lvmcache_update_vgid(struct lvmcache_info *info, const char *vgid)
/*
* vginfo must be info->vginfo unless info is NULL (orphans)
*/
static int _lvmcache_update_vgid(struct lvmcache_info *info,
struct lvmcache_vginfo *vginfo,
const char *vgid)
{
if (!vgid || !info->vginfo ||
!strncmp(info->vginfo->vgid, vgid, ID_LEN))
if (!vgid || !vginfo ||
!strncmp(vginfo->vgid, vgid, ID_LEN))
return 1;
if (info->vginfo && *info->vginfo->vgid)
dm_hash_remove(_vgid_hash, info->vginfo->vgid);
if (vginfo && *vginfo->vgid)
dm_hash_remove(_vgid_hash, vginfo->vgid);
if (!vgid) {
log_debug("lvmcache: %s: clearing VGID", dev_name(info->dev));
log_debug("lvmcache: %s: clearing VGID", info ? dev_name(info->dev) : vginfo->vgname);
return 1;
}
strncpy(info->vginfo->vgid, vgid, ID_LEN);
info->vginfo->vgid[ID_LEN] = '\0';
if (!dm_hash_insert(_vgid_hash, info->vginfo->vgid, info->vginfo)) {
strncpy(vginfo->vgid, vgid, ID_LEN);
vginfo->vgid[ID_LEN] = '\0';
if (!dm_hash_insert(_vgid_hash, vginfo->vgid, vginfo)) {
log_error("_lvmcache_update: vgid hash insertion failed: %s",
info->vginfo->vgid);
vginfo->vgid);
return 0;
}
log_debug("lvmcache: %s: setting %s VGID to %s", dev_name(info->dev),
info->vginfo->vgname, info->vginfo->vgid);
if (!is_orphan_vg(vginfo->vgname))
log_debug("lvmcache: %s: setting %s VGID to %s",
dev_name(info->dev), vginfo->vgname,
vginfo->vgid);
return 1;
}
@@ -557,25 +737,18 @@ static int _insert_vginfo(struct lvmcache_vginfo *new_vginfo, const char *vgid,
static int _lvmcache_update_vgname(struct lvmcache_info *info,
const char *vgname, const char *vgid,
uint32_t vgstatus, const char *creation_host)
uint32_t vgstatus, const char *creation_host,
const struct format_type *fmt)
{
struct lvmcache_vginfo *vginfo, *primary_vginfo;
// struct lvmcache_vginfo *old_vginfo, *next;
/* If vgname is NULL and we don't already have a vgname,
* assume ORPHAN - we want every entry to have a vginfo
* attached for scanning reasons.
*/
if (!vgname && !info->vginfo) {
vgname = ORPHAN;
vgid = ORPHAN;
}
if (!vgname || (info->vginfo && !strcmp(info->vginfo->vgname, vgname)))
if (!vgname || (info && info->vginfo && !strcmp(info->vginfo->vgname, vgname)))
return 1;
/* Remove existing vginfo entry */
_drop_vginfo(info);
if (info)
_drop_vginfo(info, info->vginfo);
/* Get existing vginfo or create new one */
if (!(vginfo = vginfo_from_vgname(vgname, vgid))) {
@@ -588,9 +761,9 @@ static int _lvmcache_update_vgname(struct lvmcache_info *info,
dm_hash_remove(_vgname_hash, old_vginfo->vgname);
if (old_vginfo->next) {
if (!dm_hash_insert(_vgname_hash, old_vginfo->vgname, old_vginfo->next)) {
log_error("vg hash re-insertion failed: %s",
log_error("vg hash re-insertion failed: %s",
old_vginfo->vgname);
return 0;
return 0;
}
}
} else do {
@@ -607,11 +780,11 @@ static int _lvmcache_update_vgname(struct lvmcache_info *info,
return 0;
}
// Rename so can assume new name does not already exist
// Rename so can assume new name does not already exist
if (!dm_hash_insert(_vgname_hash, vginfo->vgname, vginfo->next)) {
log_error("vg hash re-insertion failed: %s",
vginfo->vgname);
return 0;
return 0;
}
} else {
***/
@@ -634,7 +807,7 @@ static int _lvmcache_update_vgname(struct lvmcache_info *info,
return 0;
}
/* Ensure orphans appear last on list_iterate */
if (!*vgname)
if (is_orphan_vg(vgname))
list_add(&_vginfos, &vginfo->list);
else
list_add_h(&_vginfos, &vginfo->list);
@@ -643,17 +816,25 @@ static int _lvmcache_update_vgname(struct lvmcache_info *info,
***/
}
info->vginfo = vginfo;
list_add(&vginfo->infos, &info->list);
if (info) {
info->vginfo = vginfo;
list_add(&vginfo->infos, &info->list);
} else if (!_lvmcache_update_vgid(info, vginfo, vgid)) /* Orphans */
return_0;
_update_cache_vginfo_lock_state(vginfo, vgname_is_locked(vgname));
/* FIXME Check consistency of list! */
vginfo->fmt = info->fmt;
vginfo->fmt = fmt;
log_debug("lvmcache: %s: now %s%s%s%s%s", dev_name(info->dev),
*vgname ? "in VG " : "orphaned", vgname,
vginfo->vgid[0] ? " (" : "",
vginfo->vgid[0] ? vginfo->vgid : "",
vginfo->vgid[0] ? ")" : "");
if (info)
log_debug("lvmcache: %s: now in VG %s%s%s%s",
dev_name(info->dev),
vgname, vginfo->vgid[0] ? " (" : "",
vginfo->vgid[0] ? vginfo->vgid : "",
vginfo->vgid[0] ? ")" : "");
else
log_debug("lvmcache: initialised VG %s", vgname);
return 1;
}
@@ -693,23 +874,41 @@ static int _lvmcache_update_vgstatus(struct lvmcache_info *info, uint32_t vgstat
return 1;
}
int lvmcache_add_orphan_vginfo(const char *vgname, struct format_type *fmt)
{
if (!_lock_hash && !lvmcache_init()) {
log_error("Internal cache initialisation failed");
return 0;
}
return _lvmcache_update_vgname(NULL, vgname, vgname, 0, "", fmt);
}
int lvmcache_update_vgname_and_id(struct lvmcache_info *info,
const char *vgname, const char *vgid,
uint32_t vgstatus, const char *creation_host)
{
if (!vgname && !info->vginfo) {
log_error("Internal error: NULL vgname handed to cache");
/* FIXME Remove this */
vgname = info->fmt->orphan_vg_name;
vgid = vgname;
}
if (!_lvmcache_update_vgname(info, vgname, vgid, vgstatus,
creation_host) ||
!_lvmcache_update_vgid(info, vgid) ||
creation_host, info->fmt) ||
!_lvmcache_update_vgid(info, info->vginfo, vgid) ||
!_lvmcache_update_vgstatus(info, vgstatus, creation_host))
return_0;
return 1;
}
int lvmcache_update_vg(struct volume_group *vg)
int lvmcache_update_vg(struct volume_group *vg, unsigned precommitted)
{
struct pv_list *pvl;
struct lvmcache_info *info;
struct lvmcache_vginfo *vginfo;
char pvid_s[ID_LEN + 1] __attribute((aligned(8)));
pvid_s[sizeof(pvid_s) - 1] = '\0';
@@ -717,13 +916,18 @@ int lvmcache_update_vg(struct volume_group *vg)
list_iterate_items(pvl, &vg->pvs) {
strncpy(pvid_s, (char *) &pvl->pv->id, sizeof(pvid_s) - 1);
/* FIXME Could pvl->pv->dev->pvid ever be different? */
if ((info = info_from_pvid(pvid_s)) &&
if ((info = info_from_pvid(pvid_s, 0)) &&
!lvmcache_update_vgname_and_id(info, vg->name,
(char *) &vg->id,
vg->status, NULL))
return_0;
}
/* store text representation of vg to cache */
if (vg->cmd->current_settings.cache_vgmetadata &&
(vginfo = vginfo_from_vgname(vg->name, NULL)))
_store_metadata(vginfo, vg, precommitted);
return 1;
}
@@ -744,12 +948,10 @@ struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
strncpy(pvid_s, pvid, sizeof(pvid_s));
pvid_s[sizeof(pvid_s) - 1] = '\0';
if (!(existing = info_from_pvid(pvid_s)) &&
!(existing = info_from_pvid(dev->pvid))) {
if (!(label = label_create(labeller))) {
stack;
return NULL;
}
if (!(existing = info_from_pvid(pvid_s, 0)) &&
!(existing = info_from_pvid(dev->pvid, 0))) {
if (!(label = label_create(labeller)))
return_NULL;
if (!(info = dm_malloc(sizeof(*info)))) {
log_error("lvmcache_info allocation failed");
label_destroy(label);
@@ -805,11 +1007,9 @@ struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
/* Has labeller changed? */
if (info->label->labeller != labeller) {
label_destroy(info->label);
if (!(info->label = label_create(labeller))) {
if (!(info->label = label_create(labeller)))
/* FIXME leaves info without label! */
stack;
return NULL;
}
return_NULL;
info->label->info = info;
}
label = info->label;
@@ -858,17 +1058,30 @@ static void _lvmcache_destroy_vgnamelist(struct lvmcache_vginfo *vginfo)
dm_free(vginfo->vgname);
if (vginfo->creation_host)
dm_free(vginfo->creation_host);
_free_cached_vgmetadata(vginfo);
dm_free(vginfo);
} while ((vginfo = next));
}
static void _lvmcache_destroy_lockname(int present __attribute((unused)))
static void _lvmcache_destroy_lockname(struct dm_hash_node *n)
{
/* Nothing to do */
char *vgname;
if (!dm_hash_get_data(_lock_hash, n))
return;
vgname = dm_hash_get_key(_lock_hash, n);
if (!strcmp(vgname, VG_GLOBAL))
_vg_global_lock_held = 1;
else
log_error("Internal error: Volume Group %s was not unlocked",
dm_hash_get_key(_lock_hash, n));
}
void lvmcache_destroy(void)
void lvmcache_destroy(struct cmd_context *cmd, int retain_orphans)
{
struct dm_hash_node *n;
log_verbose("Wiping internal VG cache");
_has_scanned = 0;
@@ -892,10 +1105,14 @@ void lvmcache_destroy(void)
}
if (_lock_hash) {
dm_hash_iter(_lock_hash, (dm_hash_iterate_fn) _lvmcache_destroy_lockname);
dm_hash_iterate(n, _lock_hash)
_lvmcache_destroy_lockname(n);
dm_hash_destroy(_lock_hash);
_lock_hash = NULL;
}
list_init(&_vginfos);
if (retain_orphans)
init_lvmcache_orphans(cmd);
}

24
lib/cache/lvmcache.h vendored
View File

@@ -1,17 +1,16 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
* Copyright (C) 2004-2008 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.
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU General Public License
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#ifndef _LVM_CACHE_H
@@ -21,7 +20,8 @@
#include "uuid.h"
#include "label.h"
#define ORPHAN ""
#define ORPHAN_PREFIX "#"
#define ORPHAN_VG_NAME(fmt) ORPHAN_PREFIX "orphans_" fmt
#define CACHE_INVALID 0x00000001
#define CACHE_LOCKED 0x00000002
@@ -44,6 +44,8 @@ struct lvmcache_vginfo {
char _padding[7];
struct lvmcache_vginfo *next; /* Another VG with same name? */
char *creation_host;
char *vgmetadata; /* Copy of VG metadata as format_text string */
unsigned precommitted; /* Is vgmetadata live or precommitted? */
};
/* One per device */
@@ -60,7 +62,7 @@ struct lvmcache_info {
};
int lvmcache_init(void);
void lvmcache_destroy(void);
void lvmcache_destroy(struct cmd_context *cmd, int retain_orphans);
/* Set full_scan to 1 to reread every filtered device label or
* 2 to rescan /dev for new devices */
@@ -71,13 +73,15 @@ struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
struct device *dev,
const char *vgname, const char *vgid,
uint32_t vgstatus);
int lvmcache_add_orphan_vginfo(const char *vgname, struct format_type *fmt);
void lvmcache_del(struct lvmcache_info *info);
/* Update things */
int lvmcache_update_vgname_and_id(struct lvmcache_info *info,
const char *vgname, const char *vgid,
uint32_t vgstatus, const char *hostname);
int lvmcache_update_vg(struct volume_group *vg);
int lvmcache_update_vg(struct volume_group *vg, unsigned precommitted);
void lvmcache_drop_vg(const char *vgname);
void lvmcache_lock_vgname(const char *vgname, int read_only);
void lvmcache_unlock_vgname(const char *vgname);
@@ -87,7 +91,7 @@ const struct format_type *fmt_from_vgname(const char *vgname, const char *vgid);
struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname,
const char *vgid);
struct lvmcache_vginfo *vginfo_from_vgid(const char *vgid);
struct lvmcache_info *info_from_pvid(const char *pvid);
struct lvmcache_info *info_from_pvid(const char *pvid, int valid_only);
const char *vgname_from_vgid(struct dm_pool *mem, const char *vgid);
struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid);
int vgs_locked(void);
@@ -105,4 +109,8 @@ struct list *lvmcache_get_vgids(struct cmd_context *cmd, int full_scan);
struct list *lvmcache_get_pvids(struct cmd_context *cmd, const char *vgname,
const char *vgid);
/* Returns cached volume group metadata. */
struct volume_group *lvmcache_get_vg(const char *vgid, unsigned precommitted);
void lvmcache_drop_metadata(const char *vgname);
#endif

View File

@@ -6,9 +6,9 @@
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License v.2.
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU General Public License
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/

View File

@@ -1,17 +1,16 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004-2007 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.
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU General Public License
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include "lib.h"
@@ -59,8 +58,6 @@
# include <malloc.h>
#endif
static FILE *_log;
static int _get_env_vars(struct cmd_context *cmd)
{
const char *e;
@@ -156,6 +153,7 @@ static void _init_logging(struct cmd_context *cmd)
static int _process_config(struct cmd_context *cmd)
{
mode_t old_umask;
const char *read_ahead;
/* umask */
cmd->default_settings.umask = find_config_tree_int(cmd,
@@ -186,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';
}
@@ -210,6 +208,16 @@ static int _process_config(struct cmd_context *cmd)
return 0;
}
read_ahead = find_config_tree_str(cmd, "activation/readahead", DEFAULT_READ_AHEAD);
if (!strcasecmp(read_ahead, "auto"))
cmd->default_settings.read_ahead = DM_READ_AHEAD_AUTO;
else if (!strcasecmp(read_ahead, "none"))
cmd->default_settings.read_ahead = DM_READ_AHEAD_NONE;
else {
log_error("Invalid readahead specification");
return 0;
}
return 1;
}
@@ -274,10 +282,8 @@ static int _init_tags(struct cmd_context *cmd, struct config_tree *cft)
if (!cmd->hosttags && find_config_int(cft->root, "tags/hosttags",
DEFAULT_HOSTTAGS)) {
/* FIXME Strip out invalid chars: only A-Za-z0-9_+.- */
if (!_set_tag(cmd, cmd->hostname)) {
stack;
return 0;
}
if (!_set_tag(cmd, cmd->hostname))
return_0;
cmd->hosttags = 1;
}
@@ -293,17 +299,13 @@ static int _init_tags(struct cmd_context *cmd, struct config_tree *cft)
}
if (cn->child) {
passes = 0;
if (!_check_host_filters(cmd, cn->child, &passes)) {
stack;
return 0;
}
if (!_check_host_filters(cmd, cn->child, &passes))
return_0;
if (!passes)
continue;
}
if (!_set_tag(cmd, tag)) {
stack;
return 0;
}
if (!_set_tag(cmd, tag))
return_0;
}
return 1;
@@ -377,10 +379,8 @@ static int _init_lvm_conf(struct cmd_context *cmd)
return 1;
}
if (!_load_config_file(cmd, "")) {
stack;
return 0;
}
if (!_load_config_file(cmd, ""))
return_0;
return 1;
}
@@ -392,11 +392,8 @@ static int _init_tag_configs(struct cmd_context *cmd)
/* Tag list may grow while inside this loop */
list_iterate_items(sl, &cmd->tags) {
if (!_load_config_file(cmd, sl->str)) {
stack;
return 0;
}
if (!_load_config_file(cmd, sl->str))
return_0;
}
return 1;
@@ -416,10 +413,8 @@ static int _merge_config_files(struct cmd_context *cmd)
list_iterate_items(cfl, &cmd->config_files) {
/* Merge all config trees into cmd->cft using merge/tag rules */
if (!merge_config_tree(cmd, cmd->cft, cfl->cft)) {
stack;
return 0;
}
if (!merge_config_tree(cmd, cmd->cft, cfl->cft))
return_0;
}
return 1;
@@ -467,10 +462,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")) {
@@ -536,7 +529,7 @@ static struct dev_filter *_init_filter_components(struct cmd_context *cmd)
/*
* sysfs filter. Only available on 2.6 kernels. Non-critical.
* Listed first because it's very efficient at eliminating
* Listed first because it's very efficient at eliminating
* unavailable devices.
*/
if (find_config_tree_bool(cmd, "devices/sysfs_scan",
@@ -575,9 +568,9 @@ static struct dev_filter *_init_filter_components(struct cmd_context *cmd)
filters[0] : composite_filter_create(nr_filt, filters);
}
static int _init_filters(struct cmd_context *cmd)
static int _init_filters(struct cmd_context *cmd, unsigned load_persistent_cache)
{
const char *dev_cache;
const char *dev_cache = NULL, *cache_dir, *cache_file_prefix;
struct dev_filter *f3, *f4;
struct stat st;
char cache_file[PATH_MAX];
@@ -587,15 +580,37 @@ static int _init_filters(struct cmd_context *cmd)
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);
init_ignore_suspended_devices(find_config_tree_int(cmd,
"devices/ignore_suspended_devices", DEFAULT_IGNORE_SUSPENDED_DEVICES));
/*
* If 'cache_dir' or 'cache_file_prefix' is set, ignore 'cache'.
*/
cache_dir = find_config_tree_str(cmd, "devices/cache_dir", NULL);
cache_file_prefix = find_config_tree_str(cmd, "devices/cache_file_prefix", NULL);
if (cache_dir || cache_file_prefix) {
if (dm_snprintf(cache_file, sizeof(cache_file),
"%s%s%s/%s.cache",
cache_dir ? "" : cmd->sys_dir,
cache_dir ? "" : "/",
cache_dir ? : DEFAULT_CACHE_SUBDIR,
cache_file_prefix ? : DEFAULT_CACHE_FILE_PREFIX) < 0) {
log_error("Persistent cache filename too long.");
return 0;
}
} else if (!(dev_cache = find_config_tree_str(cmd, "devices/cache", NULL)) &&
(dm_snprintf(cache_file, sizeof(cache_file),
"%s/%s/%s.cache",
cmd->sys_dir, DEFAULT_CACHE_SUBDIR,
DEFAULT_CACHE_FILE_PREFIX) < 0)) {
log_error("Persistent cache filename too long.");
return 0;
}
dev_cache = find_config_tree_str(cmd, "devices/cache",
cache_file);
if (!dev_cache)
dev_cache = cache_file;
if (!(f4 = persistent_filter_create(f3, dev_cache))) {
log_error("Failed to create persistent device filter");
return 0;
@@ -608,8 +623,13 @@ static int _init_filters(struct cmd_context *cmd)
if (!*cmd->sys_dir)
cmd->dump_filter = 0;
if (!stat(dev_cache, &st) &&
(st.st_ctime != config_file_timestamp(cmd->cft)) &&
/*
* Only load persistent filter device cache on startup if it is newer
* than the config file and this is not a long-lived process.
*/
if (load_persistent_cache && !cmd->is_long_lived &&
!stat(dev_cache, &st) &&
(st.st_ctime > config_file_timestamp(cmd->cft)) &&
!persistent_filter_load(f4, NULL))
log_verbose("Failed to load existing device cache from %s",
dev_cache);
@@ -661,10 +681,8 @@ static int _init_formats(struct cmd_context *cmd)
return 0;
}
if (!(lib = load_shared_library(cmd, cv->v.str,
"format", 0))) {
stack;
return 0;
}
"format", 0)))
return_0;
if (!(init_format_fn = dlsym(lib, "init_format"))) {
log_error("Shared library %s does not contain "
@@ -703,6 +721,17 @@ static int _init_formats(struct cmd_context *cmd)
return 0;
}
int init_lvmcache_orphans(struct cmd_context *cmd)
{
struct format_type *fmt;
list_iterate_items(fmt, &cmd->formats)
if (!lvmcache_add_orphan_vginfo(fmt->orphan_vg_name, fmt))
return_0;
return 1;
}
static int _init_segtypes(struct cmd_context *cmd)
{
struct segment_type *segtype;
@@ -748,7 +777,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) {
@@ -758,10 +786,8 @@ static int _init_segtypes(struct cmd_context *cmd)
return 0;
}
if (!(lib = load_shared_library(cmd, cv->v.str,
"segment type", 0))) {
stack;
return 0;
}
"segment type", 0)))
return_0;
if (!(init_segtype_fn = dlsym(lib, "init_segtype"))) {
log_error("Shared library %s does not contain "
@@ -775,18 +801,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);
}
}
}
@@ -881,7 +905,8 @@ static int _init_backup(struct cmd_context *cmd)
}
/* Entry point */
struct cmd_context *create_toolcontext(struct arg *the_args, unsigned is_static)
struct cmd_context *create_toolcontext(struct arg *the_args, unsigned is_static,
unsigned is_long_lived)
{
struct cmd_context *cmd;
@@ -905,6 +930,7 @@ struct cmd_context *create_toolcontext(struct arg *the_args, unsigned is_static)
memset(cmd, 0, sizeof(*cmd));
cmd->args = the_args;
cmd->is_static = is_static;
cmd->is_long_lived = is_long_lived;
cmd->hosttags = 0;
list_init(&cmd->formats);
list_init(&cmd->segtypes);
@@ -917,7 +943,7 @@ struct cmd_context *create_toolcontext(struct arg *the_args, unsigned is_static)
goto error;
/* Create system directory if it doesn't already exist */
if (*cmd->sys_dir && !create_dir(cmd->sys_dir)) {
if (*cmd->sys_dir && !dm_create_dir(cmd->sys_dir)) {
log_error("Failed to create LVM2 system dir for metadata backups, config "
"files and internal cache.");
log_error("Set environment variable LVM_SYSTEM_DIR to alternative location "
@@ -953,7 +979,7 @@ struct cmd_context *create_toolcontext(struct arg *the_args, unsigned is_static)
if (!_init_dev_cache(cmd))
goto error;
if (!_init_filters(cmd))
if (!_init_filters(cmd, 1))
goto error;
if (!(cmd->mem = dm_pool_create("command", 4 * 1024))) {
@@ -966,12 +992,16 @@ struct cmd_context *create_toolcontext(struct arg *the_args, unsigned is_static)
if (!_init_formats(cmd))
goto error;
if (!init_lvmcache_orphans(cmd))
goto error;
if (!_init_segtypes(cmd))
goto error;
if (!_init_backup(cmd))
goto error;
cmd->default_settings.cache_vgmetadata = 1;
cmd->current_settings = cmd->default_settings;
cmd->config_valid = 1;
@@ -1022,13 +1052,13 @@ int refresh_toolcontext(struct cmd_context *cmd)
{
log_verbose("Reloading config files");
if (cmd->config_valid) {
if (cmd->dump_filter)
persistent_filter_dump(cmd->filter);
}
/*
* Don't update the persistent filter cache as we will
* perform a full rescan.
*/
activation_release();
lvmcache_destroy();
lvmcache_destroy(cmd, 0);
label_exit();
_destroy_segtypes(&cmd->segtypes);
_destroy_formats(&cmd->formats);
@@ -1064,15 +1094,25 @@ int refresh_toolcontext(struct cmd_context *cmd)
if (!_init_dev_cache(cmd))
return 0;
if (!_init_filters(cmd))
if (!_init_filters(cmd, 0))
return 0;
if (!_init_formats(cmd))
return 0;
if (!init_lvmcache_orphans(cmd))
return 0;
if (!_init_segtypes(cmd))
return 0;
/*
* If we are a long-lived process, write out the updated persistent
* device cache for the benefit of short-lived processes.
*/
if (cmd->is_long_lived && cmd->dump_filter)
persistent_filter_dump(cmd->filter);
cmd->config_valid = 1;
return 1;
}
@@ -1084,7 +1124,7 @@ void destroy_toolcontext(struct cmd_context *cmd)
archive_exit(cmd);
backup_exit(cmd);
lvmcache_destroy();
lvmcache_destroy(cmd, 0);
label_exit();
_destroy_segtypes(&cmd->segtypes);
_destroy_formats(&cmd->formats);
@@ -1100,8 +1140,4 @@ void destroy_toolcontext(struct cmd_context *cmd)
activation_exit();
fin_log();
fin_syslog();
if (_log)
fclose(_log);
}

View File

@@ -1,14 +1,14 @@
/*
* 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 copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License v.2.
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU General Public License
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
@@ -33,6 +33,8 @@ struct config_info {
int suffix;
int archive; /* should we archive ? */
int backup; /* should we backup ? */
int read_ahead; /* DM_READ_AHEAD_NONE or _AUTO */
int cache_vgmetadata;
const char *msg_prefix;
struct format_type *fmt;
uint64_t unit_factor;
@@ -65,6 +67,7 @@ struct cmd_context {
struct arg *args;
char **argv;
unsigned is_static; /* Static binary? */
unsigned is_long_lived; /* Optimises persistent_filter handling */
struct dev_filter *filter;
int dump_filter; /* Dump filter when exiting? */
@@ -88,9 +91,10 @@ struct cmd_context {
char proc_dir[PATH_MAX];
};
struct cmd_context *create_toolcontext(struct arg *the_args, unsigned is_static);
struct cmd_context *create_toolcontext(struct arg *the_args, unsigned is_static, unsigned is_long_lived);
void destroy_toolcontext(struct cmd_context *cmd);
int refresh_toolcontext(struct cmd_context *cmd);
int config_files_changed(struct cmd_context *cmd);
int init_lvmcache_orphans(struct cmd_context *cmd);
#endif

View File

@@ -1,14 +1,14 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004-2007 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.
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU General Public License
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
@@ -19,6 +19,8 @@
#include "device.h"
#include "str_list.h"
#include "toolcontext.h"
#include "lvm-string.h"
#include "lvm-file.h"
#include <sys/stat.h>
#include <sys/mman.h>
@@ -26,10 +28,14 @@
#include <fcntl.h>
#include <ctype.h>
#define SECTION_B_CHAR '{'
#define SECTION_E_CHAR '}'
enum {
TOK_INT,
TOK_FLOAT,
TOK_STRING,
TOK_STRING, /* Single quotes */
TOK_STRING_ESCAPED, /* Double quotes */
TOK_EQ,
TOK_SECTION_B,
TOK_SECTION_E,
@@ -62,6 +68,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 +90,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);
@@ -145,7 +157,7 @@ static int _parse_config_file(struct parser *p, struct config_tree *cft)
return 1;
}
struct config_tree *create_config_tree_from_string(struct cmd_context *cmd,
struct config_tree *create_config_tree_from_string(struct cmd_context *cmd __attribute((unused)),
const char *config_settings)
{
struct cs *c;
@@ -183,12 +195,10 @@ 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;
return 0;
}
if (!(p = dm_pool_alloc(c->mem, sizeof(*p))))
return_0;
p->mem = c->mem;
/* Only use mmap with regular files */
@@ -206,22 +216,12 @@ int read_config_fd(struct config_tree *cft, struct device *dev,
}
p->fb = p->fb + mmap_offset;
} else {
if (!(buf = dm_malloc(size + size2))) {
stack;
return 0;
}
if (!dev_read(dev, (uint64_t) offset, size, buf)) {
log_error("Read from %s failed", dev_name(dev));
if (!(buf = dm_malloc(size + size2)))
return_0;
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;
}
@@ -234,10 +234,8 @@ int read_config_fd(struct config_tree *cft, struct device *dev,
p->fe = p->fb + size + size2;
if (!_parse_config_file(p, cft)) {
stack;
goto out;
}
if (!_parse_config_file(p, cft))
goto_out;
r = 1;
@@ -348,33 +346,96 @@ 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, ...)
__attribute__ ((format(printf, 2, 3)));
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], sizeof buf - 1, fmt, ap);
if (n < 0 || n > (int) sizeof buf - 1) {
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_grow_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)
{
char *buf;
switch (v->type) {
case CFG_STRING:
fprintf(fp, "\"%s\"", v->v.str);
if (!(buf = alloca(escaped_len(v->v.str)))) {
log_error("temporary stack allocation for a config "
"string failed");
return 0;
}
line_append("\"%s\"", escape_double_quotes(buf, 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 +449,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,26 +492,28 @@ 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)) {
log_error("Failure while writing configuration");
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)) {
log_error("Failure while writing configuration");
if (!_write_config(cn, 1, &outline, 0)) {
log_error("Failure while writing to %s", file);
r = 0;
}
} else {
@@ -451,9 +523,12 @@ int write_config_file(struct config_tree *cft, const char *file,
argv++;
}
if (fp != stdout)
fclose(fp);
if (outline.fp && lvm_fclose(outline.fp, file)) {
stack;
r = 0;
}
dm_pool_destroy(outline.mem);
return r;
}
@@ -464,10 +539,8 @@ static struct config_node *_file(struct parser *p)
{
struct config_node *root = NULL, *n, *l = NULL;
while (p->t != TOK_EOF) {
if (!(n = _section(p))) {
stack;
return 0;
}
if (!(n = _section(p)))
return_0;
if (!root)
root = n;
@@ -480,27 +553,21 @@ 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;
return 0;
}
if (!(root = _create_node(p)))
return_0;
if (!(root->key = _dup_tok(p))) {
stack;
return 0;
}
if (!(root->key = _dup_tok(p)))
return_0;
match(TOK_IDENTIFIER);
if (p->t == TOK_SECTION_B) {
match(TOK_SECTION_B);
while (p->t != TOK_SECTION_E) {
if (!(n = _section(p))) {
stack;
return 0;
}
if (!(n = _section(p)))
return_0;
if (!root->child)
root->child = n;
@@ -511,10 +578,8 @@ static struct config_node *_section(struct parser *p)
match(TOK_SECTION_E);
} else {
match(TOK_EQ);
if (!(root->v = _value(p))) {
stack;
return 0;
}
if (!(root->v = _value(p)))
return_0;
}
return root;
@@ -527,10 +592,8 @@ static struct config_value *_value(struct parser *p)
if (p->t == TOK_ARRAY_B) {
match(TOK_ARRAY_B);
while (p->t != TOK_ARRAY_E) {
if (!(l = _type(p))) {
stack;
return 0;
}
if (!(l = _type(p)))
return_0;
if (!h)
h = l;
@@ -569,7 +632,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;
@@ -583,16 +646,26 @@ static struct config_value *_type(struct parser *p)
v->type = CFG_STRING;
p->tb++, p->te--; /* strip "'s */
if (!(v->v.str = _dup_tok(p))) {
stack;
return 0;
}
if (!(v->v.str = _dup_tok(p)))
return_0;
p->te++;
match(TOK_STRING);
break;
case TOK_STRING_ESCAPED:
v->type = CFG_STRING;
p->tb++, p->te--; /* strip "'s */
if (!(v->v.str = _dup_tok(p)))
return_0;
unescape_double_quotes(v->v.str);
p->te++;
match(TOK_STRING_ESCAPED);
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;
@@ -629,12 +702,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;
@@ -660,7 +733,7 @@ static void _get_token(struct parser *p, int tok_prev)
break;
case '"':
p->t = TOK_STRING;
p->t = TOK_STRING_ESCAPED;
p->te++;
while ((p->te != p->fe) && (*p->te) && (*p->te != '"')) {
if ((*p->te == '\\') && (p->te + 1 != p->fe) &&
@@ -714,8 +787,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;
}
@@ -772,10 +846,8 @@ static char *_dup_tok(struct parser *p)
{
size_t len = p->te - p->tb;
char *str = dm_pool_alloc(p->mem, len + 1);
if (!str) {
stack;
return 0;
}
if (!str)
return_0;
strncpy(str, p->tb, len);
str[len] = '\0';
return str;
@@ -870,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,
@@ -897,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;
}
@@ -916,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);
}
@@ -1022,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;
}
@@ -1152,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(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

@@ -1,14 +1,14 @@
/*
* 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 copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License v.2.
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU General Public License
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
@@ -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

@@ -1,14 +1,14 @@
/*
* 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 copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License v.2.
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU General Public License
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
@@ -21,6 +21,8 @@
#define DEFAULT_ARCHIVE_SUBDIR "archive"
#define DEFAULT_BACKUP_SUBDIR "backup"
#define DEFAULT_CACHE_SUBDIR "cache"
#define DEFAULT_CACHE_FILE_PREFIX ""
#define DEFAULT_ARCHIVE_DAYS 30
#define DEFAULT_ARCHIVE_NUMBER 10
@@ -30,12 +32,14 @@
#define DEFAULT_PROC_DIR "/proc"
#define DEFAULT_SYSFS_SCAN 1
#define DEFAULT_MD_COMPONENT_DETECTION 1
#define DEFAULT_IGNORE_SUSPENDED_DEVICES 1
#define DEFAULT_LOCK_DIR "/var/lock/lvm"
#define DEFAULT_LOCKING_LIB "liblvm2clusterlock.so"
#define DEFAULT_FALLBACK_TO_LOCAL_LOCKING 1
#define DEFAULT_FALLBACK_TO_CLUSTERED_LOCKING 1
#define DEFAULT_MIRRORLOG "disk"
#define DEFAULT_MIRROR_LOG_FAULT_POLICY "allocate"
#define DEFAULT_MIRROR_DEV_FAULT_POLICY "remove"
#define DEFAULT_DMEVENTD_MIRROR_LIB "libdevmapper-event-lvm2mirror.so"
@@ -59,6 +63,8 @@
#define DEFAULT_PVMETADATASIZE 255
#define DEFAULT_PVMETADATACOPIES 1
#define DEFAULT_LABELSECTOR UINT64_C(1)
#define DEFAULT_READ_AHEAD "auto"
#define DEFAULT_EXTENT_SIZE 4096 /* In KB */
#define DEFAULT_MSG_PREFIX " "
#define DEFAULT_CMD_NAME 0
@@ -98,17 +104,17 @@
#define DEFAULT_REP_HEADINGS 1
#define DEFAULT_REP_SEPARATOR " "
#define DEFAULT_LVS_COLS "lv_name,vg_name,lv_attr,lv_size,origin,snap_percent,move_pv,mirror_log,copy_percent"
#define DEFAULT_LVS_COLS "lv_name,vg_name,lv_attr,lv_size,origin,snap_percent,move_pv,mirror_log,copy_percent,convert_lv"
#define DEFAULT_VGS_COLS "vg_name,pv_count,lv_count,snap_count,vg_attr,vg_size,vg_free"
#define DEFAULT_PVS_COLS "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free"
#define DEFAULT_SEGS_COLS "lv_name,vg_name,lv_attr,stripes,segtype,seg_size"
#define DEFAULT_PVSEGS_COLS "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free,pvseg_start,pvseg_size"
#define DEFAULT_LVS_COLS_VERB "lv_name,vg_name,seg_count,lv_attr,lv_size,lv_major,lv_minor,lv_kernel_major,lv_kernel_minor,origin,snap_percent,move_pv,copy_percent,mirror_log,lv_uuid"
#define DEFAULT_LVS_COLS_VERB "lv_name,vg_name,seg_count,lv_attr,lv_size,lv_major,lv_minor,lv_kernel_major,lv_kernel_minor,origin,snap_percent,move_pv,copy_percent,mirror_log,convert_lv,lv_uuid"
#define DEFAULT_VGS_COLS_VERB "vg_name,vg_attr,vg_extent_size,pv_count,lv_count,snap_count,vg_size,vg_free,vg_uuid"
#define DEFAULT_PVS_COLS_VERB "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free,dev_size,pv_uuid"
#define DEFAULT_SEGS_COLS_VERB "lv_name,vg_name,lv_attr,seg_start,seg_size,stripes,segtype,stripesize,chunksize"
#define DEFAULT_PVSEGS_COLS_VERB "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free,pvseg_start,pvseg_size"
#define DEFAULT_PVSEGS_COLS_VERB "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free,pvseg_start,pvseg_size,lv_name,seg_start_pe,segtype,seg_pe_ranges"
#define DEFAULT_LVS_SORT "vg_name,lv_name"
#define DEFAULT_VGS_SORT "vg_name"

View File

@@ -1,14 +1,14 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004-2007 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.
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU General Public License
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
@@ -55,7 +55,8 @@ static uint32_t _shuffle(uint32_t k)
#endif
}
static struct node **_lookup(struct node **c, uint32_t key, struct node **p)
static struct node **_lookup(struct node *const *c, uint32_t key,
struct node **p)
{
*p = NULL;
while (*c) {
@@ -70,10 +71,10 @@ static struct node **_lookup(struct node **c, uint32_t key, struct node **p)
c = &(*c)->r;
}
return c;
return (struct node **)c;
}
void *btree_lookup(struct btree *t, uint32_t k)
void *btree_lookup(const struct btree *t, uint32_t k)
{
uint32_t key = _shuffle(k);
struct node *p, **c = _lookup(&t->root, key, &p);
@@ -86,10 +87,8 @@ int btree_insert(struct btree *t, uint32_t k, void *data)
struct node *p, **c = _lookup(&t->root, key, &p), *n;
if (!*c) {
if (!(n = dm_pool_alloc(t->mem, sizeof(*n)))) {
stack;
return 0;
}
if (!(n = dm_pool_alloc(t->mem, sizeof(*n))))
return_0;
n->key = key;
n->data = data;
@@ -102,7 +101,7 @@ int btree_insert(struct btree *t, uint32_t k, void *data)
return 1;
}
void *btree_get_data(struct btree_iter *it)
void *btree_get_data(const struct btree_iter *it)
{
return ((struct node *) it)->data;
}
@@ -114,7 +113,7 @@ static struct node *_left(struct node *n)
return n;
}
struct btree_iter *btree_first(struct btree *t)
struct btree_iter *btree_first(const struct btree *t)
{
if (!t->root)
return NULL;
@@ -122,7 +121,7 @@ struct btree_iter *btree_first(struct btree *t)
return (struct btree_iter *) _left(t->root);
}
struct btree_iter *btree_next(struct btree_iter *it)
struct btree_iter *btree_next(const struct btree_iter *it)
{
struct node *n = (struct node *) it;
uint32_t k = n->key;

View File

@@ -1,14 +1,14 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
* Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License v.2.
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU General Public License
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
@@ -20,13 +20,13 @@ struct btree;
struct btree *btree_create(struct dm_pool *mem);
void *btree_lookup(struct btree *t, uint32_t k);
void *btree_lookup(const struct btree *t, uint32_t k);
int btree_insert(struct btree *t, uint32_t k, void *data);
struct btree_iter;
void *btree_get_data(struct btree_iter *it);
void *btree_get_data(const struct btree_iter *it);
struct btree_iter *btree_first(struct btree *t);
struct btree_iter *btree_next(struct btree_iter *it);
struct btree_iter *btree_first(const struct btree *t);
struct btree_iter *btree_next(const struct btree_iter *it);
#endif

View File

@@ -1,14 +1,14 @@
/*
* 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 copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License v.2.
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU General Public License
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
@@ -65,10 +65,19 @@ void list_del(struct list *elem)
elem->p->n = elem->n;
}
/*
* Remove an element from existing list and insert before 'head'.
*/
void list_move(struct list *head, struct list *elem)
{
list_del(elem);
list_add(head, elem);
}
/*
* Is the list empty?
*/
int list_empty(struct list *head)
int list_empty(const struct list *head)
{
return head->n == head;
}
@@ -76,7 +85,7 @@ int list_empty(struct list *head)
/*
* Is this the first element of the list?
*/
int list_start(struct list *head, struct list *elem)
int list_start(const struct list *head, const struct list *elem)
{
return elem->p == head;
}
@@ -84,7 +93,7 @@ int list_start(struct list *head, struct list *elem)
/*
* Is this the last element of the list?
*/
int list_end(struct list *head, struct list *elem)
int list_end(const struct list *head, const struct list *elem)
{
return elem->n == head;
}
@@ -92,7 +101,7 @@ int list_end(struct list *head, struct list *elem)
/*
* Return first element of the list or NULL if empty
*/
struct list *list_first(struct list *head)
struct list *list_first(const struct list *head)
{
return (list_empty(head) ? NULL : head->n);
}
@@ -100,7 +109,7 @@ struct list *list_first(struct list *head)
/*
* Return last element of the list or NULL if empty
*/
struct list *list_last(struct list *head)
struct list *list_last(const struct list *head)
{
return (list_empty(head) ? NULL : head->p);
}
@@ -108,7 +117,7 @@ struct list *list_last(struct list *head)
/*
* Return the previous element of the list, or NULL if we've reached the start.
*/
struct list *list_prev(struct list *head, struct list *elem)
struct list *list_prev(const struct list *head, const struct list *elem)
{
return (list_start(head, elem) ? NULL : elem->p);
}
@@ -116,7 +125,7 @@ struct list *list_prev(struct list *head, struct list *elem)
/*
* Return the next element of the list, or NULL if we've reached the end.
*/
struct list *list_next(struct list *head, struct list *elem)
struct list *list_next(const struct list *head, const struct list *elem)
{
return (list_end(head, elem) ? NULL : elem->n);
}

View File

@@ -1,14 +1,14 @@
/*
* 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 copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License v.2.
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU General Public License
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
@@ -54,40 +54,45 @@ void list_add_h(struct list *head, struct list *elem);
*/
void list_del(struct list *elem);
/*
* Remove an element from existing list and insert before 'head'.
*/
void list_move(struct list *head, struct list *elem);
/*
* Is the list empty?
*/
int list_empty(struct list *head);
int list_empty(const struct list *head);
/*
* Is this the first element of the list?
*/
int list_start(struct list *head, struct list *elem);
int list_start(const struct list *head, const struct list *elem);
/*
* Is this the last element of the list?
*/
int list_end(struct list *head, struct list *elem);
int list_end(const struct list *head, const struct list *elem);
/*
* Return first element of the list or NULL if empty
*/
struct list *list_first(struct list *head);
struct list *list_first(const struct list *head);
/*
* Return last element of the list or NULL if empty
*/
struct list *list_last(struct list *head);
struct list *list_last(const struct list *head);
/*
* Return the previous element of the list, or NULL if we've reached the start.
*/
struct list *list_prev(struct list *head, struct list *elem);
struct list *list_prev(const struct list *head, const struct list *elem);
/*
* Return the next element of the list, or NULL if we've reached the end.
*/
struct list *list_next(struct list *head, struct list *elem);
struct list *list_next(const struct list *head, const struct list *elem);
/*
* Given the address v of an instance of 'struct list' called 'head'

View File

@@ -1,14 +1,14 @@
/*
* 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 copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License v.2.
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU General Public License
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
@@ -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

@@ -1,14 +1,14 @@
/*
* Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
* Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License v.2.
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU General Public License
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
@@ -20,10 +20,8 @@ struct list *str_list_create(struct dm_pool *mem)
{
struct list *sl;
if (!(sl = dm_pool_alloc(mem, sizeof(struct list)))) {
stack;
return NULL;
}
if (!(sl = dm_pool_alloc(mem, sizeof(struct list))))
return_NULL;
list_init(sl);
@@ -34,19 +32,15 @@ int str_list_add(struct dm_pool *mem, struct list *sll, const char *str)
{
struct str_list *sln;
if (!str) {
stack;
return 0;
}
if (!str)
return_0;
/* Already in list? */
if (str_list_match_item(sll, str))
return 1;
if (!(sln = dm_pool_alloc(mem, sizeof(*sln)))) {
stack;
return 0;
}
if (!(sln = dm_pool_alloc(mem, sizeof(*sln))))
return_0;
sln->str = str;
list_add(sll, &sln->list);
@@ -66,17 +60,16 @@ int str_list_del(struct list *sll, const char *str)
return 1;
}
int str_list_dup(struct dm_pool *mem, struct list *sllnew, struct list *sllold)
int str_list_dup(struct dm_pool *mem, struct list *sllnew,
const struct list *sllold)
{
struct str_list *sl;
list_init(sllnew);
list_iterate_items(sl, sllold) {
if (!str_list_add(mem, sllnew, strdup(sl->str))) {
stack;
return 0;
}
if (!str_list_add(mem, sllnew, dm_pool_strdup(mem, sl->str)))
return_0;
}
return 1;
@@ -85,7 +78,7 @@ int str_list_dup(struct dm_pool *mem, struct list *sllnew, struct list *sllold)
/*
* Is item on list?
*/
int str_list_match_item(struct list *sll, const char *str)
int str_list_match_item(const struct list *sll, const char *str)
{
struct str_list *sl;
@@ -99,7 +92,7 @@ int str_list_match_item(struct list *sll, const char *str)
/*
* Is at least one item on both lists?
*/
int str_list_match_list(struct list *sll, struct list *sll2)
int str_list_match_list(const struct list *sll, const struct list *sll2)
{
struct str_list *sl;
@@ -113,7 +106,7 @@ int str_list_match_list(struct list *sll, struct list *sll2)
/*
* Do both lists contain the same set of items?
*/
int str_list_lists_equal(struct list *sll, struct list *sll2)
int str_list_lists_equal(const struct list *sll, const struct list *sll2)
{
struct str_list *sl;

View File

@@ -1,14 +1,14 @@
/*
* Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
* Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License v.2.
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU General Public License
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
@@ -19,9 +19,10 @@
struct list *str_list_create(struct dm_pool *mem);
int str_list_add(struct dm_pool *mem, struct list *sll, const char *str);
int str_list_del(struct list *sll, const char *str);
int str_list_match_item(struct list *sll, const char *str);
int str_list_match_list(struct list *sll, struct list *sll2);
int str_list_lists_equal(struct list *sll, struct list *sll2);
int str_list_dup(struct dm_pool *mem, struct list *sllnew, struct list *sllold);
int str_list_match_item(const struct list *sll, const char *str);
int str_list_match_list(const struct list *sll, const struct list *sll2);
int str_list_lists_equal(const struct list *sll, const struct list *sll2);
int str_list_dup(struct dm_pool *mem, struct list *sllnew,
const struct list *sllold);
#endif

View File

@@ -1,14 +1,14 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004-2007 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.
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU General Public License
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
@@ -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++;
@@ -166,11 +205,11 @@ static int _compare_paths(const char *path0, const char *path1)
*s1 = '\0';
}
if (lstat(p0, &stat0)) {
log_sys_error("lstat", p0);
log_sys_very_verbose("lstat", p0);
return 1;
}
if (lstat(p1, &stat1)) {
log_sys_error("lstat", p1);
log_sys_very_verbose("lstat", p1);
return 0;
}
if (S_ISLNK(stat0.st_mode) && !S_ISLNK(stat1.st_mode))
@@ -197,10 +236,8 @@ static int _add_alias(struct device *dev, const char *path)
const char *oldpath;
int prefer_old = 1;
if (!sl) {
stack;
return 0;
}
if (!sl)
return_0;
/* Is name already there? */
list_iterate_items(strl, &dev->aliases) {
@@ -210,10 +247,8 @@ static int _add_alias(struct device *dev, const char *path)
}
}
if (!(sl->str = dm_pool_strdup(_cache.mem, path))) {
stack;
return 0;
}
if (!(sl->str = dm_pool_strdup(_cache.mem, path)))
return_0;
if (!list_empty(&dev->aliases)) {
oldpath = list_item(dev->aliases.n, struct str_list)->str;
@@ -255,14 +290,10 @@ static int _insert_dev(const char *path, dev_t d)
(uint32_t) d))) {
/* create new device */
if (loopfile) {
if (!(dev = dev_create_file(path, NULL, NULL, 0))) {
stack;
return 0;
}
} else if (!(dev = _dev_create(d))) {
stack;
return 0;
}
if (!(dev = dev_create_file(path, NULL, NULL, 0)))
return_0;
} else if (!(dev = _dev_create(d)))
return_0;
if (!(btree_insert(_cache.devices, (uint32_t) d, dev))) {
log_err("Couldn't insert device into binary tree.");
@@ -330,10 +361,8 @@ static int _insert_dir(const char *dir)
continue;
}
if (!(path = _join(dir, dirent[n]->d_name))) {
stack;
return 0;
}
if (!(path = _join(dir, dirent[n]->d_name)))
return_0;
_collapse_slashes(path);
r &= _insert(path, 1);
@@ -361,10 +390,8 @@ static int _insert_file(const char *path)
return 0;
}
if (!_insert_dev(path, 0)) {
stack;
return 0;
}
if (!_insert_dev(path, 0))
return_0;
return 1;
}
@@ -400,10 +427,8 @@ static int _insert(const char *path, int rec)
return 0;
}
if (!_insert_dev(path, info.st_rdev)) {
stack;
return 0;
}
if (!_insert_dev(path, info.st_rdev))
return_0;
r = 1;
}
@@ -441,21 +466,76 @@ 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;
if (!(_cache.mem = dm_pool_create("dev_cache", 10 * 1024))) {
stack;
return 0;
}
if (!(_cache.mem = dm_pool_create("dev_cache", 10 * 1024)))
return_0;
if (!(_cache.names = dm_hash_create(128))) {
stack;
dm_pool_destroy(_cache.mem);
_cache.mem = 0;
return 0;
return_0;
}
if (!(_cache.devices = btree_create(_cache.mem))) {
@@ -466,6 +546,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 +572,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

@@ -1,14 +1,14 @@
/*
* 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 copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License v.2.
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU General Public License
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
@@ -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

@@ -1,14 +1,14 @@
/*
* 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 copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License v.2.
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU General Public License
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
@@ -170,10 +170,8 @@ static int _aligned_io(struct device_area *where, void *buffer,
struct device_area widened;
if (!(where->dev->flags & DEV_REGULAR) &&
!_get_block_size(where->dev, &block_size)) {
stack;
return 0;
}
!_get_block_size(where->dev, &block_size))
return_0;
if (!block_size)
block_size = lvm_getpagesize();
@@ -200,10 +198,8 @@ static int _aligned_io(struct device_area *where, void *buffer,
/* channel the io through the bounce buffer */
if (!_io(&widened, bounce, 0)) {
if (!should_write) {
stack;
return 0;
}
if (!should_write)
return_0;
/* FIXME pre-extend the file */
memset(bounce, '\n', widened.size);
}
@@ -292,11 +288,14 @@ int dev_get_sectsize(struct device *dev, uint32_t *size)
if (ioctl(fd, BLKSSZGET, &s) < 0) {
log_sys_error("ioctl BLKSSZGET", name);
close(fd);
if (close(fd))
log_sys_error("close", name);
return 0;
}
close(fd);
if (close(fd))
log_sys_error("close", name);
*size = (uint32_t) s;
log_very_verbose("%s: sector size is %" PRIu32 " bytes", name, *size);
@@ -337,7 +336,7 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet)
if (dev->open_count && !need_excl) {
/* FIXME Ensure we never get here */
log_debug("WARNING: %s already opened read-only",
log_debug("WARNING: %s already opened read-only",
dev_name(dev));
dev->open_count++;
}
@@ -351,15 +350,18 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet)
if (dev->flags & DEV_REGULAR)
name = dev_name(dev);
else if (!(name = dev_name_confirmed(dev, quiet))) {
stack;
return 0;
}
else if (!(name = dev_name_confirmed(dev, quiet)))
return_0;
if (!(dev->flags & DEV_REGULAR) &&
((stat(name, &buf) < 0) || (buf.st_rdev != dev->dev))) {
log_error("%s: stat failed: Has device name changed?", name);
return 0;
if (!(dev->flags & DEV_REGULAR)) {
if (stat(name, &buf) < 0) {
log_sys_error("%s: stat failed", name);
return 0;
}
if (buf.st_rdev != dev->dev) {
log_error("%s: device changed", name);
return 0;
}
}
#ifdef O_DIRECT_SUPPORT
@@ -514,8 +516,8 @@ static int _dev_close(struct device *dev, int immediate)
/* Close unless device is known to belong to a locked VG */
if (immediate ||
(dev->open_count < 1 &&
(!(info = info_from_pvid(dev->pvid)) ||
(dev->open_count < 1 &&
(!(info = info_from_pvid(dev->pvid, 0)) ||
!info->vginfo ||
!vgname_is_locked(info->vginfo->vgname))))
_close(dev);
@@ -549,10 +551,8 @@ int dev_read(struct device *dev, uint64_t offset, size_t len, void *buffer)
{
struct device_area where;
if (!dev->open_count) {
stack;
return 0;
}
if (!dev->open_count)
return_0;
where.dev = dev;
where.start = offset;
@@ -561,6 +561,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
*/
@@ -570,10 +599,8 @@ int dev_append(struct device *dev, size_t len, void *buffer)
{
int r;
if (!dev->open_count) {
stack;
return 0;
}
if (!dev->open_count)
return_0;
r = dev_write(dev, dev->end, len, buffer);
dev->end += (uint64_t) len;
@@ -588,10 +615,8 @@ int dev_write(struct device *dev, uint64_t offset, size_t len, void *buffer)
{
struct device_area where;
if (!dev->open_count) {
stack;
return 0;
}
if (!dev->open_count)
return_0;
where.dev = dev;
where.start = offset;
@@ -607,10 +632,8 @@ int dev_set(struct device *dev, uint64_t offset, size_t len, int value)
size_t s;
char buffer[4096] __attribute((aligned(8)));
if (!dev_open(dev)) {
stack;
return 0;
}
if (!dev_open(dev))
return_0;
if ((offset % SECTOR_SIZE) || (len % SECTOR_SIZE))
log_debug("Wiping %s at %" PRIu64 " length %" PRIsize_t,

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2004 Luca Berra
* 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.
*
@@ -17,25 +17,65 @@
#include "metadata.h"
#include "xlate.h"
#ifdef linux
/* Lifted from <linux/raid/md_p.h> because of difficulty including it */
#define MD_SB_MAGIC 0xa92b4efc
#define MD_RESERVED_BYTES (64 * 1024)
#define MD_RESERVED_BYTES (64 * 1024ULL)
#define MD_RESERVED_SECTORS (MD_RESERVED_BYTES / 512)
#define MD_NEW_SIZE_SECTORS(x) ((x & ~(MD_RESERVED_SECTORS - 1)) \
- MD_RESERVED_SECTORS)
static int _dev_has_md_magic(struct device *dev, uint64_t sb_offset)
{
uint32_t md_magic;
/* 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 == MD_SB_MAGIC)))
return 1;
return 0;
}
/*
* Calculate the position of the superblock.
* It is always aligned to a 4K boundary and
* depending on minor_version, it can be:
* 0: At least 8K, but less than 12K, from end of device
* 1: At start of device
* 2: 4K from start of device.
*/
static uint64_t _v1_sb_offset(uint64_t size, unsigned minor_version)
{
uint64_t sb_offset;
switch(minor_version) {
case 0:
sb_offset = (size - 8 * 2) & ~(4 * 2 - 1ULL);
break;
case 1:
sb_offset = 0;
break;
case 2:
sb_offset = 4 * 2;
break;
}
sb_offset <<= SECTOR_SHIFT;
return sb_offset;
}
/*
* Returns -1 on error
*/
int dev_is_md(struct device *dev, uint64_t *sb)
{
int ret = 0;
#ifdef linux
int ret = 1;
unsigned minor = 0;
uint64_t size, sb_offset;
uint32_t md_magic;
if (!dev_get_size(dev, &size)) {
stack;
@@ -50,20 +90,37 @@ int dev_is_md(struct device *dev, uint64_t *sb)
return -1;
}
sb_offset = MD_NEW_SIZE_SECTORS(size) << SECTOR_SHIFT;
/* Check if it is an md component device. */
if (dev_read(dev, sb_offset, sizeof(uint32_t), &md_magic) &&
(md_magic == xlate32(MD_SB_MAGIC))) {
if (sb)
*sb = sb_offset;
ret = 1;
}
/* Version 0.90.0 */
sb_offset = MD_NEW_SIZE_SECTORS(size) << SECTOR_SHIFT;
if (_dev_has_md_magic(dev, sb_offset))
goto out;
/* Version 1, try v1.0 -> v1.2 */
do {
sb_offset = _v1_sb_offset(size, minor);
if (_dev_has_md_magic(dev, sb_offset))
goto out;
} while (++minor <= 2);
ret = 0;
out:
if (!dev_close(dev))
stack;
#endif
if (ret && sb)
*sb = sb_offset;
return ret;
}
#else
int dev_is_md(struct device *dev __attribute((unused)),
uint64_t *sb __attribute((unused)))
{
return 0;
}
#endif

View File

@@ -1,14 +1,14 @@
/*
* 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 copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License v.2.
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU General Public License
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
@@ -27,16 +27,16 @@
#define PART_OFFSET UINT64_C(0x1BE)
struct partition {
uint8_t boot_ind;
uint8_t head;
uint8_t sector;
uint8_t cyl;
uint8_t sys_ind; /* partition type */
uint8_t end_head;
uint8_t end_sector;
uint8_t end_cyl;
uint32_t start_sect;
uint32_t nr_sects;
uint8_t boot_ind;
uint8_t head;
uint8_t sector;
uint8_t cyl;
uint8_t sys_ind; /* partition type */
uint8_t end_head;
uint8_t end_sector;
uint8_t end_cyl;
uint32_t start_sect;
uint32_t nr_sects;
} __attribute__((packed));
static int _is_partitionable(struct device *dev)
@@ -62,10 +62,8 @@ static int _has_partition_table(struct device *dev)
return -1;
}
if (!dev_read(dev, UINT64_C(0), sizeof(buf), &buf)) {
stack;
goto out;
}
if (!dev_read(dev, UINT64_C(0), sizeof(buf), &buf))
goto_out;
/* FIXME Check for other types of partition table too */

View File

@@ -1,14 +1,14 @@
/*
* 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 copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License v.2.
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU General Public License
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
@@ -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

@@ -1,14 +1,14 @@
/*
* 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 copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License v.2.
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU General Public License
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
@@ -147,7 +147,8 @@ alloc_policy_t get_alloc_from_string(const char *str)
}
/* Size supplied in sectors */
static const char *_display_size(struct cmd_context *cmd, uint64_t size, size_len_t sl)
static const char *_display_size(const struct cmd_context *cmd,
uint64_t size, size_len_t sl)
{
int s;
int suffix = 1, precision;
@@ -185,17 +186,17 @@ static const char *_display_size(struct cmd_context *cmd, uint64_t size, size_le
return size_buf;
}
if (s < 10) {
size *= UINT64_C(512);
if (s < 10)
byte = cmd->current_settings.unit_factor;
size *= UINT64_C(512);
} else {
size /= 2;
else {
suffix = 1;
if (cmd->current_settings.unit_type == 'H')
units = UINT64_C(1000);
else
units = UINT64_C(1024);
byte = units * units * units * units * units;
byte = units * units * units * units * units * units;
s = 0;
while (size_str[s] && size < byte)
s++, byte /= units;
@@ -217,22 +218,22 @@ static const char *_display_size(struct cmd_context *cmd, uint64_t size, size_le
return size_buf;
}
const char *display_size_long(struct cmd_context *cmd, uint64_t size)
const char *display_size_long(const struct cmd_context *cmd, uint64_t size)
{
return _display_size(cmd, size, SIZE_LONG);
}
const char *display_size_units(struct cmd_context *cmd, uint64_t size)
const char *display_size_units(const struct cmd_context *cmd, uint64_t size)
{
return _display_size(cmd, size, SIZE_UNIT);
}
const char *display_size(struct cmd_context *cmd, uint64_t size)
const char *display_size(const struct cmd_context *cmd, uint64_t size)
{
return _display_size(cmd, size, SIZE_SHORT);
}
void pvdisplay_colons(struct physical_volume *pv)
void pvdisplay_colons(const struct physical_volume *pv)
{
char uuid[64] __attribute((aligned(8)));
@@ -245,7 +246,7 @@ void pvdisplay_colons(struct physical_volume *pv)
}
log_print("%s:%s:%" PRIu64 ":-1:%u:%u:-1:%" PRIu32 ":%u:%u:%u:%s",
dev_name(pv->dev), pv->vg_name, pv->size,
pv_dev_name(pv), pv->vg_name, pv->size,
/* FIXME pv->pv_number, Derive or remove? */
pv->status, /* FIXME Support old or new format here? */
pv->status & ALLOCATABLE_PV, /* FIXME remove? */
@@ -258,14 +259,43 @@ void pvdisplay_colons(struct physical_volume *pv)
return;
}
void pvdisplay_segments(const struct physical_volume *pv)
{
const 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_is_allocated(pvseg)) {
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 pvdisplay_full(const struct cmd_context *cmd,
const struct physical_volume *pv,
void *handle __attribute((unused)))
{
char uuid[64] __attribute((aligned(8)));
const char *size;
uint32_t pe_free;
uint64_t data_size, pvsize, unusable;
if (!pv)
return;
@@ -276,23 +306,25 @@ void pvdisplay_full(struct cmd_context *cmd, struct physical_volume *pv,
}
log_print("--- %sPhysical volume ---", pv->pe_size ? "" : "NEW ");
log_print("PV Name %s", dev_name(pv->dev));
log_print("VG Name %s%s", pv->vg_name,
log_print("PV Name %s", pv_dev_name(pv));
log_print("VG Name %s%s",
is_orphan(pv) ? "" : pv->vg_name,
pv->status & EXPORTED_VG ? " (exported)" : "");
size = display_size(cmd, (uint64_t) pv->size);
if (pv->pe_size && pv->pe_count) {
data_size = (uint64_t) pv->pe_count * pv->pe_size;
if (pv->size > data_size + pv->pe_start) {
pvsize = pv->size;
unusable = pvsize - data_size;
} else {
pvsize = data_size + pv->pe_start;
unusable = pvsize - pv->size;
}
/******** FIXME display LVM on-disk data size
size2 = display_size(cmd, pv->size);
********/
log_print("PV Size %s" " / not usable %s", /* [LVM: %s]", */
size,
display_size(cmd, (pv->size -
(uint64_t) pv->pe_count * pv->pe_size)));
} else
size = display_size(cmd, pvsize);
if (data_size)
log_print("PV Size %s / not usable %s", /* [LVM: %s]", */
size, display_size(cmd, unusable));
else
log_print("PV Size %s", size);
/* PV number not part of LVM2 design
@@ -319,9 +351,9 @@ void pvdisplay_full(struct cmd_context *cmd, struct physical_volume *pv,
return;
}
int pvdisplay_short(struct cmd_context *cmd __attribute((unused)),
struct volume_group *vg __attribute((unused)),
struct physical_volume *pv,
int pvdisplay_short(const struct cmd_context *cmd __attribute((unused)),
const struct volume_group *vg __attribute((unused)),
const struct physical_volume *pv,
void *handle __attribute((unused)))
{
char uuid[64] __attribute((aligned(8)));
@@ -329,12 +361,10 @@ int pvdisplay_short(struct cmd_context *cmd __attribute((unused)),
if (!pv)
return 0;
if (!id_write_format(&pv->id, uuid, sizeof(uuid))) {
stack;
return 0;
}
if (!id_write_format(&pv->id, uuid, sizeof(uuid)))
return_0;
log_print("PV Name %s ", dev_name(pv->dev));
log_print("PV Name %s ", pv_dev_name(pv));
/* FIXME pv->pv_number); */
log_print("PV UUID %s", *uuid ? uuid : "none");
log_print("PV Status %sallocatable",
@@ -346,11 +376,11 @@ int pvdisplay_short(struct cmd_context *cmd __attribute((unused)),
return 0;
}
void lvdisplay_colons(struct logical_volume *lv)
void lvdisplay_colons(const struct logical_volume *lv)
{
int inkernel;
struct lvinfo info;
inkernel = lv_info(lv->vg->cmd, lv, &info, 1) && info.exists;
inkernel = lv_info(lv->vg->cmd, lv, &info, 1, 0) && info.exists;
log_print("%s%s/%s:%s:%d:%d:-1:%d:%" PRIu64 ":%d:-1:%d:%d:%d:%d",
lv->vg->cmd->dev_dir,
@@ -366,7 +396,8 @@ void lvdisplay_colons(struct logical_volume *lv)
return;
}
int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv,
int lvdisplay_full(struct cmd_context *cmd,
const struct logical_volume *lv,
void *handle __attribute((unused)))
{
struct lvinfo info;
@@ -375,12 +406,10 @@ int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv,
struct lv_segment *snap_seg = NULL;
float snap_percent; /* fused, fsize; */
if (!id_write_format(&lv->lvid.id[1], uuid, sizeof(uuid))) {
stack;
return 0;
}
if (!id_write_format(&lv->lvid.id[1], uuid, sizeof(uuid)))
return_0;
inkernel = lv_info(cmd, lv, &info, 1) && info.exists;
inkernel = lv_info(cmd, lv, &info, 1, 1) && info.exists;
log_print("--- Logical volume ---");
@@ -461,7 +490,15 @@ int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv,
***********/
log_print("Allocation %s", get_alloc_string(lv->alloc));
log_print("Read ahead sectors %u", lv->read_ahead);
if (lv->read_ahead == DM_READ_AHEAD_AUTO)
log_print("Read ahead sectors auto");
else if (lv->read_ahead == DM_READ_AHEAD_NONE)
log_print("Read ahead sectors 0");
else
log_print("Read ahead sectors %u", lv->read_ahead);
if (inkernel && lv->read_ahead != info.read_ahead)
log_print("- currently set to %u", info.read_ahead);
if (lv->status & FIXED_MINOR) {
if (lv->major >= 0)
@@ -485,7 +522,7 @@ void display_stripe(const struct lv_segment *seg, uint32_t s, const char *pre)
/* FIXME Re-check the conditions for 'Missing' */
log_print("%sPhysical volume\t%s", pre,
seg_pv(seg, s) ?
dev_name(seg_dev(seg, s)) :
pv_dev_name(seg_pv(seg, s)) :
"Missing");
if (seg_pv(seg, s))
@@ -508,9 +545,9 @@ void display_stripe(const struct lv_segment *seg, uint32_t s, const char *pre)
}
}
int lvdisplay_segments(struct logical_volume *lv)
int lvdisplay_segments(const struct logical_volume *lv)
{
struct lv_segment *seg;
const struct lv_segment *seg;
log_print("--- Segments ---");
@@ -528,15 +565,17 @@ int lvdisplay_segments(struct logical_volume *lv)
return 1;
}
void vgdisplay_extents(struct volume_group *vg __attribute((unused)))
void vgdisplay_extents(const struct volume_group *vg __attribute((unused)))
{
return;
}
void vgdisplay_full(struct volume_group *vg)
void vgdisplay_full(const struct volume_group *vg)
{
uint32_t access;
uint32_t active_pvs;
uint32_t lv_count = 0;
struct lv_list *lvl;
char uuid[64] __attribute((aligned(8)));
if (vg->status & PARTIAL_VG)
@@ -565,13 +604,18 @@ void vgdisplay_full(struct volume_group *vg)
/* vg number not part of LVM2 design
log_print ("VG # %u\n", vg->vg_number);
*/
if (vg->status & CLUSTERED) {
if (vg_is_clustered(vg)) {
log_print("Clustered yes");
log_print("Shared %s",
vg->status & SHARED ? "yes" : "no");
}
list_iterate_items(lvl, &vg->lvs)
if (lv_is_visible(lvl->lv) && !(lvl->lv->status & SNAPSHOT))
lv_count++;
log_print("MAX LV %u", vg->max_lv);
log_print("Cur LV %u", vg->lv_count + vg->snapshot_count);
log_print("Cur LV %u", lv_count);
log_print("Open LV %u", lvs_in_vg_opened(vg));
/****** FIXME Max LV Size
log_print ( "MAX LV Size %s",
@@ -612,9 +656,11 @@ void vgdisplay_full(struct volume_group *vg)
return;
}
void vgdisplay_colons(struct volume_group *vg)
void vgdisplay_colons(const struct volume_group *vg)
{
uint32_t active_pvs;
uint32_t lv_count;
struct lv_list *lvl;
const char *access;
char uuid[64] __attribute((aligned(8)));
@@ -623,6 +669,10 @@ void vgdisplay_colons(struct volume_group *vg)
else
active_pvs = vg->pv_count;
list_iterate_items(lvl, &vg->lvs)
if (lv_is_visible(lvl->lv) && !(lvl->lv->status & SNAPSHOT))
lv_count++;
switch (vg->status & (LVM_READ | LVM_WRITE)) {
case LVM_READ | LVM_WRITE:
access = "r/w";
@@ -658,13 +708,13 @@ void vgdisplay_colons(struct volume_group *vg)
(uint64_t) vg->extent_count * (vg->extent_size / 2),
vg->extent_size / 2,
vg->extent_count,
vg->extent_count - vg->free_count,
vg->extent_count - vg->free_count,
vg->free_count,
uuid[0] ? uuid : "none");
return;
}
void vgdisplay_short(struct volume_group *vg)
void vgdisplay_short(const struct volume_group *vg)
{
log_print("\"%s\" %-9s [%-9s used / %s free]", vg->name,
/********* FIXME if "open" print "/used" else print "/idle"??? ******/
@@ -678,21 +728,52 @@ void vgdisplay_short(struct volume_group *vg)
return;
}
void display_formats(struct cmd_context *cmd)
void display_formats(const struct cmd_context *cmd)
{
struct format_type *fmt;
const struct format_type *fmt;
list_iterate_items(fmt, &cmd->formats) {
log_print("%s", fmt->name);
}
}
void display_segtypes(struct cmd_context *cmd)
void display_segtypes(const struct cmd_context *cmd)
{
struct segment_type *segtype;
const struct segment_type *segtype;
list_iterate_items(segtype, &cmd->segtypes) {
log_print("%s", segtype->name);
}
}
char yes_no_prompt(const char *prompt, ...)
{
int c = 0, ret = 0;
va_list ap;
sigint_allow();
do {
if (c == '\n' || !c) {
va_start(ap, prompt);
vprintf(prompt, ap);
va_end(ap);
}
if ((c = getchar()) == EOF) {
ret = 'n';
break;
}
c = tolower(c);
if ((c == 'y') || (c == 'n'))
ret = c;
} while (!ret || c != '\n');
sigint_restore();
if (c != '\n')
printf("\n");
return ret;
}

View File

@@ -1,14 +1,14 @@
/*
* 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 copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License v.2.
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU General Public License
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
@@ -16,38 +16,42 @@
#ifndef _LVM_DISPLAY_H
#define _LVM_DISPLAY_H
#include "metadata.h"
#include "metadata-exported.h"
#include "locking.h"
#include <stdint.h>
uint64_t units_to_bytes(const char *units, char *unit_type);
/* Specify size in KB */
const char *display_size(struct cmd_context *cmd, uint64_t size);
const char *display_size_long(struct cmd_context *cmd, uint64_t size);
const char *display_size_units(struct cmd_context *cmd, uint64_t size);
const char *display_size(const struct cmd_context *cmd, uint64_t size);
const char *display_size_long(const struct cmd_context *cmd, uint64_t size);
const char *display_size_units(const struct cmd_context *cmd, uint64_t size);
char *display_uuid(char *uuidstr);
void display_stripe(const struct lv_segment *seg, uint32_t s, const char *pre);
void pvdisplay_colons(struct physical_volume *pv);
void pvdisplay_full(struct cmd_context *cmd, struct physical_volume *pv,
void pvdisplay_colons(const struct physical_volume *pv);
void pvdisplay_segments(const struct physical_volume *pv);
void pvdisplay_full(const struct cmd_context *cmd,
const struct physical_volume *pv,
void *handle);
int pvdisplay_short(struct cmd_context *cmd, struct volume_group *vg,
struct physical_volume *pv, void *handle);
int pvdisplay_short(const struct cmd_context *cmd,
const struct volume_group *vg,
const struct physical_volume *pv, void *handle);
void lvdisplay_colons(struct logical_volume *lv);
int lvdisplay_segments(struct logical_volume *lv);
int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv,
void lvdisplay_colons(const struct logical_volume *lv);
int lvdisplay_segments(const struct logical_volume *lv);
int lvdisplay_full(struct cmd_context *cmd, const struct logical_volume *lv,
void *handle);
void vgdisplay_extents(struct volume_group *vg);
void vgdisplay_full(struct volume_group *vg);
void vgdisplay_colons(struct volume_group *vg);
void vgdisplay_short(struct volume_group *vg);
void vgdisplay_extents(const struct volume_group *vg);
void vgdisplay_full(const struct volume_group *vg);
void vgdisplay_colons(const struct volume_group *vg);
void vgdisplay_short(const struct volume_group *vg);
void display_formats(struct cmd_context *cmd);
void display_segtypes(struct cmd_context *cmd);
void display_formats(const struct cmd_context *cmd);
void display_segtypes(const struct cmd_context *cmd);
/*
* Allocation policy display conversion routines.
@@ -55,4 +59,6 @@ void display_segtypes(struct cmd_context *cmd);
const char *get_alloc_string(alloc_policy_t alloc);
alloc_policy_t get_alloc_from_string(const char *str);
char yes_no_prompt(const char *prompt, ...);
#endif

View File

@@ -1,13 +1,13 @@
/*
* 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 copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License v.2.
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU General Public License
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
@@ -24,6 +24,7 @@
#include "lvm-string.h"
#include "activate.h"
#include "str_list.h"
#include "metadata.h"
static const char *_errseg_name(const struct lv_segment *seg)
{
@@ -50,7 +51,8 @@ static int _errseg_add_target_line(struct dev_manager *dm __attribute((unused)),
return dm_tree_node_add_error_target(node, len);
}
static int _errseg_target_present(const struct lv_segment *seg __attribute((unused)))
static int _errseg_target_present(const struct lv_segment *seg __attribute((unused)),
unsigned *attributes __attribute((unused)))
{
static int _errseg_checked = 0;
static int _errseg_present = 0;
@@ -66,7 +68,7 @@ static int _errseg_target_present(const struct lv_segment *seg __attribute((unus
#endif
static int _errseg_modules_needed(struct dm_pool *mem,
const struct lv_segment *seg,
const struct lv_segment *seg __attribute((unused)),
struct list *modules)
{
if (!str_list_add(mem, modules, "error")) {
@@ -76,7 +78,7 @@ static int _errseg_modules_needed(struct dm_pool *mem,
return 1;
}
static void _errseg_destroy(const struct segment_type *segtype)
{
dm_free((void *)segtype);

View File

@@ -1,14 +1,14 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License v.2.
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU General Public License
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
@@ -50,10 +50,8 @@ struct dev_filter *composite_filter_create(int n, struct dev_filter **filters)
{
struct dev_filter **filters_copy, *cft;
if (!filters) {
stack;
return NULL;
}
if (!filters)
return_NULL;
if (!(filters_copy = dm_malloc(sizeof(*filters) * (n + 1)))) {
log_error("composite filters allocation failed");

View File

@@ -6,9 +6,9 @@
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License v.2.
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU General Public License
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/

View File

@@ -1,5 +1,6 @@
/*
* Copyright (C) 2004 Luca Berra
* Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
@@ -18,7 +19,8 @@
#ifdef linux
static int _ignore_md(struct dev_filter *f, struct device *dev)
static int _ignore_md(struct dev_filter *f __attribute((unused)),
struct device *dev)
{
int ret;

View File

@@ -1,14 +1,14 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004-2007 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.
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU General Public License
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
@@ -18,6 +18,7 @@
#include "dev-cache.h"
#include "filter-persistent.h"
#include "lvm-file.h"
#include "lvm-string.h"
#include <sys/stat.h>
#include <fcntl.h>
@@ -42,10 +43,8 @@ static int _init_hash(struct pfilter *pf)
if (pf->devices)
dm_hash_destroy(pf->devices);
if (!(pf->devices = dm_hash_create(128))) {
stack;
return 0;
}
if (!(pf->devices = dm_hash_create(128)))
return_0;
return 1;
}
@@ -99,13 +98,13 @@ int persistent_filter_load(struct dev_filter *f, struct config_tree **cft_out)
{
struct pfilter *pf = (struct pfilter *) f->private;
struct config_tree *cft;
struct stat info;
struct stat info;
int r = 0;
if (!stat(pf->file, &info))
if (!stat(pf->file, &info))
pf->ctime = info.st_ctime;
else {
log_very_verbose("%s: stat failed: %s", pf->file,
log_very_verbose("%s: stat failed: %s", pf->file,
strerror(errno));
return_0;
}
@@ -144,6 +143,7 @@ static void _write_array(struct pfilter *pf, FILE *fp, const char *path,
{
void *d;
int first = 1;
char *buf, *str;
struct dm_hash_node *n;
for (n = dm_hash_get_first(pf->devices); n;
@@ -160,7 +160,13 @@ static void _write_array(struct pfilter *pf, FILE *fp, const char *path,
first = 0;
}
fprintf(fp, "\t\t\"%s\"", dm_hash_get_key(pf->devices, n));
str = dm_hash_get_key(pf->devices, n);
if (!(buf = alloca(escaped_len(str)))) {
log_error("persistent filter device path stack "
"allocation failed");
return;
}
fprintf(fp, "\t\t\"%s\"", escape_double_quotes(buf, str));
}
if (!first)
@@ -208,7 +214,7 @@ int persistent_filter_dump(struct dev_filter *f)
goto out;
}
if (!memcmp(&info.st_ino, &info2.st_ino, sizeof(ino_t)))
if (is_same_inode(info, info2))
break;
fcntl_unlock_file(lockfd);
@@ -239,7 +245,8 @@ int persistent_filter_dump(struct dev_filter *f)
/* _write_array(pf, fp, "invalid_devices", PF_BAD_DEVICE); */
fprintf(fp, "}\n");
fclose(fp);
if (lvm_fclose(fp, tmp_file))
goto_out;
if (rename(tmp_file, pf->file))
log_error("%s: rename to %s failed: %s", tmp_file, pf->file,
@@ -292,16 +299,13 @@ struct dev_filter *persistent_filter_create(struct dev_filter *real,
struct pfilter *pf;
struct dev_filter *f = NULL;
if (!(pf = dm_malloc(sizeof(*pf)))) {
stack;
return NULL;
}
if (!(pf = dm_malloc(sizeof(*pf))))
return_NULL;
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;
@@ -310,10 +314,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

@@ -1,14 +1,14 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
* Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License v.2.
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU General Public License
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/

View File

@@ -1,27 +1,26 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004-2007 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.
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU General Public License
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#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,
@@ -71,10 +70,8 @@ static int _extract_pattern(struct dm_pool *mem, const char *pat,
/*
* copy the regex
*/
if (!(r = dm_pool_strdup(mem, pat))) {
stack;
return 0;
}
if (!(r = dm_pool_strdup(mem, pat)))
return_0;
/*
* trim the trailing character, having checked it's sep.
@@ -98,18 +95,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 +113,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 +128,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 +152,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;
}
@@ -203,27 +190,19 @@ struct dev_filter *regex_filter_create(struct config_value *patterns)
struct rfilter *rf;
struct dev_filter *f;
if (!mem) {
stack;
return NULL;
}
if (!mem)
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

@@ -6,9 +6,9 @@
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License v.2.
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU General Public License
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/

View File

@@ -1,13 +1,13 @@
/*
* 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 copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License v.2.
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU General Public License
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
@@ -20,12 +20,14 @@
#include <dirent.h>
static int _locate_sysfs_blocks(const char *proc, char *path, size_t len)
static int _locate_sysfs_blocks(const char *proc, char *path, size_t len,
unsigned *sysfs_depth)
{
char proc_mounts[PATH_MAX];
int r = 0;
FILE *fp;
char *split[4], buffer[PATH_MAX + 16];
const char *sys_mnt = NULL;
struct stat info;
if (!*proc) {
log_verbose("No proc filesystem found: skipping sysfs filter");
@@ -46,16 +48,78 @@ static int _locate_sysfs_blocks(const char *proc, char *path, size_t len)
while (fgets(buffer, sizeof(buffer), fp)) {
if (dm_split_words(buffer, 4, 0, split) == 4 &&
!strcmp(split[2], "sysfs")) {
if (dm_snprintf(path, len, "%s/%s", split[1],
"block") >= 0) {
r = 1;
}
sys_mnt = split[1];
break;
}
}
fclose(fp);
return r;
if (fclose(fp))
log_sys_error("fclose", proc_mounts);
if (!sys_mnt) {
log_error("Failed to find sysfs mount point");
return 0;
}
/*
* unified classification directory for all kernel subsystems
*
* /sys/subsystem/block/devices
* |-- sda -> ../../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda
* |-- sda1 -> ../../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1
* `-- sr0 -> ../../../devices/pci0000:00/0000:00:1f.2/host1/target1:0:0/1:0:0:0/block/sr0
*
*/
if (dm_snprintf(path, len, "%s/%s", sys_mnt,
"subsystem/block/devices") >= 0) {
if (!stat(path, &info)) {
*sysfs_depth = 0;
return 1;
}
}
/*
* block subsystem as a class
*
* /sys/class/block
* |-- sda -> ../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda
* |-- sda1 -> ../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1
* `-- sr0 -> ../../devices/pci0000:00/0000:00:1f.2/host1/target1:0:0/1:0:0:0/block/sr0
*
*/
if (dm_snprintf(path, len, "%s/%s", sys_mnt, "class/block") >= 0) {
if (!stat(path, &info)) {
*sysfs_depth = 0;
return 1;
}
}
/*
* old block subsystem layout with nested directories
*
* /sys/block/
* |-- sda
* | |-- capability
* | |-- dev
* ...
* | |-- sda1
* | | |-- dev
* ...
* |
* `-- sr0
* |-- capability
* |-- dev
* ...
*
*/
if (dm_snprintf(path, len, "%s/%s", sys_mnt, "block") >= 0) {
if (!stat(path, &info)) {
*sysfs_depth = 1;
return 1;
}
}
return 0;
}
/*----------------------------------------------------------------
@@ -70,11 +134,14 @@ struct entry {
struct dev_set {
struct dm_pool *mem;
const char *sys_block;
unsigned sysfs_depth;
int initialised;
struct entry *slots[SET_BUCKETS];
};
static struct dev_set *_dev_set_create(struct dm_pool *mem, const char *sys_block)
static struct dev_set *_dev_set_create(struct dm_pool *mem,
const char *sys_block,
unsigned sysfs_depth)
{
struct dev_set *ds;
@@ -83,6 +150,7 @@ static struct dev_set *_dev_set_create(struct dm_pool *mem, const char *sys_bloc
ds->mem = mem;
ds->sys_block = dm_pool_strdup(mem, sys_block);
ds->sysfs_depth = sysfs_depth;
ds->initialised = 0;
return ds;
@@ -156,7 +224,9 @@ static int _read_dev(const char *file, dev_t *result)
}
r = _parse_dev(file, fp, result);
fclose(fp);
if (fclose(fp))
log_sys_error("fclose", file);
return r;
}
@@ -164,23 +234,23 @@ static int _read_dev(const char *file, dev_t *result)
/*
* Recurse through sysfs directories, inserting any devs found.
*/
static int _read_devs(struct dev_set *ds, const char *dir)
static int _read_devs(struct dev_set *ds, const char *dir, unsigned sysfs_depth)
{
struct dirent *d;
DIR *dr;
unsigned char dtype;
struct dirent *d;
DIR *dr;
struct stat info;
char path[PATH_MAX];
char file[PATH_MAX];
dev_t dev = { 0 };
int r = 1;
if (!(dr = opendir(dir))) {
log_sys_error("opendir", dir);
return 0;
}
if (!(dr = opendir(dir))) {
log_sys_error("opendir", dir);
return 0;
}
while ((d = readdir(dr))) {
if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
while ((d = readdir(dr))) {
if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
continue;
if (dm_snprintf(path, sizeof(path), "%s/%s", dir,
@@ -190,42 +260,33 @@ static int _read_devs(struct dev_set *ds, const char *dir)
continue;
}
dtype = d->d_type;
if (dtype == DT_UNKNOWN) {
if (lstat(path, &info) >= 0) {
if (S_ISLNK(info.st_mode))
dtype = DT_LNK;
else if (S_ISDIR(info.st_mode))
dtype = DT_DIR;
else if (S_ISREG(info.st_mode))
dtype = DT_REG;
}
/* devices have a "dev" file */
if (dm_snprintf(file, sizeof(file), "%s/dev", path) < 0) {
log_error("sysfs path name too long: %s in %s",
d->d_name, dir);
continue;
}
if (dtype == DT_DIR) {
if (!_read_devs(ds, path)) {
r = 0;
break;
}
}
if (!stat(file, &info)) {
/* recurse if we found a device and expect subdirs */
if (sysfs_depth)
_read_devs(ds, path, sysfs_depth - 1);
if ((dtype == DT_REG && !strcmp(d->d_name, "dev")))
if (!_read_dev(path, &dev) || !_set_insert(ds, dev)) {
r = 0;
break;
}
/* add the device we have found */
if (_read_dev(file, &dev))
_set_insert(ds, dev);
}
}
if (closedir(dr))
log_sys_error("closedir", dir);
if (closedir(dr))
log_sys_error("closedir", dir);
return r;
}
static int _init_devs(struct dev_set *ds)
{
if (!_read_devs(ds, ds->sys_block)) {
if (!_read_devs(ds, ds->sys_block, ds->sysfs_depth)) {
ds->initialised = -1;
return 0;
}
@@ -263,11 +324,12 @@ static void _destroy(struct dev_filter *f)
struct dev_filter *sysfs_filter_create(const char *proc)
{
char sys_block[PATH_MAX];
unsigned sysfs_depth;
struct dm_pool *mem;
struct dev_set *ds;
struct dev_filter *f;
if (!_locate_sysfs_blocks(proc, sys_block, sizeof(sys_block)))
if (!_locate_sysfs_blocks(proc, sys_block, sizeof(sys_block), &sysfs_depth))
return NULL;
if (!(mem = dm_pool_create("sysfs", 256))) {
@@ -275,15 +337,13 @@ struct dev_filter *sysfs_filter_create(const char *proc)
return NULL;
}
if (!(ds = _dev_set_create(mem, sys_block))) {
if (!(ds = _dev_set_create(mem, sys_block, sysfs_depth))) {
log_error("sysfs dev_set creation failed");
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;
@@ -297,7 +357,7 @@ struct dev_filter *sysfs_filter_create(const char *proc)
#else
struct dev_filter *sysfs_filter_create(const char *proc)
struct dev_filter *sysfs_filter_create(const char *proc __attribute((unused)))
{
return NULL;
}

View File

@@ -5,9 +5,9 @@
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License v.2.
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU General Public License
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/

View File

@@ -1,14 +1,14 @@
/*
* 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 copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License v.2.
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU General Public License
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
@@ -19,6 +19,7 @@
#include "lvm-string.h"
#include "config.h"
#include "metadata.h"
#include "activate.h"
#include <dirent.h>
#include <unistd.h>
@@ -37,6 +38,7 @@ typedef struct {
} device_info_t;
static int _md_major = -1;
static int _device_mapper_major = -1;
int md_major(void)
{
@@ -73,10 +75,13 @@ static const device_info_t device_info[] = {
{"aoe", 16}, /* ATA over Ethernet */
{"device-mapper", 1}, /* Other mapped devices */
{"xvd", 16}, /* Xen virtual block device */
{"vdisk", 8}, /* SUN's LDOM virtual block device */
{"ps3disk", 16}, /* PlayStation 3 internal disk */
{"virtblk", 8}, /* VirtIO disk */
{NULL, 0}
};
static int _passes_lvm_type_device_filter(struct dev_filter *f,
static int _passes_lvm_type_device_filter(struct dev_filter *f __attribute((unused)),
struct device *dev)
{
const char *name = dev_name(dev);
@@ -90,6 +95,13 @@ static int _passes_lvm_type_device_filter(struct dev_filter *f,
return 0;
}
/* Skip suspended devices */
if (MAJOR(dev->dev) == _device_mapper_major &&
ignore_suspended_devices() && !device_is_usable(dev->dev)) {
log_debug("%s: Skipping: Suspended dm device", name);
return 0;
}
/* Check it's accessible */
if (!dev_open_flags(dev, O_RDONLY, 0, 1)) {
log_debug("%s: Skipping: open failed", name);
@@ -182,10 +194,14 @@ static int _scan_proc_dev(const char *proc, const struct config_node *cn)
if (!strncmp("md", line + i, 2) && isspace(*(line + i + 2)))
_md_major = line_maj;
/* Look for device-mapper device */
/* FIXME Cope with multiple majors */
if (!strncmp("device-mapper", line + i, 13) && isspace(*(line + i + 13)))
_device_mapper_major = line_maj;
/* Go through the valid device names and if there is a
match store max number of partitions */
for (j = 0; device_info[j].name != NULL; j++) {
dev_len = strlen(device_info[j].name);
if (dev_len <= strlen(line + i) &&
!strncmp(device_info[j].name, line + i, dev_len) &&
@@ -204,7 +220,8 @@ static int _scan_proc_dev(const char *proc, const struct config_node *cn)
if (cv->type != CFG_STRING) {
log_error("Expecting string in devices/types "
"in config file");
fclose(pd);
if (fclose(pd))
log_sys_error("fclose", proc_devices);
return 0;
}
dev_len = strlen(cv->v.str);
@@ -214,14 +231,16 @@ static int _scan_proc_dev(const char *proc, const struct config_node *cn)
log_error("Max partition count missing for %s "
"in devices/types in config file",
name);
fclose(pd);
if (fclose(pd))
log_sys_error("fclose", proc_devices);
return 0;
}
if (!cv->v.i) {
log_error("Zero partition count invalid for "
"%s in devices/types in config file",
name);
fclose(pd);
if (fclose(pd))
log_sys_error("fclose", proc_devices);
return 0;
}
if (dev_len <= strlen(line + i) &&
@@ -232,7 +251,10 @@ static int _scan_proc_dev(const char *proc, const struct config_node *cn)
}
}
}
fclose(pd);
if (fclose(pd))
log_sys_error("fclose", proc_devices);
return 1;
}
@@ -256,9 +278,8 @@ struct dev_filter *lvm_type_filter_create(const char *proc,
f->private = NULL;
if (!_scan_proc_dev(proc, cn)) {
stack;
dm_free(f);
return NULL;
return_NULL;
}
return f;

View File

@@ -1,14 +1,14 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
* Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License v.2.
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU General Public License
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/

View File

@@ -2,7 +2,7 @@
# Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
# Copyright (C) 2004 Red Hat, Inc. All rights reserved.
#
# This file is part of the LVM2.
# 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

View File

@@ -1,14 +1,14 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004-2007 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.
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU General Public License
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
@@ -21,7 +21,6 @@
#include <fcntl.h>
#define fail do {stack; return 0;} while(0)
#define xx16(v) disk->v = xlate16(disk->v)
#define xx32(v) disk->v = xlate32(disk->v)
#define xx64(v) disk->v = xlate64(disk->v)
@@ -134,15 +133,15 @@ static int _munge_formats(struct pv_disk *pvd)
return 0;
}
/* UUID too long? */
if (pvd->pv_uuid[ID_LEN]) {
/* UUID too long? */
if (pvd->pv_uuid[ID_LEN]) {
/* Retain ID_LEN chars from end */
for (e = ID_LEN; e < sizeof(pvd->pv_uuid); e++) {
if (!pvd->pv_uuid[e]) {
e--;
break;
}
}
for (e = ID_LEN; e < sizeof(pvd->pv_uuid); e++) {
if (!pvd->pv_uuid[e]) {
e--;
break;
}
}
for (b = 0; b < ID_LEN; b++) {
pvd->pv_uuid[b] = pvd->pv_uuid[++e - ID_LEN];
/* FIXME Remove all invalid chars */
@@ -150,7 +149,7 @@ static int _munge_formats(struct pv_disk *pvd)
pvd->pv_uuid[b] = '#';
}
memset(&pvd->pv_uuid[ID_LEN], 0, sizeof(pvd->pv_uuid) - ID_LEN);
}
}
/* If UUID is missing, create one */
if (pvd->pv_uuid[0] == '\0') {
@@ -161,8 +160,8 @@ static int _munge_formats(struct pv_disk *pvd)
return 1;
}
/*
* If exported, remove "PV_EXP" from end of VG name
/*
* If exported, remove "PV_EXP" from end of VG name
*/
static void _munge_exported_vg(struct pv_disk *pvd)
{
@@ -178,8 +177,8 @@ static void _munge_exported_vg(struct pv_disk *pvd)
s = sizeof(EXPORTED_TAG);
if (!strncmp((char *)pvd->vg_name + l - s + 1, EXPORTED_TAG, s)) {
pvd->vg_name[l - s + 1] = '\0';
pvd->pv_status |= VG_EXPORTED;
}
pvd->pv_status |= VG_EXPORTED;
}
}
int munge_pvd(struct device *dev, struct pv_disk *pvd)
@@ -218,7 +217,7 @@ static int _read_pvd(struct device *dev, struct pv_disk *pvd)
static int _read_lvd(struct device *dev, uint64_t pos, struct lv_disk *disk)
{
if (!dev_read(dev, pos, sizeof(*disk), disk))
fail;
return_0;
_xlate_lvd(disk);
@@ -230,12 +229,12 @@ int read_vgd(struct device *dev, struct vg_disk *vgd, struct pv_disk *pvd)
uint64_t pos = pvd->vg_on_disk.base;
if (!dev_read(dev, pos, sizeof(*vgd), vgd))
fail;
return_0;
_xlate_vgd(vgd);
if ((vgd->lv_max > MAX_LV) || (vgd->pv_max > MAX_PV))
fail;
return_0;
/* If UUID is missing, create one */
if (vgd->vg_uuid[0] == '\0')
@@ -254,10 +253,10 @@ static int _read_uuids(struct disk_list *data)
while (pos < end && num_read < data->vgd.pv_cur) {
if (!dev_read(data->dev, pos, sizeof(buffer), buffer))
fail;
return_0;
if (!(ul = dm_pool_alloc(data->mem, sizeof(*ul))))
fail;
return_0;
memcpy(ul->uuid, buffer, NAME_LEN);
ul->uuid[NAME_LEN - 1] = '\0';
@@ -288,10 +287,10 @@ static int _read_lvs(struct disk_list *data)
ll = dm_pool_alloc(data->mem, sizeof(*ll));
if (!ll)
fail;
return_0;
if (!_read_lvd(data->dev, pos, &ll->lvd))
fail;
return_0;
if (!_check_lvd(&ll->lvd))
continue;
@@ -310,10 +309,10 @@ static int _read_extents(struct disk_list *data)
uint64_t pos = data->pvd.pe_on_disk.base;
if (!extents)
fail;
return_0;
if (!dev_read(data->dev, pos, len, extents))
fail;
return_0;
_xlate_extents(extents, data->pvd.pe_total);
data->extents = extents;
@@ -327,10 +326,11 @@ static void __update_lvmcache(const struct format_type *fmt,
unsigned exported)
{
struct lvmcache_info *info;
const char *vgname = *((char *)dl->pvd.vg_name) ?
(char *)dl->pvd.vg_name : fmt->orphan_vg_name;
if (!(info = lvmcache_add(fmt->labeller, (char *)dl->pvd.pv_uuid, dev,
(char *)dl->pvd.vg_name, vgid,
exported ? EXPORTED_VG : 0))) {
vgname, vgid, exported ? EXPORTED_VG : 0))) {
stack;
return;
}
@@ -347,20 +347,16 @@ static struct disk_list *__read_disk(const struct format_type *fmt,
struct disk_list *dl = dm_pool_zalloc(mem, sizeof(*dl));
const char *name = dev_name(dev);
if (!dl) {
stack;
return NULL;
}
if (!dl)
return_NULL;
dl->dev = dev;
dl->mem = mem;
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 ?
@@ -368,20 +364,20 @@ static struct disk_list *__read_disk(const struct format_type *fmt,
if (!*dl->pvd.vg_name) {
log_very_verbose("%s is not a member of any format1 VG", name);
__update_lvmcache(fmt, dl, dev, NULL, 0);
__update_lvmcache(fmt, dl, dev, fmt->orphan_vg_name, 0);
return (vg_name) ? NULL : dl;
}
if (!read_vgd(dl->dev, &dl->vgd, &dl->pvd)) {
log_error("Failed to read VG data from PV (%s)", name);
__update_lvmcache(fmt, dl, dev, NULL, 0);
__update_lvmcache(fmt, dl, dev, fmt->orphan_vg_name, 0);
goto bad;
}
if (vg_name && strcmp(vg_name, (char *)dl->pvd.vg_name)) {
log_very_verbose("%s is not a member of the VG %s",
name, vg_name);
__update_lvmcache(fmt, dl, dev, NULL, 0);
__update_lvmcache(fmt, dl, dev, fmt->orphan_vg_name, 0);
goto bad;
}
@@ -417,19 +413,17 @@ static struct disk_list *__read_disk(const struct format_type *fmt,
struct disk_list *read_disk(const struct format_type *fmt, struct device *dev,
struct dm_pool *mem, const char *vg_name)
{
struct disk_list *r;
struct disk_list *dl;
if (!dev_open(dev)) {
stack;
return NULL;
}
if (!dev_open(dev))
return_NULL;
r = __read_disk(fmt, dev, mem, vg_name);
dl = __read_disk(fmt, dev, mem, vg_name);
if (!dev_close(dev))
stack;
return r;
return dl;
}
static void _add_pv_to_list(struct list *head, struct disk_list *data)
@@ -482,7 +476,7 @@ int read_pvs_in_vg(const struct format_type *fmt, const char *vg_name,
}
/* Did we find the whole VG? */
if (!vg_name || !*vg_name ||
if (!vg_name || is_orphan_vg(vg_name) ||
(data && *data->pvd.vg_name &&
list_size(head) == data->vgd.pv_cur))
return 1;
@@ -521,7 +515,7 @@ static int _write_vgd(struct disk_list *data)
_xlate_vgd(vgd);
if (!dev_write(data->dev, pos, sizeof(*vgd), vgd))
fail;
return_0;
_xlate_vgd(vgd);
@@ -546,7 +540,7 @@ static int _write_uuids(struct disk_list *data)
pos, NAME_LEN);
if (!dev_write(data->dev, pos, NAME_LEN, ul->uuid))
fail;
return_0;
pos += NAME_LEN;
}
@@ -562,7 +556,7 @@ static int _write_lvd(struct device *dev, uint64_t pos, struct lv_disk *disk)
_xlate_lvd(disk);
if (!dev_write(dev, pos, sizeof(*disk), disk))
fail;
return_0;
_xlate_lvd(disk);
@@ -590,7 +584,7 @@ static int _write_lvs(struct disk_list *data)
}
if (!_write_lvd(data->dev, pos + offset, &ll->lvd))
fail;
return_0;
}
return 1;
@@ -608,7 +602,7 @@ static int _write_extents(struct disk_list *data)
_xlate_extents(extents, data->pvd.pe_total);
if (!dev_write(data->dev, pos, len, extents))
fail;
return_0;
_xlate_extents(extents, data->pvd.pe_total);
@@ -645,7 +639,7 @@ static int _write_pvd(struct disk_list *data)
_xlate_pvd((struct pv_disk *) buf);
if (!dev_write(data->dev, pos, size, buf)) {
dm_free(buf);
fail;
return_0;
}
dm_free(buf);
@@ -655,7 +649,7 @@ static int _write_pvd(struct disk_list *data)
/*
* assumes the device has been opened.
*/
static int __write_all_pvd(const struct format_type *fmt,
static int __write_all_pvd(const struct format_type *fmt __attribute((unused)),
struct disk_list *data)
{
const char *pv_name = dev_name(data->dev);
@@ -709,10 +703,8 @@ static int _write_all_pvd(const struct format_type *fmt, struct disk_list *data)
{
int r;
if (!dev_open(data->dev)) {
stack;
return 0;
}
if (!dev_open(data->dev))
return_0;
r = __write_all_pvd(fmt, data);
@@ -733,7 +725,7 @@ int write_disks(const struct format_type *fmt, struct list *pvs)
list_iterate_items(dl, pvs) {
if (!(_write_all_pvd(fmt, dl)))
fail;
return_0;
log_very_verbose("Successfully wrote data to %s",
dev_name(dl->dev));

View File

@@ -1,14 +1,14 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
* Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License v.2.
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU General Public License
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/

View File

@@ -1,14 +1,14 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004-2007 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.
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU General Public License
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
@@ -18,13 +18,10 @@
#include "limits.h"
#include "display.h"
#include "toolcontext.h"
#include "lvmcache.h"
#include "lvm1-label.h"
#include "format1.h"
#include "segtype.h"
#define FMT_LVM1_NAME "lvm1"
/* VG consistency checks */
static int _check_vgs(struct list *pvs, int *partial)
{
@@ -131,10 +128,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,60 +143,53 @@ 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;
bad:
stack;
dm_pool_free(mem, vg);
return NULL;
}
static struct volume_group *_format1_vg_read(struct format_instance *fid,
const char *vg_name,
struct metadata_area *mda)
struct metadata_area *mda __attribute((unused)))
{
struct dm_pool *mem = dm_pool_create("lvm1 vg_read", 1024 * 10);
struct list pvs;
struct volume_group *vg = NULL;
list_init(&pvs);
if (!mem) {
stack;
return NULL;
}
if (!mem)
return_NULL;
/* Strip dev_dir if present */
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);
@@ -213,10 +203,8 @@ static struct disk_list *_flatten_pv(struct format_instance *fid,
{
struct disk_list *dl = dm_pool_alloc(mem, sizeof(*dl));
if (!dl) {
stack;
return NULL;
}
if (!dl)
return_NULL;
dl->mem = mem;
dl->dev = pv->dev;
@@ -228,9 +216,8 @@ static struct disk_list *_flatten_pv(struct format_instance *fid,
!export_vg(&dl->vgd, vg) ||
!export_uuids(dl, vg) ||
!export_lvs(dl, vg, pv, dev_dir) || !calculate_layout(dl)) {
stack;
dm_pool_free(mem, dl);
return NULL;
return_NULL;
}
return dl;
@@ -245,10 +232,8 @@ static int _flatten_vg(struct format_instance *fid, struct dm_pool *mem,
struct disk_list *data;
list_iterate_items(pvl, &vg->pvs) {
if (!(data = _flatten_pv(fid, mem, vg, pvl->pv, dev_dir))) {
stack;
return 0;
}
if (!(data = _flatten_pv(fid, mem, vg, pvl->pv, dev_dir)))
return_0;
list_add(pvds, &data->list);
}
@@ -256,25 +241,21 @@ static int _flatten_vg(struct format_instance *fid, struct dm_pool *mem,
export_numbers(pvds, vg);
export_pv_act(pvds);
if (!export_vg_number(fid, pvds, vg->name, filter)) {
stack;
return 0;
}
if (!export_vg_number(fid, pvds, vg->name, filter))
return_0;
return 1;
}
static int _format1_vg_write(struct format_instance *fid, struct volume_group *vg,
struct metadata_area *mda)
struct metadata_area *mda __attribute((unused)))
{
struct dm_pool *mem = dm_pool_create("lvm1 vg_write", 1024 * 10);
struct list pvds;
int r = 0;
if (!mem) {
stack;
return 0;
}
if (!mem)
return_0;
list_init(&pvds);
@@ -282,13 +263,13 @@ static int _format1_vg_write(struct format_instance *fid, struct volume_group *v
fid->fmt->cmd->filter) &&
write_disks(fid->fmt, &pvds));
lvmcache_update_vg(vg);
lvmcache_update_vg(vg, 0);
dm_pool_destroy(mem);
return r;
}
static int _format1_pv_read(const struct format_type *fmt, const char *pv_name,
struct physical_volume *pv, struct list *mdas)
struct physical_volume *pv, struct list *mdas __attribute((unused)))
{
struct dm_pool *mem = dm_pool_create("lvm1 pv_read", 1024);
struct disk_list *dl;
@@ -297,25 +278,17 @@ static int _format1_pv_read(const struct format_type *fmt, const char *pv_name,
log_very_verbose("Reading physical volume data %s from disk", pv_name);
if (!mem) {
stack;
return 0;
}
if (!mem)
return_0;
if (!(dev = dev_cache_get(pv_name, fmt->cmd->filter))) {
stack;
goto out;
}
if (!(dev = dev_cache_get(pv_name, fmt->cmd->filter)))
goto_out;
if (!(dl = read_disk(fmt, dev, mem, NULL))) {
stack;
goto out;
}
if (!(dl = read_disk(fmt, dev, mem, NULL)))
goto_out;
if (!import_pv(fmt, fmt->cmd->mem, dl->dev, NULL, pv, &dl->pvd, &dl->vgd)) {
stack;
goto out;
}
if (!import_pv(fmt, fmt->cmd->mem, dl->dev, NULL, pv, &dl->pvd, &dl->vgd))
goto_out;
pv->fmt = fmt;
@@ -329,9 +302,9 @@ static int _format1_pv_read(const struct format_type *fmt, const char *pv_name,
static int _format1_pv_setup(const struct format_type *fmt,
uint64_t pe_start, uint32_t extent_count,
uint32_t extent_size,
int pvmetadatacopies,
uint64_t pvmetadatasize, struct list *mdas,
struct physical_volume *pv, struct volume_group *vg)
int pvmetadatacopies __attribute((unused)),
uint64_t pvmetadatasize __attribute((unused)), struct list *mdas __attribute((unused)),
struct physical_volume *pv, struct volume_group *vg __attribute((unused)))
{
if (pv->size > MAX_PV_SIZE)
pv->size--;
@@ -348,10 +321,8 @@ static int _format1_pv_setup(const struct format_type *fmt,
/*
* This works out pe_start and pe_count.
*/
if (!calculate_extent_count(pv, extent_size, extent_count, pe_start)) {
stack;
return 0;
}
if (!calculate_extent_count(pv, extent_size, extent_count, pe_start))
return_0;
/* Retain existing extent locations exactly */
if (((pe_start || extent_count) && (pe_start != pv->pe_start)) ||
@@ -385,7 +356,7 @@ static int _format1_lv_setup(struct format_instance *fid, struct logical_volume
}
static int _format1_pv_write(const struct format_type *fmt, struct physical_volume *pv,
struct list *mdas, int64_t sector)
struct list *mdas __attribute((unused)), int64_t sector __attribute((unused)))
{
struct dm_pool *mem;
struct disk_list *dl;
@@ -394,10 +365,8 @@ static int _format1_pv_write(const struct format_type *fmt, struct physical_volu
struct lvmcache_info *info;
if (!(info = lvmcache_add(fmt->labeller, (char *) &pv->id, pv->dev,
pv->vg_name, NULL, 0))) {
stack;
return 0;
}
pv->vg_name, NULL, 0)))
return_0;
label = info->label;
info->device_size = pv->size << SECTOR_SHIFT;
info->fmt = fmt;
@@ -410,22 +379,17 @@ static int _format1_pv_write(const struct format_type *fmt, struct physical_volu
pv->pe_size = pv->pe_count = 0;
pv->pe_start = LVM1_PE_ALIGN;
if (!(mem = dm_pool_create("lvm1 pv_write", 1024))) {
stack;
return 0;
}
if (!(mem = dm_pool_create("lvm1 pv_write", 1024)))
return_0;
if (!(dl = dm_pool_alloc(mem, sizeof(*dl))))
goto_bad;
if (!(dl = dm_pool_alloc(mem, sizeof(*dl)))) {
stack;
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 +398,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;
@@ -479,13 +441,11 @@ static int _format1_vg_setup(struct format_instance *fid, struct volume_group *v
return 1;
}
static int _format1_segtype_supported(struct format_instance *fid,
static int _format1_segtype_supported(struct format_instance *fid __attribute((unused)),
const struct segment_type *segtype)
{
if (!(segtype->flags & SEG_FORMAT1_SUPPORT)) {
stack;
return 0;
}
if (!(segtype->flags & SEG_FORMAT1_SUPPORT))
return_0;
return 1;
}
@@ -496,26 +456,23 @@ static struct metadata_area_ops _metadata_format1_ops = {
};
static struct format_instance *_format1_create_instance(const struct format_type *fmt,
const char *vgname,
const char *vgid,
void *private)
const char *vgname __attribute((unused)),
const char *vgid __attribute((unused)),
void *private __attribute((unused)))
{
struct format_instance *fid;
struct metadata_area *mda;
if (!(fid = dm_pool_alloc(fmt->cmd->mem, sizeof(*fid)))) {
stack;
return NULL;
}
if (!(fid = dm_pool_alloc(fmt->cmd->mem, sizeof(*fid))))
return_NULL;
fid->fmt = fmt;
list_init(&fid->metadata_areas);
/* Define a NULL metadata area */
if (!(mda = dm_pool_alloc(fmt->cmd->mem, sizeof(*mda)))) {
stack;
dm_pool_free(fmt->cmd->mem, fid);
return NULL;
return_NULL;
}
mda->ops = &_metadata_format1_ops;
@@ -525,7 +482,7 @@ static struct format_instance *_format1_create_instance(const struct format_type
return fid;
}
static void _format1_destroy_instance(struct format_instance *fid)
static void _format1_destroy_instance(struct format_instance *fid __attribute((unused)))
{
return;
}
@@ -556,16 +513,16 @@ struct format_type *init_format(struct cmd_context *cmd)
{
struct format_type *fmt = dm_malloc(sizeof(*fmt));
if (!fmt) {
stack;
return NULL;
}
if (!fmt)
return_NULL;
fmt->cmd = cmd;
fmt->ops = &_format1_ops;
fmt->name = FMT_LVM1_NAME;
fmt->alias = NULL;
fmt->features = FMT_RESTRICTED_LVIDS | FMT_ORPHAN_ALLOCATABLE;
fmt->orphan_vg_name = FMT_LVM1_ORPHAN_VG_NAME;
fmt->features = FMT_RESTRICTED_LVIDS | FMT_ORPHAN_ALLOCATABLE |
FMT_RESTRICTED_READAHEAD;
fmt->private = NULL;
if (!(fmt->labeller = lvm1_labeller_create(fmt))) {

View File

@@ -6,9 +6,9 @@
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License v.2.
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU General Public License
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
@@ -17,6 +17,10 @@
#define _LVM_FORMAT1_H
#include "metadata.h"
#include "lvmcache.h"
#define FMT_LVM1_NAME "lvm1"
#define FMT_LVM1_ORPHAN_VG_NAME ORPHAN_VG_NAME(FMT_LVM1_NAME)
#ifdef LVM1_INTERNAL
struct format_type *init_lvm1_format(struct cmd_context *cmd);

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