mirror of
git://sourceware.org/git/lvm2.git
synced 2025-12-24 16:23:50 +03:00
Compare commits
216 Commits
old-dm_v1_
...
dm_v1_02_2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bc633e03aa | ||
|
|
797d0f1ef1 | ||
|
|
1be3e86aa0 | ||
|
|
e56dd38021 | ||
|
|
410904bef1 | ||
|
|
026cc120e7 | ||
|
|
ef2fda05cf | ||
|
|
92277e3ae2 | ||
|
|
fbc34d70b0 | ||
|
|
91dcddbdf7 | ||
|
|
874f42ad6c | ||
|
|
1989ef4ebc | ||
|
|
4f4c72c065 | ||
|
|
666cc72661 | ||
|
|
4524e8f5c9 | ||
|
|
bd07a29886 | ||
|
|
a0d865492e | ||
|
|
de27790de8 | ||
|
|
9c910b7be2 | ||
|
|
7f23ab94e2 | ||
|
|
77dc036c8f | ||
|
|
aa6e8d82ce | ||
|
|
3010285bb3 | ||
|
|
aaad3252f8 | ||
|
|
9065f534d8 | ||
|
|
52361c94e5 | ||
|
|
798be60fef | ||
|
|
6294154b15 | ||
|
|
6594fe077d | ||
|
|
582706cde6 | ||
|
|
6537cbdc17 | ||
|
|
53959459bb | ||
|
|
22d6121099 | ||
|
|
48d7f6f2f4 | ||
|
|
9fd4ddc490 | ||
|
|
a4d2fddbb2 | ||
|
|
c54a3f2721 | ||
|
|
04c0dba697 | ||
|
|
5406e3b7c5 | ||
|
|
6b624b7d00 | ||
|
|
2d364d4d80 | ||
|
|
1f27bf3774 | ||
|
|
d30a2653b5 | ||
|
|
3086822cd2 | ||
|
|
2c08336490 | ||
|
|
5936ac58c2 | ||
|
|
ded77e3f5c | ||
|
|
8a29df0a6c | ||
|
|
9db22babaf | ||
|
|
c318c5ed61 | ||
|
|
61243c65cd | ||
|
|
4a5d5cb462 | ||
|
|
cbf1447ebd | ||
|
|
30104441bf | ||
|
|
b4a70804f0 | ||
|
|
74f6707bde | ||
|
|
223eb8c84d | ||
|
|
107d000606 | ||
|
|
43e05607af | ||
|
|
55793452d5 | ||
|
|
686ba37255 | ||
|
|
03ed19dad5 | ||
|
|
ad2b6e5de1 | ||
|
|
767676d6ff | ||
|
|
bc7a54c615 | ||
|
|
1bda393678 | ||
|
|
bb5495c6bd | ||
|
|
484f905749 | ||
|
|
e0d61a4336 | ||
|
|
e643a16ba5 | ||
|
|
98fadec2b6 | ||
|
|
14f464ecb0 | ||
|
|
2ecdaf9bd4 | ||
|
|
707c898f66 | ||
|
|
69e4400774 | ||
|
|
695efde68d | ||
|
|
0c4b769011 | ||
|
|
e53eff0634 | ||
|
|
6c75243a06 | ||
|
|
efde37880b | ||
|
|
7d8f6381be | ||
|
|
3c361e3393 | ||
|
|
8440ecef5e | ||
|
|
6401f1b1c9 | ||
|
|
7487a7c988 | ||
|
|
f44584fa10 | ||
|
|
7b32165614 | ||
|
|
b0dc94d187 | ||
|
|
0383c4e1d8 | ||
|
|
a8c5758222 | ||
|
|
a7fabfd8cb | ||
|
|
5d5b575d16 | ||
|
|
ac1373653c | ||
|
|
b097aa787b | ||
|
|
723be0fe69 | ||
|
|
f0597a03de | ||
|
|
65f0656f54 | ||
|
|
507ece15a5 | ||
|
|
30be4d1613 | ||
|
|
366e89bda0 | ||
|
|
f159c3f768 | ||
|
|
8506d1d567 | ||
|
|
111829da46 | ||
|
|
605798073e | ||
|
|
8320f2b094 | ||
|
|
df0d8d809b | ||
|
|
062886df64 | ||
|
|
148ea3aaa8 | ||
|
|
ab5f66c13a | ||
|
|
e65ffb8e68 | ||
|
|
949c1ab517 | ||
|
|
946d8ee046 | ||
|
|
c54a8a2e10 | ||
|
|
31177e4f85 | ||
|
|
750f81b4b5 | ||
|
|
987ff02a45 | ||
|
|
f5adaf813c | ||
|
|
78ff7dc7f0 | ||
|
|
d1fced3324 | ||
|
|
e7df9c289b | ||
|
|
a78d7231a9 | ||
|
|
ba7ae0002e | ||
|
|
a090f7b839 | ||
|
|
34ed15a987 | ||
|
|
cacec4c910 | ||
|
|
3e47d4e65b | ||
|
|
8b42fa150b | ||
|
|
60e660b9c7 | ||
|
|
fe74f013e3 | ||
|
|
24c0c70f90 | ||
|
|
757f91ca89 | ||
|
|
5c34f7847e | ||
|
|
de456f014e | ||
|
|
d29565066d | ||
|
|
4d52c9233b | ||
|
|
6da1ca0cb9 | ||
|
|
2f02f1518a | ||
|
|
e8863707de | ||
|
|
6a336dfc69 | ||
|
|
35dec1b9e4 | ||
|
|
f148280c99 | ||
|
|
599fe39749 | ||
|
|
44f3fcb238 | ||
|
|
af40fdb285 | ||
|
|
9daf8b825c | ||
|
|
ef5d8ce367 | ||
|
|
4a199ab23b | ||
|
|
6f0f5a569d | ||
|
|
3172fbfde6 | ||
|
|
e97a07a505 | ||
|
|
6579ad92da | ||
|
|
ec2fad0cfa | ||
|
|
6196ac7995 | ||
|
|
095a861018 | ||
|
|
2449ed7765 | ||
|
|
117a0408d6 | ||
|
|
a54b0223a3 | ||
|
|
44ee708ba5 | ||
|
|
58a20d0fb6 | ||
|
|
063078a02d | ||
|
|
01402fea50 | ||
|
|
b7fc2d1147 | ||
|
|
43eeb7011c | ||
|
|
d7901a4220 | ||
|
|
0c6271dabc | ||
|
|
2d4cf0c9f5 | ||
|
|
0646d0dd91 | ||
|
|
83e54b45a5 | ||
|
|
5cd87d3d27 | ||
|
|
689d8a80b5 | ||
|
|
b1d82a92e7 | ||
|
|
4d65627a50 | ||
|
|
ce3a68d817 | ||
|
|
409725be24 | ||
|
|
b74f74a0d7 | ||
|
|
719d554430 | ||
|
|
13f54f4521 | ||
|
|
57dfc9cf42 | ||
|
|
57244a6823 | ||
|
|
8bdde01bef | ||
|
|
09bbd5a472 | ||
|
|
9154a74400 | ||
|
|
1399b84b32 | ||
|
|
2ddbb3a8fa | ||
|
|
e46a6d1cc1 | ||
|
|
b698ab9011 | ||
|
|
0a2572a5eb | ||
|
|
77d049cc3d | ||
|
|
7b8f053be2 | ||
|
|
2c850d5293 | ||
|
|
4056bbf10b | ||
|
|
896b04a846 | ||
|
|
93cda8b6ec | ||
|
|
bb5e930684 | ||
|
|
43761fed2a | ||
|
|
a636299680 | ||
|
|
08e5bd5b72 | ||
|
|
2f057bef5e | ||
|
|
5ab4f21444 | ||
|
|
9ec26ed481 | ||
|
|
29c9df1389 | ||
|
|
867e9c51d4 | ||
|
|
0170f7b42a | ||
|
|
74bb6ead95 | ||
|
|
303388e5cb | ||
|
|
8388779937 | ||
|
|
fc7dfca452 | ||
|
|
e5a1db2392 | ||
|
|
6790656af6 | ||
|
|
b7477bdc15 | ||
|
|
ffc61f31de | ||
|
|
e612871ea7 | ||
|
|
7f40f09f10 | ||
|
|
456e42257c | ||
|
|
8618c271cf | ||
|
|
72ca1ccc23 |
40
Makefile.in
40
Makefile.in
@@ -1,6 +1,6 @@
|
||||
#
|
||||
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
# Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
|
||||
# Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This file is part of LVM2.
|
||||
#
|
||||
@@ -36,9 +36,10 @@ ifeq ($(MAKECMDGOALS),distclean)
|
||||
lib/locking \
|
||||
lib/mirror \
|
||||
lib/snapshot \
|
||||
po \
|
||||
test/mm test/device test/format1 test/regex test/filters
|
||||
test \
|
||||
po
|
||||
DISTCLEAN_TARGETS += lib/misc/configure.h
|
||||
DISTCLEAN_DIRS += lcov_reports*
|
||||
endif
|
||||
|
||||
include make.tmpl
|
||||
@@ -71,3 +72,36 @@ endif
|
||||
|
||||
check: all
|
||||
$(MAKE) -C test all
|
||||
|
||||
ifneq ("@LCOV@", "")
|
||||
.PHONY: lcov-reset lcov lcov-dated
|
||||
|
||||
ifeq ($(MAKECMDGOALS),lcov-dated)
|
||||
LCOV_REPORTS_DIR=$(top_srcdir)/lcov_reports-$(shell date +%Y%m%d%k%M%S)
|
||||
else
|
||||
LCOV_REPORTS_DIR=$(top_srcdir)/lcov_reports
|
||||
endif
|
||||
|
||||
lcov-reset:
|
||||
$(LCOV) -d $(top_srcdir)/dmeventd --zerocounters
|
||||
$(LCOV) -d $(top_srcdir)/lib --zerocounters
|
||||
$(LCOV) -d $(top_srcdir)/tools --zerocounters
|
||||
|
||||
lcov: all
|
||||
$(RM) -rf $(LCOV_REPORTS_DIR)
|
||||
$(MKDIR_P) $(LCOV_REPORTS_DIR)
|
||||
$(LCOV) -b $(top_srcdir)/lib -d $(top_srcdir)/lib -c -o $(LCOV_REPORTS_DIR)/lib.info
|
||||
$(LCOV) -b $(top_srcdir)/tools -d $(top_srcdir)/tools -c -o $(LCOV_REPORTS_DIR)/tools.info
|
||||
DMEVENTD_INFO="$(LCOV_REPORTS_DIR)/dmeventd.info" ;\
|
||||
DMEVENTD_INFO_A="-a $$DMEVENTDINFO" ;\
|
||||
$(LCOV) -b $(top_srcdir)/dmeventd -d $(top_srcdir)/dmeventd -c -o $$DMEVENTD_INFO || DMEVENTD_INFO_A="" ;\
|
||||
$(LCOV) $$DMEVENTD_INFO_A -a $(LCOV_REPORTS_DIR)/lib.info \
|
||||
-a $(LCOV_REPORTS_DIR)/tools.info \
|
||||
-o $(LCOV_REPORTS_DIR)/lvm.info
|
||||
ifneq ("@GENHTML@", "")
|
||||
$(GENHTML) -o $(LCOV_REPORTS_DIR) -p $(top_srcdir) $(LCOV_REPORTS_DIR)/lvm.info
|
||||
endif
|
||||
|
||||
lcov-dated: lcov
|
||||
|
||||
endif
|
||||
|
||||
123
WHATS_NEW
123
WHATS_NEW
@@ -1,5 +1,128 @@
|
||||
Version 2.02.40 -
|
||||
================================
|
||||
Avoid shuffling remaining mirror images when removing one, retaining primary.
|
||||
Add missing LV error target activation in _remove_mirror_images.
|
||||
Prevent resizing an LV while lvconvert is using it.
|
||||
Avoid repeatedly wiping cache while VG_GLOBAL is held in vgscan & pvscan.
|
||||
Fix pvresize to not allow resize if PV has two metadata areas.
|
||||
Fix setting of volume limit count if converting to lvm1 format.
|
||||
Fix vgconvert logical volume id metadata validation.
|
||||
Fix lvmdump metadata gather option (-m) to work correctly.
|
||||
Fix allocation bug in text metadata format write error path.
|
||||
Fix vgcfgbackup to properly check filename if template is used.
|
||||
configure aborts if lcov or genhtml are missing with --enable-profiling
|
||||
vgremove tries to remove lv snapshot first.
|
||||
Added function lv_remove_with_dependencies().
|
||||
Improve file descriptor leak detection to display likely culprit and filename.
|
||||
Change clustered mirror kernel module name from cmirror to dm-log-clustered.
|
||||
Avoid looping forever in _pv_analyze_mda_raw used by pvck.
|
||||
Change lvchange exit status to indicate if any part of the operation failed.
|
||||
Fix pvchange and pvremove to handle PVs without mdas.
|
||||
Refactor _text_pv_read and always return mda list if requested.
|
||||
Fix configure to work w/o readline unless --enable-readline used. (2.02.39)
|
||||
Remove is_lvm_partition template which has not yet been coded.
|
||||
Refactor pvcreate to separate parameter parsing from validation logic.
|
||||
Check for label_write() failure in _text_pv_write().
|
||||
Add pvcreate tests and update vgsplit tests to handle lvm1 and lvm2 metadata.
|
||||
Fix pvchange -M1 -u to preserve existing extent locations when there's a VG.
|
||||
Cease recognising snapshot-in-use percentages returned by early devt kernels.
|
||||
Add backward-compatible flags field to on-disk format_text metadata.
|
||||
Fix dmeventd monitoring libraries to link against liblvm2cmd again. (2.02.39)
|
||||
|
||||
Version 2.02.39 - 27th June 2008
|
||||
================================
|
||||
Enable readline by default if available.
|
||||
Update autoconf to 2008-01-16.
|
||||
Add $DISTCLEAN_DIRS to make.tmpl.in.
|
||||
Create coverage reports with --enable-profiling and make lcov or lcov-dated.
|
||||
Fix up cache for PVs without mdas after consistent VG metadata is processed.
|
||||
Update validation of safe mirror log type conversions in lvconvert.
|
||||
Fix lvconvert to disallow snapshot and mirror combinations.
|
||||
Fix reporting of LV fields alongside unallocated PV segments.
|
||||
Add --unquoted and --rows to reporting tools.
|
||||
Add and use uninitialized_var() macro to suppress invalid compiler warnings.
|
||||
Introduce enum for md minor sb version to suppress compiler warning.
|
||||
Avoid undefined return value after _memlock manipulation in lvm2_run.
|
||||
Avoid link failure if configured without --enable-cmdlib or --enable-readline.
|
||||
Make clvmd return at once if other nodes down in a gulm or openais cluster.
|
||||
Fix and improve readahead 'auto' calculation for stripe_size.
|
||||
Fix lvchange output for -r auto setting if auto is already set.
|
||||
Add test case for readahead.
|
||||
Avoid ambiguous use of identifier error_message_produced.
|
||||
Begin syncing configure.in for merge/unification with device-mapper.
|
||||
Fix add_mirror_images not to dereference uninitialized log_lv upon failure.
|
||||
Don't call openlog for every debug line output by clvmd.
|
||||
Add --force to lvextend and lvresize.
|
||||
Fix vgchange not to activate component mirror volumes directly.
|
||||
Fix test directory clean up in make distclean.
|
||||
|
||||
Version 2.02.38 - 11th June 2008
|
||||
================================
|
||||
Fix tracking of validity of PVs with no mdas in lvmcache.
|
||||
Fix return values for reporting commands when run with no PVs, LVs, or VGs.
|
||||
Add omitted unlock_vg() call when sigint_caught() during vg processing.
|
||||
Fix free_count when reading pool metadata.
|
||||
Fix segfault when using pvcreate on a device containing pool metadata.
|
||||
Fix segfault after _free_vginfo by remembering to remove vginfo from list.
|
||||
Tweak detection of invalid fid after changes to PVs in VG in _vg_read.
|
||||
Revert assuming precommitted metadata is live when activating (unnecessary).
|
||||
Drop cached metadata for disappearing VG in vgmerge.
|
||||
In script-processing mode, stop if any command fails.
|
||||
Warn if command exits with non-zero status code without a prior log_error.
|
||||
Check lv_count in vg_validate.
|
||||
Add --nameprefixes to reporting tools for field name prefix output format.
|
||||
|
||||
Version 2.02.37 - 6th June 2008
|
||||
===============================
|
||||
Make clvmd-cman use a hash rather than an array for node updown info.
|
||||
Correct config file line numbers in messages when parsing comments.
|
||||
Drop cached metadata when renaming a VG.
|
||||
Allow for vginfo changing during _vg_read.
|
||||
Decode numbers in clvmd debugging output.
|
||||
Add missing deactivation after activation failure in lvcreate -Zy.
|
||||
When activating, if precommitted metadata is still cached, assume it's live.
|
||||
When removing LV symlinks, skip any where the VG name is not determined.
|
||||
Drop metadata cache if update fails in vg_revert or vg_commit.
|
||||
Avoid spurious duplicate VG messages referring to VGs that are gone.
|
||||
Drop dev_name_confirmed error message to debug level.
|
||||
Fix setpriority error message to signed int.
|
||||
Temporarily disable dmeventd mirror monitoring during lvchange --resync.
|
||||
Refactor some vginfo manipulation code.
|
||||
Add assertions to trap deprecated P_ and V_ lock usage.
|
||||
Add missing mutex around clvmd lvmcache_drop_metadata library call.
|
||||
Fix uninitialised mutex in clvmd if all daemons are not running at startup.
|
||||
Avoid using DLM locks with LCK_CACHE type P_ lock requests.
|
||||
When asked to drop cached committed VG metadata, invalidate cached PV labels.
|
||||
Drop metadata cache before writing precommitted metadata instead of after.
|
||||
Don't touch /dev in vgrename if activation is disabled.
|
||||
|
||||
Version 2.02.36 - 29th April 2008
|
||||
=================================
|
||||
Fix fsadm.sh to work with older blockdev, blkid & readlink binaries.
|
||||
Fix lvresize to pass new size to fsadm when extending device.
|
||||
Remove unused struct in clvmd-openais, and use correct node count.
|
||||
Fix nodes list in clvmd-openais, and allow for broadcast messages.
|
||||
Exclude VG_GLOBAL from internal concurrent VG lock counter.
|
||||
Fix vgsplit internal counting of snapshot LVs.
|
||||
Fix vgmerge snapshot_count when source VG contains snapshots.
|
||||
Simplify clvmd-openais by using non-async saLckResourceLock.
|
||||
Fix internal LV counter when a snapshot is removed.
|
||||
Fix metadata corruption writing lvm1-formatted metadata with snapshots.
|
||||
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.
|
||||
|
||||
31
WHATS_NEW_DM
31
WHATS_NEW_DM
@@ -1,5 +1,32 @@
|
||||
Version 1.02.26 -
|
||||
=================================
|
||||
Version 1.02.29 -
|
||||
=====================================
|
||||
|
||||
Version 1.02.28 - 18th September 2008
|
||||
=====================================
|
||||
Only resume devices in dm_tree_preload_children if size changes.
|
||||
Extend deptree buffers so the largest possible device numbers fit.
|
||||
Generate versioned libdevmapper-event.so.
|
||||
Underline longer report help text headings.
|
||||
|
||||
Version 1.02.27 - 25th June 2008
|
||||
================================
|
||||
Align struct memblock in dbg_malloc for sparc.
|
||||
Add --unquoted and --rows to dmsetup.
|
||||
Avoid compiler warning about cast in dmsetup.c's OFFSET_OF macro.
|
||||
Fix inverted no_flush debug message.
|
||||
Remove --enable-jobs from configure. (Set at runtime instead.)
|
||||
Bring configure.in and list.h into line with the lvm2 versions.
|
||||
|
||||
Version 1.02.26 - 6th June 2008
|
||||
===============================
|
||||
Initialise params buffer to empty string in _emit_segment.
|
||||
Skip add_dev_node when ioctls disabled.
|
||||
Make dm_hash_iter safe against deletion.
|
||||
Accept a NULL pointer to dm_free silently.
|
||||
Add tables_loaded, readonly and suspended columns to reports.
|
||||
Add --nameprefixes to dmsetup.
|
||||
Add field name prefix option to reporting functions.
|
||||
Calculate string size within dm_pool_grow_object.
|
||||
|
||||
Version 1.02.25 - 10th April 2008
|
||||
=================================
|
||||
|
||||
60
autoconf/config.guess
vendored
60
autoconf/config.guess
vendored
@@ -1,10 +1,10 @@
|
||||
#! /bin/sh
|
||||
# Attempt to guess a canonical system name.
|
||||
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
|
||||
# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
|
||||
# Inc.
|
||||
# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
|
||||
# Free Software Foundation, Inc.
|
||||
|
||||
timestamp='2006-07-02'
|
||||
timestamp='2008-01-23'
|
||||
|
||||
# This file is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by
|
||||
@@ -56,8 +56,8 @@ version="\
|
||||
GNU config.guess ($timestamp)
|
||||
|
||||
Originally written by Per Bothner.
|
||||
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
|
||||
Free Software Foundation, Inc.
|
||||
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
|
||||
2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||
|
||||
This is free software; see the source for copying conditions. There is NO
|
||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
|
||||
@@ -161,6 +161,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
||||
arm*) machine=arm-unknown ;;
|
||||
sh3el) machine=shl-unknown ;;
|
||||
sh3eb) machine=sh-unknown ;;
|
||||
sh5el) machine=sh5le-unknown ;;
|
||||
*) machine=${UNAME_MACHINE_ARCH}-unknown ;;
|
||||
esac
|
||||
# The Operating System including object format, if it has switched
|
||||
@@ -329,7 +330,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
||||
sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
|
||||
echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
|
||||
exit ;;
|
||||
i86pc:SunOS:5.*:*)
|
||||
i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
|
||||
echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
|
||||
exit ;;
|
||||
sun4*:SunOS:6*:*)
|
||||
@@ -531,7 +532,7 @@ EOF
|
||||
echo rs6000-ibm-aix3.2
|
||||
fi
|
||||
exit ;;
|
||||
*:AIX:*:[45])
|
||||
*:AIX:*:[456])
|
||||
IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
|
||||
if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
|
||||
IBM_ARCH=rs6000
|
||||
@@ -780,7 +781,7 @@ EOF
|
||||
i*:CYGWIN*:*)
|
||||
echo ${UNAME_MACHINE}-pc-cygwin
|
||||
exit ;;
|
||||
i*:MINGW*:*)
|
||||
*:MINGW*:*)
|
||||
echo ${UNAME_MACHINE}-pc-mingw32
|
||||
exit ;;
|
||||
i*:windows32*:*)
|
||||
@@ -790,12 +791,18 @@ EOF
|
||||
i*:PW*:*)
|
||||
echo ${UNAME_MACHINE}-pc-pw32
|
||||
exit ;;
|
||||
x86:Interix*:[3456]*)
|
||||
echo i586-pc-interix${UNAME_RELEASE}
|
||||
exit ;;
|
||||
EM64T:Interix*:[3456]*)
|
||||
echo x86_64-unknown-interix${UNAME_RELEASE}
|
||||
exit ;;
|
||||
*:Interix*:[3456]*)
|
||||
case ${UNAME_MACHINE} in
|
||||
x86)
|
||||
echo i586-pc-interix${UNAME_RELEASE}
|
||||
exit ;;
|
||||
EM64T | authenticamd)
|
||||
echo x86_64-unknown-interix${UNAME_RELEASE}
|
||||
exit ;;
|
||||
IA64)
|
||||
echo ia64-unknown-interix${UNAME_RELEASE}
|
||||
exit ;;
|
||||
esac ;;
|
||||
[345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
|
||||
echo i${UNAME_MACHINE}-pc-mks
|
||||
exit ;;
|
||||
@@ -829,7 +836,14 @@ EOF
|
||||
echo ${UNAME_MACHINE}-pc-minix
|
||||
exit ;;
|
||||
arm*:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||
eval $set_cc_for_build
|
||||
if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
|
||||
| grep -q __ARM_EABI__
|
||||
then
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||
else
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnueabi
|
||||
fi
|
||||
exit ;;
|
||||
avr32*:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||
@@ -950,6 +964,9 @@ EOF
|
||||
x86_64:Linux:*:*)
|
||||
echo x86_64-unknown-linux-gnu
|
||||
exit ;;
|
||||
xtensa*:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||
exit ;;
|
||||
i*86:Linux:*:*)
|
||||
# The BFD linker knows what the default object file format is, so
|
||||
# first see if it will tell us. cd to the root directory to prevent
|
||||
@@ -1208,6 +1225,15 @@ EOF
|
||||
SX-6:SUPER-UX:*:*)
|
||||
echo sx6-nec-superux${UNAME_RELEASE}
|
||||
exit ;;
|
||||
SX-7:SUPER-UX:*:*)
|
||||
echo sx7-nec-superux${UNAME_RELEASE}
|
||||
exit ;;
|
||||
SX-8:SUPER-UX:*:*)
|
||||
echo sx8-nec-superux${UNAME_RELEASE}
|
||||
exit ;;
|
||||
SX-8R:SUPER-UX:*:*)
|
||||
echo sx8r-nec-superux${UNAME_RELEASE}
|
||||
exit ;;
|
||||
Power*:Rhapsody:*:*)
|
||||
echo powerpc-apple-rhapsody${UNAME_RELEASE}
|
||||
exit ;;
|
||||
@@ -1458,9 +1484,9 @@ This script, last modified $timestamp, has failed to recognize
|
||||
the operating system you are using. It is advised that you
|
||||
download the most up to date version of the config scripts from
|
||||
|
||||
http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.guess
|
||||
http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
|
||||
and
|
||||
http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.sub
|
||||
http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
|
||||
|
||||
If the version you run ($0) is already up to date, please
|
||||
send the following data and any information you think might be
|
||||
|
||||
66
autoconf/config.sub
vendored
66
autoconf/config.sub
vendored
@@ -1,10 +1,10 @@
|
||||
#! /bin/sh
|
||||
# Configuration validation subroutine script.
|
||||
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
|
||||
# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
|
||||
# Inc.
|
||||
# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
|
||||
# Free Software Foundation, Inc.
|
||||
|
||||
timestamp='2006-09-20'
|
||||
timestamp='2008-01-16'
|
||||
|
||||
# This file is (in principle) common to ALL GNU software.
|
||||
# The presence of a machine in this file suggests that SOME GNU software
|
||||
@@ -72,8 +72,8 @@ 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, 2002, 2003, 2004, 2005
|
||||
Free Software Foundation, Inc.
|
||||
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
|
||||
2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||
|
||||
This is free software; see the source for copying conditions. There is NO
|
||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
|
||||
@@ -245,12 +245,12 @@ case $basic_machine in
|
||||
| bfin \
|
||||
| c4x | clipper \
|
||||
| d10v | d30v | dlx | dsp16xx \
|
||||
| fr30 | frv \
|
||||
| fido | fr30 | frv \
|
||||
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
|
||||
| i370 | i860 | i960 | ia64 \
|
||||
| ip2k | iq2000 \
|
||||
| m32c | m32r | m32rle | m68000 | m68k | m88k \
|
||||
| maxq | mb | microblaze | mcore \
|
||||
| maxq | mb | microblaze | mcore | mep \
|
||||
| mips | mipsbe | mipseb | mipsel | mipsle \
|
||||
| mips16 \
|
||||
| mips64 | mips64el \
|
||||
@@ -324,7 +324,7 @@ case $basic_machine in
|
||||
| clipper-* | craynv-* | cydra-* \
|
||||
| d10v-* | d30v-* | dlx-* \
|
||||
| elxsi-* \
|
||||
| f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \
|
||||
| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
|
||||
| h8300-* | h8500-* \
|
||||
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
|
||||
| i*86-* | i860-* | i960-* | ia64-* \
|
||||
@@ -369,10 +369,14 @@ case $basic_machine in
|
||||
| v850-* | v850e-* | vax-* \
|
||||
| we32k-* \
|
||||
| x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \
|
||||
| xstormy16-* | xtensa-* \
|
||||
| xstormy16-* | xtensa*-* \
|
||||
| ymp-* \
|
||||
| z8k-*)
|
||||
;;
|
||||
# Recognize the basic CPU types without company name, with glob match.
|
||||
xtensa*)
|
||||
basic_machine=$basic_machine-unknown
|
||||
;;
|
||||
# Recognize the various machine names and aliases which stand
|
||||
# for a CPU type and a company and sometimes even an OS.
|
||||
386bsd)
|
||||
@@ -443,6 +447,14 @@ case $basic_machine in
|
||||
basic_machine=ns32k-sequent
|
||||
os=-dynix
|
||||
;;
|
||||
blackfin)
|
||||
basic_machine=bfin-unknown
|
||||
os=-linux
|
||||
;;
|
||||
blackfin-*)
|
||||
basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
os=-linux
|
||||
;;
|
||||
c90)
|
||||
basic_machine=c90-cray
|
||||
os=-unicos
|
||||
@@ -475,8 +487,8 @@ case $basic_machine in
|
||||
basic_machine=craynv-cray
|
||||
os=-unicosmp
|
||||
;;
|
||||
cr16c)
|
||||
basic_machine=cr16c-unknown
|
||||
cr16)
|
||||
basic_machine=cr16-unknown
|
||||
os=-elf
|
||||
;;
|
||||
crds | unos)
|
||||
@@ -668,6 +680,14 @@ case $basic_machine in
|
||||
basic_machine=m68k-isi
|
||||
os=-sysv
|
||||
;;
|
||||
m68knommu)
|
||||
basic_machine=m68k-unknown
|
||||
os=-linux
|
||||
;;
|
||||
m68knommu-*)
|
||||
basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
os=-linux
|
||||
;;
|
||||
m88k-omron*)
|
||||
basic_machine=m88k-omron
|
||||
;;
|
||||
@@ -683,6 +703,10 @@ case $basic_machine in
|
||||
basic_machine=i386-pc
|
||||
os=-mingw32
|
||||
;;
|
||||
mingw32ce)
|
||||
basic_machine=arm-unknown
|
||||
os=-mingw32ce
|
||||
;;
|
||||
miniframe)
|
||||
basic_machine=m68000-convergent
|
||||
;;
|
||||
@@ -809,6 +833,14 @@ case $basic_machine in
|
||||
basic_machine=i860-intel
|
||||
os=-osf
|
||||
;;
|
||||
parisc)
|
||||
basic_machine=hppa-unknown
|
||||
os=-linux
|
||||
;;
|
||||
parisc-*)
|
||||
basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
os=-linux
|
||||
;;
|
||||
pbd)
|
||||
basic_machine=sparc-tti
|
||||
;;
|
||||
@@ -925,6 +957,9 @@ case $basic_machine in
|
||||
basic_machine=sh-hitachi
|
||||
os=-hms
|
||||
;;
|
||||
sh5el)
|
||||
basic_machine=sh5le-unknown
|
||||
;;
|
||||
sh64)
|
||||
basic_machine=sh64-unknown
|
||||
;;
|
||||
@@ -1014,6 +1049,10 @@ case $basic_machine in
|
||||
basic_machine=tic6x-unknown
|
||||
os=-coff
|
||||
;;
|
||||
tile*)
|
||||
basic_machine=tile-unknown
|
||||
os=-linux-gnu
|
||||
;;
|
||||
tx39)
|
||||
basic_machine=mipstx39-unknown
|
||||
;;
|
||||
@@ -1219,7 +1258,7 @@ case $os in
|
||||
| -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
|
||||
| -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
|
||||
| -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
|
||||
| -skyos* | -haiku* | -rdos* | -toppers*)
|
||||
| -skyos* | -haiku* | -rdos* | -toppers* | -drops*)
|
||||
# Remember, each alternative MUST END IN *, to match a version number.
|
||||
;;
|
||||
-qnx*)
|
||||
@@ -1414,6 +1453,9 @@ case $basic_machine in
|
||||
m68*-cisco)
|
||||
os=-aout
|
||||
;;
|
||||
mep-*)
|
||||
os=-elf
|
||||
;;
|
||||
mips*-cisco)
|
||||
os=-elf
|
||||
;;
|
||||
|
||||
282
configure.in
282
configure.in
@@ -1,8 +1,6 @@
|
||||
##
|
||||
###############################################################################
|
||||
## Copyright (C) 2000-2004 Sistina Software, Inc. All rights reserved.
|
||||
## Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
|
||||
##
|
||||
## This file is part of LVM2.
|
||||
## Copyright (C) 2004-2008 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
|
||||
@@ -18,9 +16,7 @@ AC_PREREQ(2.57)
|
||||
dnl -- Process this file with autoconf to produce a configure script.
|
||||
AC_INIT
|
||||
AC_CONFIG_SRCDIR([lib/device/dev-cache.h])
|
||||
|
||||
################################################################################
|
||||
AC_CONFIG_HEADERS(lib/misc/configure.h)
|
||||
AC_CONFIG_HEADERS([lib/misc/configure.h])
|
||||
|
||||
################################################################################
|
||||
dnl -- Setup the directory where autoconf has auxilary files
|
||||
@@ -32,57 +28,63 @@ AC_CANONICAL_TARGET([])
|
||||
|
||||
case "$host_os" in
|
||||
linux*)
|
||||
CFLAGS="$CFLAGS"
|
||||
COPTIMISE_FLAG="-O2"
|
||||
CLDFLAGS="$CLDFLAGS -Wl,--version-script,.export.sym"
|
||||
CLDWHOLEARCHIVE="-Wl,-whole-archive"
|
||||
CLDNOWHOLEARCHIVE="-Wl,-no-whole-archive"
|
||||
LDDEPS="$LDDEPS .export.sym"
|
||||
LDFLAGS="$LDFLAGS -Wl,--export-dynamic"
|
||||
LIB_SUFFIX="so"
|
||||
LIB_SUFFIX=so
|
||||
DEVMAPPER=yes
|
||||
ODIRECT=yes
|
||||
DM_IOCTLS=yes
|
||||
SELINUX=yes
|
||||
REALTIME=yes
|
||||
CLUSTER=internal
|
||||
FSADM=no ;;
|
||||
FSADM=no
|
||||
;;
|
||||
darwin*)
|
||||
CFLAGS="$CFLAGS -no-cpp-precomp -fno-common"
|
||||
COPTIMISE_FLAG="-O2"
|
||||
CLDFLAGS="$CLDFLAGS"
|
||||
CLDWHOLEARCHIVE="-all_load"
|
||||
CLDNOWHOLEARCHIVE=
|
||||
LDDEPS="$LDDEPS"
|
||||
LDFLAGS="$LDFLAGS"
|
||||
LIB_SUFFIX="dylib"
|
||||
LIB_SUFFIX=dylib
|
||||
DEVMAPPER=yes
|
||||
ODIRECT=no
|
||||
DM_IOCTLS=no
|
||||
SELINUX=no
|
||||
REALTIME=no
|
||||
CLUSTER=none
|
||||
FSADM=no ;;
|
||||
FSADM=no
|
||||
;;
|
||||
esac
|
||||
|
||||
################################################################################
|
||||
dnl -- Checks for programs.
|
||||
AC_PROG_AWK
|
||||
AC_PROG_CC
|
||||
|
||||
dnl probably no longer needed in 2008, but...
|
||||
AC_PROG_GCC_TRADITIONAL
|
||||
AC_PROG_INSTALL
|
||||
AC_PROG_LN_S
|
||||
AC_PROG_MAKE_SET
|
||||
AC_PROG_MKDIR_P
|
||||
AC_PROG_RANLIB
|
||||
AC_PATH_PROG(CFLOW_CMD, cflow)
|
||||
AC_PATH_PROG(CSCOPE_CMD, cscope)
|
||||
|
||||
################################################################################
|
||||
dnl -- Checks for header files.
|
||||
dnl -- Check for header files.
|
||||
AC_HEADER_DIRENT
|
||||
AC_HEADER_STDC
|
||||
AC_HEADER_SYS_WAIT
|
||||
AC_HEADER_TIME
|
||||
|
||||
AC_CHECK_HEADERS(fcntl.h limits.h locale.h stddef.h syslog.h sys/file.h sys/ioctl.h sys/param.h sys/time.h,,AC_MSG_ERROR(bailing out))
|
||||
AC_CHECK_HEADERS(assert.h ctype.h libgen.h signal.h stdio.h sys/mman.h sys/resource.h sys/stat.h sys/types.h sys/utsname.h sys/wait.h time.h,,AC_MSG_ERROR(bailing out))
|
||||
AC_CHECK_HEADERS([locale.h stddef.h syslog.h sys/file.h sys/time.h assert.h \
|
||||
libgen.h signal.h sys/mman.h sys/resource.h sys/utsname.h sys/wait.h time.h], ,
|
||||
[AC_MSG_ERROR(bailing out)])
|
||||
|
||||
case "$host_os" in
|
||||
linux*)
|
||||
@@ -91,12 +93,19 @@ case "$host_os" in
|
||||
AC_CHECK_HEADERS(machine/endian.h sys/disk.h,,AC_MSG_ERROR(bailing out)) ;;
|
||||
esac
|
||||
|
||||
AC_CHECK_HEADERS([ctype.h dirent.h errno.h fcntl.h getopt.h inttypes.h limits.h \
|
||||
stdarg.h stdio.h stdlib.h string.h sys/ioctl.h sys/param.h sys/stat.h \
|
||||
sys/types.h unistd.h], , [AC_MSG_ERROR(bailing out)])
|
||||
AC_CHECK_HEADERS(termios.h sys/statvfs.h)
|
||||
|
||||
################################################################################
|
||||
dnl -- Checks for typedefs, structures, and compiler characteristics.
|
||||
dnl -- Check for typedefs, structures, and compiler characteristics.
|
||||
AC_C_CONST
|
||||
AC_C_INLINE
|
||||
AC_CHECK_MEMBERS([struct stat.st_rdev])
|
||||
AC_TYPE_OFF_T
|
||||
AC_TYPE_PID_T
|
||||
AC_TYPE_SIGNAL
|
||||
AC_TYPE_SIZE_T
|
||||
AC_TYPE_MODE_T
|
||||
AC_CHECK_MEMBERS([struct stat.st_rdev])
|
||||
@@ -104,7 +113,9 @@ AC_STRUCT_TM
|
||||
|
||||
################################################################################
|
||||
dnl -- Check for functions
|
||||
AC_CHECK_FUNCS(gethostname getpagesize memset munmap setlocale strcasecmp strchr strdup strncasecmp strerror strrchr strstr strtol strtoul,,AC_MSG_ERROR(bailing out))
|
||||
AC_CHECK_FUNCS([gethostname getpagesize memset mkdir rmdir munmap setlocale \
|
||||
strcasecmp strchr strdup strncasecmp strerror strrchr strstr strtol strtoul \
|
||||
uname], , [AC_MSG_ERROR(bailing out)])
|
||||
AC_FUNC_ALLOCA
|
||||
AC_FUNC_CLOSEDIR_VOID
|
||||
AC_FUNC_FORK
|
||||
@@ -114,22 +125,19 @@ AC_FUNC_MEMCMP
|
||||
AC_FUNC_MMAP
|
||||
AC_FUNC_STAT
|
||||
AC_FUNC_STRTOD
|
||||
AC_FUNC_VPRINTF
|
||||
|
||||
################################################################################
|
||||
dnl -- Prefix is /usr by default, the exec_prefix default is setup later
|
||||
AC_PREFIX_DEFAULT(/usr)
|
||||
|
||||
################################################################################
|
||||
dnl -- Parallel make jobs?
|
||||
AC_ARG_ENABLE(jobs, [ --enable-jobs=NUM Number of jobs to run simultaneously], JOBS=-j$enableval, JOBS=-j2)
|
||||
|
||||
################################################################################
|
||||
dnl -- Setup the ownership of the files
|
||||
AC_MSG_CHECKING(file owner)
|
||||
OWNER="root"
|
||||
|
||||
AC_ARG_WITH(user,
|
||||
[ --with-user=USER Set the owner of installed files ],
|
||||
[ --with-user=USER Set the owner of installed files [[USER=root]] ],
|
||||
[ OWNER="$withval" ])
|
||||
AC_MSG_RESULT($OWNER)
|
||||
|
||||
@@ -142,7 +150,7 @@ dnl -- Setup the group ownership of the files
|
||||
AC_MSG_CHECKING(group owner)
|
||||
GROUP="root"
|
||||
AC_ARG_WITH(group,
|
||||
[ --with-group=GROUP Set the group owner of installed files ],
|
||||
[ --with-group=GROUP Set the group owner of installed files [[GROUP=root]] ],
|
||||
[ GROUP="$withval" ])
|
||||
AC_MSG_RESULT($GROUP)
|
||||
|
||||
@@ -261,30 +269,13 @@ if test x$MIRRORS = xinternal; then
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
dnl -- Enables staticly-linked tools
|
||||
AC_MSG_CHECKING(whether to use static linking)
|
||||
AC_ARG_ENABLE(static_link, [ --enable-static_link Use this to link the tools to their libraries
|
||||
statically. Default is dynamic linking], STATIC_LINK=$enableval, STATIC_LINK=no)
|
||||
AC_MSG_RESULT($STATIC_LINK)
|
||||
|
||||
################################################################################
|
||||
dnl -- Enable readline
|
||||
dnl -- Disable readline
|
||||
AC_MSG_CHECKING(whether to enable readline)
|
||||
AC_ARG_ENABLE(readline, [ --enable-readline Enable readline support],
|
||||
READLINE=$enableval, READLINE=no)
|
||||
AC_ARG_ENABLE([readline],
|
||||
[ --disable-readline Disable readline support],
|
||||
[READLINE=$enableval], [READLINE=maybe])
|
||||
AC_MSG_RESULT($READLINE)
|
||||
|
||||
if test x$READLINE = xyes; then
|
||||
AC_DEFINE([READLINE_SUPPORT], 1, [Define to 1 to include the LVM readline shell.])
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
dnl -- Disable selinux
|
||||
AC_MSG_CHECKING(whether to enable selinux support)
|
||||
AC_ARG_ENABLE(selinux, [ --disable-selinux Disable selinux support],
|
||||
SELINUX=$enableval)
|
||||
AC_MSG_RESULT($SELINUX)
|
||||
|
||||
################################################################################
|
||||
dnl -- Disable realtime clock support
|
||||
AC_MSG_CHECKING(whether to enable realtime support)
|
||||
@@ -314,7 +305,7 @@ fi
|
||||
dnl -- Enable debugging
|
||||
AC_MSG_CHECKING(whether to enable debugging)
|
||||
AC_ARG_ENABLE(debug, [ --enable-debug Enable debugging],
|
||||
DEBUG=$enableval, DEBUG=no)
|
||||
DEBUG=$enableval, DEBUG=no)
|
||||
AC_MSG_RESULT($DEBUG)
|
||||
|
||||
dnl -- Normally turn off optimisation for debug builds
|
||||
@@ -328,10 +319,27 @@ fi
|
||||
dnl -- Override optimisation
|
||||
AC_MSG_CHECKING(for C optimisation flag)
|
||||
AC_ARG_WITH(optimisation,
|
||||
[ --with-optimisation=OPT C optimisation flag [OPT=-O2] ],
|
||||
[ --with-optimisation=OPT C optimisation flag [[OPT=-O2]] ],
|
||||
[ COPTIMISE_FLAG="$withval" ])
|
||||
AC_MSG_RESULT($COPTIMISE_FLAG)
|
||||
|
||||
################################################################################
|
||||
dnl -- Enable profiling
|
||||
AC_MSG_CHECKING(whether to gather gcov profiling data)
|
||||
AC_ARG_ENABLE(profiling,
|
||||
AC_HELP_STRING(--enable-profiling, [Gather gcov profiling data]),
|
||||
PROFILING=$enableval, PROFILING=no)
|
||||
AC_MSG_RESULT($PROFILING)
|
||||
|
||||
if test "x$PROFILING" = xyes; then
|
||||
COPTIMISE_FLAG="$COPTIMISE_FLAG -fprofile-arcs -ftest-coverage"
|
||||
AC_PATH_PROG(LCOV, lcov, no)
|
||||
AC_PATH_PROG(GENHTML, genhtml, no)
|
||||
if test "$LCOV" = no -o "$GENHTML" = no ; then
|
||||
AC_MSG_ERROR([lcov and genhtml are required for profiling])
|
||||
fi
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
dnl -- Disable devmapper
|
||||
AC_MSG_CHECKING(whether to use device-mapper)
|
||||
@@ -360,6 +368,11 @@ AC_MSG_CHECKING(whether to compile liblvm2cmd.so)
|
||||
AC_ARG_ENABLE(cmdlib, [ --enable-cmdlib Build shared command library],
|
||||
CMDLIB=$enableval, CMDLIB=no)
|
||||
AC_MSG_RESULT($CMDLIB)
|
||||
AC_SUBST([LVM2CMD_LIB])
|
||||
test x$CMDLIB = xyes \
|
||||
&& LVM2CMD_LIB=-llvm2cmd \
|
||||
|| LVM2CMD_LIB=
|
||||
|
||||
|
||||
################################################################################
|
||||
dnl -- Enable fsadm
|
||||
@@ -376,33 +389,35 @@ DMEVENTD=$enableval)
|
||||
AC_MSG_RESULT($DMEVENTD)
|
||||
|
||||
dnl -- dmeventd currently requires internal mirror support
|
||||
if test x$DMEVENTD = xyes && test x$MIRRORS != xinternal; then
|
||||
AC_MSG_ERROR(
|
||||
--enable-dmeventd currently requires --with-mirrors=internal
|
||||
)
|
||||
if test x$DMEVENTD = xyes; then
|
||||
if test x$MIRRORS != xinternal; then
|
||||
AC_MSG_ERROR(
|
||||
--enable-dmeventd currently requires --with-mirrors=internal
|
||||
)
|
||||
fi
|
||||
if test x$CMDLIB = xno; then
|
||||
AC_MSG_ERROR(
|
||||
--enable-dmeventd requires --enable-cmdlib to be used as well
|
||||
)
|
||||
fi
|
||||
fi
|
||||
|
||||
if test x$DMEVENTD = xyes; then
|
||||
AC_DEFINE([DMEVENTD], 1, [Define to 1 to enable the device-mapper event daemon.])
|
||||
fi
|
||||
################################################################################
|
||||
dnl -- Mess with default exec_prefix
|
||||
dnl -- Clear default exec_prefix - install into /sbin rather than /usr/sbin
|
||||
if [[ "x$exec_prefix" = xNONE -a "x$prefix" = xNONE ]];
|
||||
then exec_prefix="";
|
||||
fi;
|
||||
|
||||
################################################################################
|
||||
dnl -- Checks for library functions.
|
||||
AC_PROG_GCC_TRADITIONAL
|
||||
AC_TYPE_SIGNAL
|
||||
AC_FUNC_VPRINTF
|
||||
AC_CHECK_FUNCS(mkdir rmdir uname,,AC_MSG_ERROR(bailing out))
|
||||
|
||||
################################################################################
|
||||
dnl -- Check for termcap (Shamelessly copied from parted 1.4.17)
|
||||
if test x$READLINE = xyes; then
|
||||
AC_SEARCH_LIBS(tgetent, ncurses curses termcap termlib, ,
|
||||
AC_MSG_ERROR(
|
||||
if test x$READLINE != xno; then
|
||||
AC_SEARCH_LIBS([tgetent], [ncurses curses termcap termlib],
|
||||
[tg_found=yes], [tg_found=no])
|
||||
test x$READLINE:$tg_found = xyes:no &&
|
||||
AC_MSG_ERROR(
|
||||
termcap could not be found which is required for the
|
||||
--enable-readline option (which is enabled by default). Either disable readline
|
||||
support with --disable-readline or download and install termcap from:
|
||||
@@ -412,7 +427,6 @@ Note: if you are using precompiled packages you will also need the development
|
||||
Note: (n)curses also seems to work as a substitute for termcap. This was
|
||||
not found either - but you could try installing that as well.
|
||||
)
|
||||
)
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
@@ -436,12 +450,30 @@ Features cannot be 'shared' when building statically
|
||||
)
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
dnl -- Enables statically-linked tools
|
||||
AC_MSG_CHECKING(whether to use static linking)
|
||||
AC_ARG_ENABLE(static_link,
|
||||
[ --enable-static_link Use this to link the tools to their libraries
|
||||
statically. Default is dynamic linking],
|
||||
STATIC_LINK=$enableval, STATIC_LINK=no)
|
||||
AC_MSG_RESULT($STATIC_LINK)
|
||||
|
||||
################################################################################
|
||||
dnl -- Disable selinux
|
||||
AC_MSG_CHECKING(whether to enable selinux support)
|
||||
AC_ARG_ENABLE(selinux, [ --disable-selinux Disable selinux support],
|
||||
SELINUX=$enableval)
|
||||
AC_MSG_RESULT($SELINUX)
|
||||
|
||||
################################################################################
|
||||
dnl -- Check for selinux
|
||||
if test x$SELINUX = xyes; then
|
||||
AC_CHECK_LIB(sepol, sepol_check_context, HAVE_SEPOL=yes, HAVE_SEPOL=no)
|
||||
|
||||
if test x$HAVE_SEPOL = xyes; then
|
||||
AC_DEFINE([HAVE_SEPOL], 1,
|
||||
[Define to 1 if sepol_check_context is available.])
|
||||
LIBS="-lsepol $LIBS"
|
||||
fi
|
||||
|
||||
@@ -454,7 +486,7 @@ if test x$SELINUX = xyes; then
|
||||
AC_MSG_WARN(Disabling selinux)
|
||||
fi
|
||||
|
||||
# With --enable-static_link and selinux enabled, linking lvm.static
|
||||
# With --enable-static_link and selinux enabled, linking
|
||||
# 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
|
||||
@@ -482,13 +514,15 @@ fi
|
||||
|
||||
################################################################################
|
||||
dnl -- Check for getopt
|
||||
AC_CHECK_HEADERS(getopt.h, AC_DEFINE([HAVE_GETOPTLONG], 1, [Define to 1 to if getopt_long is available.]))
|
||||
AC_CHECK_HEADERS(getopt.h, AC_DEFINE([HAVE_GETOPTLONG], 1, [Define to 1 if getopt_long is available.]))
|
||||
|
||||
################################################################################
|
||||
dnl -- Check for readline (Shamelessly copied from parted 1.4.17)
|
||||
if test x$READLINE = xyes; then
|
||||
AC_CHECK_LIB(readline, readline, ,
|
||||
AC_MSG_ERROR(
|
||||
if test x$READLINE != xno; then
|
||||
rl_found=yes
|
||||
AC_CHECK_LIB([readline], [readline], , [rl_found=no])
|
||||
test x$READLINE:$rl_found = xyes:no &&
|
||||
AC_MSG_ERROR(
|
||||
GNU Readline could not be found which is required for the
|
||||
--enable-readline option (which is enabled by default). Either disable readline
|
||||
support with --disable-readline or download and install readline from:
|
||||
@@ -496,8 +530,11 @@ support with --disable-readline or download and install readline from:
|
||||
Note: if you are using precompiled packages you will also need the development
|
||||
package as well (which may be called readline-devel or something similar).
|
||||
)
|
||||
)
|
||||
AC_CHECK_FUNC(rl_completion_matches, AC_DEFINE([HAVE_RL_COMPLETION_MATCHES], 1, [Define to 1 if rl_completion_matches() is available.]))
|
||||
if test $rl_found = yes; then
|
||||
AC_CHECK_FUNCS([rl_completion_matches])
|
||||
AC_DEFINE([READLINE_SUPPORT], 1,
|
||||
[Define to 1 to include the LVM readline shell.])
|
||||
fi
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
@@ -517,25 +554,25 @@ if test x$INTL = xyes; then
|
||||
fi;
|
||||
|
||||
AC_ARG_WITH(localedir,
|
||||
[ --with-localedir=DIR Translation files in DIR [PREFIX/share/locale]],
|
||||
[ LOCALEDIR="$withval" ],
|
||||
[ LOCALEDIR='${prefix}/share/locale' ])
|
||||
[ --with-localedir=DIR Translation files in DIR [[PREFIX/share/locale]] ],
|
||||
[ LOCALEDIR="$withval" ],
|
||||
[ LOCALEDIR='${prefix}/share/locale' ])
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
AC_ARG_WITH(confdir,
|
||||
[ --with-confdir=DIR Configuration files in DIR [/etc]],
|
||||
[ CONFDIR="$withval" ],
|
||||
[ CONFDIR='/etc' ])
|
||||
[ CONFDIR="$withval" ],
|
||||
[ CONFDIR='/etc' ])
|
||||
|
||||
AC_ARG_WITH(staticdir,
|
||||
[ --with-staticdir=DIR Static binary in DIR [EXEC_PREFIX/sbin]],
|
||||
[ STATICDIR="$withval" ],
|
||||
[ STATICDIR='${exec_prefix}/sbin' ])
|
||||
[ STATICDIR="$withval" ],
|
||||
[ STATICDIR='${exec_prefix}/sbin' ])
|
||||
|
||||
AC_ARG_WITH(dmdir,
|
||||
[ --with-dmdir=DIR Build against device-mapper source tree in DIR],
|
||||
[ DMDIR="$withval" CPPFLAGS="$CPPFLAGS -I$DMDIR/include"],
|
||||
[ DMDIR="$withval" CPPFLAGS="$CPPFLAGS -I$DMDIR/include"],
|
||||
[ DMDIR= ])
|
||||
|
||||
# Convert a relative dir name to absolute.
|
||||
@@ -585,51 +622,56 @@ if test x$MODPROBE_CMD != x; then
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
if test "-f VERSION"; then
|
||||
LVM_VERSION="\"`cat VERSION`\""
|
||||
else
|
||||
LVM_VERSION="Unknown"
|
||||
fi
|
||||
LVM_VERSION="\"`cat VERSION 2>/dev/null || echo Unknown`\""
|
||||
|
||||
################################################################################
|
||||
AC_SUBST(JOBS)
|
||||
AC_SUBST(STATIC_LINK)
|
||||
AC_SUBST(LVM1)
|
||||
AC_SUBST(POOL)
|
||||
AC_SUBST(SNAPSHOTS)
|
||||
AC_SUBST(MIRRORS)
|
||||
AC_SUBST(OWNER)
|
||||
AC_SUBST(GROUP)
|
||||
AC_SUBST(BUILD_DMEVENTD)
|
||||
AC_SUBST(CFLAGS)
|
||||
AC_SUBST(COPTIMISE_FLAG)
|
||||
AC_SUBST(CFLOW_CMD)
|
||||
AC_SUBST(CLDFLAGS)
|
||||
AC_SUBST(CLDWHOLEARCHIVE)
|
||||
AC_SUBST(CLDNOWHOLEARCHIVE)
|
||||
AC_SUBST(LDDEPS)
|
||||
AC_SUBST(LDFLAGS)
|
||||
AC_SUBST(LIB_SUFFIX)
|
||||
AC_SUBST(LIBS)
|
||||
AC_SUBST(LVM_VERSION)
|
||||
AC_SUBST(LVM1_FALLBACK)
|
||||
AC_SUBST(CLDWHOLEARCHIVE)
|
||||
AC_SUBST(CLUSTER)
|
||||
AC_SUBST(CLVMD)
|
||||
AC_SUBST(CMDLIB)
|
||||
AC_SUBST(COPTIMISE_FLAG)
|
||||
AC_SUBST(CSCOPE_CMD)
|
||||
AC_SUBST(DEBUG)
|
||||
AC_SUBST(DEVMAPPER)
|
||||
AC_SUBST(HAVE_LIBDL)
|
||||
AC_SUBST(HAVE_SELINUX)
|
||||
AC_SUBST(HAVE_REALTIME)
|
||||
AC_SUBST(CMDLIB)
|
||||
AC_SUBST(MSGFMT)
|
||||
AC_SUBST(LOCALEDIR)
|
||||
AC_SUBST(CONFDIR)
|
||||
AC_SUBST(STATICDIR)
|
||||
AC_SUBST(DMDIR)
|
||||
AC_SUBST(INTL_PACKAGE)
|
||||
AC_SUBST(INTL)
|
||||
AC_SUBST(CLVMD)
|
||||
AC_SUBST(CLUSTER)
|
||||
AC_SUBST(FSADM)
|
||||
# FIXME: rename to LVM_USE_DMEVENTD
|
||||
AC_SUBST(DMEVENTD)
|
||||
AC_SUBST(CFLOW_CMD)
|
||||
AC_SUBST(CSCOPE_CMD)
|
||||
AC_SUBST(DM_COMPAT)
|
||||
AC_SUBST(DM_DEVICE_GID)
|
||||
AC_SUBST(DM_DEVICE_MODE)
|
||||
AC_SUBST(DM_DEVICE_UID)
|
||||
AC_SUBST(DM_IOCTLS)
|
||||
AC_SUBST(DM_LIB_VERSION)
|
||||
AC_SUBST(FSADM)
|
||||
AC_SUBST(GROUP)
|
||||
AC_SUBST(HAVE_LIBDL)
|
||||
AC_SUBST(HAVE_REALTIME)
|
||||
AC_SUBST(HAVE_SELINUX)
|
||||
AC_SUBST(INTL)
|
||||
AC_SUBST(INTL_PACKAGE)
|
||||
AC_SUBST(JOBS)
|
||||
AC_SUBST(LDDEPS)
|
||||
AC_SUBST(LIBS)
|
||||
AC_SUBST(LIB_SUFFIX)
|
||||
AC_SUBST(LOCALEDIR)
|
||||
AC_SUBST(LVM1)
|
||||
AC_SUBST(LVM1_FALLBACK)
|
||||
# FIXME: rename to LVM_CONF_DIR
|
||||
AC_SUBST(CONFDIR)
|
||||
AC_SUBST(LVM_VERSION)
|
||||
AC_SUBST(MIRRORS)
|
||||
AC_SUBST(MSGFMT)
|
||||
AC_SUBST(OWNER)
|
||||
AC_SUBST(PKGCONFIG)
|
||||
AC_SUBST(POOL)
|
||||
AC_SUBST(SNAPSHOTS)
|
||||
AC_SUBST(STATICDIR)
|
||||
AC_SUBST(STATIC_LINK)
|
||||
AC_SUBST([LIB_PTHREAD])
|
||||
|
||||
################################################################################
|
||||
@@ -638,22 +680,22 @@ dnl -- keep utility scripts running properly
|
||||
AC_CONFIG_FILES([
|
||||
Makefile
|
||||
make.tmpl
|
||||
include/Makefile
|
||||
lib/Makefile
|
||||
man/Makefile
|
||||
po/Makefile
|
||||
dmeventd/Makefile
|
||||
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
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include <fcntl.h>
|
||||
#include <getopt.h>
|
||||
#include <errno.h>
|
||||
#include <libdevmapper.h>
|
||||
#include <libdlm.h>
|
||||
|
||||
#include "clvmd-comms.h"
|
||||
@@ -46,13 +47,17 @@
|
||||
|
||||
#define LOCKSPACE_NAME "clvmd"
|
||||
|
||||
struct clvmd_node
|
||||
{
|
||||
struct cman_node *node;
|
||||
int clvmd_up;
|
||||
};
|
||||
|
||||
static int num_nodes;
|
||||
static struct cman_node *nodes = NULL;
|
||||
static struct cman_node this_node;
|
||||
static int count_nodes; /* size of allocated nodes array */
|
||||
static int max_updown_nodes = 50; /* Current size of the allocated array */
|
||||
/* Node up/down status, indexed by nodeid */
|
||||
static int *node_updown = NULL;
|
||||
static struct dm_hash_table *node_updown_hash;
|
||||
static dlm_lshandle_t *lockspace;
|
||||
static cman_handle_t c_handle;
|
||||
|
||||
@@ -72,6 +77,8 @@ struct lock_wait {
|
||||
|
||||
static int _init_cluster(void)
|
||||
{
|
||||
node_updown_hash = dm_hash_create(100);
|
||||
|
||||
/* Open the cluster communication socket */
|
||||
c_handle = cman_init(NULL);
|
||||
if (!c_handle) {
|
||||
@@ -165,8 +172,10 @@ static int _cluster_do_node_callback(struct local_client *client,
|
||||
|
||||
for (i = 0; i < _get_num_nodes(); i++) {
|
||||
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])
|
||||
int up = (int)(long)dm_hash_lookup_binary(node_updown_hash, (char *)&nodes[i].cn_nodeid, sizeof(int));
|
||||
|
||||
callback(client, (char *)&nodes[i].cn_nodeid, up);
|
||||
if (!up)
|
||||
somedown = -1;
|
||||
}
|
||||
}
|
||||
@@ -184,7 +193,7 @@ static void event_callback(cman_handle_t handle, void *private, int reason, int
|
||||
log_notice("clvmd on node %s has died\n", namebuf);
|
||||
DEBUGLOG("Got port closed message, removing node %s\n", namebuf);
|
||||
|
||||
node_updown[arg] = 0;
|
||||
dm_hash_insert_binary(node_updown_hash, (char *)&arg, sizeof(int), (void *)0);
|
||||
break;
|
||||
|
||||
case CMAN_REASON_STATECHANGE:
|
||||
@@ -239,22 +248,7 @@ 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, sizeof(int) * new_size);
|
||||
|
||||
if (new_updown) {
|
||||
node_updown = new_updown;
|
||||
max_updown_nodes = new_size;
|
||||
DEBUGLOG("realloced more space for nodes. now %d\n",
|
||||
max_updown_nodes);
|
||||
} else {
|
||||
log_error
|
||||
("Realloc failed. Node status for clvmd will be wrong. quitting\n");
|
||||
exit(999);
|
||||
}
|
||||
}
|
||||
node_updown[nodeid] = 1;
|
||||
dm_hash_insert_binary(node_updown_hash, (char *)&nodeid, sizeof(int), (void *)1);
|
||||
DEBUGLOG("Added new node %d to updown list\n", nodeid);
|
||||
}
|
||||
|
||||
@@ -288,7 +282,12 @@ static void count_clvmds_running(void)
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_nodes; i++) {
|
||||
node_updown[nodes[i].cn_nodeid] = is_listening(nodes[i].cn_nodeid);
|
||||
int nodeid = nodes[i].cn_nodeid;
|
||||
|
||||
if (is_listening(nodeid) == 1)
|
||||
dm_hash_insert_binary(node_updown_hash, (void *)&nodeid, sizeof(int), (void*)1);
|
||||
else
|
||||
dm_hash_insert_binary(node_updown_hash, (void *)&nodeid, sizeof(int), (void*)0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -332,16 +331,6 @@ static void get_members()
|
||||
if (nodes[i].cn_nodeid > high_nodeid)
|
||||
high_nodeid = nodes[i].cn_nodeid;
|
||||
}
|
||||
|
||||
if (node_updown == NULL) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -118,9 +118,11 @@ int do_command(struct local_client *client, struct clvm_header *msg, int msglen,
|
||||
lockname = &args[2];
|
||||
/* Check to see if the VG is in use by LVM1 */
|
||||
status = do_check_lvm1(lockname);
|
||||
/* P_global causes a cache refresh */
|
||||
if (strcmp(lockname, "P_global") == 0)
|
||||
do_refresh_cache();
|
||||
/* P_#global causes a full cache refresh */
|
||||
if (!strcmp(lockname, "P_" VG_GLOBAL))
|
||||
do_refresh_cache();
|
||||
else
|
||||
drop_metadata(lockname + 2);
|
||||
|
||||
break;
|
||||
|
||||
@@ -251,7 +253,11 @@ int do_pre_command(struct local_client *client)
|
||||
break;
|
||||
|
||||
case CLVMD_CMD_LOCK_VG:
|
||||
status = lock_vg(client);
|
||||
lockname = &args[2];
|
||||
/* We take out a real lock unless LCK_CACHE was set */
|
||||
if (!strncmp(lockname, "V_", 2) ||
|
||||
!strncmp(lockname, "P_#", 3))
|
||||
status = lock_vg(client);
|
||||
break;
|
||||
|
||||
case CLVMD_CMD_LOCK_LV:
|
||||
|
||||
@@ -665,6 +665,7 @@ static int _cluster_do_node_callback(struct local_client *master_client,
|
||||
{
|
||||
struct dm_hash_node *hn;
|
||||
struct node_info *ninfo;
|
||||
int somedown = 0;
|
||||
|
||||
dm_hash_iterate(hn, node_hash)
|
||||
{
|
||||
@@ -686,12 +687,14 @@ static int _cluster_do_node_callback(struct local_client *master_client,
|
||||
client = dm_hash_lookup_binary(sock_hash, csid, GULM_MAX_CSID_LEN);
|
||||
|
||||
}
|
||||
DEBUGLOG("down_callback2. node %s, state = %d\n", ninfo->name, ninfo->state);
|
||||
if (ninfo->state != NODE_DOWN)
|
||||
callback(master_client, csid, ninfo->state == NODE_CLVMD);
|
||||
|
||||
|
||||
if (ninfo->state != NODE_CLVMD)
|
||||
somedown = -1;
|
||||
}
|
||||
return 0;
|
||||
return somedown;
|
||||
}
|
||||
|
||||
/* Convert gulm error codes to unix errno numbers */
|
||||
|
||||
@@ -50,11 +50,6 @@
|
||||
/* 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,
|
||||
@@ -92,11 +87,6 @@ cpg_callbacks_t cpg_callbacks = {
|
||||
.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;
|
||||
@@ -110,13 +100,6 @@ struct lock_info
|
||||
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)
|
||||
{
|
||||
@@ -255,12 +238,13 @@ static void cpg_deliver_callback (cpg_handle_t handle,
|
||||
|
||||
memcpy(&target_nodeid, msg, OPENAIS_CSID_LEN);
|
||||
|
||||
DEBUGLOG("Got message from nodeid %d for %d. len %d\n",
|
||||
nodeid, target_nodeid, msg_len-4);
|
||||
DEBUGLOG("%u got message from nodeid %d for %d. len %d\n",
|
||||
our_nodeid, 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);
|
||||
if (nodeid != our_nodeid)
|
||||
if (target_nodeid == our_nodeid || target_nodeid == 0)
|
||||
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,
|
||||
@@ -302,34 +286,27 @@ static void cpg_confchg_callback(cpg_handle_t handle,
|
||||
ninfo->state = NODE_DOWN;
|
||||
}
|
||||
|
||||
num_nodes = joined_list_entries;
|
||||
}
|
||||
for (i=0; i<member_list_entries; i++) {
|
||||
if (member_list[i].nodeid == 0) continue;
|
||||
ninfo = dm_hash_lookup_binary(node_hash,
|
||||
(char *)&member_list[i].nodeid,
|
||||
OPENAIS_CSID_LEN);
|
||||
if (!ninfo) {
|
||||
ninfo = malloc(sizeof(struct node_info));
|
||||
if (!ninfo) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
ninfo->nodeid = member_list[i].nodeid;
|
||||
dm_hash_insert_binary(node_hash,
|
||||
(char *)&ninfo->nodeid,
|
||||
OPENAIS_CSID_LEN, ninfo);
|
||||
}
|
||||
}
|
||||
ninfo->state = NODE_CLVMD;
|
||||
}
|
||||
|
||||
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);
|
||||
num_nodes = member_list_entries;
|
||||
}
|
||||
|
||||
static int lck_dispatch(struct local_client *client, char *buf, int len,
|
||||
@@ -359,7 +336,7 @@ static int _init_cluster(void)
|
||||
}
|
||||
|
||||
err = saLckInitialize(&lck_handle,
|
||||
&lck_callbacks,
|
||||
NULL,
|
||||
&ver);
|
||||
if (err != SA_AIS_OK) {
|
||||
cpg_initialize(&cpg_handle, &cpg_callbacks);
|
||||
@@ -475,6 +452,7 @@ static int _cluster_do_node_callback(struct local_client *master_client,
|
||||
{
|
||||
struct dm_hash_node *hn;
|
||||
struct node_info *ninfo;
|
||||
int somedown = 0;
|
||||
|
||||
dm_hash_iterate(hn, node_hash)
|
||||
{
|
||||
@@ -488,22 +466,20 @@ static int _cluster_do_node_callback(struct local_client *master_client,
|
||||
|
||||
if (ninfo->state != NODE_DOWN)
|
||||
callback(master_client, csid, ninfo->state == NODE_CLVMD);
|
||||
if (ninfo->state != NODE_CLVMD)
|
||||
somedown = -1;
|
||||
}
|
||||
return 0;
|
||||
return somedown;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
SaLckLockStatusT lockStatus;
|
||||
|
||||
/* This needs to be converted from DLM/LVM2 value for OpenAIS LCK */
|
||||
if (flags & LCK_NONBLOCK) flags = SA_LCK_LOCK_NO_QUEUE;
|
||||
@@ -526,24 +502,24 @@ static int _lock_resource(char *resource, int mode, int flags, int *lockid)
|
||||
return ais_to_errno(err);
|
||||
}
|
||||
|
||||
err = saLckResourceLockAsync(res_handle,
|
||||
(SaInvocationT)(long)&lwait,
|
||||
&lock_id,
|
||||
mode,
|
||||
flags,
|
||||
0);
|
||||
if (err != SA_AIS_OK)
|
||||
err = saLckResourceLock(
|
||||
res_handle,
|
||||
&lock_id,
|
||||
mode,
|
||||
flags,
|
||||
0,
|
||||
SA_TIME_END,
|
||||
&lockStatus);
|
||||
if (err != SA_AIS_OK && lockStatus != SA_LCK_LOCK_GRANTED)
|
||||
{
|
||||
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,
|
||||
DEBUGLOG("lock_resource returning %d, lock_id=%llx\n", err,
|
||||
lock_id);
|
||||
|
||||
linfo->lock_id = lock_id;
|
||||
@@ -551,43 +527,34 @@ static int _lock_resource(char *resource, int mode, int flags, int *lockid)
|
||||
|
||||
dm_hash_insert(lock_hash, resource, linfo);
|
||||
|
||||
return ais_to_errno(lwait.status);
|
||||
return ais_to_errno(err);
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
err = saLckResourceUnlock(linfo->lock_id, SA_TIME_END);
|
||||
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);
|
||||
return ais_to_errno(err);
|
||||
}
|
||||
|
||||
static int _sync_lock(const char *resource, int mode, int flags, int *lockid)
|
||||
|
||||
@@ -182,8 +182,10 @@ void debuglog(const char *fmt, ...)
|
||||
va_end(ap);
|
||||
}
|
||||
if (debug == DEBUG_SYSLOG) {
|
||||
if (!syslog_init)
|
||||
if (!syslog_init) {
|
||||
openlog("clvmd", LOG_PID, LOG_DAEMON);
|
||||
syslog_init = 1;
|
||||
}
|
||||
|
||||
va_start(ap,fmt);
|
||||
vsyslog(LOG_DEBUG, fmt, ap);
|
||||
@@ -191,6 +193,58 @@ void debuglog(const char *fmt, ...)
|
||||
}
|
||||
}
|
||||
|
||||
static const char *decode_cmd(unsigned char cmdl)
|
||||
{
|
||||
static char buf[128];
|
||||
const char *command;
|
||||
|
||||
switch (cmdl) {
|
||||
case CLVMD_CMD_TEST:
|
||||
command = "TEST";
|
||||
break;
|
||||
case CLVMD_CMD_LOCK_VG:
|
||||
command = "LOCK_VG";
|
||||
break;
|
||||
case CLVMD_CMD_LOCK_LV:
|
||||
command = "LOCK_LV";
|
||||
break;
|
||||
case CLVMD_CMD_REFRESH:
|
||||
command = "REFRESH";
|
||||
break;
|
||||
case CLVMD_CMD_SET_DEBUG:
|
||||
command = "SET_DEBUG";
|
||||
break;
|
||||
case CLVMD_CMD_GET_CLUSTERNAME:
|
||||
command = "GET_CLUSTERNAME";
|
||||
break;
|
||||
case CLVMD_CMD_VG_BACKUP:
|
||||
command = "VG_BACKUP";
|
||||
break;
|
||||
case CLVMD_CMD_REPLY:
|
||||
command = "REPLY";
|
||||
break;
|
||||
case CLVMD_CMD_VERSION:
|
||||
command = "VERSION";
|
||||
break;
|
||||
case CLVMD_CMD_GOAWAY:
|
||||
command = "GOAWAY";
|
||||
break;
|
||||
case CLVMD_CMD_LOCK:
|
||||
command = "LOCK";
|
||||
break;
|
||||
case CLVMD_CMD_UNLOCK:
|
||||
command = "UNLOCK";
|
||||
break;
|
||||
default:
|
||||
command = "unknown";
|
||||
break;
|
||||
}
|
||||
|
||||
sprintf(buf, "%s (0x%x)", command, cmdl);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int local_sock;
|
||||
@@ -530,7 +584,7 @@ static void timedout_callback(struct local_client *client, const char *csid,
|
||||
char nodename[max_cluster_member_name_len];
|
||||
|
||||
clops->name_from_csid(csid, nodename);
|
||||
DEBUGLOG("PJC: checking for a reply from %s\n", nodename);
|
||||
DEBUGLOG("Checking for a reply from %s\n", nodename);
|
||||
pthread_mutex_lock(&client->bits.localsock.reply_mutex);
|
||||
|
||||
reply = client->bits.localsock.replies;
|
||||
@@ -541,7 +595,7 @@ static void timedout_callback(struct local_client *client, const char *csid,
|
||||
pthread_mutex_unlock(&client->bits.localsock.reply_mutex);
|
||||
|
||||
if (!reply) {
|
||||
DEBUGLOG("PJC: node %s timed-out\n", nodename);
|
||||
DEBUGLOG("Node %s timed-out\n", nodename);
|
||||
add_reply_to_list(client, ETIMEDOUT, csid,
|
||||
"Command timed out", 18);
|
||||
}
|
||||
@@ -985,6 +1039,14 @@ static int read_from_local_sock(struct local_client *thisfd)
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialise and lock the mutex so the subthread will wait after
|
||||
finishing the PRE routine */
|
||||
if (!thisfd->bits.localsock.threadid) {
|
||||
pthread_mutex_init(&thisfd->bits.localsock.mutex, NULL);
|
||||
pthread_cond_init(&thisfd->bits.localsock.cond, NULL);
|
||||
pthread_mutex_init(&thisfd->bits.localsock.reply_mutex, NULL);
|
||||
}
|
||||
|
||||
/* Only run the command if all the cluster nodes are running CLVMD */
|
||||
if (((inheader->flags & CLVMD_FLAG_LOCAL) == 0) &&
|
||||
(check_all_clvmds_running(thisfd) == -1)) {
|
||||
@@ -1056,12 +1118,6 @@ static int read_from_local_sock(struct local_client *thisfd)
|
||||
|
||||
thisfd->bits.localsock.pipe = comms_pipe[1];
|
||||
|
||||
/* Initialise and lock the mutex so the subthread will wait after
|
||||
finishing the PRE routine */
|
||||
pthread_mutex_init(&thisfd->bits.localsock.mutex, NULL);
|
||||
pthread_cond_init(&thisfd->bits.localsock.cond, NULL);
|
||||
pthread_mutex_init(&thisfd->bits.localsock.reply_mutex, NULL);
|
||||
|
||||
/* Make sure the thread has a copy of it's own ID */
|
||||
newfd->bits.pipe.threadid = thisfd->bits.localsock.threadid;
|
||||
|
||||
@@ -1167,8 +1223,8 @@ static void process_remote_command(struct clvm_header *msg, int msglen, int fd,
|
||||
/* Get the node name as we /may/ need it later */
|
||||
clops->name_from_csid(csid, nodename);
|
||||
|
||||
DEBUGLOG("process_remote_command %d for clientid 0x%x XID %d on node %s\n",
|
||||
msg->cmd, msg->clientid, msg->xid, nodename);
|
||||
DEBUGLOG("process_remote_command %s for clientid 0x%x XID %d on node %s\n",
|
||||
decode_cmd(msg->cmd), msg->clientid, msg->xid, nodename);
|
||||
|
||||
/* Check for GOAWAY and sulk */
|
||||
if (msg->cmd == CLVMD_CMD_GOAWAY) {
|
||||
@@ -1439,8 +1495,9 @@ static int process_local_command(struct clvm_header *msg, int msglen,
|
||||
int replylen = 0;
|
||||
int status;
|
||||
|
||||
DEBUGLOG("process_local_command: msg=%p, msglen =%d, client=%p\n", msg,
|
||||
msglen, client);
|
||||
DEBUGLOG("process_local_command: %s msg=%p, msglen =%d, client=%p\n",
|
||||
decode_cmd(msg->cmd), msg, msglen, client);
|
||||
|
||||
if (replybuf == NULL)
|
||||
return -1;
|
||||
|
||||
|
||||
@@ -61,6 +61,94 @@ struct lv_info {
|
||||
int lock_mode;
|
||||
};
|
||||
|
||||
#define LCK_MASK (LCK_TYPE_MASK | LCK_SCOPE_MASK)
|
||||
|
||||
static const char *decode_locking_cmd(unsigned char cmdl)
|
||||
{
|
||||
static char buf[128];
|
||||
const char *type;
|
||||
const char *scope;
|
||||
const char *command;
|
||||
|
||||
switch (cmdl & LCK_TYPE_MASK) {
|
||||
case LCK_NULL:
|
||||
type = "NULL";
|
||||
break;
|
||||
case LCK_READ:
|
||||
type = "READ";
|
||||
break;
|
||||
case LCK_PREAD:
|
||||
type = "PREAD";
|
||||
break;
|
||||
case LCK_WRITE:
|
||||
type = "WRITE";
|
||||
break;
|
||||
case LCK_EXCL:
|
||||
type = "EXCL";
|
||||
break;
|
||||
case LCK_UNLOCK:
|
||||
type = "UNLOCK";
|
||||
break;
|
||||
default:
|
||||
type = "unknown";
|
||||
break;
|
||||
}
|
||||
|
||||
switch (cmdl & LCK_SCOPE_MASK) {
|
||||
case LCK_VG:
|
||||
scope = "VG";
|
||||
break;
|
||||
case LCK_LV:
|
||||
scope = "LV";
|
||||
break;
|
||||
default:
|
||||
scope = "unknown";
|
||||
break;
|
||||
}
|
||||
|
||||
switch (cmdl & LCK_MASK) {
|
||||
case LCK_LV_EXCLUSIVE & LCK_MASK:
|
||||
command = "LCK_LV_EXCLUSIVE";
|
||||
break;
|
||||
case LCK_LV_SUSPEND & LCK_MASK:
|
||||
command = "LCK_LV_SUSPEND";
|
||||
break;
|
||||
case LCK_LV_RESUME & LCK_MASK:
|
||||
command = "LCK_LV_RESUME";
|
||||
break;
|
||||
case LCK_LV_ACTIVATE & LCK_MASK:
|
||||
command = "LCK_LV_ACTIVATE";
|
||||
break;
|
||||
case LCK_LV_DEACTIVATE & LCK_MASK:
|
||||
command = "LCK_LV_DEACTIVATE";
|
||||
break;
|
||||
default:
|
||||
command = "unknown";
|
||||
break;
|
||||
}
|
||||
|
||||
sprintf(buf, "0x%x %s (%s|%s%s%s%s%s%s)", cmdl, command, type, scope,
|
||||
cmdl & LCK_NONBLOCK ? "|NONBLOCK" : "",
|
||||
cmdl & LCK_HOLD ? "|HOLD" : "",
|
||||
cmdl & LCK_LOCAL ? "|LOCAL" : "",
|
||||
cmdl & LCK_CLUSTER_VG ? "|CLUSTER_VG" : "",
|
||||
cmdl & LCK_CACHE ? "|CACHE" : "");
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
static const char *decode_flags(unsigned char flags)
|
||||
{
|
||||
static char buf[128];
|
||||
|
||||
sprintf(buf, "0x%x (%s%s%s)", flags,
|
||||
flags & LCK_PARTIAL_MODE ? "PARTIAL " : "",
|
||||
flags & LCK_MIRROR_NOSYNC_MODE ? "MIRROR_NOSYNC " : "",
|
||||
flags & LCK_DMEVENTD_MONITOR_MODE ? "DMEVENTD_MONITOR " : "");
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
char *get_last_lvm_error()
|
||||
{
|
||||
return last_error;
|
||||
@@ -312,8 +400,8 @@ int do_lock_lv(unsigned char command, unsigned char lock_flags, char *resource)
|
||||
{
|
||||
int status = 0;
|
||||
|
||||
DEBUGLOG("do_lock_lv: resource '%s', cmd = 0x%x, flags = %x\n",
|
||||
resource, command, lock_flags);
|
||||
DEBUGLOG("do_lock_lv: resource '%s', cmd = %s, flags = %s\n",
|
||||
resource, decode_locking_cmd(command), decode_flags(lock_flags));
|
||||
|
||||
pthread_mutex_lock(&lvm_lock);
|
||||
if (!cmd->config_valid || config_files_changed(cmd)) {
|
||||
@@ -391,8 +479,8 @@ int pre_lock_lv(unsigned char command, unsigned char lock_flags, char *resource)
|
||||
before suspending cluster-wide.
|
||||
*/
|
||||
if (command == LCK_LV_SUSPEND) {
|
||||
DEBUGLOG("pre_lock_lv: resource '%s', cmd = 0x%x, flags = %d\n",
|
||||
resource, command, lock_flags);
|
||||
DEBUGLOG("pre_lock_lv: resource '%s', cmd = %s, flags = %s\n",
|
||||
resource, decode_locking_cmd(command), decode_flags(lock_flags));
|
||||
|
||||
if (hold_lock(resource, LKM_PWMODE, LKF_NOQUEUE))
|
||||
return errno;
|
||||
@@ -411,8 +499,8 @@ int post_lock_lv(unsigned char command, unsigned char lock_flags,
|
||||
int oldmode;
|
||||
|
||||
DEBUGLOG
|
||||
("post_lock_lv: resource '%s', cmd = 0x%x, flags = %d\n",
|
||||
resource, command, lock_flags);
|
||||
("post_lock_lv: resource '%s', cmd = %s, flags = %s\n",
|
||||
resource, decode_locking_cmd(command), decode_flags(lock_flags));
|
||||
|
||||
/* If the lock state is PW then restore it to what it was */
|
||||
oldmode = get_current_lock(resource);
|
||||
@@ -472,7 +560,8 @@ static void drop_vg_locks()
|
||||
popen
|
||||
("lvm pvs --config 'log{command_names=0 prefix=\"\"}' --nolocking --noheadings -o vg_name", "r");
|
||||
|
||||
sync_unlock("P_orphans", LCK_EXCL);
|
||||
sync_unlock("P_" VG_ORPHANS, LCK_EXCL);
|
||||
sync_unlock("P_" VG_GLOBAL, LCK_EXCL);
|
||||
|
||||
if (!vgs)
|
||||
return;
|
||||
@@ -499,6 +588,17 @@ static void drop_vg_locks()
|
||||
DEBUGLOG("vgs fclose failed: %s\n", strerror(errno));
|
||||
}
|
||||
|
||||
/*
|
||||
* Drop lvmcache metadata
|
||||
*/
|
||||
void drop_metadata(const char *vgname)
|
||||
{
|
||||
DEBUGLOG("Dropping metadata for VG %s\n", vgname);
|
||||
pthread_mutex_lock(&lvm_lock);
|
||||
lvmcache_drop_metadata(vgname);
|
||||
pthread_mutex_unlock(&lvm_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Ideally, clvmd should be started before any LVs are active
|
||||
* but this may not be the case...
|
||||
|
||||
@@ -33,5 +33,6 @@ extern int hold_unlock(char *resource);
|
||||
extern int hold_lock(char *resource, int mode, int flags);
|
||||
extern void unlock_all(void);
|
||||
extern char *get_last_lvm_error(void);
|
||||
extern void drop_metadata(const char *vgname);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -23,6 +23,7 @@ ifeq ("@LIB_SUFFIX@","dylib")
|
||||
LIB_SHARED = libdevmapper-event.dylib
|
||||
else
|
||||
LIB_SHARED = libdevmapper-event.so
|
||||
VERSIONED_SHLIB = $(LIB_SHARED).$(LIB_VERSION)
|
||||
endif
|
||||
|
||||
TARGETS = dmeventd
|
||||
@@ -33,7 +34,7 @@ include ../make.tmpl
|
||||
LDFLAGS += -ldl -ldevmapper -lpthread
|
||||
CLDFLAGS += -ldl -ldevmapper -lpthread
|
||||
|
||||
dmeventd: $(LIB_SHARED) dmeventd.o
|
||||
dmeventd: $(LIB_SHARED) $(VERSIONED_SHLIB) dmeventd.o
|
||||
$(CC) -o $@ dmeventd.o $(CFLAGS) $(LDFLAGS) \
|
||||
-L. -ldevmapper-event $(LIBS) -rdynamic
|
||||
|
||||
@@ -74,6 +75,10 @@ install_static: libdevmapper-event.a
|
||||
$(libdir)/libdevmapper-event.a.$(LIB_VERSION)
|
||||
$(LN_S) -f libdevmapper-event.a.$(LIB_VERSION) $(libdir)/libdevmapper-event.a
|
||||
|
||||
$(VERSIONED_SHLIB): $(LIB_SHARED)
|
||||
$(RM) -f $@
|
||||
$(LN_S) $(LIB_SHARED) $@
|
||||
|
||||
.PHONY: distclean_lib distclean
|
||||
|
||||
distclean_lib:
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <arpa/inet.h> /* for htonl, ntohl */
|
||||
|
||||
#ifdef linux
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#
|
||||
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
# Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
|
||||
# Copyright (C) 2004-2005, 2008 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This file is part of LVM2.
|
||||
#
|
||||
@@ -17,7 +17,7 @@ top_srcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
INCLUDES += -I${top_srcdir}/tools
|
||||
CLDFLAGS += -L${top_srcdir}/tools -ldevmapper -llvm2cmd
|
||||
CLDFLAGS += -L${top_srcdir}/tools -ldevmapper @LVM2CMD_LIB@
|
||||
|
||||
SOURCES = dmeventd_mirror.c
|
||||
|
||||
@@ -33,4 +33,3 @@ install: libdevmapper-event-lvm2mirror.$(LIB_SUFFIX)
|
||||
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
|
||||
$(libdir)/$<.$(LIB_VERSION)
|
||||
$(LN_S) -f $<.$(LIB_VERSION) $(libdir)/$<
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ top_srcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
INCLUDES += -I${top_srcdir}/tools
|
||||
CLDFLAGS += -L${top_srcdir}/tools -ldevmapper -llvm2cmd
|
||||
CLDFLAGS += -L${top_srcdir}/tools -ldevmapper @LVM2CMD_LIB@
|
||||
|
||||
SOURCES = dmeventd_snapshot.c
|
||||
|
||||
@@ -33,4 +33,3 @@ install: libdevmapper-event-lvm2snapshot.$(LIB_SUFFIX)
|
||||
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
|
||||
$(libdir)/$<.$(LIB_VERSION)
|
||||
$(LN_S) -f $<.$(LIB_VERSION) $(libdir)/$<
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#
|
||||
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
# Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
|
||||
# Copyright (C) 2004-2005, 2008 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This file is part of LVM2.
|
||||
#
|
||||
@@ -17,7 +17,7 @@ top_srcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
INCLUDES += -I${top_srcdir}/tools
|
||||
CLDFLAGS += -L${top_srcdir}/tools -ldevmapper -llvm2cmd
|
||||
CLDFLAGS += -L${top_srcdir}/tools -ldevmapper @LVM2CMD_LIB@
|
||||
|
||||
SOURCES = dmeventd_mirror.c
|
||||
|
||||
@@ -33,4 +33,3 @@ install: libdevmapper-event-lvm2mirror.$(LIB_SUFFIX)
|
||||
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
|
||||
$(libdir)/$<.$(LIB_VERSION)
|
||||
$(LN_S) -f $<.$(LIB_VERSION) $(libdir)/$<
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ top_srcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
INCLUDES += -I${top_srcdir}/tools
|
||||
CLDFLAGS += -L${top_srcdir}/tools -ldevmapper -llvm2cmd
|
||||
CLDFLAGS += -L${top_srcdir}/tools -ldevmapper @LVM2CMD_LIB@
|
||||
|
||||
SOURCES = dmeventd_snapshot.c
|
||||
|
||||
@@ -33,4 +33,3 @@ install: libdevmapper-event-lvm2snapshot.$(LIB_SUFFIX)
|
||||
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
|
||||
$(libdir)/$<.$(LIB_VERSION)
|
||||
$(LN_S) -f $<.$(LIB_VERSION) $(libdir)/$<
|
||||
|
||||
|
||||
@@ -25,9 +25,8 @@ devices {
|
||||
# list of regular expressions in turn and the first match is used.
|
||||
preferred_names = [ ]
|
||||
|
||||
# If device-mapper multipath is used, more descriptive names might
|
||||
# be preferred over the dm-N names:
|
||||
# preferred_names = [ "^/dev/mapper/mpath" ]
|
||||
# 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
|
||||
|
||||
@@ -61,6 +61,7 @@ SOURCES =\
|
||||
format_text/import_vsn1.c \
|
||||
format_text/tags.c \
|
||||
format_text/text_label.c \
|
||||
freeseg/freeseg.c \
|
||||
label/label.c \
|
||||
locking/file_locking.c \
|
||||
locking/locking.c \
|
||||
|
||||
@@ -673,6 +673,38 @@ int lvs_in_vg_opened(const 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.
|
||||
|
||||
@@ -91,6 +91,7 @@ int lvs_in_vg_activated(struct volume_group *vg);
|
||||
int lvs_in_vg_activated_by_uuid_only(struct volume_group *vg);
|
||||
int lvs_in_vg_opened(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);
|
||||
|
||||
@@ -379,8 +379,7 @@ static int _percent_run(struct dev_manager *dm, const char *name,
|
||||
!segtype->ops->target_percent(&dm->target_state, dm->mem,
|
||||
dm->cmd, seg, params,
|
||||
&total_numerator,
|
||||
&total_denominator,
|
||||
percent))
|
||||
&total_denominator))
|
||||
goto_out;
|
||||
|
||||
} while (next);
|
||||
@@ -393,7 +392,7 @@ static int _percent_run(struct dev_manager *dm, const char *name,
|
||||
|
||||
if (total_denominator)
|
||||
*percent = (float) total_numerator *100 / total_denominator;
|
||||
else if (*percent < 0)
|
||||
else
|
||||
*percent = 100;
|
||||
|
||||
log_debug("LV percent: %f", *percent);
|
||||
@@ -928,8 +927,8 @@ 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 (max_stripe_size < seg->stripe_size * seg->area_count)
|
||||
max_stripe_size = seg->stripe_size * seg->area_count;
|
||||
}
|
||||
|
||||
if (read_ahead == DM_READ_AHEAD_AUTO) {
|
||||
@@ -995,6 +994,9 @@ static int _remove_lv_symlinks(struct dev_manager *dm, struct dm_tree_node *root
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!*vgname)
|
||||
continue;
|
||||
|
||||
/* only top level layer has symlinks */
|
||||
if (*layer)
|
||||
continue;
|
||||
|
||||
259
lib/cache/lvmcache.c
vendored
259
lib/cache/lvmcache.c
vendored
@@ -22,12 +22,16 @@
|
||||
#include "filter.h"
|
||||
#include "memlock.h"
|
||||
#include "str_list.h"
|
||||
#include "format-text.h"
|
||||
#include "format_pool.h"
|
||||
#include "format1.h"
|
||||
|
||||
static struct dm_hash_table *_pvid_hash = NULL;
|
||||
static struct dm_hash_table *_vgid_hash = NULL;
|
||||
static struct dm_hash_table *_vgname_hash = NULL;
|
||||
static struct dm_hash_table *_lock_hash = NULL;
|
||||
static struct list _vginfos;
|
||||
static int _scanning_in_progress = 0;
|
||||
static int _has_scanned = 0;
|
||||
static int _vgs_locked = 0;
|
||||
static int _vg_global_lock_held = 0; /* Global lock held when cache wiped? */
|
||||
@@ -63,7 +67,6 @@ static void _free_cached_vgmetadata(struct lvmcache_vginfo *vginfo)
|
||||
dm_free(vginfo->vgmetadata);
|
||||
|
||||
vginfo->vgmetadata = NULL;
|
||||
vginfo->fid = NULL;
|
||||
|
||||
log_debug("Metadata cache: VG %s wiped.", vginfo->vgname);
|
||||
}
|
||||
@@ -81,7 +84,6 @@ static void _store_metadata(struct lvmcache_vginfo *vginfo,
|
||||
return;
|
||||
}
|
||||
|
||||
vginfo->fid = vg->fid;
|
||||
vginfo->precommitted = precommitted;
|
||||
|
||||
log_debug("Metadata cache: VG %s stored (%d bytes%s).", vginfo->vgname,
|
||||
@@ -95,9 +97,10 @@ static void _update_cache_info_lock_state(struct lvmcache_info *info,
|
||||
int was_locked = (info->status & CACHE_LOCKED) ? 1 : 0;
|
||||
|
||||
/*
|
||||
* Cache becomes invalid whenever lock state changes
|
||||
* Cache becomes invalid whenever lock state changes unless
|
||||
* exclusive VG_GLOBAL is held (i.e. while scanning).
|
||||
*/
|
||||
if (was_locked != locked) {
|
||||
if (!vgname_is_locked(VG_GLOBAL) && (was_locked != locked)) {
|
||||
info->status |= CACHE_INVALID;
|
||||
*cached_vgmetadata_valid = 0;
|
||||
}
|
||||
@@ -132,6 +135,42 @@ static void _update_cache_lock_state(const char *vgname, int locked)
|
||||
_update_cache_vginfo_lock_state(vginfo, locked);
|
||||
}
|
||||
|
||||
static void _drop_metadata(const char *vgname)
|
||||
{
|
||||
struct lvmcache_vginfo *vginfo;
|
||||
struct lvmcache_info *info;
|
||||
|
||||
if (!(vginfo = vginfo_from_vgname(vgname, NULL)))
|
||||
return;
|
||||
|
||||
/*
|
||||
* Invalidate cached PV labels.
|
||||
* If cached precommitted metadata exists that means we
|
||||
* already invalidated the PV labels (before caching it)
|
||||
* and we must not do it again.
|
||||
*/
|
||||
|
||||
if (!vginfo->precommitted)
|
||||
list_iterate_items(info, &vginfo->infos)
|
||||
info->status |= CACHE_INVALID;
|
||||
|
||||
_free_cached_vgmetadata(vginfo);
|
||||
}
|
||||
|
||||
void lvmcache_drop_metadata(const char *vgname)
|
||||
{
|
||||
/* For VG_ORPHANS, we need to invalidate all labels on orphan PVs. */
|
||||
if (!strcmp(vgname, VG_ORPHANS)) {
|
||||
_drop_metadata(FMT_TEXT_ORPHAN_VG_NAME);
|
||||
_drop_metadata(FMT_LVM1_ORPHAN_VG_NAME);
|
||||
_drop_metadata(FMT_POOL_ORPHAN_VG_NAME);
|
||||
|
||||
/* Indicate that PVs could now be missing from the cache */
|
||||
init_full_scan_done(0);
|
||||
} else if (!vgname_is_locked(VG_GLOBAL))
|
||||
_drop_metadata(vgname);
|
||||
}
|
||||
|
||||
void lvmcache_lock_vgname(const char *vgname, int read_only __attribute((unused)))
|
||||
{
|
||||
if (!_lock_hash && !lvmcache_init()) {
|
||||
@@ -148,7 +187,8 @@ void lvmcache_lock_vgname(const char *vgname, int read_only __attribute((unused)
|
||||
|
||||
_update_cache_lock_state(vgname, 1);
|
||||
|
||||
_vgs_locked++;
|
||||
if (strcmp(vgname, VG_GLOBAL))
|
||||
_vgs_locked++;
|
||||
}
|
||||
|
||||
int vgname_is_locked(const char *vgname)
|
||||
@@ -170,7 +210,7 @@ void lvmcache_unlock_vgname(const char *vgname)
|
||||
dm_hash_remove(_lock_hash, vgname);
|
||||
|
||||
/* FIXME Do this per-VG */
|
||||
if (!--_vgs_locked)
|
||||
if (strcmp(vgname, VG_GLOBAL) && !--_vgs_locked)
|
||||
dev_close_all();
|
||||
}
|
||||
|
||||
@@ -179,11 +219,34 @@ int vgs_locked(void)
|
||||
return _vgs_locked;
|
||||
}
|
||||
|
||||
static void _vginfo_attach_info(struct lvmcache_vginfo *vginfo,
|
||||
struct lvmcache_info *info)
|
||||
{
|
||||
if (!vginfo)
|
||||
return;
|
||||
|
||||
info->vginfo = vginfo;
|
||||
list_add(&vginfo->infos, &info->list);
|
||||
}
|
||||
|
||||
static void _vginfo_detach_info(struct lvmcache_info *info)
|
||||
{
|
||||
if (!list_empty(&info->list)) {
|
||||
list_del(&info->list);
|
||||
list_init(&info->list);
|
||||
}
|
||||
|
||||
info->vginfo = NULL;
|
||||
}
|
||||
|
||||
/* If vgid supplied, require a match. */
|
||||
struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname, const char *vgid)
|
||||
{
|
||||
struct lvmcache_vginfo *vginfo;
|
||||
|
||||
if (!vgname)
|
||||
return vginfo_from_vgid(vgid);
|
||||
|
||||
if (!_vgname_hash)
|
||||
return NULL;
|
||||
|
||||
@@ -298,6 +361,7 @@ static int _vginfo_is_valid(struct lvmcache_vginfo *vginfo)
|
||||
{
|
||||
struct lvmcache_info *info;
|
||||
|
||||
/* Invalid if any info is invalid */
|
||||
list_iterate_items(info, &vginfo->infos)
|
||||
if (!_info_is_valid(info))
|
||||
return 0;
|
||||
@@ -305,6 +369,18 @@ static int _vginfo_is_valid(struct lvmcache_vginfo *vginfo)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* vginfo is invalid if it does not contain at least one valid info */
|
||||
static int _vginfo_is_invalid(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.
|
||||
@@ -351,7 +427,6 @@ int lvmcache_label_scan(struct cmd_context *cmd, int full_scan)
|
||||
struct device *dev;
|
||||
struct format_type *fmt;
|
||||
|
||||
static int _scanning_in_progress = 0;
|
||||
int r = 0;
|
||||
|
||||
/* Avoid recursion when a PVID can't be found! */
|
||||
@@ -400,6 +475,7 @@ 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;
|
||||
@@ -407,17 +483,35 @@ struct volume_group *lvmcache_get_vg(const char *vgid, unsigned precommitted)
|
||||
if (!_vginfo_is_valid(vginfo))
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* Don't return cached data if either:
|
||||
* (i) precommitted metadata is requested but we don't have it cached
|
||||
* - caller should read it off disk;
|
||||
* (ii) live metadata is requested but we have precommitted metadata cached
|
||||
* and no devices are suspended so caller may read it off disk.
|
||||
*
|
||||
* If live metadata is requested but we have precommitted metadata cached
|
||||
* and devices are suspended, we assume this precommitted metadata has
|
||||
* already been preloaded and committed so it's OK to return it as live.
|
||||
* Note that we do not clear the PRECOMMITTED flag.
|
||||
*/
|
||||
if ((precommitted && !vginfo->precommitted) ||
|
||||
(!precommitted && vginfo->precommitted))
|
||||
(!precommitted && vginfo->precommitted && !memlock()))
|
||||
return NULL;
|
||||
|
||||
if (!(vg = import_vg_from_buffer(vginfo->vgmetadata, vginfo->fid)) ||
|
||||
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);
|
||||
log_debug("Using cached %smetadata for VG %s.",
|
||||
vginfo->precommitted ? "pre-committed" : "", vginfo->vgname);
|
||||
|
||||
return vg;
|
||||
}
|
||||
@@ -536,38 +630,62 @@ struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int _free_vginfo(struct lvmcache_vginfo *vginfo)
|
||||
{
|
||||
struct lvmcache_vginfo *primary_vginfo, *vginfo2;
|
||||
int r = 1;
|
||||
|
||||
_free_cached_vgmetadata(vginfo);
|
||||
|
||||
vginfo2 = primary_vginfo = vginfo_from_vgname(vginfo->vgname, NULL);
|
||||
|
||||
if (vginfo == primary_vginfo) {
|
||||
dm_hash_remove(_vgname_hash, vginfo->vgname);
|
||||
if (vginfo->next && !dm_hash_insert(_vgname_hash, vginfo->vgname,
|
||||
vginfo->next)) {
|
||||
log_error("_vgname_hash re-insertion for %s failed",
|
||||
vginfo->vgname);
|
||||
r = 0;
|
||||
}
|
||||
} else do
|
||||
if (vginfo2->next == vginfo) {
|
||||
vginfo2->next = vginfo->next;
|
||||
break;
|
||||
}
|
||||
while ((vginfo2 = primary_vginfo->next));
|
||||
|
||||
if (vginfo->vgname)
|
||||
dm_free(vginfo->vgname);
|
||||
|
||||
if (vginfo->creation_host)
|
||||
dm_free(vginfo->creation_host);
|
||||
|
||||
if (*vginfo->vgid && _vgid_hash &&
|
||||
vginfo_from_vgid(vginfo->vgid) == vginfo)
|
||||
dm_hash_remove(_vgid_hash, vginfo->vgid);
|
||||
|
||||
list_del(&vginfo->list);
|
||||
|
||||
dm_free(vginfo);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* vginfo must be info->vginfo unless info is NULL
|
||||
*/
|
||||
static int _drop_vginfo(struct lvmcache_info *info, struct lvmcache_vginfo *vginfo)
|
||||
{
|
||||
if (info && !list_empty(&info->list)) {
|
||||
list_del(&info->list);
|
||||
list_init(&info->list);
|
||||
}
|
||||
|
||||
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 (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);
|
||||
}
|
||||
|
||||
if (info)
|
||||
info->vginfo = NULL;
|
||||
_vginfo_detach_info(info);
|
||||
|
||||
/* vginfo still referenced? */
|
||||
if (!vginfo || is_orphan_vg(vginfo->vgname) ||
|
||||
!list_empty(&vginfo->infos))
|
||||
return 1;
|
||||
|
||||
if (!_free_vginfo(vginfo))
|
||||
return_0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -726,7 +844,9 @@ static int _lvmcache_update_vgname(struct lvmcache_info *info,
|
||||
uint32_t vgstatus, const char *creation_host,
|
||||
const struct format_type *fmt)
|
||||
{
|
||||
struct lvmcache_vginfo *vginfo, *primary_vginfo;
|
||||
struct lvmcache_vginfo *vginfo, *primary_vginfo, *orphan_vginfo;
|
||||
struct lvmcache_info *info2, *info3;
|
||||
char mdabuf[32];
|
||||
// struct lvmcache_vginfo *old_vginfo, *next;
|
||||
|
||||
if (!vgname || (info && info->vginfo && !strcmp(info->vginfo->vgname, vgname)))
|
||||
@@ -785,7 +905,29 @@ static int _lvmcache_update_vgname(struct lvmcache_info *info,
|
||||
return 0;
|
||||
}
|
||||
list_init(&vginfo->infos);
|
||||
primary_vginfo = vginfo_from_vgname(vgname, NULL);
|
||||
|
||||
/*
|
||||
* If we're scanning and there's an invalidated entry, remove it.
|
||||
* Otherwise we risk bogus warnings of duplicate VGs.
|
||||
*/
|
||||
while ((primary_vginfo = vginfo_from_vgname(vgname, NULL)) &&
|
||||
_scanning_in_progress && _vginfo_is_invalid(primary_vginfo))
|
||||
list_iterate_items_safe(info2, info3, &primary_vginfo->infos) {
|
||||
orphan_vginfo = vginfo_from_vgname(primary_vginfo->fmt->orphan_vg_name, NULL);
|
||||
_drop_vginfo(info2, primary_vginfo);
|
||||
_vginfo_attach_info(orphan_vginfo, info2);
|
||||
if (info2->mdas.n)
|
||||
sprintf(mdabuf, " with %u mdas",
|
||||
list_size(&info2->mdas));
|
||||
else
|
||||
mdabuf[0] = '\0';
|
||||
log_debug("lvmcache: %s: now in VG %s%s%s%s%s",
|
||||
dev_name(info2->dev),
|
||||
vgname, orphan_vginfo->vgid[0] ? " (" : "",
|
||||
orphan_vginfo->vgid[0] ? orphan_vginfo->vgid : "",
|
||||
orphan_vginfo->vgid[0] ? ")" : "", mdabuf);
|
||||
}
|
||||
|
||||
if (!_insert_vginfo(vginfo, vgid, vgstatus, creation_host,
|
||||
primary_vginfo)) {
|
||||
dm_free(vginfo->vgname);
|
||||
@@ -802,10 +944,9 @@ static int _lvmcache_update_vgname(struct lvmcache_info *info,
|
||||
***/
|
||||
}
|
||||
|
||||
if (info) {
|
||||
info->vginfo = vginfo;
|
||||
list_add(&vginfo->infos, &info->list);
|
||||
} else if (!_lvmcache_update_vgid(info, vginfo, vgid)) /* Orphans */
|
||||
if (info)
|
||||
_vginfo_attach_info(vginfo, info);
|
||||
else if (!_lvmcache_update_vgid(NULL, vginfo, vgid)) /* Orphans */
|
||||
return_0;
|
||||
|
||||
_update_cache_vginfo_lock_state(vginfo, vgname_is_locked(vgname));
|
||||
@@ -813,13 +954,17 @@ static int _lvmcache_update_vgname(struct lvmcache_info *info,
|
||||
/* FIXME Check consistency of list! */
|
||||
vginfo->fmt = fmt;
|
||||
|
||||
if (info)
|
||||
log_debug("lvmcache: %s: now in VG %s%s%s%s",
|
||||
if (info) {
|
||||
if (info->mdas.n)
|
||||
sprintf(mdabuf, " with %u mdas", list_size(&info->mdas));
|
||||
else
|
||||
mdabuf[0] = '\0';
|
||||
log_debug("lvmcache: %s: now in VG %s%s%s%s%s",
|
||||
dev_name(info->dev),
|
||||
vgname, vginfo->vgid[0] ? " (" : "",
|
||||
vginfo->vgid[0] ? vginfo->vgid : "",
|
||||
vginfo->vgid[0] ? ")" : "");
|
||||
else
|
||||
vginfo->vgid[0] ? ")" : "", mdabuf);
|
||||
} else
|
||||
log_debug("lvmcache: initialised VG %s", vgname);
|
||||
|
||||
return 1;
|
||||
@@ -881,6 +1026,15 @@ int lvmcache_update_vgname_and_id(struct lvmcache_info *info,
|
||||
vgid = vgname;
|
||||
}
|
||||
|
||||
/* If PV without mdas is already in a real VG, don't make it orphan */
|
||||
if (is_orphan_vg(vgname) && info->vginfo && !list_size(&info->mdas) &&
|
||||
!is_orphan_vg(info->vginfo->vgname) && memlock())
|
||||
return 1;
|
||||
|
||||
/* If moving PV from orphan to real VG, always mark it valid */
|
||||
if (!is_orphan_vg(vgname))
|
||||
info->status &= ~CACHE_INVALID;
|
||||
|
||||
if (!_lvmcache_update_vgname(info, vgname, vgid, vgstatus,
|
||||
creation_host, info->fmt) ||
|
||||
!_lvmcache_update_vgid(info, info->vginfo, vgid) ||
|
||||
@@ -1027,8 +1181,7 @@ struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
|
||||
|
||||
static void _lvmcache_destroy_entry(struct lvmcache_info *info)
|
||||
{
|
||||
if (!list_empty(&info->list))
|
||||
list_del(&info->list);
|
||||
_vginfo_detach_info(info);
|
||||
strcpy(info->dev->pvid, "");
|
||||
label_destroy(info->label);
|
||||
dm_free(info);
|
||||
@@ -1040,12 +1193,8 @@ static void _lvmcache_destroy_vgnamelist(struct lvmcache_vginfo *vginfo)
|
||||
|
||||
do {
|
||||
next = vginfo->next;
|
||||
if (vginfo->vgname)
|
||||
dm_free(vginfo->vgname);
|
||||
if (vginfo->creation_host)
|
||||
dm_free(vginfo->creation_host);
|
||||
_free_cached_vgmetadata(vginfo);
|
||||
dm_free(vginfo);
|
||||
if (!_free_vginfo(vginfo))
|
||||
stack;
|
||||
} while ((vginfo = next));
|
||||
}
|
||||
|
||||
@@ -1097,6 +1246,8 @@ void lvmcache_destroy(struct cmd_context *cmd, int retain_orphans)
|
||||
_lock_hash = NULL;
|
||||
}
|
||||
|
||||
if (!list_empty(&_vginfos))
|
||||
log_error("Internal error: _vginfos list should be empty");
|
||||
list_init(&_vginfos);
|
||||
|
||||
if (retain_orphans)
|
||||
|
||||
3
lib/cache/lvmcache.h
vendored
3
lib/cache/lvmcache.h
vendored
@@ -45,7 +45,6 @@ struct lvmcache_vginfo {
|
||||
struct lvmcache_vginfo *next; /* Another VG with same name? */
|
||||
char *creation_host;
|
||||
char *vgmetadata; /* Copy of VG metadata as format_text string */
|
||||
struct format_instance *fid; /* fid associated with vgmetadata */
|
||||
unsigned precommitted; /* Is vgmetadata live or precommitted? */
|
||||
};
|
||||
|
||||
@@ -82,7 +81,6 @@ 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, 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);
|
||||
@@ -112,5 +110,6 @@ struct list *lvmcache_get_pvids(struct cmd_context *cmd, const char *vgname,
|
||||
|
||||
/* Returns cached volume group metadata. */
|
||||
struct volume_group *lvmcache_get_vg(const char *vgid, unsigned precommitted);
|
||||
void lvmcache_drop_metadata(const char *vgname);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -755,6 +755,11 @@ static int _init_segtypes(struct cmd_context *cmd)
|
||||
segtype->library = NULL;
|
||||
list_add(&cmd->segtypes, &segtype->list);
|
||||
|
||||
if (!(segtype = init_free_segtype(cmd)))
|
||||
return 0;
|
||||
segtype->library = NULL;
|
||||
list_add(&cmd->segtypes, &segtype->list);
|
||||
|
||||
#ifdef SNAPSHOT_INTERNAL
|
||||
if (!(segtype = init_snapshot_segtype(cmd)))
|
||||
return 0;
|
||||
|
||||
@@ -798,11 +798,9 @@ static void _get_token(struct parser *p, int tok_prev)
|
||||
static void _eat_space(struct parser *p)
|
||||
{
|
||||
while ((p->tb != p->fe) && (*p->tb)) {
|
||||
if (*p->te == '#') {
|
||||
if (*p->te == '#')
|
||||
while ((p->te != p->fe) && (*p->te) && (*p->te != '\n'))
|
||||
p->te++;
|
||||
p->line++;
|
||||
}
|
||||
|
||||
else if (isspace(*p->te)) {
|
||||
while ((p->te != p->fe) && (*p->te) && isspace(*p->te)) {
|
||||
@@ -1013,7 +1011,7 @@ float find_config_tree_float(struct cmd_context *cmd, const char *path,
|
||||
return _find_config_float(cmd->cft_override ? cmd->cft_override->root : NULL, cmd->cft->root, path, fail);
|
||||
}
|
||||
|
||||
static int _str_in_array(const char *str, const char *values[])
|
||||
static int _str_in_array(const char *str, const char * const values[])
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -1026,9 +1024,8 @@ static int _str_in_array(const char *str, const char *values[])
|
||||
|
||||
static int _str_to_bool(const char *str, int fail)
|
||||
{
|
||||
static const char *_true_values[] = { "y", "yes", "on", "true", NULL };
|
||||
static const char *_false_values[] =
|
||||
{ "n", "no", "off", "false", NULL };
|
||||
const char * const _true_values[] = { "y", "yes", "on", "true", NULL };
|
||||
const char * const _false_values[] = { "n", "no", "off", "false", NULL };
|
||||
|
||||
if (_str_in_array(str, _true_values))
|
||||
return 1;
|
||||
@@ -1278,7 +1275,7 @@ unsigned maybe_config_section(const char *str, unsigned len)
|
||||
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))
|
||||
if (begin_count && end_count && (begin_count == end_count))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
|
||||
@@ -101,7 +101,10 @@
|
||||
|
||||
#define DEFAULT_REP_ALIGNED 1
|
||||
#define DEFAULT_REP_BUFFERED 1
|
||||
#define DEFAULT_REP_COLUMNS_AS_ROWS 0
|
||||
#define DEFAULT_REP_HEADINGS 1
|
||||
#define DEFAULT_REP_PREFIXES 0
|
||||
#define DEFAULT_REP_QUOTED 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,convert_lv"
|
||||
|
||||
@@ -65,6 +65,15 @@ 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?
|
||||
*/
|
||||
|
||||
@@ -55,14 +55,9 @@ void list_add_h(struct list *head, struct list *elem);
|
||||
void list_del(struct list *elem);
|
||||
|
||||
/*
|
||||
* Move an element from an existing list to list 'head'.
|
||||
* Insert the element before 'head'.
|
||||
* Remove an element from existing list and insert before 'head'.
|
||||
*/
|
||||
static inline void list_move(struct list *item, struct list *head)
|
||||
{
|
||||
list_del(item);
|
||||
list_add(head, item);
|
||||
}
|
||||
void list_move(struct list *head, struct list *elem);
|
||||
|
||||
/*
|
||||
* Is the list empty?
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
/* Define some portable printing types */
|
||||
#define PRIsize_t "zu"
|
||||
#define PRIptrdiff_t "td"
|
||||
#define PRIpid_t PRId32
|
||||
|
||||
struct str_list {
|
||||
struct list list;
|
||||
|
||||
@@ -687,7 +687,8 @@ const char *dev_name_confirmed(struct device *dev, int quiet)
|
||||
continue;
|
||||
}
|
||||
|
||||
log_error("Aborting - please provide new pathname for what "
|
||||
/* Scanning issues this inappropriately sometimes. */
|
||||
log_debug("Aborting - please provide new pathname for what "
|
||||
"used to be %s", name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -48,18 +48,26 @@ static int _dev_has_md_magic(struct device *dev, uint64_t sb_offset)
|
||||
* 1: At start of device
|
||||
* 2: 4K from start of device.
|
||||
*/
|
||||
static uint64_t _v1_sb_offset(uint64_t size, unsigned minor_version)
|
||||
typedef enum {
|
||||
MD_MINOR_VERSION_MIN,
|
||||
MD_MINOR_V0 = MD_MINOR_VERSION_MIN,
|
||||
MD_MINOR_V1,
|
||||
MD_MINOR_V2,
|
||||
MD_MINOR_VERSION_MAX = MD_MINOR_V2
|
||||
} md_minor_version_t;
|
||||
|
||||
static uint64_t _v1_sb_offset(uint64_t size, md_minor_version_t minor_version)
|
||||
{
|
||||
uint64_t sb_offset;
|
||||
uint64_t uninitialized_var(sb_offset);
|
||||
|
||||
switch(minor_version) {
|
||||
case 0:
|
||||
case MD_MINOR_V0:
|
||||
sb_offset = (size - 8 * 2) & ~(4 * 2 - 1ULL);
|
||||
break;
|
||||
case 1:
|
||||
case MD_MINOR_V1:
|
||||
sb_offset = 0;
|
||||
break;
|
||||
case 2:
|
||||
case MD_MINOR_V2:
|
||||
sb_offset = 4 * 2;
|
||||
break;
|
||||
}
|
||||
@@ -74,7 +82,7 @@ static uint64_t _v1_sb_offset(uint64_t size, unsigned minor_version)
|
||||
int dev_is_md(struct device *dev, uint64_t *sb)
|
||||
{
|
||||
int ret = 1;
|
||||
unsigned minor = 0;
|
||||
md_minor_version_t minor;
|
||||
uint64_t size, sb_offset;
|
||||
|
||||
if (!dev_get_size(dev, &size)) {
|
||||
@@ -96,12 +104,13 @@ int dev_is_md(struct device *dev, uint64_t *sb)
|
||||
if (_dev_has_md_magic(dev, sb_offset))
|
||||
goto out;
|
||||
|
||||
minor = MD_MINOR_VERSION_MIN;
|
||||
/* 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);
|
||||
} while (++minor <= MD_MINOR_VERSION_MAX);
|
||||
|
||||
ret = 0;
|
||||
|
||||
|
||||
@@ -94,11 +94,6 @@ const char *dev_name_confirmed(struct device *dev, int quiet);
|
||||
/* Does device contain md superblock? If so, where? */
|
||||
int dev_is_md(struct device *dev, uint64_t *sb);
|
||||
|
||||
/* FIXME Check partition type if appropriate */
|
||||
|
||||
#define is_lvm_partition(a) 1
|
||||
/* int is_lvm_partition(const char *name); */
|
||||
|
||||
int is_partitioned_dev(struct device *dev);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -24,9 +24,9 @@
|
||||
|
||||
typedef enum { SIZE_LONG = 0, SIZE_SHORT = 1, SIZE_UNIT = 2 } size_len_t;
|
||||
|
||||
static struct {
|
||||
static const struct {
|
||||
alloc_policy_t alloc;
|
||||
const char *str;
|
||||
const char str[12]; /* must be changed when size extends 11 chars */
|
||||
} _policies[] = {
|
||||
{
|
||||
ALLOC_CONTIGUOUS, "contiguous"}, {
|
||||
@@ -36,7 +36,7 @@ static struct {
|
||||
ALLOC_INHERIT, "inherit"}
|
||||
};
|
||||
|
||||
static int _num_policies = sizeof(_policies) / sizeof(*_policies);
|
||||
static const int _num_policies = sizeof(_policies) / sizeof(*_policies);
|
||||
|
||||
uint64_t units_to_bytes(const char *units, char *unit_type)
|
||||
{
|
||||
@@ -155,7 +155,7 @@ static const char *_display_size(const struct cmd_context *cmd,
|
||||
uint64_t byte = UINT64_C(0);
|
||||
uint64_t units = UINT64_C(1024);
|
||||
char *size_buf = NULL;
|
||||
const char *size_str[][3] = {
|
||||
const char * const size_str[][3] = {
|
||||
{" Exabyte", " EB", "E"},
|
||||
{" Petabyte", " PB", "P"},
|
||||
{" Terabyte", " TB", "T"},
|
||||
@@ -670,7 +670,7 @@ void vgdisplay_colons(const struct volume_group *vg)
|
||||
active_pvs = vg->pv_count;
|
||||
|
||||
list_iterate_items(lvl, &vg->lvs)
|
||||
if (lv_is_visible(lvl->lv) || (lvl->lv->status & SNAPSHOT))
|
||||
if (lv_is_visible(lvl->lv) && !(lvl->lv->status & SNAPSHOT))
|
||||
lv_count++;
|
||||
|
||||
switch (vg->status & (LVM_READ | LVM_WRITE)) {
|
||||
|
||||
@@ -356,7 +356,7 @@ static struct disk_list *__read_disk(const struct format_type *fmt,
|
||||
list_init(&dl->lvds);
|
||||
|
||||
if (!_read_pvd(dev, &dl->pvd))
|
||||
goto_bad;
|
||||
goto bad;
|
||||
|
||||
/*
|
||||
* is it an orphan ?
|
||||
|
||||
@@ -284,7 +284,7 @@ int export_vg(struct vg_disk *vgd, struct volume_group *vg)
|
||||
vgd->vg_status |= VG_EXTENDABLE;
|
||||
|
||||
vgd->lv_max = vg->max_lv;
|
||||
vgd->lv_cur = vg->lv_count;
|
||||
vgd->lv_cur = vg->lv_count + vg->snapshot_count;
|
||||
|
||||
vgd->pv_max = vg->max_pv;
|
||||
vgd->pv_cur = vg->pv_count;
|
||||
|
||||
@@ -36,6 +36,7 @@ int import_pool_vg(struct volume_group *vg, struct dm_pool *mem, struct list *pl
|
||||
vg->extent_count +=
|
||||
((pl->pd.pl_blocks) / POOL_PE_SIZE);
|
||||
|
||||
vg->free_count = vg->extent_count;
|
||||
vg->pv_count++;
|
||||
|
||||
if (vg->name)
|
||||
@@ -45,7 +46,6 @@ int import_pool_vg(struct volume_group *vg, struct dm_pool *mem, struct list *pl
|
||||
get_pool_vg_uuid(&vg->id, &pl->pd);
|
||||
vg->extent_size = POOL_PE_SIZE;
|
||||
vg->status |= LVM_READ | LVM_WRITE | CLUSTERED | SHARED;
|
||||
vg->free_count = vg->extent_count;
|
||||
vg->max_lv = 1;
|
||||
vg->max_pv = POOL_MAX_DEVICES;
|
||||
vg->alloc = ALLOC_NORMAL;
|
||||
@@ -165,7 +165,8 @@ int import_pool_pv(const struct format_type *fmt, struct dm_pool *mem,
|
||||
log_error("Unable to duplicate vg_name string");
|
||||
return 0;
|
||||
}
|
||||
memcpy(&pv->vgid, &vg->id, sizeof(vg->id));
|
||||
if (vg != NULL)
|
||||
memcpy(&pv->vgid, &vg->id, sizeof(vg->id));
|
||||
pv->status = 0;
|
||||
pv->size = pd->pl_blocks;
|
||||
pv->pe_size = POOL_PE_SIZE;
|
||||
|
||||
@@ -321,6 +321,20 @@ static int _print_header(struct formatter *f,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _print_flag_config(struct formatter *f, int status, int type)
|
||||
{
|
||||
char buffer[4096];
|
||||
if (!print_flags(status, type | STATUS_FLAG, buffer, sizeof(buffer)))
|
||||
return_0;
|
||||
outf(f, "status = %s", buffer);
|
||||
|
||||
if (!print_flags(status, type, buffer, sizeof(buffer)))
|
||||
return_0;
|
||||
outf(f, "flags = %s", buffer);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _print_vg(struct formatter *f, struct volume_group *vg)
|
||||
{
|
||||
char buffer[4096];
|
||||
@@ -332,9 +346,8 @@ static int _print_vg(struct formatter *f, struct volume_group *vg)
|
||||
|
||||
outf(f, "seqno = %u", vg->seqno);
|
||||
|
||||
if (!print_flags(vg->status, VG_FLAGS, buffer, sizeof(buffer)))
|
||||
if (!_print_flag_config(f, vg->status, VG_FLAGS))
|
||||
return_0;
|
||||
outf(f, "status = %s", buffer);
|
||||
|
||||
if (!list_empty(&vg->tags)) {
|
||||
if (!print_tags(&vg->tags, buffer, sizeof(buffer)))
|
||||
@@ -408,9 +421,8 @@ static int _print_pvs(struct formatter *f, struct volume_group *vg)
|
||||
return_0;
|
||||
outnl(f);
|
||||
|
||||
if (!print_flags(pv->status, PV_FLAGS, buffer, sizeof(buffer)))
|
||||
if (!_print_flag_config(f, pv->status, PV_FLAGS))
|
||||
return_0;
|
||||
outf(f, "status = %s", buffer);
|
||||
|
||||
if (!list_empty(&pv->tags)) {
|
||||
if (!print_tags(&pv->tags, buffer, sizeof(buffer)))
|
||||
@@ -520,9 +532,8 @@ static int _print_lv(struct formatter *f, struct logical_volume *lv)
|
||||
|
||||
outf(f, "id = \"%s\"", buffer);
|
||||
|
||||
if (!print_flags(lv->status, LV_FLAGS, buffer, sizeof(buffer)))
|
||||
if (!_print_flag_config(f, lv->status, LV_FLAGS))
|
||||
return_0;
|
||||
outf(f, "status = %s", buffer);
|
||||
|
||||
if (!list_empty(&lv->tags)) {
|
||||
if (!print_tags(&lv->tags, buffer, sizeof(buffer)))
|
||||
|
||||
@@ -25,48 +25,49 @@
|
||||
struct flag {
|
||||
const int mask;
|
||||
const char *description;
|
||||
int kind;
|
||||
};
|
||||
|
||||
static struct flag _vg_flags[] = {
|
||||
{EXPORTED_VG, "EXPORTED"},
|
||||
{RESIZEABLE_VG, "RESIZEABLE"},
|
||||
{PARTIAL_VG, "PARTIAL"},
|
||||
{PVMOVE, "PVMOVE"},
|
||||
{LVM_READ, "READ"},
|
||||
{LVM_WRITE, "WRITE"},
|
||||
{CLUSTERED, "CLUSTERED"},
|
||||
{SHARED, "SHARED"},
|
||||
{PRECOMMITTED, NULL},
|
||||
{0, NULL}
|
||||
{EXPORTED_VG, "EXPORTED", STATUS_FLAG},
|
||||
{RESIZEABLE_VG, "RESIZEABLE", STATUS_FLAG},
|
||||
{PARTIAL_VG, "PARTIAL", STATUS_FLAG},
|
||||
{PVMOVE, "PVMOVE", STATUS_FLAG},
|
||||
{LVM_READ, "READ", STATUS_FLAG},
|
||||
{LVM_WRITE, "WRITE", STATUS_FLAG},
|
||||
{CLUSTERED, "CLUSTERED", STATUS_FLAG},
|
||||
{SHARED, "SHARED", STATUS_FLAG},
|
||||
{PRECOMMITTED, NULL, 0},
|
||||
{0, NULL, 0}
|
||||
};
|
||||
|
||||
static struct flag _pv_flags[] = {
|
||||
{ALLOCATABLE_PV, "ALLOCATABLE"},
|
||||
{EXPORTED_VG, "EXPORTED"},
|
||||
{0, NULL}
|
||||
{ALLOCATABLE_PV, "ALLOCATABLE", STATUS_FLAG},
|
||||
{EXPORTED_VG, "EXPORTED", STATUS_FLAG},
|
||||
{0, NULL, 0}
|
||||
};
|
||||
|
||||
static struct flag _lv_flags[] = {
|
||||
{LVM_READ, "READ"},
|
||||
{LVM_WRITE, "WRITE"},
|
||||
{FIXED_MINOR, "FIXED_MINOR"},
|
||||
{VISIBLE_LV, "VISIBLE"},
|
||||
{PVMOVE, "PVMOVE"},
|
||||
{LOCKED, "LOCKED"},
|
||||
{MIRROR_NOTSYNCED, "NOTSYNCED"},
|
||||
{MIRROR_IMAGE, NULL},
|
||||
{MIRROR_LOG, NULL},
|
||||
{MIRRORED, NULL},
|
||||
{VIRTUAL, NULL},
|
||||
{SNAPSHOT, NULL},
|
||||
{ACTIVATE_EXCL, NULL},
|
||||
{CONVERTING, NULL},
|
||||
{0, NULL}
|
||||
{LVM_READ, "READ", STATUS_FLAG},
|
||||
{LVM_WRITE, "WRITE", STATUS_FLAG},
|
||||
{FIXED_MINOR, "FIXED_MINOR", STATUS_FLAG},
|
||||
{VISIBLE_LV, "VISIBLE", STATUS_FLAG},
|
||||
{PVMOVE, "PVMOVE", STATUS_FLAG},
|
||||
{LOCKED, "LOCKED", STATUS_FLAG},
|
||||
{MIRROR_NOTSYNCED, "NOTSYNCED", STATUS_FLAG},
|
||||
{MIRROR_IMAGE, NULL, 0},
|
||||
{MIRROR_LOG, NULL, 0},
|
||||
{MIRRORED, NULL, 0},
|
||||
{VIRTUAL, NULL, 0},
|
||||
{SNAPSHOT, NULL, 0},
|
||||
{ACTIVATE_EXCL, NULL, 0},
|
||||
{CONVERTING, NULL, 0},
|
||||
{0, NULL, 0}
|
||||
};
|
||||
|
||||
static struct flag *_get_flags(int type)
|
||||
{
|
||||
switch (type) {
|
||||
switch (type & ~STATUS_FLAG) {
|
||||
case VG_FLAGS:
|
||||
return _vg_flags;
|
||||
|
||||
@@ -101,6 +102,9 @@ int print_flags(uint32_t status, int type, char *buffer, size_t size)
|
||||
if (status & flags[f].mask) {
|
||||
status &= ~flags[f].mask;
|
||||
|
||||
if ((type & STATUS_FLAG) != flags[f].kind)
|
||||
continue;
|
||||
|
||||
/* Internal-only flag? */
|
||||
if (!flags[f].description)
|
||||
continue;
|
||||
@@ -151,7 +155,7 @@ int read_flags(uint32_t *status, int type, struct config_value *cv)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!flags[f].description) {
|
||||
if (!flags[f].description && (type & STATUS_FLAG)) {
|
||||
log_err("Unknown status flag '%s'.", cv->v.str);
|
||||
return 0;
|
||||
}
|
||||
@@ -160,6 +164,6 @@ int read_flags(uint32_t *status, int type, struct config_value *cv)
|
||||
}
|
||||
|
||||
out:
|
||||
*status = s;
|
||||
*status |= s;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -139,7 +139,7 @@ static int _pv_analyze_mda_raw (const struct format_type * fmt,
|
||||
struct raw_locn *rlocn;
|
||||
uint64_t area_start;
|
||||
uint64_t area_size;
|
||||
uint64_t prev_sector;
|
||||
uint64_t prev_sector, prev_sector2;
|
||||
uint64_t latest_mrec_offset;
|
||||
int i;
|
||||
uint64_t offset;
|
||||
@@ -184,8 +184,11 @@ static int _pv_analyze_mda_raw (const struct format_type * fmt,
|
||||
offset2 = size2 = 0;
|
||||
i = 0;
|
||||
while (prev_sector != latest_mrec_offset) {
|
||||
prev_sector2 = prev_sector;
|
||||
prev_sector = _get_prev_sector_circular(area_start, area_size,
|
||||
prev_sector);
|
||||
if (prev_sector > prev_sector2)
|
||||
goto_out;
|
||||
/*
|
||||
* FIXME: for some reason, the whole metadata region from
|
||||
* area->start to area->start+area->size is not used.
|
||||
@@ -343,10 +346,8 @@ static int _raw_write_mda_header(const struct format_type *fmt,
|
||||
MDA_HEADER_SIZE -
|
||||
sizeof(mdah->checksum_xl)));
|
||||
|
||||
if (!dev_write(dev, start_byte, MDA_HEADER_SIZE, mdah)) {
|
||||
dm_pool_free(fmt->cmd->mem, mdah);
|
||||
if (!dev_write(dev, start_byte, MDA_HEADER_SIZE, mdah))
|
||||
return_0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -667,6 +668,7 @@ static int _vg_commit_raw_rlocn(struct format_instance *fid,
|
||||
|
||||
if (!_raw_write_mda_header(fid->fmt, mdac->area.dev, mdac->area.start,
|
||||
mdah)) {
|
||||
dm_pool_free(fid->fmt->cmd->mem, mdah);
|
||||
log_error("Failed to write metadata area header");
|
||||
goto out;
|
||||
}
|
||||
@@ -749,6 +751,7 @@ static int _vg_remove_raw(struct format_instance *fid, struct volume_group *vg,
|
||||
|
||||
if (!_raw_write_mda_header(fid->fmt, mdac->area.dev, mdac->area.start,
|
||||
mdah)) {
|
||||
dm_pool_free(fid->fmt->cmd->mem, mdah);
|
||||
log_error("Failed to write metadata area header");
|
||||
goto out;
|
||||
}
|
||||
@@ -1363,7 +1366,10 @@ static int _text_pv_write(const struct format_type *fmt, struct physical_volume
|
||||
}
|
||||
}
|
||||
|
||||
label_write(pv->dev, label);
|
||||
if (!label_write(pv->dev, label)) {
|
||||
dev_close(pv->dev);
|
||||
return_0;
|
||||
}
|
||||
|
||||
if (!dev_close(pv->dev))
|
||||
return_0;
|
||||
@@ -1393,43 +1399,33 @@ static int _add_raw(struct list *raw_list, struct device_area *dev_area)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _text_pv_read(const struct format_type *fmt, const char *pv_name,
|
||||
struct physical_volume *pv, struct list *mdas)
|
||||
static int _get_pv_if_in_vg(struct lvmcache_info *info,
|
||||
struct physical_volume *pv)
|
||||
{
|
||||
struct label *label;
|
||||
struct device *dev;
|
||||
struct lvmcache_info *info;
|
||||
struct metadata_area *mda, *mda_new;
|
||||
struct mda_context *mdac, *mdac_new;
|
||||
struct data_area_list *da;
|
||||
|
||||
if (!(dev = dev_cache_get(pv_name, fmt->cmd->filter)))
|
||||
return_0;
|
||||
|
||||
/* FIXME Optimise out repeated reading when cache lock held */
|
||||
if (!(label_read(dev, &label, UINT64_C(0))))
|
||||
return_0;
|
||||
info = (struct lvmcache_info *) label->info;
|
||||
|
||||
/* Have we already cached vgname? */
|
||||
if (info->vginfo && info->vginfo->vgname &&
|
||||
!is_orphan_vg(info->vginfo->vgname) &&
|
||||
get_pv_from_vg_by_id(info->fmt, info->vginfo->vgname,
|
||||
info->vginfo->vgid, info->dev->pvid, pv)) {
|
||||
info->vginfo->vgid, info->dev->pvid, pv))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _populate_pv_fields(struct lvmcache_info *info,
|
||||
struct physical_volume *pv)
|
||||
{
|
||||
struct data_area_list *da;
|
||||
|
||||
/* Have we already cached vgname? */
|
||||
if (_get_pv_if_in_vg(info, pv))
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Perform full scan (just the first time) and try again */
|
||||
if (!memlock() && !full_scan_done()) {
|
||||
lvmcache_label_scan(fmt->cmd, 2);
|
||||
lvmcache_label_scan(info->fmt->cmd, 2);
|
||||
|
||||
if (info->vginfo && info->vginfo->vgname &&
|
||||
!is_orphan_vg(info->vginfo->vgname) &&
|
||||
get_pv_from_vg_by_id(info->fmt, info->vginfo->vgname,
|
||||
info->vginfo->vgid,
|
||||
info->dev->pvid, pv)) {
|
||||
if (_get_pv_if_in_vg(info, pv))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Orphan */
|
||||
@@ -1442,13 +1438,35 @@ static int _text_pv_read(const struct format_type *fmt, const char *pv_name,
|
||||
/* Currently only support exactly one data area */
|
||||
if (list_size(&info->das) != 1) {
|
||||
log_error("Must be exactly one data area (found %d) on PV %s",
|
||||
list_size(&info->das), dev_name(dev));
|
||||
list_size(&info->das), dev_name(info->dev));
|
||||
return 0;
|
||||
}
|
||||
|
||||
list_iterate_items(da, &info->das)
|
||||
pv->pe_start = da->disk_locn.offset >> SECTOR_SHIFT;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _text_pv_read(const struct format_type *fmt, const char *pv_name,
|
||||
struct physical_volume *pv, struct list *mdas)
|
||||
{
|
||||
struct label *label;
|
||||
struct device *dev;
|
||||
struct lvmcache_info *info;
|
||||
struct metadata_area *mda, *mda_new;
|
||||
struct mda_context *mdac, *mdac_new;
|
||||
|
||||
if (!(dev = dev_cache_get(pv_name, fmt->cmd->filter)))
|
||||
return_0;
|
||||
|
||||
if (!(label_read(dev, &label, UINT64_C(0))))
|
||||
return_0;
|
||||
info = (struct lvmcache_info *) label->info;
|
||||
|
||||
if (!_populate_pv_fields(info, pv))
|
||||
return 0;
|
||||
|
||||
if (!mdas)
|
||||
return 1;
|
||||
|
||||
|
||||
@@ -36,9 +36,11 @@
|
||||
* common code for reading and writing them.
|
||||
*/
|
||||
enum {
|
||||
COMPATIBLE_FLAG = 0x0,
|
||||
VG_FLAGS,
|
||||
PV_FLAGS,
|
||||
LV_FLAGS
|
||||
LV_FLAGS,
|
||||
STATUS_FLAG = 0x8,
|
||||
};
|
||||
|
||||
struct text_vg_version_ops {
|
||||
|
||||
@@ -125,6 +125,31 @@ static int _read_id(struct id *id, struct config_node *cn, const char *path)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _read_flag_config(struct config_node *n, uint32_t *status, int type)
|
||||
{
|
||||
struct config_node *cn;
|
||||
*status = 0;
|
||||
|
||||
if (!(cn = find_config_node(n, "status"))) {
|
||||
log_error("Could not find status flags.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(read_flags(status, type | STATUS_FLAG, cn->v))) {
|
||||
log_error("Could not read status flags.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((cn = find_config_node(n, "flags"))) {
|
||||
if (!(read_flags(status, type, cn->v))) {
|
||||
log_error("Could not read flags.");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _read_pv(struct format_instance *fid, struct dm_pool *mem,
|
||||
struct volume_group *vg, struct config_node *pvn,
|
||||
struct config_node *vgn __attribute((unused)),
|
||||
@@ -181,12 +206,7 @@ static int _read_pv(struct format_instance *fid, struct dm_pool *mem,
|
||||
|
||||
memcpy(&pv->vgid, &vg->id, sizeof(vg->id));
|
||||
|
||||
if (!(cn = find_config_node(pvn, "status"))) {
|
||||
log_error("Couldn't find status flags for physical volume.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(read_flags(&pv->status, PV_FLAGS, cn->v))) {
|
||||
if (!_read_flag_config(pvn, &pv->status, PV_FLAGS)) {
|
||||
log_error("Couldn't read status flags for physical volume.");
|
||||
return 0;
|
||||
}
|
||||
@@ -493,13 +513,9 @@ static int _read_lvnames(struct format_instance *fid __attribute((unused)),
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(cn = find_config_node(lvn, "status"))) {
|
||||
log_error("Couldn't find status flags for logical volume.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(read_flags(&lv->status, LV_FLAGS, cn->v))) {
|
||||
log_error("Couldn't read status flags for logical volume.");
|
||||
if (!_read_flag_config(lvn, &lv->status, LV_FLAGS)) {
|
||||
log_error("Couldn't read status flags for logical volume %s.",
|
||||
lv->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -692,14 +708,8 @@ static struct volume_group *_read_vg(struct format_instance *fid,
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (!(cn = find_config_node(vgn, "status"))) {
|
||||
log_error("Couldn't find status flags for volume group %s.",
|
||||
vg->name);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (!(read_flags(&vg->status, VG_FLAGS, cn->v))) {
|
||||
log_error("Couldn't read status flags for volume group %s.",
|
||||
if (!_read_flag_config(vgn, &vg->status, VG_FLAGS)) {
|
||||
log_error("Error reading flags of volume group %s.",
|
||||
vg->name);
|
||||
goto bad;
|
||||
}
|
||||
@@ -826,7 +836,7 @@ static const char *_read_vgname(const struct format_type *fmt,
|
||||
struct config_tree *cft, struct id *vgid,
|
||||
uint32_t *vgstatus, char **creation_host)
|
||||
{
|
||||
struct config_node *vgn, *cn;
|
||||
struct config_node *vgn;
|
||||
struct dm_pool *mem = fmt->cmd->mem;
|
||||
char *vgname;
|
||||
int old_suppress;
|
||||
@@ -855,18 +865,12 @@ static const char *_read_vgname(const struct format_type *fmt,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(cn = find_config_node(vgn, "status"))) {
|
||||
if (!_read_flag_config(vgn, vgstatus, VG_FLAGS)) {
|
||||
log_error("Couldn't find status flags for volume group %s.",
|
||||
vgname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(read_flags(vgstatus, VG_FLAGS, cn->v))) {
|
||||
log_error("Couldn't read status flags for volume group %s.",
|
||||
vgname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return vgname;
|
||||
}
|
||||
|
||||
|
||||
60
lib/freeseg/freeseg.c
Normal file
60
lib/freeseg/freeseg.c
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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 Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
#include "toolcontext.h"
|
||||
#include "segtype.h"
|
||||
#include "display.h"
|
||||
#include "text_export.h"
|
||||
#include "text_import.h"
|
||||
#include "config.h"
|
||||
#include "str_list.h"
|
||||
#include "targets.h"
|
||||
#include "lvm-string.h"
|
||||
#include "activate.h"
|
||||
#include "str_list.h"
|
||||
#include "metadata.h"
|
||||
|
||||
static const char *_freeseg_name(const struct lv_segment *seg)
|
||||
{
|
||||
return seg->segtype->name;
|
||||
}
|
||||
|
||||
static void _freeseg_destroy(const struct segment_type *segtype)
|
||||
{
|
||||
dm_free((void *)segtype);
|
||||
}
|
||||
|
||||
static struct segtype_handler _freeseg_ops = {
|
||||
.name = _freeseg_name,
|
||||
.destroy = _freeseg_destroy,
|
||||
};
|
||||
|
||||
struct segment_type *init_free_segtype(struct cmd_context *cmd)
|
||||
{
|
||||
struct segment_type *segtype = dm_malloc(sizeof(*segtype));
|
||||
|
||||
if (!segtype)
|
||||
return_NULL;
|
||||
|
||||
segtype->cmd = cmd;
|
||||
segtype->ops = &_freeseg_ops;
|
||||
segtype->name = "free";
|
||||
segtype->private = NULL;
|
||||
segtype->flags = SEG_VIRTUAL | SEG_CANNOT_BE_ZEROED;
|
||||
|
||||
log_very_verbose("Initialised segtype: %s", segtype->name);
|
||||
|
||||
return segtype;
|
||||
}
|
||||
@@ -284,7 +284,7 @@ int label_read(struct device *dev, struct label **result,
|
||||
}
|
||||
|
||||
if (!(l = _find_labeller(dev, buf, §or, scan_sector)))
|
||||
goto_out;
|
||||
goto out;
|
||||
|
||||
if ((r = (l->ops->read)(l, dev, buf, result)) && result && *result)
|
||||
(*result)->sector = sector;
|
||||
@@ -361,7 +361,7 @@ int label_verify(struct device *dev)
|
||||
}
|
||||
|
||||
if (!(l = _find_labeller(dev, buf, §or, UINT64_C(0))))
|
||||
goto_out;
|
||||
goto out;
|
||||
|
||||
r = l->ops->verify ? l->ops->verify(l, buf, sector) : 1;
|
||||
|
||||
|
||||
@@ -387,13 +387,12 @@ int lock_resource(struct cmd_context *cmd, const char *resource, uint32_t flags)
|
||||
switch (flags & LCK_SCOPE_MASK) {
|
||||
case LCK_VG:
|
||||
/* If the VG name is empty then lock the unused PVs */
|
||||
if (!*resource) /* FIXME Deprecated */
|
||||
dm_snprintf(lockname, sizeof(lockname), "P_orphans");
|
||||
else if (*resource == '#')
|
||||
dm_snprintf(lockname, sizeof(lockname), "P_%s", resource + 1);
|
||||
if (*resource == '#' || (flags & LCK_CACHE))
|
||||
dm_snprintf(lockname, sizeof(lockname), "P_%s",
|
||||
resource);
|
||||
else
|
||||
dm_snprintf(lockname, sizeof(lockname), "V_%s",
|
||||
resource);
|
||||
resource);
|
||||
|
||||
lock_scope = "VG";
|
||||
cluster_cmd = CLVMD_CMD_LOCK_VG;
|
||||
@@ -438,8 +437,10 @@ int lock_resource(struct cmd_context *cmd, const char *resource, uint32_t flags)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If we are unlocking a VG, then trigger remote metadata backups */
|
||||
if (cluster_cmd == CLVMD_CMD_LOCK_VG && ((flags & LCK_TYPE_MASK) == LCK_UNLOCK)) {
|
||||
/* If we are unlocking a clustered VG, then trigger remote metadata backups */
|
||||
if (cluster_cmd == CLVMD_CMD_LOCK_VG &&
|
||||
((flags & LCK_TYPE_MASK) == LCK_UNLOCK) &&
|
||||
(flags & LCK_CLUSTER_VG)) {
|
||||
log_very_verbose("Requesing backup of VG metadata for %s", resource);
|
||||
_lock_for_cluster(CLVMD_CMD_VG_BACKUP, LCK_CLUSTER_VG, resource);
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "defaults.h"
|
||||
#include "lvm-file.h"
|
||||
#include "lvm-string.h"
|
||||
#include "lvmcache.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <unistd.h>
|
||||
@@ -209,10 +210,15 @@ static int _file_lock_resource(struct cmd_context *cmd, const char *resource,
|
||||
|
||||
switch (flags & LCK_SCOPE_MASK) {
|
||||
case LCK_VG:
|
||||
if (!*resource) /* FIXME Deprecated */
|
||||
dm_snprintf(lockfile, sizeof(lockfile),
|
||||
"%s/P_orphans", _lock_dir);
|
||||
else if (*resource == '#')
|
||||
/* Skip cache refresh for VG_GLOBAL - the caller handles it */
|
||||
if (strcmp(resource, VG_GLOBAL))
|
||||
lvmcache_drop_metadata(resource);
|
||||
|
||||
/* LCK_CACHE does not require a real lock */
|
||||
if (flags & LCK_CACHE)
|
||||
break;
|
||||
|
||||
if (*resource == '#')
|
||||
dm_snprintf(lockfile, sizeof(lockfile),
|
||||
"%s/P_%s", _lock_dir, resource + 1);
|
||||
else
|
||||
|
||||
@@ -292,6 +292,10 @@ int check_lvm1_vg_inactive(struct cmd_context *cmd, const char *vgname)
|
||||
if (is_orphan_vg(vgname))
|
||||
return 1;
|
||||
|
||||
/* LVM1 is only present in 2.4 kernels. */
|
||||
if (strncmp(cmd->kernel_vsn, "2.4.", 4))
|
||||
return 1;
|
||||
|
||||
if (dm_snprintf(path, sizeof(path), "%s/lvm/VGs/%s", cmd->proc_dir,
|
||||
vgname) < 0) {
|
||||
log_error("LVM1 proc VG pathname too long for %s", vgname);
|
||||
@@ -323,8 +327,19 @@ static int _lock_vol(struct cmd_context *cmd, const char *resource, uint32_t fla
|
||||
|
||||
assert(resource);
|
||||
|
||||
if (!*resource) {
|
||||
log_error("Internal error: Use of P_orphans is deprecated.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (*resource == '#' && (flags & LCK_CACHE)) {
|
||||
log_error("Internal error: P_%s referenced", resource);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((ret = _locking.lock_resource(cmd, resource, flags))) {
|
||||
if ((flags & LCK_SCOPE_MASK) == LCK_VG) {
|
||||
if ((flags & LCK_SCOPE_MASK) == LCK_VG &&
|
||||
!(flags & LCK_CACHE)) {
|
||||
if ((flags & LCK_TYPE_MASK) == LCK_UNLOCK)
|
||||
lvmcache_unlock_vgname(resource);
|
||||
else
|
||||
@@ -369,8 +384,12 @@ int lock_vol(struct cmd_context *cmd, const char *vol, uint32_t flags)
|
||||
if (!_lock_vol(cmd, resource, flags))
|
||||
return 0;
|
||||
|
||||
/* Perform immediate unlock unless LCK_HOLD set */
|
||||
if (!(flags & LCK_HOLD) && ((flags & LCK_TYPE_MASK) != LCK_UNLOCK)) {
|
||||
/*
|
||||
* If a real lock was acquired (i.e. not LCK_CACHE),
|
||||
* perform an immediate unlock unless LCK_HOLD was requested.
|
||||
*/
|
||||
if (!(flags & LCK_CACHE) && !(flags & LCK_HOLD) &&
|
||||
((flags & LCK_TYPE_MASK) != LCK_UNLOCK)) {
|
||||
if (!_lock_vol(cmd, resource,
|
||||
(flags & ~LCK_TYPE_MASK) | LCK_UNLOCK))
|
||||
return 0;
|
||||
|
||||
@@ -27,9 +27,11 @@ int locking_is_clustered(void);
|
||||
|
||||
/*
|
||||
* LCK_VG:
|
||||
* Lock/unlock on-disk volume group data
|
||||
* Use VG_ORPHANS to lock orphan PVs
|
||||
* char *vol holds volume group name
|
||||
* Lock/unlock on-disk volume group data.
|
||||
* Use VG_ORPHANS to lock all orphan PVs.
|
||||
* Use VG_GLOBAL as a global lock and to wipe the internal cache.
|
||||
* char *vol holds volume group name.
|
||||
* Set the LCK_CACHE flag to invalidate 'vol' in the internal cache.
|
||||
*
|
||||
* LCK_LV:
|
||||
* Lock/unlock an individual logical volume
|
||||
@@ -37,6 +39,13 @@ int locking_is_clustered(void);
|
||||
*/
|
||||
int lock_vol(struct cmd_context *cmd, const char *vol, uint32_t flags);
|
||||
|
||||
/*
|
||||
* Internal locking representation.
|
||||
* LCK_VG: Uses prefix V_ unless the vol begins with # (i.e. #global or #orphans)
|
||||
* or the LCK_CACHE flag is set when it uses the prefix P_.
|
||||
* If LCK_CACHE is set, we do not take out a real lock.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Does the LVM1 driver have this VG active?
|
||||
*/
|
||||
@@ -69,6 +78,7 @@ int check_lvm1_vg_inactive(struct cmd_context *cmd, const char *vgname);
|
||||
#define LCK_HOLD 0x00000020U /* Hold lock when lock_vol returns? */
|
||||
#define LCK_LOCAL 0x00000040U /* Don't propagate to other nodes */
|
||||
#define LCK_CLUSTER_VG 0x00000080U /* VG is clustered */
|
||||
#define LCK_CACHE 0x00000100U /* Operation on cache only using P_ lock */
|
||||
|
||||
/*
|
||||
* Additional lock bits for cluster communication
|
||||
@@ -91,6 +101,7 @@ int check_lvm1_vg_inactive(struct cmd_context *cmd, const char *vgname);
|
||||
#define LCK_VG_READ (LCK_VG | LCK_READ | LCK_HOLD)
|
||||
#define LCK_VG_WRITE (LCK_VG | LCK_WRITE | LCK_HOLD)
|
||||
#define LCK_VG_UNLOCK (LCK_VG | LCK_UNLOCK)
|
||||
#define LCK_VG_DROP_CACHE (LCK_VG | LCK_WRITE | LCK_CACHE)
|
||||
|
||||
#define LCK_LV_EXCLUSIVE (LCK_LV | LCK_EXCL | LCK_NONBLOCK)
|
||||
#define LCK_LV_SUSPEND (LCK_LV | LCK_WRITE | LCK_NONBLOCK)
|
||||
@@ -116,6 +127,8 @@ int check_lvm1_vg_inactive(struct cmd_context *cmd, const char *vgname);
|
||||
lock_lv_vol(cmd, lv, LCK_LV_ACTIVATE | LCK_HOLD | LCK_LOCAL)
|
||||
#define deactivate_lv_local(cmd, lv) \
|
||||
lock_lv_vol(cmd, lv, LCK_LV_DEACTIVATE | LCK_LOCAL)
|
||||
#define drop_cached_metadata(vg) \
|
||||
lock_vol((vg)->cmd, (vg)->name, LCK_VG_DROP_CACHE)
|
||||
|
||||
/* Process list of LVs */
|
||||
int suspend_lvs(struct cmd_context *cmd, struct list *lvs);
|
||||
|
||||
@@ -51,6 +51,7 @@ static int _already_logging = 0;
|
||||
static int _mirror_in_sync = 0;
|
||||
static int _dmeventd_monitor = DEFAULT_DMEVENTD_MONITOR;
|
||||
static int _ignore_suspended_devices = 0;
|
||||
static int _error_message_produced = 0;
|
||||
|
||||
static lvm2_log_fn_t _lvm2_log_fn = NULL;
|
||||
|
||||
@@ -238,6 +239,16 @@ void init_indent(int indent)
|
||||
_indent = indent;
|
||||
}
|
||||
|
||||
void init_error_message_produced(int value)
|
||||
{
|
||||
_error_message_produced = value;
|
||||
}
|
||||
|
||||
int error_message_produced(void)
|
||||
{
|
||||
return _error_message_produced;
|
||||
}
|
||||
|
||||
int test_mode()
|
||||
{
|
||||
return _test;
|
||||
@@ -322,6 +333,9 @@ void print_log(int level, const char *file, int line, const char *format, ...)
|
||||
if (_log_suppress == 2)
|
||||
return;
|
||||
|
||||
if (level <= _LOG_ERR)
|
||||
_error_message_produced = 1;
|
||||
|
||||
trformat = _(format);
|
||||
|
||||
if (_lvm2_log_fn) {
|
||||
|
||||
@@ -79,6 +79,7 @@ void init_security_level(int level);
|
||||
void init_mirror_in_sync(int in_sync);
|
||||
void init_dmeventd_monitor(int reg);
|
||||
void init_ignore_suspended_devices(int ignore);
|
||||
void init_error_message_produced(int error_message_produced);
|
||||
|
||||
void set_cmd_name(const char *cmd_name);
|
||||
|
||||
@@ -94,6 +95,7 @@ int lockingfailed(void);
|
||||
int security_level(void);
|
||||
int mirror_in_sync(void);
|
||||
int ignore_suspended_devices(void);
|
||||
int error_message_produced(void);
|
||||
|
||||
#define DMEVENTD_MONITOR_IGNORE -1
|
||||
int dmeventd_monitor_mode(void);
|
||||
|
||||
@@ -439,7 +439,8 @@ static int _lv_reduce(struct logical_volume *lv, uint32_t extents, int delete)
|
||||
|
||||
list_del(&lvl->list);
|
||||
|
||||
lv->vg->lv_count--;
|
||||
if (!(lv->status & SNAPSHOT))
|
||||
lv->vg->lv_count--;
|
||||
} else if (lv->vg->fid->fmt->ops->lv_setup &&
|
||||
!lv->vg->fid->fmt->ops->lv_setup(lv->vg->fid, lv))
|
||||
return_0;
|
||||
@@ -2047,6 +2048,27 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* remove LVs with its dependencies - LV leaf nodes should be removed first
|
||||
*/
|
||||
int lv_remove_with_dependencies(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
const force_t force)
|
||||
{
|
||||
struct list *snh, *snht;
|
||||
|
||||
if (lv_is_origin(lv)) {
|
||||
/* remove snapshot LVs first */
|
||||
list_iterate_safe(snh, snht, &lv->snapshot_segs) {
|
||||
if (!lv_remove_with_dependencies(cmd, list_struct_base(snh, struct lv_segment,
|
||||
origin_list)->cow,
|
||||
force))
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return lv_remove_single(cmd, lv, force);
|
||||
}
|
||||
|
||||
/*
|
||||
* insert_layer_for_segments_on_pv() inserts a layer segment for a segment area.
|
||||
* However, layer modification could split the underlying layer segment.
|
||||
|
||||
@@ -202,7 +202,23 @@ struct volume_group {
|
||||
uint32_t pv_count;
|
||||
struct list pvs;
|
||||
|
||||
/* logical volumes */
|
||||
/*
|
||||
* logical volumes
|
||||
* The following relationship should always hold:
|
||||
* list_size(lvs) = lv_count + 2 * snapshot_count
|
||||
*
|
||||
* Snapshots consist of 2 instances of "struct logical_volume":
|
||||
* - cow (lv_name is visible to the user)
|
||||
* - snapshot (lv_name is 'snapshotN')
|
||||
* Neither of these instances is reflected in lv_count, but we
|
||||
* multiply the snapshot_count by 2.
|
||||
*
|
||||
* Mirrors consist of multiple instances of "struct logical_volume":
|
||||
* - one for the mirror log
|
||||
* - one for each mirror leg
|
||||
* - one for the user-visible mirror LV
|
||||
* all of the instances are reflected in lv_count.
|
||||
*/
|
||||
uint32_t lv_count;
|
||||
uint32_t snapshot_count;
|
||||
struct list lvs;
|
||||
@@ -331,7 +347,7 @@ vg_t *vg_lock_and_read(struct cmd_context *cmd, const char *vg_name,
|
||||
|
||||
/* pe_start and pe_end relate to any existing data so that new metadata
|
||||
* areas can avoid overlap */
|
||||
pv_t *pv_create(const struct format_type *fmt,
|
||||
pv_t *pv_create(const struct cmd_context *cmd,
|
||||
struct device *dev,
|
||||
struct id *id,
|
||||
uint64_t size,
|
||||
@@ -400,6 +416,9 @@ int lv_remove(struct logical_volume *lv);
|
||||
int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
force_t force);
|
||||
|
||||
int lv_remove_with_dependencies(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
force_t force);
|
||||
|
||||
int lv_rename(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
const char *new_name);
|
||||
|
||||
@@ -513,6 +532,7 @@ int add_mirror_log(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
int reconfigure_mirror_images(struct lv_segment *mirrored_seg, uint32_t num_mirrors,
|
||||
struct list *removable_pvs, unsigned remove_log);
|
||||
int collapse_mirrored_lv(struct logical_volume *lv);
|
||||
int shift_mirror_images(struct lv_segment *mirrored_seg, unsigned mimage);
|
||||
|
||||
struct logical_volume *find_pvmove_lv(struct volume_group *vg,
|
||||
struct device *dev, uint32_t lv_type);
|
||||
|
||||
@@ -296,11 +296,14 @@ static int remove_lvs_in_vg(struct cmd_context *cmd,
|
||||
struct volume_group *vg,
|
||||
force_t force)
|
||||
{
|
||||
struct list *lst;
|
||||
struct lv_list *lvl;
|
||||
|
||||
list_iterate_items(lvl, &vg->lvs)
|
||||
if (!lv_remove_single(cmd, lvl->lv, force))
|
||||
return 0;
|
||||
while ((lst = list_first(&vg->lvs))) {
|
||||
lvl = list_item(lst, struct lv_list);
|
||||
if (!lv_remove_with_dependencies(cmd, lvl->lv, force))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -716,7 +719,7 @@ int vg_split_mdas(struct cmd_context *cmd __attribute((unused)),
|
||||
if (is_orphan_vg(vg_to->name))
|
||||
list_del(&mda->list);
|
||||
else
|
||||
list_move(&mda->list, mdas_to);
|
||||
list_move(mdas_to, &mda->list);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -747,7 +750,7 @@ int vg_split_mdas(struct cmd_context *cmd __attribute((unused)),
|
||||
* Note:
|
||||
* FIXME - liblvm todo - tidy up arguments for external use (fmt, mdas, etc)
|
||||
*/
|
||||
pv_t *pv_create(const struct format_type *fmt,
|
||||
pv_t *pv_create(const struct cmd_context *cmd,
|
||||
struct device *dev,
|
||||
struct id *id, uint64_t size,
|
||||
uint64_t pe_start,
|
||||
@@ -756,7 +759,7 @@ pv_t *pv_create(const struct format_type *fmt,
|
||||
int pvmetadatacopies,
|
||||
uint64_t pvmetadatasize, struct list *mdas)
|
||||
{
|
||||
return _pv_create(fmt, dev, id, size, pe_start,
|
||||
return _pv_create(cmd->fmt, dev, id, size, pe_start,
|
||||
existing_extent_count,
|
||||
existing_extent_size,
|
||||
pvmetadatacopies,
|
||||
@@ -885,6 +888,7 @@ struct pv_list *find_pv_in_pv_list(const struct list *pl,
|
||||
list_iterate_items(pvl, pl)
|
||||
if (pvl->pv == pv)
|
||||
return pvl;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -957,6 +961,7 @@ struct lv_list *find_lv_in_lv_list(const struct list *ll,
|
||||
list_iterate_items(lvl, ll)
|
||||
if (lvl->lv == lv)
|
||||
return lvl;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1175,6 +1180,7 @@ int vg_validate(struct volume_group *vg)
|
||||
struct lv_list *lvl, *lvl2;
|
||||
char uuid[64] __attribute((aligned(8)));
|
||||
int r = 1;
|
||||
uint32_t lv_count;
|
||||
|
||||
/* FIXME Also check there's no data/metadata overlap */
|
||||
|
||||
@@ -1208,6 +1214,15 @@ int vg_validate(struct volume_group *vg)
|
||||
r = 0;
|
||||
}
|
||||
|
||||
if ((lv_count = (uint32_t) list_size(&vg->lvs)) !=
|
||||
vg->lv_count + 2 * vg->snapshot_count) {
|
||||
log_error("Internal error: #internal LVs (%u) != #LVs (%"
|
||||
PRIu32 ") + 2 * #snapshots (%" PRIu32 ") in VG %s",
|
||||
list_size(&vg->lvs), vg->lv_count,
|
||||
vg->snapshot_count, vg->name);
|
||||
r = 0;
|
||||
}
|
||||
|
||||
list_iterate_items(lvl, &vg->lvs) {
|
||||
list_iterate_items(lvl2, &vg->lvs) {
|
||||
if (lvl == lvl2)
|
||||
@@ -1240,6 +1255,13 @@ int vg_validate(struct volume_group *vg)
|
||||
}
|
||||
}
|
||||
|
||||
if (!(vg->fid->fmt->features & FMT_UNLIMITED_VOLS) &&
|
||||
(!vg->max_lv || !vg->max_pv)) {
|
||||
log_error("Internal error: Volume group %s has limited PV/LV count"
|
||||
" but limit is not set.", vg->name);
|
||||
r = 0;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -1266,6 +1288,11 @@ int vg_write(struct volume_group *vg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!drop_cached_metadata(vg)) {
|
||||
log_error("Unable to drop cached metadata for VG %s.", vg->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
vg->seqno++;
|
||||
|
||||
/* Write to each copy of the metadata area */
|
||||
@@ -1346,6 +1373,11 @@ int vg_commit(struct volume_group *vg)
|
||||
}
|
||||
}
|
||||
|
||||
/* If update failed, remove any cached precommitted metadata. */
|
||||
if (!cache_updated && !drop_cached_metadata(vg))
|
||||
log_error("Attempt to drop cached metadata failed "
|
||||
"after commit for VG %s.", vg->name);
|
||||
|
||||
/* If at least one mda commit succeeded, it was committed */
|
||||
return cache_updated;
|
||||
}
|
||||
@@ -1362,6 +1394,10 @@ int vg_revert(struct volume_group *vg)
|
||||
}
|
||||
}
|
||||
|
||||
if (!drop_cached_metadata(vg))
|
||||
log_error("Attempt to drop cached metadata failed "
|
||||
"after reverted update for VG %s.", vg->name);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1450,6 +1486,8 @@ static int _update_pv_list(struct list *all_pvs, struct volume_group *vg)
|
||||
* and call vg_read again).
|
||||
*
|
||||
* If precommitted is set, use precommitted metadata if present.
|
||||
*
|
||||
* Either of vgname or vgid may be NULL.
|
||||
*/
|
||||
static struct volume_group *_vg_read(struct cmd_context *cmd,
|
||||
const char *vgname,
|
||||
@@ -1460,8 +1498,10 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
|
||||
const struct format_type *fmt;
|
||||
struct volume_group *vg, *correct_vg = NULL;
|
||||
struct metadata_area *mda;
|
||||
struct lvmcache_info *info;
|
||||
int inconsistent = 0;
|
||||
int inconsistent_vgid = 0;
|
||||
int inconsistent_pvs = 0;
|
||||
unsigned use_precommitted = precommitted;
|
||||
struct list *pvids;
|
||||
struct pv_list *pvl, *pvl2;
|
||||
@@ -1496,19 +1536,23 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
|
||||
}
|
||||
}
|
||||
|
||||
/* Now determine the correct vgname if none was supplied */
|
||||
if (!vgname && !(vgname = vgname_from_vgid(cmd->mem, vgid)))
|
||||
return_NULL;
|
||||
|
||||
if (use_precommitted && !(fmt->features & FMT_PRECOMMIT))
|
||||
use_precommitted = 0;
|
||||
|
||||
/* Store pvids for later so we can check if any are missing */
|
||||
if (!(pvids = lvmcache_get_pvids(cmd, vgname, vgid)))
|
||||
return_NULL;
|
||||
|
||||
/* create format instance with appropriate metadata area */
|
||||
if (!(fid = fmt->ops->create_instance(fmt, vgname, vgid, NULL))) {
|
||||
log_error("Failed to create format instance");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Store pvids for later so we can check if any are missing */
|
||||
if (!(pvids = lvmcache_get_pvids(cmd, vgname, vgid)))
|
||||
return_NULL;
|
||||
|
||||
/* Ensure contents of all metadata areas match - else do recovery */
|
||||
list_iterate_items(mda, &fid->metadata_areas) {
|
||||
if ((use_precommitted &&
|
||||
@@ -1532,6 +1576,44 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
|
||||
|
||||
/* Ensure every PV in the VG was in the cache */
|
||||
if (correct_vg) {
|
||||
/*
|
||||
* If the VG has PVs without mdas, they may still be
|
||||
* orphans in the cache: update the cache state here.
|
||||
*/
|
||||
if (!inconsistent &&
|
||||
list_size(&correct_vg->pvs) > list_size(pvids)) {
|
||||
list_iterate_items(pvl, &correct_vg->pvs) {
|
||||
if (!pvl->pv->dev) {
|
||||
inconsistent_pvs = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (str_list_match_item(pvids, pvl->pv->dev->pvid))
|
||||
continue;
|
||||
|
||||
/*
|
||||
* PV not marked as belonging to this VG in cache.
|
||||
* Check it's an orphan without metadata area.
|
||||
*/
|
||||
if (!(info = info_from_pvid(pvl->pv->dev->pvid, 1)) ||
|
||||
!info->vginfo || !is_orphan_vg(info->vginfo->vgname) ||
|
||||
list_size(&info->mdas)) {
|
||||
inconsistent_pvs = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* If the check passed, let's update VG and recalculate pvids */
|
||||
if (!inconsistent_pvs) {
|
||||
log_debug("Updating cache for PVs without mdas "
|
||||
"in VG %s.", vgname);
|
||||
lvmcache_update_vg(correct_vg, use_precommitted);
|
||||
|
||||
if (!(pvids = lvmcache_get_pvids(cmd, vgname, vgid)))
|
||||
return_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (list_size(&correct_vg->pvs) != list_size(pvids)) {
|
||||
log_debug("Cached VG %s had incorrect PV list",
|
||||
vgname);
|
||||
@@ -1726,12 +1808,12 @@ static struct volume_group *_vg_read_by_vgid(struct cmd_context *cmd,
|
||||
/* Is corresponding vgname already cached? */
|
||||
if ((vginfo = vginfo_from_vgid(vgid)) &&
|
||||
vginfo->vgname && !is_orphan_vg(vginfo->vgname)) {
|
||||
if ((vg = _vg_read(cmd, vginfo->vgname, vgid,
|
||||
if ((vg = _vg_read(cmd, NULL, vgid,
|
||||
&consistent, precommitted)) &&
|
||||
!strncmp((char *)vg->id.uuid, vgid, ID_LEN)) {
|
||||
if (!consistent) {
|
||||
log_error("Volume group %s metadata is "
|
||||
"inconsistent", vginfo->vgname);
|
||||
"inconsistent", vg->name);
|
||||
if (!partial_mode())
|
||||
return NULL;
|
||||
}
|
||||
@@ -1888,7 +1970,7 @@ struct list *get_vgids(struct cmd_context *cmd, int full_scan)
|
||||
static int _get_pvs(struct cmd_context *cmd, struct list **pvslist)
|
||||
{
|
||||
struct str_list *strl;
|
||||
struct list *results;
|
||||
struct list * uninitialized_var(results);
|
||||
const char *vgname, *vgid;
|
||||
struct list *pvh, *tmp;
|
||||
struct list *vgids;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
@@ -135,6 +135,53 @@ uint32_t adjusted_mirror_region_size(uint32_t extent_size, uint32_t extents,
|
||||
return region_size;
|
||||
}
|
||||
|
||||
/*
|
||||
* shift_mirror_images
|
||||
* @mirrored_seg
|
||||
* @mimage: The position (index) of the image to move to the end
|
||||
*
|
||||
* When dealing with removal of legs, we often move a 'removable leg'
|
||||
* to the back of the 'areas' array. It is critically important not
|
||||
* to simply swap it for the last area in the array. This would have
|
||||
* the affect of reordering the remaining legs - altering position of
|
||||
* the primary. So, we must shuffle all of the areas in the array
|
||||
* to maintain their relative position before moving the 'removable
|
||||
* leg' to the end.
|
||||
*
|
||||
* Short illustration of the problem:
|
||||
* - Mirror consists of legs A, B, C and we want to remove A
|
||||
* - We swap A and C and then remove A, leaving C, B
|
||||
* This scenario is problematic in failure cases where A dies, because
|
||||
* B becomes the primary. If the above happens, we effectively throw
|
||||
* away any changes made between the time of failure and the time of
|
||||
* restructuring the mirror.
|
||||
*
|
||||
* So, any time we want to move areas to the end to be removed, use
|
||||
* this function.
|
||||
*/
|
||||
int shift_mirror_images(struct lv_segment *mirrored_seg, unsigned mimage)
|
||||
{
|
||||
int i;
|
||||
struct lv_segment_area area;
|
||||
|
||||
if (mimage >= mirrored_seg->area_count) {
|
||||
log_error("Invalid index (%u) of mirror image supplied "
|
||||
"to shift_mirror_images()", mimage);
|
||||
return 0;
|
||||
}
|
||||
|
||||
area = mirrored_seg->areas[mimage];
|
||||
|
||||
/* Shift remaining images down to fill the hole */
|
||||
for (i = mimage + 1; i < mirrored_seg->area_count; i++)
|
||||
mirrored_seg->areas[i-1] = mirrored_seg->areas[i];
|
||||
|
||||
/* Place this one at the end */
|
||||
mirrored_seg->areas[i-1] = area;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function writes a new header to the mirror log header to the lv
|
||||
*
|
||||
@@ -469,13 +516,12 @@ static int _remove_mirror_images(struct logical_volume *lv,
|
||||
for (s = 0; s < mirrored_seg->area_count &&
|
||||
old_area_count - new_area_count < num_removed; s++) {
|
||||
sub_lv = seg_lv(mirrored_seg, s);
|
||||
|
||||
if (!is_temporary_mirror_layer(sub_lv) &&
|
||||
_is_mirror_image_removable(sub_lv, removable_pvs)) {
|
||||
/* Swap segment to end */
|
||||
if (!shift_mirror_images(mirrored_seg, s))
|
||||
return_0;
|
||||
new_area_count--;
|
||||
area = mirrored_seg->areas[new_area_count];
|
||||
mirrored_seg->areas[new_area_count] = mirrored_seg->areas[s];
|
||||
mirrored_seg->areas[s] = area;
|
||||
}
|
||||
}
|
||||
if (num_removed && old_area_count == new_area_count)
|
||||
@@ -552,6 +598,17 @@ static int _remove_mirror_images(struct logical_volume *lv,
|
||||
|
||||
log_very_verbose("Updating \"%s\" in kernel", mirrored_seg->lv->name);
|
||||
|
||||
/*
|
||||
* Avoid having same mirror target loaded twice simultaneouly by first
|
||||
* activating the removed LV which now contains an error segment.
|
||||
* As it's now detached from mirrored_seg->lv we must activate it
|
||||
* explicitly.
|
||||
*/
|
||||
if (lv1 && !activate_lv(lv1->vg->cmd, lv1)) {
|
||||
log_error("Problem reactivating removed %s", lv1->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!resume_lv(mirrored_seg->lv->vg->cmd, mirrored_seg->lv)) {
|
||||
log_error("Problem reactivating %s", mirrored_seg->lv->name);
|
||||
return 0;
|
||||
@@ -1140,6 +1197,8 @@ int remove_mirror_log(struct cmd_context *cmd,
|
||||
struct list *removable_pvs)
|
||||
{
|
||||
float sync_percent;
|
||||
struct lvinfo info;
|
||||
struct volume_group *vg = lv->vg;
|
||||
|
||||
/* Unimplemented features */
|
||||
if (list_size(&lv->segments) != 1) {
|
||||
@@ -1148,10 +1207,21 @@ int remove_mirror_log(struct cmd_context *cmd,
|
||||
}
|
||||
|
||||
/* Had disk log, switch to core. */
|
||||
if (!lv_mirror_percent(cmd, lv, 0, &sync_percent, NULL)) {
|
||||
log_error("Unable to determine mirror sync status.");
|
||||
if (lv_info(cmd, lv, &info, 0, 0) && info.exists) {
|
||||
if (!lv_mirror_percent(cmd, lv, 0, &sync_percent, NULL)) {
|
||||
log_error("Unable to determine mirror sync status.");
|
||||
return 0;
|
||||
}
|
||||
} else if (vg_is_clustered(vg)) {
|
||||
log_error("Unable to convert the log of inactive "
|
||||
"cluster mirror %s", lv->name);
|
||||
return 0;
|
||||
} else if (yes_no_prompt("Full resync required to convert "
|
||||
"inactive mirror %s to core log. "
|
||||
"Proceed? [y/n]: "))
|
||||
sync_percent = 0;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sync_percent >= 100.0)
|
||||
init_mirror_in_sync(1);
|
||||
@@ -1269,12 +1339,9 @@ int attach_mirror_log(struct lv_segment *seg, struct logical_volume *log_lv)
|
||||
return add_seg_to_segs_using_this_lv(log_lv, seg);
|
||||
}
|
||||
|
||||
int add_mirror_log(struct cmd_context *cmd,
|
||||
struct logical_volume *lv,
|
||||
uint32_t log_count,
|
||||
uint32_t region_size,
|
||||
struct list *allocatable_pvs,
|
||||
alloc_policy_t alloc)
|
||||
int add_mirror_log(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
uint32_t log_count, uint32_t region_size,
|
||||
struct list *allocatable_pvs, alloc_policy_t alloc)
|
||||
{
|
||||
struct alloc_handle *ah;
|
||||
const struct segment_type *segtype;
|
||||
@@ -1282,17 +1349,31 @@ int add_mirror_log(struct cmd_context *cmd,
|
||||
float sync_percent;
|
||||
int in_sync;
|
||||
struct logical_volume *log_lv;
|
||||
struct lvinfo info;
|
||||
|
||||
/* Unimplemented features */
|
||||
if (log_count > 1) {
|
||||
log_error("log_count > 1 is not supported");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (list_size(&lv->segments) != 1) {
|
||||
log_error("Multiple-segment mirror is not supported");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* We are unable to convert the log of inactive cluster mirrors
|
||||
* due to the inability to detect whether the mirror is active
|
||||
* on remote nodes (even though it is inactive on this node)
|
||||
*/
|
||||
if (vg_is_clustered(lv->vg) &&
|
||||
!(lv_info(cmd, lv, &info, 0, 0) && info.exists)) {
|
||||
log_error("Unable to convert the log of inactive "
|
||||
"cluster mirror %s", lv->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(parallel_areas = build_parallel_areas_from_lv(cmd, lv)))
|
||||
return_0;
|
||||
|
||||
@@ -1344,7 +1425,8 @@ int add_mirror_images(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
struct alloc_handle *ah;
|
||||
const struct segment_type *segtype;
|
||||
struct list *parallel_areas;
|
||||
struct logical_volume **img_lvs, *log_lv;
|
||||
struct logical_volume **img_lvs;
|
||||
struct logical_volume *log_lv = NULL;
|
||||
|
||||
if (stripes > 1) {
|
||||
log_error("stripes > 1 is not supported");
|
||||
@@ -1416,8 +1498,8 @@ int add_mirror_images(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
return 1;
|
||||
|
||||
out_remove_log:
|
||||
if (!lv_remove(log_lv) || !vg_write(log_lv->vg) ||
|
||||
(backup(log_lv->vg), !vg_commit(log_lv->vg)))
|
||||
if (log_lv && (!lv_remove(log_lv) || !vg_write(log_lv->vg) ||
|
||||
(backup(log_lv->vg), !vg_commit(log_lv->vg))))
|
||||
log_error("Manual intervention may be required to remove "
|
||||
"abandoned log LV before retrying.");
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ struct segtype_handler {
|
||||
struct cmd_context *cmd,
|
||||
struct lv_segment *seg, char *params,
|
||||
uint64_t *total_numerator,
|
||||
uint64_t *total_denominator, float *percent);
|
||||
uint64_t *total_denominator);
|
||||
int (*target_present) (const struct lv_segment *seg,
|
||||
unsigned *attributes);
|
||||
int (*modules_needed) (struct dm_pool *mem,
|
||||
@@ -95,6 +95,7 @@ struct segment_type *get_segtype_from_string(struct cmd_context *cmd,
|
||||
struct segment_type *init_striped_segtype(struct cmd_context *cmd);
|
||||
struct segment_type *init_zero_segtype(struct cmd_context *cmd);
|
||||
struct segment_type *init_error_segtype(struct cmd_context *cmd);
|
||||
struct segment_type *init_free_segtype(struct cmd_context *cmd);
|
||||
|
||||
#ifdef SNAPSHOT_INTERNAL
|
||||
struct segment_type *init_snapshot_segtype(struct cmd_context *cmd);
|
||||
|
||||
@@ -176,8 +176,7 @@ static struct mirror_state *_mirrored_init_target(struct dm_pool *mem,
|
||||
static int _mirrored_target_percent(void **target_state, struct dm_pool *mem,
|
||||
struct cmd_context *cmd, struct lv_segment *seg,
|
||||
char *params, uint64_t *total_numerator,
|
||||
uint64_t *total_denominator,
|
||||
float *percent __attribute((unused)))
|
||||
uint64_t *total_denominator)
|
||||
{
|
||||
struct mirror_state *mirr_state;
|
||||
uint64_t numerator, denominator;
|
||||
@@ -373,10 +372,10 @@ static int _mirrored_target_present(const struct lv_segment *seg __attribute((un
|
||||
|
||||
/*
|
||||
* Check only for modules if atttributes requested and no previous check.
|
||||
* FIXME: need better check
|
||||
* FIXME: Fails incorrectly if cmirror was built into kernel.
|
||||
*/
|
||||
if (attributes) {
|
||||
if (!_mirror_attributes && module_present("cmirror"))
|
||||
if (!_mirror_attributes && module_present("log-clustered"))
|
||||
_mirror_attributes |= MIRROR_LOG_CLUSTERED;
|
||||
*attributes = _mirror_attributes;
|
||||
}
|
||||
|
||||
@@ -36,8 +36,7 @@
|
||||
/* Define to 1 if you have the <ctype.h> header file. */
|
||||
#undef HAVE_CTYPE_H
|
||||
|
||||
/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
|
||||
*/
|
||||
/* Define to 1 if you have the <dirent.h> header file. */
|
||||
#undef HAVE_DIRENT_H
|
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
@@ -49,6 +48,9 @@
|
||||
/* Define to 1 if you have the `dup2' function. */
|
||||
#undef HAVE_DUP2
|
||||
|
||||
/* Define to 1 if you have the <errno.h> header file. */
|
||||
#undef HAVE_ERRNO_H
|
||||
|
||||
/* Define to 1 if you have the <fcntl.h> header file. */
|
||||
#undef HAVE_FCNTL_H
|
||||
|
||||
@@ -61,7 +63,7 @@
|
||||
/* Define to 1 if you have the `getmntent' function. */
|
||||
#undef HAVE_GETMNTENT
|
||||
|
||||
/* Define to 1 to if getopt_long is available. */
|
||||
/* Define to 1 if getopt_long is available. */
|
||||
#undef HAVE_GETOPTLONG
|
||||
|
||||
/* Define to 1 if you have the <getopt.h> header file. */
|
||||
@@ -171,6 +173,9 @@
|
||||
/* Define to 1 if you have the <selinux/selinux.h> header file. */
|
||||
#undef HAVE_SELINUX_SELINUX_H
|
||||
|
||||
/* Define to 1 if sepol_check_context is available. */
|
||||
#undef HAVE_SEPOL
|
||||
|
||||
/* Define to 1 if you have the `setlocale' function. */
|
||||
#undef HAVE_SETLOCALE
|
||||
|
||||
@@ -184,6 +189,9 @@
|
||||
zero-length file name argument. */
|
||||
#undef HAVE_STAT_EMPTY_STRING_BUG
|
||||
|
||||
/* Define to 1 if you have the <stdarg.h> header file. */
|
||||
#undef HAVE_STDARG_H
|
||||
|
||||
/* Define to 1 if you have the <stddef.h> header file. */
|
||||
#undef HAVE_STDDEF_H
|
||||
|
||||
@@ -270,6 +278,9 @@
|
||||
/* Define to 1 if you have the <sys/socket.h> header file. */
|
||||
#undef HAVE_SYS_SOCKET_H
|
||||
|
||||
/* Define to 1 if you have the <sys/statvfs.h> header file. */
|
||||
#undef HAVE_SYS_STATVFS_H
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#undef HAVE_SYS_STAT_H
|
||||
|
||||
@@ -291,6 +302,9 @@
|
||||
/* Define to 1 if you have the <sys/wait.h> header file. */
|
||||
#undef HAVE_SYS_WAIT_H
|
||||
|
||||
/* Define to 1 if you have the <termios.h> header file. */
|
||||
#undef HAVE_TERMIOS_H
|
||||
|
||||
/* Define to 1 if you have the <time.h> header file. */
|
||||
#undef HAVE_TIME_H
|
||||
|
||||
|
||||
@@ -21,7 +21,8 @@
|
||||
|
||||
static inline char *last_path_component(char const *name)
|
||||
{
|
||||
char const *slash = strrchr (name, '/');
|
||||
char const *slash = strrchr(name, '/');
|
||||
char const *res = slash ? slash + 1 : name;
|
||||
return (char *) res;
|
||||
|
||||
return (char *)res;
|
||||
}
|
||||
|
||||
@@ -25,4 +25,6 @@
|
||||
(void) (&_a == &_b); \
|
||||
_a > _b ? _a : _b; })
|
||||
|
||||
#define uninitialized_var(x) x = x
|
||||
|
||||
#endif
|
||||
|
||||
@@ -105,7 +105,7 @@ static void _lock_mem(void)
|
||||
log_sys_error("getpriority", "");
|
||||
else
|
||||
if (setpriority(PRIO_PROCESS, 0, _default_priority))
|
||||
log_error("setpriority %u failed: %s",
|
||||
log_error("setpriority %d failed: %s",
|
||||
_default_priority, strerror(errno));
|
||||
}
|
||||
|
||||
|
||||
@@ -303,6 +303,10 @@ static int _lvstatus_disp(struct dm_report *rh __attribute((unused)), struct dm_
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Blank if this is a "free space" LV. */
|
||||
if (!*lv->name)
|
||||
goto out;
|
||||
|
||||
if (lv->status & PVMOVE)
|
||||
repstr[0] = 'p';
|
||||
else if (lv->status & CONVERTING)
|
||||
@@ -332,8 +336,10 @@ static int _lvstatus_disp(struct dm_report *rh __attribute((unused)), struct dm_
|
||||
repstr[1] = '-';
|
||||
else if (lv->status & LVM_WRITE)
|
||||
repstr[1] = 'w';
|
||||
else
|
||||
else if (lv->status & LVM_READ)
|
||||
repstr[1] = 'r';
|
||||
else
|
||||
repstr[1] = '-';
|
||||
|
||||
repstr[2] = _alloc_policy_char(lv->alloc);
|
||||
|
||||
@@ -375,6 +381,7 @@ static int _lvstatus_disp(struct dm_report *rh __attribute((unused)), struct dm_
|
||||
repstr[5] = '-';
|
||||
}
|
||||
|
||||
out:
|
||||
dm_report_field_set_value(field, repstr, NULL);
|
||||
return 1;
|
||||
}
|
||||
@@ -386,7 +393,7 @@ static int _pvstatus_disp(struct dm_report *rh __attribute((unused)), struct dm_
|
||||
const uint32_t status = *(const uint32_t *) data;
|
||||
char *repstr;
|
||||
|
||||
if (!(repstr = dm_pool_zalloc(mem, 4))) {
|
||||
if (!(repstr = dm_pool_zalloc(mem, 3))) {
|
||||
log_error("dm_pool_alloc failed");
|
||||
return 0;
|
||||
}
|
||||
@@ -1077,9 +1084,11 @@ static struct dm_report_field_type _fields[] = {
|
||||
|
||||
void *report_init(struct cmd_context *cmd, const char *format, const char *keys,
|
||||
report_type_t *report_type, const char *separator,
|
||||
int aligned, int buffered, int headings)
|
||||
int aligned, int buffered, int headings, int field_prefixes,
|
||||
int quoted, int columns_as_rows)
|
||||
{
|
||||
uint32_t report_flags = 0;
|
||||
void *rh;
|
||||
|
||||
if (aligned)
|
||||
report_flags |= DM_REPORT_OUTPUT_ALIGNED;
|
||||
@@ -1090,8 +1099,22 @@ void *report_init(struct cmd_context *cmd, const char *format, const char *keys,
|
||||
if (headings)
|
||||
report_flags |= DM_REPORT_OUTPUT_HEADINGS;
|
||||
|
||||
return dm_report_init(report_type, _report_types, _fields, format,
|
||||
separator, report_flags, keys, cmd);
|
||||
if (field_prefixes)
|
||||
report_flags |= DM_REPORT_OUTPUT_FIELD_NAME_PREFIX;
|
||||
|
||||
if (!quoted)
|
||||
report_flags |= DM_REPORT_OUTPUT_FIELD_UNQUOTED;
|
||||
|
||||
if (columns_as_rows)
|
||||
report_flags |= DM_REPORT_OUTPUT_COLUMNS_AS_ROWS;
|
||||
|
||||
rh = dm_report_init(report_type, _report_types, _fields, format,
|
||||
separator, report_flags, keys, cmd);
|
||||
|
||||
if (field_prefixes)
|
||||
dm_report_set_output_field_name_prefix(rh, "lvm2_");
|
||||
|
||||
return rh;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -28,7 +28,8 @@ typedef int (*field_report_fn) (struct report_handle * dh, struct field * field,
|
||||
|
||||
void *report_init(struct cmd_context *cmd, const char *format, const char *keys,
|
||||
report_type_t *report_type, const char *separator,
|
||||
int aligned, int buffered, int headings);
|
||||
int aligned, int buffered, int headings, int field_prefixes,
|
||||
int quoted, int columns_as_rows);
|
||||
void report_free(void *handle);
|
||||
int report_object(void *handle, struct volume_group *vg,
|
||||
struct logical_volume *lv, struct physical_volume *pv,
|
||||
|
||||
@@ -95,20 +95,14 @@ static int _snap_target_percent(void **target_state __attribute((unused)),
|
||||
struct cmd_context *cmd __attribute((unused)),
|
||||
struct lv_segment *seg __attribute((unused)),
|
||||
char *params, uint64_t *total_numerator,
|
||||
uint64_t *total_denominator, float *percent)
|
||||
uint64_t *total_denominator)
|
||||
{
|
||||
float percent2;
|
||||
uint64_t numerator, denominator;
|
||||
|
||||
if (strchr(params, '/')) {
|
||||
if (sscanf(params, "%" PRIu64 "/%" PRIu64,
|
||||
&numerator, &denominator) == 2) {
|
||||
*total_numerator += numerator;
|
||||
*total_denominator += denominator;
|
||||
}
|
||||
} else if (sscanf(params, "%f", &percent2) == 1) {
|
||||
*percent += percent2;
|
||||
*percent /= 2;
|
||||
if (sscanf(params, "%" PRIu64 "/%" PRIu64,
|
||||
&numerator, &denominator) == 2) {
|
||||
*total_numerator += numerator;
|
||||
*total_denominator += denominator;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
@@ -19,8 +19,9 @@
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
|
||||
static char _c[] =
|
||||
static const char _c[] =
|
||||
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!#";
|
||||
|
||||
static int _built_inverse;
|
||||
@@ -67,11 +68,29 @@ int lvnum_from_lvid(union lvid *lvid)
|
||||
lv_num *= sizeof(_c) - 1;
|
||||
if ((c = strchr(_c, lvid->id[1].uuid[i])))
|
||||
lv_num += (int) (c - _c);
|
||||
if (lv_num < 0)
|
||||
lv_num = 0;
|
||||
}
|
||||
|
||||
return lv_num;
|
||||
}
|
||||
|
||||
int lvid_in_restricted_range(union lvid *lvid)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ID_LEN - 3; i++)
|
||||
if (lvid->id[1].uuid[i] != '0')
|
||||
return 0;
|
||||
|
||||
for (i = ID_LEN - 3; i < ID_LEN; i++)
|
||||
if (!isdigit(lvid->id[1].uuid[i]))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int id_create(struct id *id)
|
||||
{
|
||||
int randomfile;
|
||||
@@ -110,7 +129,7 @@ int id_create(struct id *id)
|
||||
*/
|
||||
static void _build_inverse(void)
|
||||
{
|
||||
char *ptr;
|
||||
const char *ptr;
|
||||
|
||||
if (_built_inverse)
|
||||
return;
|
||||
|
||||
@@ -34,6 +34,7 @@ union lvid {
|
||||
|
||||
int lvid_from_lvnum(union lvid *lvid, struct id *vgid, uint32_t lv_num);
|
||||
int lvnum_from_lvid(union lvid *lvid);
|
||||
int lvid_in_restricted_range(union lvid *lvid);
|
||||
|
||||
void uuid_from_num(char *uuid, uint32_t num);
|
||||
|
||||
|
||||
@@ -132,5 +132,6 @@ dm_report_field_int32
|
||||
dm_report_field_uint32
|
||||
dm_report_field_uint64
|
||||
dm_report_field_set_value
|
||||
dm_report_set_output_field_name_prefix
|
||||
dm_regex_create
|
||||
dm_regex_match
|
||||
|
||||
@@ -43,8 +43,8 @@ else
|
||||
endif
|
||||
VERSIONED_SHLIB = libdevmapper.$(LIB_SUFFIX).$(LIB_VERSION)
|
||||
|
||||
DEFS += -DDEVICE_UID=@DEVICE_UID@ -DDEVICE_GID=@DEVICE_GID@ \
|
||||
-DDEVICE_MODE=@DEVICE_MODE@
|
||||
DEFS += -DDM_DEVICE_UID=@DM_DEVICE_UID@ -DDM_DEVICE_GID=@DM_DEVICE_GID@ \
|
||||
-DDM_DEVICE_MODE=@DM_DEVICE_MODE@
|
||||
|
||||
include ../make.tmpl
|
||||
|
||||
|
||||
@@ -215,12 +215,14 @@ unsigned dm_hash_get_num_entries(struct dm_hash_table *t)
|
||||
|
||||
void dm_hash_iter(struct dm_hash_table *t, dm_hash_iterate_fn f)
|
||||
{
|
||||
struct dm_hash_node *c;
|
||||
struct dm_hash_node *c, *n;
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < t->num_slots; i++)
|
||||
for (c = t->slots[i]; c; c = c->next)
|
||||
for (c = t->slots[i]; c; c = n) {
|
||||
n = c->next;
|
||||
f(c->data);
|
||||
}
|
||||
}
|
||||
|
||||
void dm_hash_wipe(struct dm_hash_table *t)
|
||||
|
||||
@@ -65,6 +65,15 @@ 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?
|
||||
*/
|
||||
|
||||
@@ -55,14 +55,9 @@ void list_add_h(struct list *head, struct list *elem);
|
||||
void list_del(struct list *elem);
|
||||
|
||||
/*
|
||||
* Move an element from an existing list to list 'head'.
|
||||
* Insert the element before 'head'.
|
||||
* Remove an element from existing list and insert before 'head'.
|
||||
*/
|
||||
static inline void list_move(struct list *item, struct list *head)
|
||||
{
|
||||
list_del(item);
|
||||
list_add(head, item);
|
||||
}
|
||||
void list_move(struct list *head, struct list *elem);
|
||||
|
||||
/*
|
||||
* Is the list empty?
|
||||
|
||||
@@ -1501,6 +1501,11 @@ static int _create_and_load_v4(struct dm_task *dmt)
|
||||
return r;
|
||||
}
|
||||
|
||||
uint64_t dm_task_get_existing_table_size(struct dm_task *dmt)
|
||||
{
|
||||
return dmt->existing_table_size;
|
||||
}
|
||||
|
||||
static int _reload_with_suppression_v4(struct dm_task *dmt)
|
||||
{
|
||||
struct dm_task *task;
|
||||
@@ -1534,6 +1539,12 @@ static int _reload_with_suppression_v4(struct dm_task *dmt)
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Store existing table size */
|
||||
t2 = task->head;
|
||||
while (t2 && t2->next)
|
||||
t2 = t2->next;
|
||||
dmt->existing_table_size = t2 ? t2->start + t2->length : 0;
|
||||
|
||||
if ((task->dmi.v4->flags & DM_READONLY_FLAG) ? 1 : 0 != dmt->read_only)
|
||||
goto no_match;
|
||||
|
||||
@@ -1690,8 +1701,10 @@ repeat_ioctl:
|
||||
|
||||
switch (dmt->type) {
|
||||
case DM_DEVICE_CREATE:
|
||||
add_dev_node(dmt->dev_name, MAJOR(dmi->dev), MINOR(dmi->dev),
|
||||
dmt->uid, dmt->gid, dmt->mode);
|
||||
if (dmt->dev_name && *dmt->dev_name)
|
||||
add_dev_node(dmt->dev_name, MAJOR(dmi->dev),
|
||||
MINOR(dmi->dev), dmt->uid, dmt->gid,
|
||||
dmt->mode);
|
||||
break;
|
||||
|
||||
case DM_DEVICE_REMOVE:
|
||||
|
||||
@@ -58,6 +58,7 @@ struct dm_task {
|
||||
int no_open_count;
|
||||
int skip_lockfs;
|
||||
int suppress_identical_reload;
|
||||
uint64_t existing_table_size;
|
||||
|
||||
char *uuid;
|
||||
};
|
||||
@@ -69,5 +70,6 @@ struct cmd_data {
|
||||
};
|
||||
|
||||
int dm_check_version(void);
|
||||
uint64_t dm_task_get_existing_table_size(struct dm_task *dmt);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -181,8 +181,9 @@ int dm_task_add_target(struct dm_task *dmt,
|
||||
uint64_t size, const char *ttype, const char *params);
|
||||
|
||||
/*
|
||||
* Format major/minor numbers correctly for input to driver
|
||||
* Format major/minor numbers correctly for input to driver.
|
||||
*/
|
||||
#define DM_FORMAT_DEV_BUFSIZE 13 /* Minimum bufsize to handle worst case. */
|
||||
int dm_format_dev(char *buf, int bufsize, uint32_t dev_major, uint32_t dev_minor);
|
||||
|
||||
/* Use this to retrive target information returned from a STATUS call */
|
||||
@@ -500,7 +501,7 @@ void dm_pool_free(struct dm_pool *p, void *ptr);
|
||||
*
|
||||
* for (i = 0; i < 50; i++) {
|
||||
* snprintf(buffer, sizeof(buffer), "%d, ", i);
|
||||
* if (!dm_pool_grow_object(mem, buffer, strlen(buffer)))
|
||||
* if (!dm_pool_grow_object(mem, buffer, 0))
|
||||
* goto bad;
|
||||
* }
|
||||
*
|
||||
@@ -524,6 +525,7 @@ void dm_pool_free(struct dm_pool *p, void *ptr);
|
||||
* dm_pool_grow_object. Finally get your object with
|
||||
* a call to dm_pool_end_object.
|
||||
*
|
||||
* Setting delta to 0 means it will use strlen(extra).
|
||||
*/
|
||||
int dm_pool_begin_object(struct dm_pool *p, size_t hint);
|
||||
int dm_pool_grow_object(struct dm_pool *p, const void *extra, size_t delta);
|
||||
@@ -734,10 +736,13 @@ struct dm_report_field_type {
|
||||
/*
|
||||
* dm_report_init output_flags
|
||||
*/
|
||||
#define DM_REPORT_OUTPUT_MASK 0x000000FF
|
||||
#define DM_REPORT_OUTPUT_ALIGNED 0x00000001
|
||||
#define DM_REPORT_OUTPUT_BUFFERED 0x00000002
|
||||
#define DM_REPORT_OUTPUT_HEADINGS 0x00000004
|
||||
#define DM_REPORT_OUTPUT_MASK 0x000000FF
|
||||
#define DM_REPORT_OUTPUT_ALIGNED 0x00000001
|
||||
#define DM_REPORT_OUTPUT_BUFFERED 0x00000002
|
||||
#define DM_REPORT_OUTPUT_HEADINGS 0x00000004
|
||||
#define DM_REPORT_OUTPUT_FIELD_NAME_PREFIX 0x00000008
|
||||
#define DM_REPORT_OUTPUT_FIELD_UNQUOTED 0x00000010
|
||||
#define DM_REPORT_OUTPUT_COLUMNS_AS_ROWS 0x00000020
|
||||
|
||||
struct dm_report *dm_report_init(uint32_t *report_types,
|
||||
const struct dm_report_object_type *types,
|
||||
@@ -751,6 +756,12 @@ int dm_report_object(struct dm_report *rh, void *object);
|
||||
int dm_report_output(struct dm_report *rh);
|
||||
void dm_report_free(struct dm_report *rh);
|
||||
|
||||
/*
|
||||
* Prefix added to each field name with DM_REPORT_OUTPUT_FIELD_NAME_PREFIX
|
||||
*/
|
||||
int dm_report_set_output_field_name_prefix(struct dm_report *rh,
|
||||
const char *report_prefix);
|
||||
|
||||
/*
|
||||
* Report functions are provided for simple data types.
|
||||
* They take care of allocating copies of the data.
|
||||
|
||||
@@ -120,9 +120,9 @@ struct dm_task *dm_task_create(int type)
|
||||
dmt->type = type;
|
||||
dmt->minor = -1;
|
||||
dmt->major = -1;
|
||||
dmt->uid = DEVICE_UID;
|
||||
dmt->gid = DEVICE_GID;
|
||||
dmt->mode = DEVICE_MODE;
|
||||
dmt->uid = DM_DEVICE_UID;
|
||||
dmt->gid = DM_DEVICE_GID;
|
||||
dmt->mode = DM_DEVICE_MODE;
|
||||
dmt->no_open_count = 0;
|
||||
dmt->read_ahead = DM_READ_AHEAD_AUTO;
|
||||
dmt->read_ahead_flags = 0;
|
||||
|
||||
@@ -99,6 +99,7 @@ struct load_properties {
|
||||
uint32_t read_ahead_flags;
|
||||
|
||||
unsigned segment_count;
|
||||
unsigned size_changed;
|
||||
struct list segs;
|
||||
|
||||
const char *new_name;
|
||||
@@ -603,6 +604,7 @@ struct dm_tree_node *dm_tree_add_new_dev(struct dm_tree *dtree,
|
||||
dnode->props.major = major;
|
||||
dnode->props.minor = minor;
|
||||
dnode->props.new_name = NULL;
|
||||
dnode->props.size_changed = 0;
|
||||
} else if (strcmp(name, dnode->name)) {
|
||||
/* Do we need to rename node? */
|
||||
if (!(dnode->props.new_name = dm_pool_strdup(dtree->mem, name))) {
|
||||
@@ -937,7 +939,7 @@ static int _suspend_node(const char *name, uint32_t major, uint32_t minor,
|
||||
log_verbose("Suspending %s (%" PRIu32 ":%" PRIu32 ")%s%s",
|
||||
name, major, minor,
|
||||
skip_lockfs ? "" : " with filesystem sync",
|
||||
no_flush ? "" : " without device flush");
|
||||
no_flush ? "" : " with device flush");
|
||||
|
||||
if (!(dmt = dm_task_create(DM_DEVICE_SUSPEND))) {
|
||||
log_error("Suspend dm_task creation failed for %s", name);
|
||||
@@ -1243,7 +1245,7 @@ static int _emit_areas_line(struct dm_task *dmt __attribute((unused)),
|
||||
size_t paramsize, int *pos)
|
||||
{
|
||||
struct seg_area *area;
|
||||
char devbuf[10];
|
||||
char devbuf[DM_FORMAT_DEV_BUFSIZE];
|
||||
int tw;
|
||||
const char *prefix = "";
|
||||
|
||||
@@ -1270,13 +1272,13 @@ static int _emit_segment_line(struct dm_task *dmt, struct load_segment *seg, uin
|
||||
int pos = 0;
|
||||
int tw;
|
||||
int r;
|
||||
char originbuf[10], cowbuf[10], logbuf[10];
|
||||
char originbuf[DM_FORMAT_DEV_BUFSIZE], cowbuf[DM_FORMAT_DEV_BUFSIZE];
|
||||
char logbuf[DM_FORMAT_DEV_BUFSIZE];
|
||||
const char *logtype;
|
||||
|
||||
switch(seg->type) {
|
||||
case SEG_ERROR:
|
||||
case SEG_ZERO:
|
||||
params[0] = '\0';
|
||||
case SEG_LINEAR:
|
||||
break;
|
||||
case SEG_MIRRORED:
|
||||
@@ -1434,6 +1436,7 @@ static int _emit_segment(struct dm_task *dmt, struct load_segment *seg,
|
||||
return 0;
|
||||
}
|
||||
|
||||
params[0] = '\0';
|
||||
ret = _emit_segment_line(dmt, seg, seg_start, params, paramsize);
|
||||
dm_free(params);
|
||||
|
||||
@@ -1493,6 +1496,13 @@ static int _load_node(struct dm_tree_node *dnode)
|
||||
if (r && !dnode->info.inactive_table)
|
||||
log_verbose("Suppressed %s identical table reload.",
|
||||
dnode->name);
|
||||
|
||||
if ((dnode->props.size_changed =
|
||||
(dm_task_get_existing_table_size(dmt) == seg_start) ? 0 : 1))
|
||||
log_debug("Table size changed from %" PRIu64 " to %"
|
||||
PRIu64 " for %s",
|
||||
dm_task_get_existing_table_size(dmt),
|
||||
seg_start, dnode->name);
|
||||
}
|
||||
|
||||
dnode->props.segment_count = 0;
|
||||
@@ -1504,8 +1514,8 @@ out:
|
||||
}
|
||||
|
||||
int dm_tree_preload_children(struct dm_tree_node *dnode,
|
||||
const char *uuid_prefix,
|
||||
size_t uuid_prefix_len)
|
||||
const char *uuid_prefix,
|
||||
size_t uuid_prefix_len)
|
||||
{
|
||||
void *handle = NULL;
|
||||
struct dm_tree_node *child;
|
||||
@@ -1540,8 +1550,8 @@ int dm_tree_preload_children(struct dm_tree_node *dnode,
|
||||
}
|
||||
}
|
||||
|
||||
/* Resume device immediately if it has parents */
|
||||
if (!dm_tree_node_num_children(child, 1))
|
||||
/* Resume device immediately if it has parents and its size changed */
|
||||
if (!dm_tree_node_num_children(child, 1) || !child->props.size_changed)
|
||||
continue;
|
||||
|
||||
if (!child->info.inactive_table && !child->info.suspended)
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
#include "list.h"
|
||||
#include "log.h"
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
/*
|
||||
* Internal flags
|
||||
*/
|
||||
@@ -27,6 +29,7 @@ struct dm_report {
|
||||
struct dm_pool *mem;
|
||||
|
||||
uint32_t report_types;
|
||||
const char *output_field_name_prefix;
|
||||
const char *field_prefix;
|
||||
uint32_t flags;
|
||||
const char *separator;
|
||||
@@ -264,8 +267,7 @@ static void _display_fields(struct dm_report *rh)
|
||||
log_warn("%s Fields", desc);
|
||||
log_warn("%*.*s", (int) strlen(desc) + 7,
|
||||
(int) strlen(desc) + 7,
|
||||
"------------------------------------------");
|
||||
|
||||
"-------------------------------------------------------------------------------");
|
||||
}
|
||||
|
||||
/* FIXME Add line-wrapping at terminal width (or 80 cols) */
|
||||
@@ -510,6 +512,14 @@ struct dm_report *dm_report_init(uint32_t *report_types,
|
||||
|
||||
rh->flags |= output_flags & DM_REPORT_OUTPUT_MASK;
|
||||
|
||||
/* With columns_as_rows we must buffer and not align. */
|
||||
if (output_flags & DM_REPORT_OUTPUT_COLUMNS_AS_ROWS) {
|
||||
if (!(output_flags & DM_REPORT_OUTPUT_BUFFERED))
|
||||
rh->flags |= DM_REPORT_OUTPUT_BUFFERED;
|
||||
if (output_flags & DM_REPORT_OUTPUT_ALIGNED)
|
||||
rh->flags &= ~DM_REPORT_OUTPUT_ALIGNED;
|
||||
}
|
||||
|
||||
if (output_flags & DM_REPORT_OUTPUT_BUFFERED)
|
||||
rh->flags |= RH_SORT_REQUIRED;
|
||||
|
||||
@@ -551,6 +561,31 @@ void dm_report_free(struct dm_report *rh)
|
||||
dm_free(rh);
|
||||
}
|
||||
|
||||
static char *_toupperstr(char *str)
|
||||
{
|
||||
char *u = str;
|
||||
|
||||
do
|
||||
*u = toupper(*u);
|
||||
while (*u++);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
int dm_report_set_output_field_name_prefix(struct dm_report *rh, const char *output_field_name_prefix)
|
||||
{
|
||||
char *prefix;
|
||||
|
||||
if (!(prefix = dm_pool_strdup(rh->mem, output_field_name_prefix))) {
|
||||
log_error("dm_report_set_output_field_name_prefix: dm_pool_strdup failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
rh->output_field_name_prefix = _toupperstr(prefix);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a row of data for an object
|
||||
*/
|
||||
@@ -668,15 +703,13 @@ static int _report_headings(struct dm_report *rh)
|
||||
log_error("dm_report: Failed to generate report headings for printing");
|
||||
goto bad;
|
||||
}
|
||||
} else if (!dm_pool_grow_object(rh->mem, heading,
|
||||
strlen(heading))) {
|
||||
} else if (!dm_pool_grow_object(rh->mem, heading, 0)) {
|
||||
log_error("dm_report: Failed to generate report headings for printing");
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (!list_end(&rh->field_props, &fp->list))
|
||||
if (!dm_pool_grow_object(rh->mem, rh->separator,
|
||||
strlen(rh->separator))) {
|
||||
if (!dm_pool_grow_object(rh->mem, rh->separator, 0)) {
|
||||
log_error("dm_report: Failed to generate report headings for printing");
|
||||
goto bad;
|
||||
}
|
||||
@@ -767,22 +800,152 @@ static int _sort_rows(struct dm_report *rh)
|
||||
/*
|
||||
* Produce report output
|
||||
*/
|
||||
int dm_report_output(struct dm_report *rh)
|
||||
static int _output_field(struct dm_report *rh, struct dm_report_field *field)
|
||||
{
|
||||
char *field_id;
|
||||
int32_t width;
|
||||
uint32_t align;
|
||||
const char *repstr;
|
||||
char buf[4096];
|
||||
|
||||
if (rh->flags & DM_REPORT_OUTPUT_FIELD_NAME_PREFIX) {
|
||||
if (!(field_id = strdup(rh->fields[field->props->field_num].id))) {
|
||||
log_error("dm_report: Failed to copy field name");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!dm_pool_grow_object(rh->mem, rh->output_field_name_prefix, 0)) {
|
||||
log_error("dm_report: Unable to extend output line");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!dm_pool_grow_object(rh->mem, _toupperstr(field_id), 0)) {
|
||||
log_error("dm_report: Unable to extend output line");
|
||||
return 0;
|
||||
}
|
||||
|
||||
free(field_id);
|
||||
|
||||
if (!dm_pool_grow_object(rh->mem, "=", 1)) {
|
||||
log_error("dm_report: Unable to extend output line");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(rh->flags & DM_REPORT_OUTPUT_FIELD_UNQUOTED) &&
|
||||
!dm_pool_grow_object(rh->mem, "\'", 1)) {
|
||||
log_error("dm_report: Unable to extend output line");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
repstr = field->report_string;
|
||||
width = field->props->width;
|
||||
if (!(rh->flags & DM_REPORT_OUTPUT_ALIGNED)) {
|
||||
if (!dm_pool_grow_object(rh->mem, repstr, 0)) {
|
||||
log_error("dm_report: Unable to extend output line");
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if (!(align = field->props->flags & DM_REPORT_FIELD_ALIGN_MASK))
|
||||
align = (field->props->flags & DM_REPORT_FIELD_TYPE_NUMBER) ?
|
||||
DM_REPORT_FIELD_ALIGN_RIGHT : DM_REPORT_FIELD_ALIGN_LEFT;
|
||||
if (align & DM_REPORT_FIELD_ALIGN_LEFT) {
|
||||
if (dm_snprintf(buf, sizeof(buf), "%-*.*s",
|
||||
width, width, repstr) < 0) {
|
||||
log_error("dm_report: left-aligned snprintf() failed");
|
||||
return 0;
|
||||
}
|
||||
if (!dm_pool_grow_object(rh->mem, buf, width)) {
|
||||
log_error("dm_report: Unable to extend output line");
|
||||
return 0;
|
||||
}
|
||||
} else if (align & DM_REPORT_FIELD_ALIGN_RIGHT) {
|
||||
if (dm_snprintf(buf, sizeof(buf), "%*.*s",
|
||||
width, width, repstr) < 0) {
|
||||
log_error("dm_report: right-aligned snprintf() failed");
|
||||
return 0;
|
||||
}
|
||||
if (!dm_pool_grow_object(rh->mem, buf, width)) {
|
||||
log_error("dm_report: Unable to extend output line");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((rh->flags & DM_REPORT_OUTPUT_FIELD_NAME_PREFIX) &&
|
||||
!(rh->flags & DM_REPORT_OUTPUT_FIELD_UNQUOTED))
|
||||
if (!dm_pool_grow_object(rh->mem, "\'", 1)) {
|
||||
log_error("dm_report: Unable to extend output line");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _output_as_rows(struct dm_report *rh)
|
||||
{
|
||||
struct field_properties *fp;
|
||||
struct dm_report_field *field;
|
||||
struct row *row;
|
||||
|
||||
if (!dm_pool_begin_object(rh->mem, 512)) {
|
||||
log_error("dm_report: Unable to allocate output line");
|
||||
return 0;
|
||||
}
|
||||
|
||||
list_iterate_items(fp, &rh->field_props) {
|
||||
if (fp->flags & FLD_HIDDEN) {
|
||||
list_iterate_items(row, &rh->rows) {
|
||||
field = list_item(list_first(&row->fields), struct dm_report_field);
|
||||
list_del(&field->list);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((rh->flags & DM_REPORT_OUTPUT_HEADINGS)) {
|
||||
if (!dm_pool_grow_object(rh->mem, rh->fields[fp->field_num].heading, 0)) {
|
||||
log_error("dm_report: Failed to extend row for field name");
|
||||
goto bad;
|
||||
}
|
||||
if (!dm_pool_grow_object(rh->mem, rh->separator, 0)) {
|
||||
log_error("dm_report: Failed to extend row with separator");
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
|
||||
list_iterate_items(row, &rh->rows) {
|
||||
if ((field = list_item(list_first(&row->fields), struct dm_report_field))) {
|
||||
if (!_output_field(rh, field))
|
||||
goto bad;
|
||||
list_del(&field->list);
|
||||
}
|
||||
|
||||
if (!list_end(&rh->rows, &row->list))
|
||||
if (!dm_pool_grow_object(rh->mem, rh->separator, 0)) {
|
||||
log_error("dm_report: Unable to extend output line");
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
|
||||
if (!dm_pool_grow_object(rh->mem, "\0", 1)) {
|
||||
log_error("dm_report: Failed to terminate row");
|
||||
goto bad;
|
||||
}
|
||||
log_print("%s", (char *) dm_pool_end_object(rh->mem));
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
bad:
|
||||
dm_pool_abandon_object(rh->mem);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _output_as_columns(struct dm_report *rh)
|
||||
{
|
||||
struct list *fh, *rowh, *ftmp, *rtmp;
|
||||
struct row *row = NULL;
|
||||
struct dm_report_field *field;
|
||||
const char *repstr;
|
||||
char buf[4096];
|
||||
int32_t width;
|
||||
uint32_t align;
|
||||
|
||||
if (list_empty(&rh->rows))
|
||||
return 1;
|
||||
|
||||
/* Sort rows */
|
||||
if ((rh->flags & RH_SORT_REQUIRED))
|
||||
_sort_rows(rh);
|
||||
|
||||
/* If headings not printed yet, calculate field widths and print them */
|
||||
if (!(rh->flags & RH_HEADINGS_PRINTED))
|
||||
@@ -800,47 +963,15 @@ int dm_report_output(struct dm_report *rh)
|
||||
if (field->props->flags & FLD_HIDDEN)
|
||||
continue;
|
||||
|
||||
repstr = field->report_string;
|
||||
width = field->props->width;
|
||||
if (!(rh->flags & DM_REPORT_OUTPUT_ALIGNED)) {
|
||||
if (!dm_pool_grow_object(rh->mem, repstr,
|
||||
strlen(repstr))) {
|
||||
log_error("dm_report: Unable to extend output line");
|
||||
goto bad;
|
||||
}
|
||||
} else {
|
||||
if (!(align = field->props->flags & DM_REPORT_FIELD_ALIGN_MASK))
|
||||
align = (field->props->flags & DM_REPORT_FIELD_TYPE_NUMBER) ?
|
||||
DM_REPORT_FIELD_ALIGN_RIGHT : DM_REPORT_FIELD_ALIGN_LEFT;
|
||||
if (align & DM_REPORT_FIELD_ALIGN_LEFT) {
|
||||
if (dm_snprintf(buf, sizeof(buf), "%-*.*s",
|
||||
width, width, repstr) < 0) {
|
||||
log_error("dm_report: left-aligned snprintf() failed");
|
||||
goto bad;
|
||||
}
|
||||
if (!dm_pool_grow_object(rh->mem, buf, width)) {
|
||||
log_error("dm_report: Unable to extend output line");
|
||||
goto bad;
|
||||
}
|
||||
} else if (align & DM_REPORT_FIELD_ALIGN_RIGHT) {
|
||||
if (dm_snprintf(buf, sizeof(buf), "%*.*s",
|
||||
width, width, repstr) < 0) {
|
||||
log_error("dm_report: right-aligned snprintf() failed");
|
||||
goto bad;
|
||||
}
|
||||
if (!dm_pool_grow_object(rh->mem, buf, width)) {
|
||||
log_error("dm_report: Unable to extend output line");
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!_output_field(rh, field))
|
||||
goto bad;
|
||||
|
||||
if (!list_end(&row->fields, fh))
|
||||
if (!dm_pool_grow_object(rh->mem, rh->separator,
|
||||
strlen(rh->separator))) {
|
||||
if (!dm_pool_grow_object(rh->mem, rh->separator, 0)) {
|
||||
log_error("dm_report: Unable to extend output line");
|
||||
goto bad;
|
||||
}
|
||||
|
||||
list_del(&field->list);
|
||||
}
|
||||
if (!dm_pool_grow_object(rh->mem, "\0", 1)) {
|
||||
@@ -860,3 +991,17 @@ int dm_report_output(struct dm_report *rh)
|
||||
dm_pool_abandon_object(rh->mem);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dm_report_output(struct dm_report *rh)
|
||||
{
|
||||
if (list_empty(&rh->rows))
|
||||
return 1;
|
||||
|
||||
if ((rh->flags & RH_SORT_REQUIRED))
|
||||
_sort_rows(rh);
|
||||
|
||||
if ((rh->flags & DM_REPORT_OUTPUT_COLUMNS_AS_ROWS))
|
||||
return _output_as_rows(rh);
|
||||
else
|
||||
return _output_as_columns(rh);
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ struct memblock {
|
||||
const char *file; /* File that allocated */
|
||||
int line; /* Line that allocated */
|
||||
void *magic; /* Address of this block */
|
||||
};
|
||||
} __attribute__((aligned(8)));
|
||||
|
||||
static struct {
|
||||
unsigned block_serialno;/* Non-decreasing serialno of block */
|
||||
|
||||
@@ -36,7 +36,7 @@ void bounds_check(void);
|
||||
|
||||
#else
|
||||
|
||||
# define dm_free(p) free(p)
|
||||
# define dm_free(p) do {if (p) free(p); } while (0)
|
||||
# define dbg_realloc(p, s) realloc(p, s)
|
||||
# define dump_memory()
|
||||
# define bounds_check()
|
||||
|
||||
@@ -216,10 +216,10 @@ int dm_pool_begin_object(struct dm_pool *p, size_t init_size)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int dm_pool_grow_object(struct dm_pool *p, const void *buffer, size_t delta)
|
||||
int dm_pool_grow_object(struct dm_pool *p, const void *extra, size_t delta)
|
||||
{
|
||||
struct block *new;
|
||||
size_t size = delta;
|
||||
size_t size = delta ? : strlen(extra);
|
||||
|
||||
assert(p->begun);
|
||||
|
||||
@@ -238,7 +238,7 @@ int dm_pool_grow_object(struct dm_pool *p, const void *buffer, size_t delta)
|
||||
}
|
||||
p->object = new;
|
||||
|
||||
memcpy(new->data + size - delta, buffer, delta);
|
||||
memcpy(new->data + size - delta, extra, delta);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -162,14 +162,17 @@ int dm_pool_begin_object(struct dm_pool *p, size_t hint)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int dm_pool_grow_object(struct dm_pool *p, const void *extra, size_t n)
|
||||
int dm_pool_grow_object(struct dm_pool *p, const void *extra, size_t delta)
|
||||
{
|
||||
struct chunk *c = p->chunk, *nc;
|
||||
|
||||
if (c->end - (c->begin + p->object_len) < n) {
|
||||
if (!delta)
|
||||
delta = strlen(extra);
|
||||
|
||||
if (c->end - (c->begin + p->object_len) < delta) {
|
||||
/* move into a new chunk */
|
||||
if (p->object_len + n > (p->chunk_size / 2))
|
||||
nc = _new_chunk(p, (p->object_len + n) * 2);
|
||||
if (p->object_len + delta > (p->chunk_size / 2))
|
||||
nc = _new_chunk(p, (p->object_len + delta) * 2);
|
||||
else
|
||||
nc = _new_chunk(p, p->chunk_size);
|
||||
|
||||
@@ -181,8 +184,8 @@ int dm_pool_grow_object(struct dm_pool *p, const void *extra, size_t n)
|
||||
c = p->chunk;
|
||||
}
|
||||
|
||||
memcpy(c->begin + p->object_len, extra, n);
|
||||
p->object_len += n;
|
||||
memcpy(c->begin + p->object_len, extra, delta);
|
||||
p->object_len += delta;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
15
make.tmpl.in
15
make.tmpl.in
@@ -1,7 +1,7 @@
|
||||
# @configure_input@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
@@ -21,7 +21,10 @@ CC = @CC@
|
||||
RANLIB = @RANLIB@
|
||||
SHELL = /bin/sh
|
||||
INSTALL = @INSTALL@
|
||||
MKDIR_P = @MKDIR_P@
|
||||
MSGFMT = @MSGFMT@
|
||||
LCOV = @LCOV@
|
||||
GENHTML = @GENHTML@
|
||||
LN_S = @LN_S@
|
||||
LIBS = @LIBS@
|
||||
DEFS += @DEFS@
|
||||
@@ -204,11 +207,15 @@ $(LIB_STATIC): $(OBJECTS)
|
||||
|
||||
clean: $(SUBDIRS.clean)
|
||||
$(RM) $(OBJECTS) $(TARGETS) $(CLEAN_TARGETS) $(SOURCES:%.c=%.d) \
|
||||
$(SOURCES:%.c=%.pot) $(LDDEPS)
|
||||
$(SOURCES:%.c=%.pot) $(SOURCES:%.c=%.gcno) \
|
||||
$(SOURCES:%.c=%.gcda) $(LDDEPS)
|
||||
|
||||
distclean: $(SUBDIRS.distclean)
|
||||
$(RM) $(OBJECTS) $(TARGETS) $(CLEAN_TARGETS) $(DISTCLEAN_TARGETS) \
|
||||
$(SOURCES:%.c=%.d) $(SOURCES:%.c=%.pot) $(LDDEPS) \
|
||||
$(RM) -rf $(DISTCLEAN_DIRS)
|
||||
$(RM) $(DISTCLEAN_TARGETS) \
|
||||
$(OBJECTS) $(TARGETS) $(CLEAN_TARGETS) $(SOURCES:%.c=%.d) \
|
||||
$(SOURCES:%.c=%.pot) $(SOURCES:%.c=%.gcno) \
|
||||
$(SOURCES:%.c=%.gcda) $(LDDEPS) \
|
||||
config.cache config.log config.status \
|
||||
Makefile make.tmpl core \
|
||||
version.h lvm2.po
|
||||
|
||||
@@ -30,7 +30,7 @@ Communicates with the kernel device-mapper driver via
|
||||
libdevmapper to activate (-ay) or deactivate (-an) the
|
||||
logical volumes.
|
||||
.IP
|
||||
If clustered locking is enabled, -ae will activate exclusively
|
||||
If clustered locking is enabled, -aey will activate exclusively
|
||||
on one node and -aly will activate only on the local node.
|
||||
To deactivate only on the local node use -aln.
|
||||
Logical volumes with single-host snapshots are always activated
|
||||
|
||||
@@ -11,7 +11,7 @@ lvcreate \- create a logical volume in an existing volume group
|
||||
{\-l/\-\-extents LogicalExtentsNumber[%{VG|PVS|FREE}] |
|
||||
\-L/\-\-size LogicalVolumeSize[kKmMgGtT]}
|
||||
[\-M/\-\-persistent y/n] [\-\-minor minor]
|
||||
[\-m/\-\-mirrors Mirrors [\-\-nosync] [\-\-mirrorlog {disk|log}] [\-\-corelog]
|
||||
[\-m/\-\-mirrors Mirrors [\-\-nosync] [\-\-mirrorlog {disk|core}] [\-\-corelog]
|
||||
[\-R/\-\-regionsize MirrorLogRegionSize]]
|
||||
[\-n/\-\-name LogicalVolumeName]
|
||||
[\-p/\-\-permission r/rw] [\-r/\-\-readahead ReadAheadSectors|auto|none]
|
||||
|
||||
@@ -84,7 +84,7 @@ Defaults to "/dev".
|
||||
\fBpreferred_names\fP \(em List of patterns compared in turn against
|
||||
all the pathnames referencing the same device in in the scanned directories.
|
||||
The pathname that matches the earliest pattern in the list is the
|
||||
one used in any output. As an example, if device mapper multipathing
|
||||
one used in any output. As an example, if device-mapper multipathing
|
||||
is used, the following will select multipath device names:
|
||||
.br
|
||||
\fBdevices { preferred_names = [ "^/dev/mapper/mpath" ] }\fP
|
||||
|
||||
@@ -126,5 +126,5 @@ SCSI disk for later use by LVM:
|
||||
.sp
|
||||
.SH SEE ALSO
|
||||
.BR lvm "(8), " vgcreate "(8), " vgextend "(8), " lvcreate "(8), "
|
||||
.BR cfdisk "(8), " fdisk "(8), " losetup "(8), " mdadd "(8), "
|
||||
.BR cfdisk "(8), " fdisk "(8), " losetup "(8), " mdadm "(8), "
|
||||
.BR vgcfgrestore "(8), " vgconvert "(8)"
|
||||
|
||||
@@ -43,7 +43,9 @@ RMDIR=rmdir
|
||||
BLOCKDEV=blockdev
|
||||
BLKID=blkid
|
||||
GREP=grep
|
||||
CUT=cut
|
||||
READLINK=readlink
|
||||
READLINK_E="-e"
|
||||
FSCK=fsck
|
||||
XFS_CHECK=xfs_check
|
||||
|
||||
@@ -154,9 +156,10 @@ decode_size() {
|
||||
# dereference device name if it is symbolic link
|
||||
detect_fs() {
|
||||
VOLUME=${1#/dev/}
|
||||
VOLUME=$($READLINK -e -n "/dev/$VOLUME") || error "Cannot get readlink $1"
|
||||
VOLUME=$($READLINK $READLINK_E -n "/dev/$VOLUME") || error "Cannot get readlink $1"
|
||||
# use /dev/null as cache file to be sure about the result
|
||||
FSTYPE=$($BLKID -c /dev/null -o value -s TYPE "$VOLUME") || error "Cannot get FSTYPE of \"$VOLUME\""
|
||||
# use 'cut' to be compatible with older version of blkid that does not provide option '-o value'
|
||||
FSTYPE=$($BLKID -c /dev/null -s TYPE "$VOLUME" | $CUT -d \" -f 2) || error "Cannot get FSTYPE of \"$VOLUME\""
|
||||
verbose "\"$FSTYPE\" filesystem found on \"$VOLUME\""
|
||||
}
|
||||
|
||||
@@ -171,7 +174,15 @@ detect_mounted() {
|
||||
|
||||
# get the full size of device in bytes
|
||||
detect_device_size() {
|
||||
DEVSIZE=$($BLOCKDEV --getsize64 "$VOLUME") || error "Cannot read device \"$VOLUME\""
|
||||
# check if blockdev supports getsize64
|
||||
$BLOCKDEV 2>&1 | $GREP getsize64 >/dev/null
|
||||
if test $? -eq 0; then
|
||||
DEVSIZE=$($BLOCKDEV --getsize64 "$VOLUME") || error "Cannot read size of device \"$VOLUME\""
|
||||
else
|
||||
DEVSIZE=$($BLOCKDEV --getsize "$VOLUME") || error "Cannot read size of device \"$VOLUME\""
|
||||
SSSIZE=$($BLOCKDEV --getss "$VOLUME") || error "Cannot block size read device \"$VOLUME\""
|
||||
DEVSIZE=$(($DEVSIZE * $SSSIZE))
|
||||
fi
|
||||
}
|
||||
|
||||
# round up $1 / $2
|
||||
@@ -349,9 +360,10 @@ test -n "$FSADM_RUNNING" && exit 0
|
||||
test -n "$TUNE_EXT" -a -n "$RESIZE_EXT" -a -n "$TUNE_REISER" -a -n "$RESIZE_REISER" \
|
||||
-a -n "$TUNE_XFS" -a -n "$RESIZE_XFS" -a -n "$MOUNT" -a -n "$UMOUNT" -a -n "$MKDIR" \
|
||||
-a -n "$RMDIR" -a -n "$BLOCKDEV" -a -n "$BLKID" -a -n "$GREP" -a -n "$READLINK" \
|
||||
-a -n "$FSCK" -a -n "$XFS_CHECK" -a -n "LVRESIZE" \
|
||||
-a -n "$FSCK" -a -n "$XFS_CHECK" -a -n "LVRESIZE" -a -n "$CUT" \
|
||||
|| error "Required command definitions in the script are missing!"
|
||||
$($READLINK -e -n / >/dev/null 2>&1) || error "$READLINK does not support options -e -n"
|
||||
|
||||
$($READLINK -e -n / >/dev/null 2>&1) || READLINK_E="-f"
|
||||
TEST64BIT=$(( 1000 * 1000000000000 ))
|
||||
test $TEST64BIT -eq 1000000000000000 || error "Shell does not handle 64bit arithmetic"
|
||||
$(echo Y | $GREP Y >/dev/null) || error "Grep does not work properly"
|
||||
|
||||
@@ -206,7 +206,7 @@ if (( $metadata )); then
|
||||
|
||||
pvs="$("$LVM" pvs --separator , --noheadings --units s --nosuffix -o \
|
||||
name,pe_start 2>> "$log" | $SED -e 's/^ *//')"
|
||||
for line in "$pvs"
|
||||
for line in $pvs
|
||||
do
|
||||
test -z "$line" && continue
|
||||
pv="$(echo $line | $CUT -d, -f1)"
|
||||
|
||||
@@ -48,7 +48,7 @@ Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
|
||||
$(T): init.sh
|
||||
@echo "*** $@ ***"; '$(SHELL_PATH_SQ)' \
|
||||
$(TESTS_ENVIRONMENT) $@ $(GIT_TEST_OPTS)
|
||||
$(TESTS_ENVIRONMENT) $@ $(LVM_TEST_OPTS)
|
||||
|
||||
.bin-dir-stamp: lvm-wrapper
|
||||
rm -rf bin
|
||||
@@ -63,7 +63,7 @@ lvm-wrapper: Makefile
|
||||
rm -f $@-t $@
|
||||
echo '#!/bin/sh' > $@-t
|
||||
test -n "@DMDIR@" \
|
||||
&& echo 'export LD_LIBRARY_PATH="@DMDIR@/lib"' >> $@-t
|
||||
&& echo 'export LD_LIBRARY_PATH="@DMDIR@/lib:@DMDIR@/dmeventd"' >> $@-t
|
||||
echo 'cmd=$$(echo ./$$0|sed "s,.*/,,")' >> $@-t
|
||||
echo 'test "$$cmd" = lvm &&' >> $@-t
|
||||
echo 'exec "$(abs_top_builddir)/tools/lvm" "$$@"' >> $@-t
|
||||
@@ -74,6 +74,8 @@ lvm-wrapper: Makefile
|
||||
clean:
|
||||
rm -rf init.sh lvm-wrapper bin .bin-dir-stamp
|
||||
|
||||
distclean: clean
|
||||
|
||||
all: $(T)
|
||||
.PHONY: $(T) clean
|
||||
.PHONY: $(T) clean distclean
|
||||
.NOTPARALLEL:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Put lvm-related utilities here.
|
||||
# This file is sourced from test-lib.sh.
|
||||
|
||||
# Copyright (C) 2007 Red Hat, Inc. All rights reserved.
|
||||
# Copyright (C) 2007, 2008 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
|
||||
@@ -52,38 +52,76 @@ loop_setup_()
|
||||
|
||||
compare_vg_field_()
|
||||
{
|
||||
local vg1=$1;
|
||||
local vg2=$2;
|
||||
local field=$3;
|
||||
local val1;
|
||||
local val2;
|
||||
|
||||
val1=$(vgs --noheadings -o $field $vg1)
|
||||
val2=$(vgs --noheadings -o $field $vg2)
|
||||
if test "$verbose" = "t"
|
||||
then
|
||||
echo "compare_vg_field_ VG1: `vgs --noheadings -o $3 $1` VG2: `vgs --noheadings -o $3 $2`"
|
||||
echo "compare_vg_field_ VG1: $val1 VG2: $val2"
|
||||
fi
|
||||
return $(test $(vgs --noheadings -o $3 $1) == $(vgs --noheadings -o $3 $2) )
|
||||
return $(test $val1 == $val2 )
|
||||
}
|
||||
|
||||
check_vg_field_()
|
||||
{
|
||||
local vg=$1;
|
||||
local field=$2;
|
||||
local expected=$3;
|
||||
local actual;
|
||||
|
||||
actual=$(vgs --noheadings -o $field $vg)
|
||||
if test "$verbose" = "t"
|
||||
then
|
||||
echo "check_vg_field_ VG: $1 actual: `vgs --noheadings -o $2 $1` expected $3"
|
||||
echo "check_vg_field_ VG=$vg, field=$field, actual=$actual, expected=$expected"
|
||||
fi
|
||||
return $(test $(vgs --noheadings -o $2 $1) == $3)
|
||||
return $(test $actual == $expected)
|
||||
}
|
||||
|
||||
check_pv_field_()
|
||||
{
|
||||
local pv=$1;
|
||||
local field=$2;
|
||||
local expected=$3;
|
||||
local actual;
|
||||
|
||||
actual=$(pvs --noheadings -o $field $pv)
|
||||
if test "$verbose" = "t"
|
||||
then
|
||||
echo "check_pv_field_ PV: $1 actual: `pvs --noheadings -o $2 $1` expected $3"
|
||||
echo "check_pv_field_ PV=$pv, field=$field, actual=$actual, expected=$expected"
|
||||
fi
|
||||
return $(test $(pvs --noheadings -o $2 $1) == $3)
|
||||
return $(test $actual == $expected)
|
||||
}
|
||||
|
||||
check_lv_field_()
|
||||
{
|
||||
local lv=$1;
|
||||
local field=$2;
|
||||
local expected=$3;
|
||||
local actual;
|
||||
|
||||
actual=$(lvs --noheadings -o $field $lv)
|
||||
if test "$verbose" = "t"
|
||||
then
|
||||
echo "check_lv_field_ LV: $1 actual: `lvs --noheadings -o $2 $1` expected $3"
|
||||
echo "check_lv_field_ LV=$lv, field=$field, actual=$actual, expected=$expected"
|
||||
fi
|
||||
return $(test $(lvs --noheadings -o $2 $1) == $3)
|
||||
return $(test $actual == $expected)
|
||||
}
|
||||
|
||||
vg_validate_pvlv_counts_()
|
||||
{
|
||||
local local_vg=$1
|
||||
local num_pvs=$2
|
||||
local num_lvs=$3
|
||||
local num_snaps=$4
|
||||
|
||||
check_vg_field_ $local_vg pv_count $num_pvs &&
|
||||
check_vg_field_ $local_vg lv_count $num_lvs &&
|
||||
check_vg_field_ $local_vg snap_count $num_snaps
|
||||
}
|
||||
|
||||
dmsetup_has_dm_devdir_support_()
|
||||
@@ -100,7 +138,7 @@ init_root_dir_()
|
||||
{
|
||||
test -n "$test_dir_rand_" \
|
||||
|| error "Internal error: called init_root_dir_ before" \
|
||||
" defining $test_dir_rand_"
|
||||
"defining \$test_dir_rand_"
|
||||
|
||||
# Define these two globals.
|
||||
G_root_=$test_dir_rand_/root
|
||||
@@ -110,10 +148,20 @@ init_root_dir_()
|
||||
export DM_DEV_DIR=$G_dev_
|
||||
|
||||
# Only the first caller does anything.
|
||||
mkdir -p $G_root_/etc $G_dev_ $G_dev_/mapper
|
||||
mkdir -p $G_root_/etc $G_dev_ $G_dev_/mapper $G_root_/lib
|
||||
for i in 0 1 2 3 4 5 6 7; do
|
||||
mknod $G_root_/dev/loop$i b 7 $i
|
||||
done
|
||||
for i in $abs_top_builddir/dmeventd/mirror/*.so $abs_top_builddir/dmeventd/snapshot/*.so
|
||||
do
|
||||
# NOTE: This check is necessary because the loop above will give us the value
|
||||
# "$abs_top_builddir/dmeventd/mirror/*.so" if no files ending in 'so' exist.
|
||||
# This is the best way I could quickly determine to skip over this bogus value.
|
||||
if [ -f $i ]; then
|
||||
echo Setting up symlink from $i to $G_root_/lib
|
||||
ln -s $i $G_root_/lib
|
||||
fi
|
||||
done
|
||||
cat > $G_root_/etc/lvm.conf <<-EOF
|
||||
devices {
|
||||
dir = "$G_dev_"
|
||||
@@ -122,6 +170,18 @@ init_root_dir_()
|
||||
cache_dir = "$G_root_/etc"
|
||||
sysfs_scan = 0
|
||||
}
|
||||
log {
|
||||
verbose = $verboselevel
|
||||
syslog = 0
|
||||
indent = 1
|
||||
}
|
||||
backup {
|
||||
backup = 0
|
||||
archive = 0
|
||||
}
|
||||
global {
|
||||
library_dir = "$G_root_/lib"
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
|
||||
@@ -32,4 +32,9 @@ test_expect_success \
|
||||
'ensure they are the same' \
|
||||
'diff -u actual expected'
|
||||
|
||||
# Need mdadm for some pvcreate tests
|
||||
test_expect_success \
|
||||
'verify mdadm is installed and in path (needed for pvcreate tests)' \
|
||||
'which mdadm'
|
||||
|
||||
test_done
|
||||
|
||||
99
test/t-covercmd.sh
Executable file
99
test/t-covercmd.sh
Executable file
@@ -0,0 +1,99 @@
|
||||
#!/bin/sh
|
||||
# Copyright (C) 2007 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.
|
||||
#
|
||||
# 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
|
||||
|
||||
#
|
||||
# tests basic functionality of read-ahead and ra regressions
|
||||
#
|
||||
|
||||
test_description='Test coverage'
|
||||
privileges_required_=1
|
||||
|
||||
. ./test-lib.sh
|
||||
|
||||
cleanup_()
|
||||
{
|
||||
vgremove -f "$vg" 2>/dev/null || true
|
||||
test -n "$d1" && losetup -d "$d1"
|
||||
test -n "$d2" && losetup -d "$d2"
|
||||
test -n "$d3" && losetup -d "$d3"
|
||||
test -n "$d4" && losetup -d "$d4"
|
||||
test -n "$d5" && losetup -d "$d5"
|
||||
rm -f "$f1" "$f2" "$f3" "$f4" "$f5"
|
||||
}
|
||||
|
||||
get_lvs_()
|
||||
{
|
||||
case $(lvs --units s --nosuffix --noheadings -o $1_read_ahead "$vg"/"$lv") in
|
||||
*$2) true ;;
|
||||
*) false ;;
|
||||
esac
|
||||
}
|
||||
|
||||
test_expect_success "set up temp files, loopback devices" \
|
||||
'f1=$(pwd)/1 && d1=$(loop_setup_ "$f1") &&
|
||||
f2=$(pwd)/2 && d2=$(loop_setup_ "$f2") &&
|
||||
f3=$(pwd)/3 && d3=$(loop_setup_ "$f3") &&
|
||||
f4=$(pwd)/4 && d4=$(loop_setup_ "$f4") &&
|
||||
f5=$(pwd)/5 && d5=$(loop_setup_ "$f5") &&
|
||||
vg=$(this_test_)-test-vg-$$ &&
|
||||
lv=$(this_test_)-test-lv-$$
|
||||
pvcreate "$d1" &&
|
||||
pvcreate --metadatacopies 0 "$d2" &&
|
||||
pvcreate --metadatacopies 0 "$d3" &&
|
||||
pvcreate "$d4" &&
|
||||
pvcreate --metadatacopies 0 "$d5" &&
|
||||
vgcreate -c n "$vg" "$d1" "$d2" "$d3" "$d4" "$d5" &&
|
||||
lvcreate -n "$lv" -l 1%FREE -i5 -I256 "$vg"'
|
||||
|
||||
test_expect_success "test *scan and *display tools" \
|
||||
'pvscan &&
|
||||
vgscan &&
|
||||
lvscan &&
|
||||
lvmdiskscan &&
|
||||
vgdisplay --units k &&
|
||||
lvdisplay --units g &&
|
||||
for i in b k m g t p e H B K M G T P E ; do \
|
||||
pvdisplay --units "$i" "$d1" || return $? ; done'
|
||||
|
||||
test_expect_success "test vgexport vgimport tools" \
|
||||
'vgchange -an "$vg" &&
|
||||
vgexport "$vg" &&
|
||||
vgimport "$vg" &&
|
||||
vgchange -ay "$vg"'
|
||||
|
||||
# "-persistent y --major 254 --minor 20"
|
||||
# "-persistent n"
|
||||
test_expect_success "test various lvm utils" \
|
||||
'for i in dumpconfig formats segtypes
|
||||
do lvm "$i" || return $? ; done &&
|
||||
for i in pr "p rw" an ay "-monitor y" "-monitor n" \
|
||||
-resync -refresh "-addtag MYTAG" "-deltag MYETAG"
|
||||
do lvchange -$i "$vg"/"$lv" || return $? ; done &&
|
||||
pvck "$d1" &&
|
||||
vgck "$vg" &&
|
||||
lvrename "$vg" "$lv" "$lv-rename" &&
|
||||
vgcfgbackup -f "$(pwd)/backup.$$" "$vg" &&
|
||||
vgchange -an "$vg" &&
|
||||
vgcfgrestore -f "$(pwd)/backup.$$" "$vg" &&
|
||||
vgremove -f "$vg" &&
|
||||
pvresize --setphysicalvolumesize 10M "$d1"'
|
||||
|
||||
test_expect_failure "test various errors and obsoleted tools" \
|
||||
'lvmchange ||
|
||||
lvrename "$vg" ||
|
||||
lvrename "$vg-xxx" ||
|
||||
lvrename "$vg" "$vg"/"$lv-rename" "$vg"/"$lv"'
|
||||
|
||||
test_done
|
||||
|
||||
# Local Variables:
|
||||
# indent-tabs-mode: nil
|
||||
# End:
|
||||
@@ -36,6 +36,15 @@ test_expect_success \
|
||||
|
||||
lv=lvcreate-usage-$$
|
||||
|
||||
test_expect_success \
|
||||
"lvcreate rejects repeated invocation (run 2 times)" '
|
||||
lvcreate -n $lv -l 4 $vg &&
|
||||
{ lvcreate -n $lv -l 4 $vg;
|
||||
status=$?; echo status=$status; test $status = 5 &&
|
||||
lvremove -ff $vg/$lv
|
||||
}
|
||||
'
|
||||
|
||||
test_expect_success \
|
||||
'lvcreate rejects a negative stripe_size' \
|
||||
'lvcreate -L 64M -n $lv -i2 --stripesize -4 $vg 2>err;
|
||||
|
||||
61
test/t-lvmcache-exercise.sh
Executable file
61
test/t-lvmcache-exercise.sh
Executable file
@@ -0,0 +1,61 @@
|
||||
#!/bin/sh
|
||||
# Copyright (C) 2007 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.
|
||||
#
|
||||
# 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
|
||||
|
||||
test_description='Test lvmcache operation'
|
||||
privileges_required_=1
|
||||
|
||||
. ./test-lib.sh
|
||||
|
||||
cleanup_()
|
||||
{
|
||||
test -n "$d1" && losetup -d "$d1"
|
||||
test -n "$d2" && losetup -d "$d2"
|
||||
test -n "$d3" && losetup -d "$d3"
|
||||
test -n "$d4" && losetup -d "$d4"
|
||||
test -n "$d5" && losetup -d "$d5"
|
||||
rm -f "$f1" "$f2" "$f3" "$f4" "$f5"
|
||||
}
|
||||
|
||||
# FIXME: paramaterize lvm1 vs lvm2 metadata; most of these tests should run
|
||||
# fine with lvm1 metadata as well; for now, just add disks 5 and 6 as lvm1
|
||||
# metadata
|
||||
test_expect_success \
|
||||
'set up temp files, loopback devices, PVs, vgnames' \
|
||||
'f1=$(pwd)/1 && d1=$(loop_setup_ "$f1") &&
|
||||
f2=$(pwd)/2 && d2=$(loop_setup_ "$f2") &&
|
||||
f3=$(pwd)/3 && d3=$(loop_setup_ "$f3") &&
|
||||
f4=$(pwd)/4 && d4=$(loop_setup_ "$f4") &&
|
||||
f5=$(pwd)/5 && d5=$(loop_setup_ "$f5") &&
|
||||
vg1=$(this_test_)-test-vg1-$$ &&
|
||||
vg2=$(this_test_)-test-vg2-$$ &&
|
||||
lv1=$(this_test_)-test-lv1-$$ &&
|
||||
lv2=$(this_test_)-test-lv2-$$ &&
|
||||
lv3=$(this_test_)-test-lv3-$$ &&
|
||||
pvcreate $d1 $d2 $d3 $d4 $d5'
|
||||
|
||||
#
|
||||
# Duplicate vg name should cause warnings (but not segfault!)
|
||||
#
|
||||
test_expect_success \
|
||||
"Duplicate vg name might cause warnings but should succeed" \
|
||||
'vgcreate $vg1 $d1 &&
|
||||
vgcreate $vg2 $d3 &&
|
||||
losetup -d $d1 &&
|
||||
vgcreate $vg1 $d2 &&
|
||||
losetup $d1 $f1 &&
|
||||
pvs &&
|
||||
pvs'
|
||||
|
||||
test_done
|
||||
|
||||
# Local Variables:
|
||||
# indent-tabs-mode: nil
|
||||
# End:
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/bin/sh
|
||||
# Copyright (C) 2007 Red Hat, Inc. All rights reserved.
|
||||
# Copyright (C) 2007-2008 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
|
||||
|
||||
68
test/t-metadata.sh
Executable file
68
test/t-metadata.sh
Executable file
@@ -0,0 +1,68 @@
|
||||
#!/bin/sh
|
||||
# Copyright (C) 2007 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.
|
||||
#
|
||||
# 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
|
||||
|
||||
#
|
||||
# tests basic functionality of read-ahead and ra regressions
|
||||
#
|
||||
|
||||
test_description='Test --metadatatype 1'
|
||||
privileges_required_=1
|
||||
|
||||
. ./test-lib.sh
|
||||
|
||||
cleanup_()
|
||||
{
|
||||
vgremove -f "$vg"
|
||||
test -n "$d1" && losetup -d "$d1"
|
||||
test -n "$d2" && losetup -d "$d2"
|
||||
test -n "$d3" && losetup -d "$d3"
|
||||
test -n "$d4" && losetup -d "$d4"
|
||||
test -n "$d5" && losetup -d "$d5"
|
||||
rm -f "$f1" "$f2" "$f3" "$f4" "$f5"
|
||||
}
|
||||
|
||||
test_expect_success "set up temp files, loopback devices" \
|
||||
'f1=$(pwd)/1 && d1=$(loop_setup_ "$f1") &&
|
||||
f2=$(pwd)/2 && d2=$(loop_setup_ "$f2") &&
|
||||
f3=$(pwd)/3 && d3=$(loop_setup_ "$f3") &&
|
||||
f4=$(pwd)/4 && d4=$(loop_setup_ "$f4") &&
|
||||
f5=$(pwd)/5 && d5=$(loop_setup_ "$f5") &&
|
||||
vg=$(this_test_)-test-vg-$$ &&
|
||||
lv=$(this_test_)-test-lv-$$
|
||||
pvcreate "$d1" &&
|
||||
pvcreate --metadatacopies 0 "$d2" &&
|
||||
pvcreate --metadatacopies 0 "$d3" &&
|
||||
pvcreate "$d4" &&
|
||||
pvcreate --metadatacopies 0 "$d5" &&
|
||||
vgcreate -c n "$vg" "$d1" "$d2" "$d3" "$d4" "$d5" &&
|
||||
lvcreate -n "$lv" -l 1%FREE -i5 -I256 "$vg"'
|
||||
|
||||
test_expect_success "test medatasize 0" \
|
||||
'pvchange -x n "$d1" &&
|
||||
pvchange -x y "$d1" &&
|
||||
vgchange -a n "$vg" &&
|
||||
pvchange --uuid "$d1" &&
|
||||
pvchange --uuid "$d2" &&
|
||||
vgremove -f "$vg"'
|
||||
|
||||
|
||||
test_expect_success "test metadatatype 1" \
|
||||
'pvcreate -M1 "$d1" &&
|
||||
pvcreate -M1 "$d2" &&
|
||||
pvcreate -M1 "$d3" &&
|
||||
vgcreate -M1 "$vg" "$d1" "$d2" "$d3" &&
|
||||
pvchange --uuid "$d1"'
|
||||
|
||||
test_done
|
||||
|
||||
# Local Variables:
|
||||
# indent-tabs-mode: nil
|
||||
# End:
|
||||
@@ -387,6 +387,16 @@ test_expect_success "remove from original mirror (the original becomes linear)"
|
||||
mirrorlog_is_on_ $vg/$lv1 $(pv_ 3) &&
|
||||
check_and_cleanup_lvs_'
|
||||
|
||||
test_expect_success "rhbz440405: lvconvert -m0 incorrectly fails if all PEs allocated" \
|
||||
'prepare_lvs_ &&
|
||||
lvcreate -l`pvs --noheadings -ope_count $(pv_ 1)` -m1 -n $lv1 $vg $(pv_ 1) $(pv_ 2) $(pv_ 3):0 &&
|
||||
check_mirror_count_ $vg/$lv1 2 &&
|
||||
check_mirror_log_ $vg/$lv1 &&
|
||||
lvconvert -m0 $vg/$lv1 $(pv_ 1) &&
|
||||
check_no_tmplvs_ $vg/$lv1 &&
|
||||
check_mirror_count_ $vg/$lv1 1 &&
|
||||
check_and_cleanup_lvs_'
|
||||
|
||||
# ---------------------------------------------------------------------
|
||||
|
||||
test_done
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user